diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 064ceb1e1c1..cd3cc43b853 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -619,14 +619,11 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> { let tcx = self.tcx(); - // It is illegal to create a trait object with methods which includes - // the Self type. An error will be reported when we coerce to a trait - // object if the method refers to the `Self` type. Substituting ty_err - // here allows compiler to soldier on. - // - // `confirm_candidate()` also relies upon this substitution - // for Self. (fix) - let rcvr_substs = substs.with_self_ty(ty::mk_err()); + // It is illegal to invoke a method on a trait instance that refers to + // the `Self` type. Here, we use a substitution that replaces `Self` + // with the object type itself. Hence, a `&self` method will wind up + // with an argument type like `&Trait`. + let rcvr_substs = substs.with_self_ty(self_ty); let trait_ref = Rc::new(TraitRef { def_id: did, @@ -1337,6 +1334,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> { self.ty_to_string(rcvr_ty), candidate.repr(self.tcx())); + let rcvr_substs = candidate.rcvr_substs.clone(); self.enforce_drop_trait_limitations(candidate); // Determine the values for the generic parameters of the method. diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 7a5ce9a528c..94c4d7c25e0 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1687,7 +1687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_unsize_obligations(span, &**u) } ty::UnsizeVtable(ref ty_trait, self_ty) => { - vtable2::check_object_safety(self.tcx(), ty_trait, span); + vtable::check_object_safety(self.tcx(), ty_trait, span); // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` implements `Foo`: vtable::register_object_cast_obligations(self, diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 115b224241b..b7195734e8b 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -179,7 +179,7 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa */ let mut msgs = Vec::new(); - let method_name = method.ident.repr(tcx); + let method_name = method.name.repr(tcx); match method.explicit_self { ty::ByValueExplicitSelfCategory => { // reason (a) above @@ -204,12 +204,18 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa } }; let ref sig = method.fty.sig; - for &input_ty in sig.inputs.tail().iter().chain([sig.output].iter()) { + for &input_ty in sig.inputs[1..].iter() { match check_for_self_ty(input_ty) { Some(msg) => msgs.push(msg), _ => {} } } + if let ty::FnConverging(result_type) = sig.output { + match check_for_self_ty(result_type) { + Some(msg) => msgs.push(msg), + _ => {} + } + } if method.generics.has_type_params(FnSpace) { // reason (b) above diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs index 6791b7c5870..dfeba041092 100644 --- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs +++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs @@ -11,24 +11,27 @@ // Test that attempts to implicitly coerce a value into an // object respect the lifetime bound on the object type. -fn a(v: &[u8]) -> Box { - let x: Box = box v; //~ ERROR does not outlive +trait Foo {} +impl<'a> Foo for &'a [u8] {} + +fn a(v: &[u8]) -> Box { + let x: Box = box v; //~ ERROR does not outlive x } -fn b(v: &[u8]) -> Box { +fn b(v: &[u8]) -> Box { box v //~ ERROR does not outlive } -fn c(v: &[u8]) -> Box { +fn c(v: &[u8]) -> Box { box v // OK thanks to lifetime elision } -fn d<'a,'b>(v: &'a [u8]) -> Box { +fn d<'a,'b>(v: &'a [u8]) -> Box { box v //~ ERROR does not outlive } -fn e<'a:'b,'b>(v: &'a [u8]) -> Box { +fn e<'a:'b,'b>(v: &'a [u8]) -> Box { box v // OK, thanks to 'a:'b }