]> git.lizzy.rs Git - rust.git/commitdiff
Move comparing of impl methods against trait from collect to check.
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 29 Oct 2013 10:11:22 +0000 (06:11 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Sat, 9 Nov 2013 00:45:49 +0000 (19:45 -0500)
This code fits better in check because it is checking that the impl
matches the interface. This allows us to avoid the awkward constructions
that lazilly collect traits and so forth. It also permits us to make
use of the results of variance inference.

src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/coherence.rs
src/librustc/middle/typeck/collect.rs
src/test/compile-fail/class-method-missing.rs
src/test/compile-fail/issue-3344.rs
src/test/compile-fail/missing-derivable-attr.rs

index 982bc493417677c053a34e361653e046dcfa4717..cf362384f3adeb6017d08d7bb59afa35f720ab76 100644 (file)
@@ -603,7 +603,23 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
         for m in ms.iter() {
             check_method_body(ccx, &impl_tpt.generics, None, *m);
         }
-        vtable::resolve_impl(ccx, it);
+
+        match *opt_trait_ref {
+            Some(ref ast_trait_ref) => {
+                let impl_trait_ref =
+                    ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
+                check_impl_methods_against_trait(ccx,
+                                             it.span,
+                                             &impl_tpt.generics,
+                                             ast_trait_ref,
+                                             impl_trait_ref,
+                                             *ms);
+                vtable::resolve_impl(ccx, it, &impl_tpt.generics,
+                                     impl_trait_ref);
+            }
+            None => { }
+        }
+
       }
       ast::item_trait(_, _, ref trait_methods) => {
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
@@ -707,6 +723,311 @@ fn check_method_body(ccx: @mut CrateCtxt,
         param_env);
 }
 
