From fa829feb2f7a3fee5890f3acf57b66029b123d18 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 17 May 2024 11:14:36 -0400 Subject: [PATCH] Only make GAT ambiguous in match_projection_projections considering shallow resolvability --- .../src/traits/select/mod.rs | 12 +++++++++++- .../guide-inference-in-gat-arg-deeper.rs | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6a0ad2d19c45e..19affac7970b9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1778,9 +1778,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If this type is a GAT, and of the GAT args resolve to something new, // that means that we must have newly inferred something about the GAT. // We should give up in that case. + // FIXME(generic-associated-types): This only detects one layer of inference, + // which is probably not what we actually want, but fixing it causes some ambiguity: + // . if !generics.own_params.is_empty() && obligation.predicate.args[generics.parent_count..].iter().any(|&p| { - p.has_non_region_infer() && self.infcx.resolve_vars_if_possible(p) != p + p.has_non_region_infer() + && match p.unpack() { + ty::GenericArgKind::Const(ct) => { + self.infcx.shallow_resolve_const(ct) != ct + } + ty::GenericArgKind::Type(ty) => self.infcx.shallow_resolve(ty) != ty, + ty::GenericArgKind::Lifetime(_) => false, + } }) { ProjectionMatchesProjection::Ambiguous diff --git a/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs b/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs new file mode 100644 index 0000000000000..96a0f2f40bf49 --- /dev/null +++ b/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs @@ -0,0 +1,19 @@ +// Fix for . +//@ check-pass + +trait Tr { + type Gat; +} + +struct W(T); + +fn foo() where for<'a> &'a T: Tr> = i32> { + let x: <&T as Tr>::Gat> = 1i32; + // Previously, `match_projection_projections` only checked that + // `shallow_resolve(W) = W`. This won't prevent *all* inference guidance + // from projection predicates in the environment, just ones that guide the + // outermost type of each GAT constructor. This is definitely wrong, but there is + // code that relies on it in the wild :/ +} + +fn main() {}