diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 07ff9ac1936c..37e29b10cd5a 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -31,7 +31,7 @@ use hir_def::{ }; use rustc_hash::{FxHashMap, FxHashSet}; use rustc_type_ir::{ - TypeVisitableExt, VisitorResult, + TypeFoldable, TypeVisitableExt, VisitorResult, fast_reject::{TreatParams, simplify_type}, inherent::{BoundExistentialPredicates, IntoKind}, try_visit, @@ -49,6 +49,7 @@ use crate::{ SimplifiedType, SolverDefId, TraitRef, Ty, TyKind, TypingMode, Unnormalized, infer::{ BoundRegionConversionTime, DbInternerInferExt, InferCtxt, InferOk, + resolve::ReplaceInferWithError, select::ImplSource, traits::{Obligation, ObligationCause, PredicateObligations}, }, @@ -510,8 +511,15 @@ pub(crate) fn find_matching_impl<'db>( return None; } + // Selection may leave region inference variables unresolved; replace them before they escape + // this inference context. + // + // FIXME: decide whether inferred regions should be replaced with error or erased. match impl_source { - ImplSource::UserDefined(impl_source) => Some((impl_source.impl_def_id, impl_source.args)), + ImplSource::UserDefined(impl_source) => Some(( + impl_source.impl_def_id, + impl_source.args.fold_with(&mut ReplaceInferWithError::new(infcx.interner)), + )), ImplSource::Param(_) | ImplSource::Builtin(..) => None, } } diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs index 7431ac8293e9..f09ac6f20d27 100644 --- a/crates/hir-ty/src/mir/eval/tests.rs +++ b/crates/hir-ty/src/mir/eval/tests.rs @@ -458,6 +458,29 @@ fn main() { ); } +#[test] +fn region_infer_var_does_not_escape_impl_lookup() { + check_pass( + r#" +//- minicore: fn, sized + +trait Bound {} +trait Trait { fn f(self); } + +struct S; + +impl<'a> Bound<&'a ()> for S {} +impl<'a, T: Bound<&'a ()>> Trait for T { + fn f(self) { make::<'a>(); } +} + +fn make<'a>() -> impl Fn(&'a ()) { |_| {} } + +fn main() { S.f(); } +"#, + ); +} + #[test] fn index_of_slice_should_preserve_len() { check_pass(