+fn check_impl_methods_against_trait(ccx: @mut CrateCtxt,
+                                    impl_span: Span,
+                                    impl_generics: &ty::Generics,
+                                    ast_trait_ref: &ast::trait_ref,
+                                    impl_trait_ref: &ty::TraitRef,
+                                    impl_methods: &[@ast::method]) {
+    // Locate trait methods
+    let tcx = ccx.tcx;
+    let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
+
+    // Check existing impl methods to see if they are both present in trait
+    // and compatible with trait signature
+    for impl_method in impl_methods.iter() {
+        let impl_method_def_id = local_def(impl_method.id);
+        let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
+
+        // If this is an impl of a trait method, find the corresponding
+        // method definition in the trait.
+        let opt_trait_method_ty =
+            trait_methods.iter().
+            find(|tm| tm.ident.name == impl_method_ty.ident.name);
+        match opt_trait_method_ty {
+            Some(trait_method_ty) => {
+                compare_impl_method(ccx.tcx,
+                                    impl_generics,
+                                    impl_method_ty,
+                                    impl_method.span,
+                                    impl_method.body.id,
+                                    *trait_method_ty,
+                                    &impl_trait_ref.substs);
+            }
+            None => {
+                tcx.sess.span_err(
+                    impl_method.span,
+                    format!("method `{}` is not a member of trait `{}`",
+                            tcx.sess.str_of(impl_method_ty.ident),
+                            pprust::path_to_str(&ast_trait_ref.path,
+                                                tcx.sess.intr())));
+            }
+        }
+    }
+
+    // Check for missing methods from trait
+    let provided_methods = ty::provided_trait_methods(tcx,
+                                                      impl_trait_ref.def_id);
+    let mut missing_methods = ~[];
+    for trait_method in trait_methods.iter() {
+        let is_implemented =
+            impl_methods.iter().any(
+                |m| m.ident.name == trait_method.ident.name);
+        let is_provided =
+            provided_methods.iter().any(
+                |m| m.ident.name == trait_method.ident.name);
+        if !is_implemented && !is_provided {
+            missing_methods.push(
+                format!("`{}`", ccx.tcx.sess.str_of(trait_method.ident)));
+        }
+    }
+
+    if !missing_methods.is_empty() {
+        tcx.sess.span_err(
+            impl_span,
+            format!("not all trait methods implemented, missing: {}",
+                    missing_methods.connect(", ")));
+    }
+}
+
+/**
+ * Checks that a method from an impl/class conforms to the signature of
+ * the same method as declared in the trait.
+ *
+ * # Parameters
+ *
+ * - impl_generics: the generics declared on the impl itself (not the method!)
+ * - impl_m: type of the method we are checking
+ * - impl_m_span: span to use for reporting errors
+ * - impl_m_body_id: id of the method body
+ * - trait_m: the method in the trait
+ * - trait_substs: the substitutions used on the type of the trait
+ * - self_ty: the self type of the impl
+ */
+pub fn compare_impl_method(tcx: ty::ctxt,
+                           impl_generics: &ty::Generics,
+                           impl_m: @ty::Method,
+                           impl_m_span: Span,
+                           impl_m_body_id: ast::NodeId,
+                           trait_m: &ty::Method,
+                           trait_substs: &ty::substs) {
+    debug!("compare_impl_method()");
+    let infcx = infer::new_infer_ctxt(tcx);
+
+    let impl_tps = impl_generics.type_param_defs.len();
+
+    // Try to give more informative error messages about self typing
+    // mismatches.  Note that any mismatch will also be detected
+    // below, where we construct a canonical function type that
+    // includes the self parameter as a normal parameter.  It's just
+    // that the error messages you get out of this code are a bit more
+    // inscrutable, particularly for cases where one method has no
+    // self.
+    match (&trait_m.explicit_self, &impl_m.explicit_self) {
+        (&ast::sty_static, &ast::sty_static) => {}
+        (&ast::sty_static, _) => {
+            tcx.sess.span_err(
+                impl_m_span,
+                format!("method `{}` has a `{}` declaration in the impl, \
+                        but not in the trait",
+                        tcx.sess.str_of(trait_m.ident),
+                        pprust::explicit_self_to_str(&impl_m.explicit_self,
+                                                     tcx.sess.intr())));
+            return;
+        }
+        (_, &ast::sty_static) => {
+            tcx.sess.span_err(
+                impl_m_span,
+                format!("method `{}` has a `{}` declaration in the trait, \
+                        but not in the impl",
+                        tcx.sess.str_of(trait_m.ident),
+                        pprust::explicit_self_to_str(&trait_m.explicit_self,
+                                                     tcx.sess.intr())));
+            return;
+        }
+        _ => {
+            // Let the type checker catch other errors below
+        }
+    }
+
+    let num_impl_m_type_params = impl_m.generics.type_param_defs.len();
+    let num_trait_m_type_params = trait_m.generics.type_param_defs.len();
+    if num_impl_m_type_params != num_trait_m_type_params {
+        tcx.sess.span_err(
+            impl_m_span,
+            format!("method `{}` has {} type parameter(s), but its trait \
+                    declaration has {} type parameter(s)",
+                    tcx.sess.str_of(trait_m.ident),
+                    num_impl_m_type_params,
+                    num_trait_m_type_params));
+        return;
+    }
+
+    if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
+        tcx.sess.span_err(
+            impl_m_span,
+            format!("method `{}` has {} parameter(s) \
+                    but the trait has {} parameter(s)",
+                    tcx.sess.str_of(trait_m.ident),
+                    impl_m.fty.sig.inputs.len(),
+                    trait_m.fty.sig.inputs.len()));
+        return;
+    }
+
+    for (i, trait_param_def) in trait_m.generics.type_param_defs.iter().enumerate() {
+        // For each of the corresponding impl ty param's bounds...
+        let impl_param_def = &impl_m.generics.type_param_defs[i];
+
+        // Check that the impl does not require any builtin-bounds
+        // that the trait does not guarantee:
+        let extra_bounds =
+            impl_param_def.bounds.builtin_bounds -
+            trait_param_def.bounds.builtin_bounds;
+        if !extra_bounds.is_empty() {
+           tcx.sess.span_err(
+               impl_m_span,
+               format!("in method `{}`, \
+                       type parameter {} requires `{}`, \
+                       which is not required by \
+                       the corresponding type parameter \
+                       in the trait declaration",
+                       tcx.sess.str_of(trait_m.ident),
+                       i,
+                       extra_bounds.user_string(tcx)));
+           return;
+        }
+
+        // FIXME(#2687)---we should be checking that the bounds of the
+        // trait imply the bounds of the subtype, but it appears we
+        // are...not checking this.
+        if impl_param_def.bounds.trait_bounds.len() !=
+            trait_param_def.bounds.trait_bounds.len()
+        {
+            tcx.sess.span_err(
+                impl_m_span,
+                format!("in method `{}`, \
+                        type parameter {} has {} trait bound(s), but the \
+                        corresponding type parameter in \
+                        the trait declaration has {} trait bound(s)",
+                        tcx.sess.str_of(trait_m.ident),
+                        i, impl_param_def.bounds.trait_bounds.len(),
+                        trait_param_def.bounds.trait_bounds.len()));
+            return;
+        }
+    }
+
+    // Create a substitution that maps the type parameters on the impl
+    // to themselves and which replace any references to bound regions
+    // in the self type with free regions.  So, for example, if the
+    // impl type is "&'self str", then this would replace the self
+    // type with a free region `self`.
+    let dummy_impl_tps: ~[ty::t] =
+        impl_generics.type_param_defs.iter().enumerate().
+        map(|(i,t)| ty::mk_param(tcx, i, t.def_id)).
+        collect();
+    let dummy_method_tps: ~[ty::t] =
+        impl_m.generics.type_param_defs.iter().enumerate().
+        map(|(i,t)| ty::mk_param(tcx, i + impl_tps, t.def_id)).
+        collect();
+    let dummy_impl_regions: OptVec<ty::Region> =
+        impl_generics.region_param_defs.iter().
+        map(|l| ty::re_free(ty::FreeRegion {
+                scope_id: impl_m_body_id,
+                bound_region: ty::br_named(l.def_id, l.ident)})).
+        collect();
+    let dummy_substs = ty::substs {
+        tps: vec::append(dummy_impl_tps, dummy_method_tps),
+        regions: ty::NonerasedRegions(dummy_impl_regions),
+        self_ty: None };
+
+    // We are going to create a synthetic fn type that includes
+    // both the method's self argument and its normal arguments.
+    // So a method like `fn(&self, a: uint)` would be converted
+    // into a function `fn(self: &T, a: uint)`.
+    let mut trait_fn_args = ~[];
+    let mut impl_fn_args = ~[];
+
+    // For both the trait and the impl, create an argument to
+    // represent the self argument (unless this is a static method).
+    // This argument will have the *transformed* self type.
+    for &t in trait_m.transformed_self_ty.iter() {
+        trait_fn_args.push(t);
+    }
+    for &t in impl_m.transformed_self_ty.iter() {
+        impl_fn_args.push(t);
+    }
+
+    // Add in the normal arguments.
+    trait_fn_args.push_all(trait_m.fty.sig.inputs);
+    impl_fn_args.push_all(impl_m.fty.sig.inputs);
+
+    // Create a bare fn type for trait/impl that includes self argument
+    let trait_fty =
+        ty::mk_bare_fn(tcx,
+                       ty::BareFnTy {
+                            purity: trait_m.fty.purity,
+                            abis: trait_m.fty.abis,
+                            sig: ty::FnSig {
+                                binder_id: trait_m.fty.sig.binder_id,
+                                inputs: trait_fn_args,
+                                output: trait_m.fty.sig.output,
+                                variadic: false
+                            }
+                        });
+    let impl_fty =
+        ty::mk_bare_fn(tcx,
+                       ty::BareFnTy {
+                            purity: impl_m.fty.purity,
+                            abis: impl_m.fty.abis,
+                            sig: ty::FnSig {
+                                binder_id: impl_m.fty.sig.binder_id,
+                                inputs: impl_fn_args,
+                                output: impl_m.fty.sig.output,
+                                variadic: false
+                            }
+                        });
+
+    // Perform substitutions so that the trait/impl methods are expressed
+    // in terms of the same set of type/region parameters:
+    // - replace trait type parameters with those from `trait_substs`,
+    //   except with any reference to bound self replaced with `dummy_self_r`
+    // - replace method parameters on the trait with fresh, dummy parameters
+    //   that correspond to the parameters we will find on the impl
+    // - replace self region with a fresh, dummy region
+    let impl_fty = {
+        debug!("impl_fty (pre-subst): {}", ppaux::ty_to_str(tcx, impl_fty));
+        impl_fty.subst(tcx, &dummy_substs)
+    };
+    debug!("impl_fty (post-subst): {}", ppaux::ty_to_str(tcx, impl_fty));
+    let trait_fty = {
+        let substs { regions: trait_regions,
+                     tps: trait_tps,
+                     self_ty: self_ty } = trait_substs.subst(tcx, &dummy_substs);
+        let substs = substs {
+            regions: trait_regions,
+            tps: vec::append(trait_tps, dummy_method_tps),
+            self_ty: self_ty,
+        };
+        debug!("trait_fty (pre-subst): {} substs={}",
+               trait_fty.repr(tcx), substs.repr(tcx));
+        trait_fty.subst(tcx, &substs)
+    };
+    debug!("trait_fty (post-subst): {}", trait_fty.repr(tcx));
+
+    match infer::mk_subty(infcx, false, infer::MethodCompatCheck(impl_m_span),
+                          impl_fty, trait_fty) {
+        result::Ok(()) => {}
+        result::Err(ref terr) => {
+            tcx.sess.span_err(
+                impl_m_span,
+                format!("method `{}` has an incompatible type: {}",
+                        tcx.sess.str_of(trait_m.ident),
+                        ty::type_err_to_str(tcx, terr)));
+            ty::note_and_explain_type_err(tcx, terr);
+        }
+    }
+}
+
 impl AstConv for FnCtxt {
     fn tcx(&self) -> ty::ctxt { self.ccx.tcx }
 
index b959c80db38a81a6267668b439962abf83455598..bf00bee270943359215444504410f1a898bfc0e7 100644 (file)
@@ -536,33 +536,6 @@ pub fn trait_ref_to_trait_def_id(&self, trait_ref: &trait_ref) -> DefId {
         return trait_id;
     }
 
-    // This check doesn't really have anything to do with coherence. It's
-    // here for historical reasons
-    pub fn check_trait_methods_are_implemented(
-        &self,
-        all_methods: &mut ~[@Method],
-        trait_did: DefId,
-        trait_ref_span: Span) {
-
-        let tcx = self.crate_context.tcx;
-
-        let mut provided_names = HashSet::new();
-        // Implemented methods
-        for elt in all_methods.iter() {
-            provided_names.insert(elt.ident.name);
-        }
-
-        let r = ty::trait_methods(tcx, trait_did);
-        for method in r.iter() {
-            debug!("checking for {}", method.ident.repr(tcx));
-            if provided_names.contains(&method.ident.name) { continue; }
-
-            tcx.sess.span_err(trait_ref_span,
-                              format!("missing method `{}`",
-                                   tcx.sess.str_of(method.ident)));
-        }
-    }
-
     /// For coherence, when we have `impl Type`, we need to guarantee that
     /// `Type` is "local" to the crate. For our purposes, this means that it
     /// must precisely name some nominal type defined in this crate.
@@ -617,17 +590,10 @@ pub fn create_impl_from_item(&self, item: @item) -> @Impl {
                     let ty_trait_ref = ty::node_id_to_trait_ref(
                         self.crate_context.tcx,
                         trait_ref.ref_id);
-                    let trait_did = ty_trait_ref.def_id;
 
                     self.instantiate_default_methods(local_def(item.id),
                                                      ty_trait_ref,
                                                      &mut methods);
-
-                    // Check that we have implementations of every trait method
-                    self.check_trait_methods_are_implemented(
-                        &mut methods,
-                        trait_did,
-                        trait_ref.path.span);
                 }
 
                 return @Impl {
index c1908e69f1e09681f05dc903d958b28cd782d4fb..7cf004be5e2a5774a0d4a1f9d4c5e4d7162d9e58 100644 (file)
@@ -411,290 +411,6 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
     bounds
 }
 
-/**
- * Checks that a method from an impl/class conforms to the signature of
- * the same method as declared in the trait.
- *
- * # Parameters
- *
- * - impl_tps: the type params declared on the impl itself (not the method!)
- * - cm: info about the method we are checking
- * - trait_m: the method in the trait
- * - trait_substs: the substitutions used on the type of the trait
- * - self_ty: the self type of the impl
- */
-pub fn compare_impl_method(tcx: ty::ctxt,
-                           impl_tps: uint,
-                           cm: &ConvertedMethod,
-                           trait_m: &ty::Method,
-                           trait_substs: &ty::substs,
-                           self_ty: ty::t) {
-    debug!("compare_impl_method()");
-    let infcx = infer::new_infer_ctxt(tcx);
-
-    let impl_m = &cm.mty;
-
-    // Try to give more informative error messages about self typing
-    // mismatches.  Note that any mismatch will also be detected
-    // below, where we construct a canonical function type that
-    // includes the self parameter as a normal parameter.  It's just
-    // that the error messages you get out of this code are a bit more
-    // inscrutable, particularly for cases where one method has no
-    // self.
-    match (&trait_m.explicit_self, &impl_m.explicit_self) {
-        (&ast::sty_static, &ast::sty_static) => {}
-        (&ast::sty_static, _) => {
-            tcx.sess.span_err(
-                cm.span,
-                format!("method `{}` has a `{}` declaration in the impl, \
-                      but not in the trait",
-                     tcx.sess.str_of(trait_m.ident),
-                     explicit_self_to_str(&impl_m.explicit_self, tcx.sess.intr())));
-            return;
-        }
-        (_, &ast::sty_static) => {
-            tcx.sess.span_err(
-                cm.span,
-                format!("method `{}` has a `{}` declaration in the trait, \
-                      but not in the impl",
-                     tcx.sess.str_of(trait_m.ident),
-                     explicit_self_to_str(&trait_m.explicit_self, tcx.sess.intr())));
-            return;
-        }
-        _ => {
-            // Let the type checker catch other errors below
-        }
-    }
-
-    let num_impl_m_type_params = impl_m.generics.type_param_defs.len();
-    let num_trait_m_type_params = trait_m.generics.type_param_defs.len();
-    if num_impl_m_type_params != num_trait_m_type_params {
-        tcx.sess.span_err(
-            cm.span,
-            format!("method `{}` has {} type {}, but its trait \
-                  declaration has {} type {}",
-                 tcx.sess.str_of(trait_m.ident),
-                 num_impl_m_type_params,
-                 pluralize(num_impl_m_type_params, ~"parameter"),
-                 num_trait_m_type_params,
-                 pluralize(num_trait_m_type_params, ~"parameter")));
-        return;
-    }
-
-    if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
-        tcx.sess.span_err(
-            cm.span,
-            format!("method `{}` has {} parameter{} \
-                  but the trait has {}",
-                 tcx.sess.str_of(trait_m.ident),
-                 impl_m.fty.sig.inputs.len(),
-                 if impl_m.fty.sig.inputs.len() == 1 { "" } else { "s" },
-                 trait_m.fty.sig.inputs.len()));
-        return;
-    }
-
-    for (i, trait_param_def) in trait_m.generics.type_param_defs.iter().enumerate() {
-        // For each of the corresponding impl ty param's bounds...
-        let impl_param_def = &impl_m.generics.type_param_defs[i];
-
-        // Check that the impl does not require any builtin-bounds
-        // that the trait does not guarantee:
-        let extra_bounds =
-            impl_param_def.bounds.builtin_bounds -
-            trait_param_def.bounds.builtin_bounds;
-        if !extra_bounds.is_empty() {
-           tcx.sess.span_err(
-               cm.span,
-               format!("in method `{}`, \
-                     type parameter {} requires `{}`, \
-                     which is not required by \
-                     the corresponding type parameter \
-                     in the trait declaration",
-                    tcx.sess.str_of(trait_m.ident),
-                    i,
-                    extra_bounds.user_string(tcx)));
-           return;
-        }
-
-        // FIXME(#2687)---we should be checking that the bounds of the
-        // trait imply the bounds of the subtype, but it appears we
-        // are...not checking this.
-        if impl_param_def.bounds.trait_bounds.len() !=
-            trait_param_def.bounds.trait_bounds.len()
-        {
-            tcx.sess.span_err(
-                cm.span,
-                format!("in method `{}`, \
-                      type parameter {} has {} trait {}, but the \
-                      corresponding type parameter in \
-                      the trait declaration has {} trait {}",
-                     tcx.sess.str_of(trait_m.ident),
-                     i, impl_param_def.bounds.trait_bounds.len(),
-                     pluralize(impl_param_def.bounds.trait_bounds.len(),
-                               ~"bound"),
-                     trait_param_def.bounds.trait_bounds.len(),
-                     pluralize(trait_param_def.bounds.trait_bounds.len(),
-                               ~"bound")));
-            return;
-        }
-    }
-
-    // Replace any references to the self region in the self type with
-    // a free region.  So, for example, if the impl type is
-    // "&'self str", then this would replace the self type with a free
-    // region `self`.
-    let dummy_self_r = ty::re_free(ty::FreeRegion {scope_id: cm.body_id,
-                                                   bound_region: ty::br_self});
-    let self_ty = replace_bound_self(tcx, self_ty, dummy_self_r);
-
-    // We are going to create a synthetic fn type that includes
-    // both the method's self argument and its normal arguments.
-    // So a method like `fn(&self, a: uint)` would be converted
-    // into a function `fn(self: &T, a: uint)`.
-    let mut trait_fn_args = ~[];
-    let mut impl_fn_args = ~[];
-
-    // For both the trait and the impl, create an argument to
-    // represent the self argument (unless this is a static method).
-    // This argument will have the *transformed* self type.
-    for &t in trait_m.transformed_self_ty.iter() {
-        trait_fn_args.push(t);
-    }
-    for &t in impl_m.transformed_self_ty.iter() {
-        impl_fn_args.push(t);
-    }
-
-    // Add in the normal arguments.
-    trait_fn_args.push_all(trait_m.fty.sig.inputs);
-    impl_fn_args.push_all(impl_m.fty.sig.inputs);
-
-    // Create a bare fn type for trait/impl that includes self argument
-    let trait_fty =
-        ty::mk_bare_fn(tcx,
-                       ty::BareFnTy {
-                            purity: trait_m.fty.purity,
-                            abis: trait_m.fty.abis,
-                            sig: ty::FnSig {
-                                bound_lifetime_names:
-                                    trait_m.fty
-                                           .sig
-                                           .bound_lifetime_names
-                                           .clone(),
-                                inputs: trait_fn_args,
-                                output: trait_m.fty.sig.output,
-                                variadic: false
-                            }
-                        });
-    let impl_fty =
-        ty::mk_bare_fn(tcx,
-                       ty::BareFnTy {
-                            purity: impl_m.fty.purity,
-                            abis: impl_m.fty.abis,
-                            sig: ty::FnSig {
-                                bound_lifetime_names:
-                                    impl_m.fty
-                                          .sig
-                                          .bound_lifetime_names
-                                          .clone(),
-                                    inputs: impl_fn_args,
-                                    output: impl_m.fty.sig.output,
-                                    variadic: false
-                            }
-                        });
-
-    // Perform substitutions so that the trait/impl methods are expressed
-    // in terms of the same set of type/region parameters:
-    // - replace trait type parameters with those from `trait_substs`,
-    //   except with any reference to bound self replaced with `dummy_self_r`
-    // - replace method parameters on the trait with fresh, dummy parameters
-    //   that correspond to the parameters we will find on the impl
-    // - replace self region with a fresh, dummy region
-    let impl_fty = {
-        debug!("impl_fty (pre-subst): {}", ppaux::ty_to_str(tcx, impl_fty));
-        replace_bound_self(tcx, impl_fty, dummy_self_r)
-    };
-    debug!("impl_fty (post-subst): {}", ppaux::ty_to_str(tcx, impl_fty));
-    let trait_fty = {
-        let num_trait_m_type_params = trait_m.generics.type_param_defs.len();
-        let dummy_tps = do vec::from_fn(num_trait_m_type_params) |i| {
-            ty::mk_param(tcx, i + impl_tps,
-                         impl_m.generics.type_param_defs[i].def_id)
-        };
-        let trait_tps = trait_substs.tps.map(
-            |t| replace_bound_self(tcx, *t, dummy_self_r));
-        let substs = substs {
-            regions: ty::NonerasedRegions(opt_vec::with(dummy_self_r)),
-            self_ty: Some(self_ty),
-            tps: vec::append(trait_tps, dummy_tps)
-        };
-        debug!("trait_fty (pre-subst): {} substs={}",
-               trait_fty.repr(tcx), substs.repr(tcx));
-        ty::subst(tcx, &substs, trait_fty)
-    };
-    debug!("trait_fty (post-subst): {}", trait_fty.repr(tcx));
-
-    match infer::mk_subty(infcx, false, infer::MethodCompatCheck(cm.span),
-                          impl_fty, trait_fty) {
-        result::Ok(()) => {}
-        result::Err(ref terr) => {
-            tcx.sess.span_err(
-                cm.span,
-                format!("method `{}` has an incompatible type: {}",
-                     tcx.sess.str_of(trait_m.ident),
-                     ty::type_err_to_str(tcx, terr)));
-            ty::note_and_explain_type_err(tcx, terr);
-        }
-    }
-    return;
-
-    // Replaces bound references to the self region with `with_r`.
-    fn replace_bound_self(tcx: ty::ctxt, ty: ty::t,
-                          with_r: ty::Region) -> ty::t {
-        do ty::fold_regions(tcx, ty) |r, _in_fn| {
-            if r == ty::re_bound(ty::br_self) {with_r} else {r}
-        }
-    }
-}
-
-pub fn check_methods_against_trait(ccx: &CrateCtxt,
-                                   generics: &ast::Generics,
-                                   rp: Option<ty::region_variance>,
-                                   selfty: ty::t,
-                                   a_trait_ty: &ast::trait_ref,
-                                   impl_ms: &[ConvertedMethod])
-{
-    let tcx = ccx.tcx;
-    let trait_ref = instantiate_trait_ref(ccx, a_trait_ty, rp,
-                                          generics, selfty);
-
-    if trait_ref.def_id.crate == ast::LOCAL_CRATE {
-        ensure_trait_methods(ccx, trait_ref.def_id.node);
-    }
-
-    // Check that each method we impl is a method on the trait
-    // Trait methods we don't implement must be default methods, but if not
-    // we'll catch it in coherence
-    let trait_ms = ty::trait_methods(tcx, trait_ref.def_id);
-    for impl_m in impl_ms.iter() {
-        match trait_ms.iter().find(|trait_m| trait_m.ident.name == impl_m.mty.ident.name) {
-            Some(trait_m) => {
-                let num_impl_tps = generics.ty_params.len();
-                compare_impl_method(
-                    ccx.tcx, num_impl_tps, impl_m, *trait_m,
-                    &trait_ref.substs, selfty);
-            }
-            None => {
-                // This method is not part of the trait
-                tcx.sess.span_err(
-                    impl_m.span,
-                    format!("method `{}` is not a member of trait `{}`",
-                         tcx.sess.str_of(impl_m.mty.ident),
-                         path_to_str(&a_trait_ty.path, tcx.sess.intr())));
-            }
-        }
-    }
-} // fn
-
 pub fn convert_field(ccx: &CrateCtxt,
                      struct_generics: &ty::Generics,
                      v: &ast::struct_field) {
@@ -849,8 +565,6 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
                     "cannot provide an explicit implementation \
                      for a builtin kind");
             }
