diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index 1d6f9b2917651..38a53a7da67fc 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -251,15 +251,26 @@ fn compare_predicate_entailment<'tcx>( let mut wf_tys = FxIndexSet::default(); - let impl_sig = infcx.replace_bound_vars_with_fresh_vars( + let unnormalized_impl_sig = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, infer::HigherRankedType, tcx.fn_sig(impl_m.def_id), ); + let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig)); + + // We need to check that the impl's args are well-formed given + // the hybrid param-env (impl + trait method where-clauses). + ocx.register_obligation(traits::Obligation::new( + tcx, + cause.clone(), + param_env, + ty::Binder::dummy(ty::PredicateKind::WellFormed( + tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig)).into(), + )), + )); let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id); - let impl_sig = ocx.normalize(&norm_cause, param_env, impl_sig); - let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); + let impl_fty = ocx.normalize(&norm_cause, param_env, unnormalized_impl_fty); debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs); diff --git a/src/test/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.rs b/src/test/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.rs new file mode 100644 index 0000000000000..280856805e551 --- /dev/null +++ b/src/test/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.rs @@ -0,0 +1,19 @@ +trait Project { + type Ty; +} +impl Project for &'_ &'_ () { + type Ty = (); +} +trait Trait { + fn get<'s>(s: &'s str, _: ()) -> &'static str; +} +impl Trait for () { + fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements + s + } +} +fn main() { + let val = <() as Trait>::get(&String::from("blah blah blah"), ()); + println!("{}", val); +} diff --git a/src/test/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/src/test/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr new file mode 100644 index 0000000000000..4e4d9102db338 --- /dev/null +++ b/src/test/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -0,0 +1,28 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:5 + | +LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'s` as defined here... + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:12 + | +LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + | ^^ +note: ...so that the method type is compatible with trait + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:5 + | +LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `fn(&'s str, ()) -> &'static str` + found `fn(&str, ()) -> &'static str` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the reference type `&'static &()` does not outlive the data it points at + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:5 + | +LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/implied-bounds/impl-implied-bounds-compatibility.rs b/src/test/ui/implied-bounds/impl-implied-bounds-compatibility.rs new file mode 100644 index 0000000000000..442179c072f07 --- /dev/null +++ b/src/test/ui/implied-bounds/impl-implied-bounds-compatibility.rs @@ -0,0 +1,18 @@ +use std::cell::RefCell; + +pub struct MessageListeners<'a> { + listeners: RefCell>>, +} + +pub trait MessageListenersInterface { + fn listeners<'c>(&'c self) -> &'c MessageListeners<'c>; +} + +impl<'a> MessageListenersInterface for MessageListeners<'a> { + fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter 'b in generic type due to conflicting requirement + self + } +} + +fn main() {} diff --git a/src/test/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/src/test/ui/implied-bounds/impl-implied-bounds-compatibility.stderr new file mode 100644 index 0000000000000..cca31ea4fcc16 --- /dev/null +++ b/src/test/ui/implied-bounds/impl-implied-bounds-compatibility.stderr @@ -0,0 +1,32 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'b in generic type due to conflicting requirements + --> $DIR/impl-implied-bounds-compatibility.rs:12:5 + | +LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'c` as defined here... + --> $DIR/impl-implied-bounds-compatibility.rs:12:5 + | +LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...so that the method type is compatible with trait + --> $DIR/impl-implied-bounds-compatibility.rs:12:5 + | +LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `fn(&'c MessageListeners<'a>) -> &'c MessageListeners<'c>` + found `fn(&MessageListeners<'a>) -> &'a MessageListeners<'_>` +note: but, the lifetime must be valid for the lifetime `'a` as defined here... + --> $DIR/impl-implied-bounds-compatibility.rs:11:6 + | +LL | impl<'a> MessageListenersInterface for MessageListeners<'a> { + | ^^ +note: ...so that the reference type `&'a MessageListeners<'_>` does not outlive the data it points at + --> $DIR/impl-implied-bounds-compatibility.rs:12:5 + | +LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`.