diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 6656007b50e..d6b653c6189 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -39,6 +39,12 @@ fn mk_raw_path(sp: span, idents: ~[ast::ident]) -> @ast::path {
                            rp: None, types: ~[]};
     return p;
 }
+fn mk_raw_path_(sp: span,
+                idents: ~[ast::ident],
+                +types: ~[@ast::Ty])
+             -> @ast::path {
+    @{ span: sp, global: false, idents: idents, rp: None, types: move types }
+}
 fn mk_path(cx: ext_ctxt, sp: span, idents: ~[ast::ident]) ->
     @ast::expr {
     mk_expr(cx, sp, ast::expr_path(mk_raw_path(sp, idents)))
@@ -224,4 +230,10 @@ fn mk_arg(cx: ext_ctxt,
 fn mk_fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl {
     { inputs: move inputs, output: output, cf: ast::return_val }
 }
+fn mk_ty_param(cx: ext_ctxt,
+               ident: ast::ident,
+               bounds: @~[ast::ty_param_bound])
+            -> ast::ty_param {
+    { ident: ident, id: cx.next_id(), bounds: bounds }
+}
 
diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs
index cf8aa764eea..4a92086963e 100644
--- a/src/libsyntax/ext/deriving.rs
+++ b/src/libsyntax/ext/deriving.rs
@@ -1,15 +1,13 @@
 /// The compiler code necessary to implement the #[deriving_eq] and
 /// #[deriving_iter_bytes] extensions.
 
-use ast::{and, bind_by_ref, binop, blk, default_blk, deref, enum_def};
-use ast::{enum_variant_kind, expr};
-use ast::{expr_, expr_addr_of, expr_binary, expr_call, expr_field, expr_lit};
-use ast::{expr_match, expr_path, expr_unary, ident, infer, item, item_};
-use ast::{item_class, item_enum, item_impl, lit_bool, m_imm, meta_item};
-use ast::{method, named_field, or, pat, pat_ident, pat_wild, path, public};
-use ast::{pure_fn, re_anon, return_val, stmt, struct_def};
+use ast::{Ty, and, bind_by_ref, binop, deref, enum_def, enum_variant_kind};
+use ast::{expr, expr_match, ident, item, item_, item_class, item_enum};
+use ast::{item_impl, m_imm, meta_item, method, named_field, or, pat};
+use ast::{pat_ident, pat_wild, public, pure_fn, re_anon, stmt, struct_def};
 use ast::{struct_variant_kind, sty_by_ref, sty_region, tuple_variant_kind};
-use ast::{ty_nil, ty_path, ty_rptr, unnamed_field, variant};
+use ast::{ty_nil, ty_param, ty_param_bound, ty_path, ty_rptr, unnamed_field};
+use ast::{variant};
 use base::ext_ctxt;
 use codemap::span;
 use parse::token::special_idents::clownshoes_extensions;
@@ -31,13 +29,15 @@ impl Junction {
 type ExpandDerivingStructDefFn = &fn(ext_ctxt,
                                      span,
                                      x: &struct_def,
-                                     ident)
-                                  -> @item;
-type ExpandDerivingEnumDefFn   = &fn(ext_ctxt,
-                                     span,
-                                     x: &enum_def,
-                                     ident)
+                                     ident,
+                                     +y: ~[ty_param])
                                   -> @item;
+type ExpandDerivingEnumDefFn = &fn(ext_ctxt,
+                                   span,
+                                   x: &enum_def,
+                                   ident,
+                                   +y: ~[ty_param])
+                                -> @item;
 
 pub fn expand_deriving_eq(cx: ext_ctxt,
                           span: span,
@@ -73,17 +73,19 @@ fn expand_deriving(cx: ext_ctxt,
     for in_items.each |item| {
         result.push(copy *item);
         match item.node {
-            item_class(struct_def, _) => {
+            item_class(struct_def, copy ty_params) => {
                 result.push(expand_deriving_struct_def(cx,
                                                        span,
                                                        struct_def,
-                                                       item.ident));
+                                                       item.ident,
+                                                       move ty_params));
             }
-            item_enum(ref enum_definition, _) => {
+            item_enum(ref enum_definition, copy ty_params) => {
                 result.push(expand_deriving_enum_def(cx,
                                                      span,
                                                      enum_definition,
-                                                     item.ident));
+                                                     item.ident,
+                                                     move ty_params));
             }
             _ => ()
         }
@@ -97,7 +99,7 @@ fn create_impl_item(cx: ext_ctxt, span: span, +item: item_) -> @item {
         attrs: ~[],
         id: cx.next_id(),
         node: move item,
-        vis: ast::public,
+        vis: public,
         span: span,
     }
 }
@@ -108,10 +110,14 @@ fn create_eq_method(cx: ext_ctxt,
                     span: span,
                     method_ident: ident,
                     type_ident: ident,
+                    ty_params: &[ty_param],
                     body: @expr)
                  -> @method {
     // Create the type of the `other` parameter.
-    let arg_path_type = build::mk_simple_ty_path(cx, span, type_ident);
+    let arg_path_type = create_self_type_with_params(cx,
+                                                     span,
+                                                     type_ident,
+                                                     ty_params);
     let arg_region = @{ id: cx.next_id(), node: re_anon };
     let arg_type = ty_rptr(arg_region, { ty: arg_path_type, mutbl: m_imm });
     let arg_type = @{ id: cx.next_id(), node: move arg_type, span: span };
@@ -153,12 +159,46 @@ fn create_eq_method(cx: ext_ctxt,
     };
 }
 
+fn create_self_type_with_params(cx: ext_ctxt,
+                                span: span,
+                                type_ident: ident,
+                                ty_params: &[ty_param])
+                             -> @Ty {
+    // Create the type parameters on the `self` path.
+    let self_ty_params = dvec::DVec();
+    for ty_params.each |ty_param| {
+        let self_ty_param = build::mk_simple_ty_path(cx,
+                                                     span,
+                                                     ty_param.ident);
+        self_ty_params.push(move self_ty_param);
+    }
+    let self_ty_params = dvec::unwrap(move self_ty_params);
+
+    // Create the type of `self`.
+    let self_type = build::mk_raw_path_(span,
+                                        ~[ type_ident ],
+                                        move self_ty_params);
+    let self_type = ty_path(self_type, cx.next_id());
+    @{ id: cx.next_id(), node: move self_type, span: span }
+}
+
 fn create_derived_impl(cx: ext_ctxt,
                        span: span,
                        type_ident: ident,
+                       +ty_params: ~[ty_param],
                        methods: &[@method],
-                       trait_path: &[ast::ident])
+                       trait_path: &[ident])
                     -> @item {
+    // Create the type parameters.
+    let impl_ty_params = dvec::DVec();
+    for ty_params.each |ty_param| {
+        let bound = build::mk_ty_path(cx, span, trait_path.map(|x| *x));
+        let bounds = @~[ ty_param_bound(bound) ];
+        let impl_ty_param = build::mk_ty_param(cx, ty_param.ident, bounds);
+        impl_ty_params.push(move impl_ty_param);
+    }
+    let impl_ty_params = dvec::unwrap(move impl_ty_params);
+
     // Create the reference to the trait.
     let trait_path = {
         span: span,
@@ -176,12 +216,13 @@ fn create_derived_impl(cx: ext_ctxt,
     let trait_ref = @move trait_ref;
 
     // Create the type of `self`.
-    let self_type = build::mk_raw_path(span, ~[ type_ident ]);
-    let self_type = ty_path(self_type, cx.next_id());
-    let self_type = @{ id: cx.next_id(), node: move self_type, span: span };
+    let self_type = create_self_type_with_params(cx,
+                                                 span,
+                                                 type_ident,
+                                                 ty_params);
 
     // Create the impl item.
-    let impl_item = item_impl(~[],
+    let impl_item = item_impl(move impl_ty_params,
                               Some(trait_ref),
                               self_type,
                               methods.map(|x| *x));
@@ -191,6 +232,7 @@ fn create_derived_impl(cx: ext_ctxt,
 fn create_derived_eq_impl(cx: ext_ctxt,
                           span: span,
                           type_ident: ident,
+                          +ty_params: ~[ty_param],
                           eq_method: @method,
                           ne_method: @method)
                        -> @item {
@@ -200,20 +242,22 @@ fn create_derived_eq_impl(cx: ext_ctxt,
         cx.ident_of(~"cmp"),
         cx.ident_of(~"Eq")
     ];
-    create_derived_impl(cx, span, type_ident, methods, trait_path)
+    create_derived_impl(cx, span, type_ident, ty_params, methods, trait_path)
 }
 
 fn create_derived_iter_bytes_impl(cx: ext_ctxt,
                                   span: span,
                                   type_ident: ident,
+                                  +ty_params: ~[ty_param],
                                   method: @method)
                                -> @item {
+    let methods = [ method ];
     let trait_path = [
         cx.ident_of(~"core"),
         cx.ident_of(~"to_bytes"),
         cx.ident_of(~"IterBytes")
     ];
-    create_derived_impl(cx, span, type_ident, [ method ], trait_path)
+    create_derived_impl(cx, span, type_ident, ty_params, methods, trait_path)
 }
 
 // Creates a method from the given set of statements conforming to the
@@ -267,9 +311,9 @@ fn create_iter_bytes_method(cx: ext_ctxt,
 
 fn create_enum_variant_pattern(cx: ext_ctxt,
                                span: span,
-                               variant: &ast::variant,
+                               variant: &variant,
                                prefix: ~str)
-                            -> @ast::pat {
+                            -> @pat {
     let variant_ident = variant.node.name;
     match variant.node.kind {
         tuple_variant_kind(ref variant_args) => {
@@ -386,7 +430,8 @@ fn variant_arg_count(cx: ext_ctxt, span: span, variant: &variant) -> uint {
 fn expand_deriving_eq_struct_def(cx: ext_ctxt,
                                  span: span,
                                  struct_def: &struct_def,
-                                 type_ident: ident)
+                                 type_ident: ident,
+                                 +ty_params: ~[ty_param])
                               -> @item {
     // Create the methods.
     let eq_ident = cx.ident_of(~"eq");
@@ -396,22 +441,63 @@ fn expand_deriving_eq_struct_def(cx: ext_ctxt,
                                                      struct_def,
                                                      eq_ident,
                                                      type_ident,
+                                                     ty_params,
                                                      Conjunction);
     let ne_method = expand_deriving_eq_struct_method(cx,
                                                      span,
                                                      struct_def,
                                                      ne_ident,
                                                      type_ident,
+                                                     ty_params,
                                                      Disjunction);
 
     // Create the implementation.
-    return create_derived_eq_impl(cx, span, type_ident, eq_method, ne_method);
+    return create_derived_eq_impl(cx,
+                                  span,
+                                  type_ident,
+                                  move ty_params,
+                                  eq_method,
+                                  ne_method);
+}
+
+fn expand_deriving_eq_enum_def(cx: ext_ctxt,
+                               span: span,
+                               enum_definition: &enum_def,
+                               type_ident: ident,
+                               +ty_params: ~[ty_param])
+                            -> @item {
+    // Create the methods.
+    let eq_ident = cx.ident_of(~"eq");
+    let ne_ident = cx.ident_of(~"ne");
+    let eq_method = expand_deriving_eq_enum_method(cx,
+                                                   span,
+                                                   enum_definition,
+                                                   eq_ident,
+                                                   type_ident,
+                                                   ty_params,
+                                                   Conjunction);
+    let ne_method = expand_deriving_eq_enum_method(cx,
+                                                   span,
+                                                   enum_definition,
+                                                   ne_ident,
+                                                   type_ident,
+                                                   ty_params,
+                                                   Disjunction);
+
+    // Create the implementation.
+    return create_derived_eq_impl(cx,
+                                  span,
+                                  type_ident,
+                                  move ty_params,
+                                  eq_method,
+                                  ne_method);
 }
 
 fn expand_deriving_iter_bytes_struct_def(cx: ext_ctxt,
                                          span: span,
                                          struct_def: &struct_def,
-                                         type_ident: ident)
+                                         type_ident: ident,
+                                         +ty_params: ~[ty_param])
                                       -> @item {
     // Create the method.
     let method = expand_deriving_iter_bytes_struct_method(cx,
@@ -419,13 +505,18 @@ fn expand_deriving_iter_bytes_struct_def(cx: ext_ctxt,
                                                           struct_def);
 
     // Create the implementation.
-    return create_derived_iter_bytes_impl(cx, span, type_ident, method);
+    return create_derived_iter_bytes_impl(cx,
+                                          span,
+                                          type_ident,
+                                          move ty_params,
+                                          method);
 }
 
 fn expand_deriving_iter_bytes_enum_def(cx: ext_ctxt,
                                        span: span,
                                        enum_definition: &enum_def,
-                                       type_ident: ident)
+                                       type_ident: ident,
+                                       +ty_params: ~[ty_param])
                                     -> @item {
     // Create the method.
     let method = expand_deriving_iter_bytes_enum_method(cx,
@@ -433,7 +524,11 @@ fn expand_deriving_iter_bytes_enum_def(cx: ext_ctxt,
                                                         enum_definition);
 
     // Create the implementation.
-    return create_derived_iter_bytes_impl(cx, span, type_ident, method);
+    return create_derived_iter_bytes_impl(cx,
+                                          span,
+                                          type_ident,
+                                          move ty_params,
+                                          method);
 }
 
 fn expand_deriving_eq_struct_method(cx: ext_ctxt,
@@ -441,6 +536,7 @@ fn expand_deriving_eq_struct_method(cx: ext_ctxt,
                                     struct_def: &struct_def,
                                     method_ident: ident,
                                     type_ident: ident,
+                                    ty_params: &[ty_param],
                                     junction: Junction)
                                  -> @method {
     let self_ident = cx.ident_of(~"self");
@@ -483,7 +579,12 @@ fn expand_deriving_eq_struct_method(cx: ext_ctxt,
 
     // Create the method itself.
     let body = finish_eq_chain_expr(cx, span, outer_expr, junction);
-    return create_eq_method(cx, span, method_ident, type_ident, body);
+    return create_eq_method(cx,
+                            span,
+                            method_ident,
+                            type_ident,
+                            ty_params,
+                            body);
 }
 
 fn expand_deriving_iter_bytes_struct_method(cx: ext_ctxt,
@@ -521,36 +622,12 @@ fn expand_deriving_iter_bytes_struct_method(cx: ext_ctxt,
     return create_iter_bytes_method(cx, span, move statements);
 }
 
-fn expand_deriving_eq_enum_def(cx: ext_ctxt,
-                               span: span,
-                               enum_definition: &enum_def,
-                               type_ident: ident)
-                            -> @item {
-    // Create the methods.
-    let eq_ident = cx.ident_of(~"eq");
-    let ne_ident = cx.ident_of(~"ne");
-    let eq_method = expand_deriving_eq_enum_method(cx,
-                                                span,
-                                                enum_definition,
-                                                eq_ident,
-                                                type_ident,
-                                                Conjunction);
-    let ne_method = expand_deriving_eq_enum_method(cx,
-                                                   span,
-                                                   enum_definition,
-                                                   ne_ident,
-                                                   type_ident,
-                                                   Disjunction);
-
-    // Create the implementation.
-    return create_derived_eq_impl(cx, span, type_ident, eq_method, ne_method);
-}
-
 fn expand_deriving_eq_enum_method(cx: ext_ctxt,
                                   span: span,
                                   enum_definition: &enum_def,
                                   method_ident: ident,
                                   type_ident: ident,
+                                  ty_params: &[ty_param],
                                   junction: Junction)
                                -> @method {
     let self_ident = cx.ident_of(~"self");
@@ -672,6 +749,7 @@ fn expand_deriving_eq_enum_method(cx: ext_ctxt,
                             span,
                             method_ident,
                             type_ident,
+                            ty_params,
                             self_match_expr);
 }
 
diff --git a/src/test/run-pass/deriving-via-extension-type-params.rs b/src/test/run-pass/deriving-via-extension-type-params.rs
new file mode 100644
index 00000000000..74ecac67f49
--- /dev/null
+++ b/src/test/run-pass/deriving-via-extension-type-params.rs
@@ -0,0 +1,17 @@
+#[deriving_eq]
+#[deriving_iter_bytes]
+struct Foo<T> {
+    x: int,
+    y: T,
+    z: int
+}
+
+fn main() {
+    let a = Foo { x: 1, y: 2.0, z: 3 };
+    let b = Foo { x: 1, y: 2.0, z: 3 };
+    assert a == b;
+    assert !(a != b);
+    assert a.eq(&b);
+    assert !a.ne(&b);
+}
+