-
-            check_methods_against_trait(ccx, generics, rp, selfty, t, cms);
         }
       }
       ast::item_trait(ref generics, _, ref trait_methods) => {
index f3c5ab2019daec88da80533e1759b47a065b1b26..ca97a8997689f87786d551c541d1718a0c2a2e50 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:missing method `eat`
 trait animal {
   fn eat(&self);
 }
@@ -18,6 +17,7 @@ struct cat {
 }
 
 impl animal for cat {
+    //~^ ERROR not all trait methods implemented, missing: `eat`
 }
 
 fn cat(in_x : uint) -> cat {
index 9a3fff453f3a0cee5089ced283494485d68c233c..1a649c8ad2f83128c3ae252b5e6888ec11c8f1b2 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 struct thing(uint);
-impl Ord for thing { //~ ERROR missing method `lt`
+impl Ord for thing { //~ ERROR not all trait methods implemented, missing: `lt`
     fn le(&self, other: &thing) -> bool { **self < **other }
     fn ge(&self, other: &thing) -> bool { **self < **other }
 }
index 70c16e0baefb873dd2e3905e18aa2ade3d259575..4e45f33fe9b141e4f5953ba76f3ecc98799bae8f 100644 (file)
@@ -20,7 +20,7 @@ impl MyEq for int {
     fn eq(&self, other: &int) -> bool { *self == *other }
 }
 
-impl MyEq for A {}  //~ ERROR missing method
+impl MyEq for A {}  //~ ERROR not all trait methods implemented, missing: `eq`
 
 fn main() {
 }