diff --git a/crates/flux-infer/src/projections.rs b/crates/flux-infer/src/projections.rs index 00baf7797a..51d8dbacf0 100644 --- a/crates/flux-infer/src/projections.rs +++ b/crates/flux-infer/src/projections.rs @@ -218,7 +218,7 @@ impl<'a, 'infcx, 'genv, 'tcx> Normalizer<'a, 'infcx, 'genv, 'tcx> { // 2. Gather the ProjectionPredicates and solve them see issue-808.rs self.resolve_projection_predicates(&mut subst, impl_def_id)?; - let args = subst.finish(self.tcx(), generics)?; + let mut args = subst.finish(self.tcx(), generics)?; // 3. Get the associated type in the impl block and apply the substitution to it let assoc_type_id = tcx @@ -229,6 +229,15 @@ impl<'a, 'infcx, 'genv, 'tcx> Normalizer<'a, 'infcx, 'genv, 'tcx> { .ok_or_else(|| { query_bug!("no associated type for {obligation:?} in impl {impl_def_id:?}") })?; + + // 4. Append the GAT's own generic args from the obligation. + // The obligation's args are [trait_args..., gat_own_args...]. + // The trait-level args were matched above; the GAT's own args + // (e.g., lifetime parameters on `type Tok<'a>`) start after + // the trait's generic params. + let trait_arg_count = impl_trait_ref.args.len(); + args.extend(obligation.args[trait_arg_count..].iter().cloned()); + Ok(self .genv() .type_of(assoc_type_id)? diff --git a/tests/tests/pos/surface/gat00.rs b/tests/tests/pos/surface/gat00.rs new file mode 100644 index 0000000000..2eab05b300 --- /dev/null +++ b/tests/tests/pos/surface/gat00.rs @@ -0,0 +1,16 @@ +// Test that generic associated types with lifetime parameters work correctly. +// See issue #1716. + +pub trait D { + type Tok<'a>; +} + +pub struct L; + +impl D for L { + type Tok<'a> = &'a L; +} + +pub fn f(x: &L) -> ::Tok<'_> { + x +}