diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 35a5e836388..0e07c58b399 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -662,8 +662,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity(); - let param_env = tcx.param_env(impl_m_def_id); - // First, check a few of the same things as `compare_impl_method`, // just so we don't ICE during substitution later. check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?; @@ -689,6 +687,19 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let trait_to_placeholder_args = impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args); + let hybrid_preds = tcx + .predicates_of(impl_m.container_id(tcx)) + .instantiate_identity(tcx) + .into_iter() + .chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_placeholder_args)) + .map(|(clause, _)| clause); + let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing); + let param_env = traits::normalize_param_env_or_error( + tcx, + param_env, + ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id), + ); + let infcx = &tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(infcx); diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs new file mode 100644 index 00000000000..5e14a7f8e72 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs @@ -0,0 +1,26 @@ +#![feature(return_position_impl_trait_in_trait)] + +trait Extend { + fn extend<'a: 'a>(_: &'a str) -> (impl Sized + 'a, &'static str); +} + +impl Extend for () { + fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) + //~^ ERROR in type `&'static &'a ()`, reference has a longer lifetime than the data it references + where + 'a: 'static, + { + (None, s) + } +} + +// This indirection is not necessary for reproduction, +// but it makes this test future-proof against #114936. +fn extend(s: &str) -> &'static str { + ::extend(s).1 +} + +fn main() { + let use_after_free = extend::<()>(&String::from("temporary")); + println!("{}", use_after_free); +} diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr new file mode 100644 index 00000000000..1d947310e12 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr @@ -0,0 +1,16 @@ +error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:8:38 + | +LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the pointer is valid for the static lifetime +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/rpitit-hidden-types-self-implied-wf-via-param.rs:8:15 + | +LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`.