From e8381f10475507834e5d21f60acd86cec2d76614 Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Sun, 27 Sep 2026 20:52:00 +0330 Subject: [PATCH 1/5] associated type suggestion ICE with const generics Signed-off-by: Amirhossein Akhlaghpour --- .../src/hir_ty_lowering/mod.rs | 34 ++++- .../assoc-ty-const-generics-issue-163320.rs | 57 ++++++++ ...ssoc-ty-const-generics-issue-163320.stderr | 123 ++++++++++++++++++ ...const-generics-suggestions-issue-163320.rs | 37 ++++++ ...t-generics-suggestions-issue-163320.stderr | 31 +++++ 5 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.rs create mode 100644 tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr create mode 100644 tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs create mode 100644 tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e9dc2a61d698d..7842bff1ed144 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1871,6 +1871,38 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &infcx_ }; + // The full param-env isn't available yet but the solver still needs + // const-parameter typing clauses. when lowering a generic parameter + // only include earlier parameters to avoid querying its own type + let (generics_def_id, cutoff) = + if matches!(tcx.def_kind(self.item_def_id()), DefKind::ConstParam | DefKind::TyParam) { + let parent = tcx.local_parent(self.item_def_id()); + let index = tcx + .generics_of(parent) + .param_def_id_to_index(tcx, self.item_def_id().to_def_id()) + .expect("generic parameter must belong to its parent"); + (parent, index as usize) + } else { + (self.item_def_id(), usize::MAX) + }; + + let generics = tcx.generics_of(generics_def_id); + let identity_args = ty::GenericArgs::identity_for_item(tcx, generics_def_id); + let const_param_env = ty::ParamEnv::new( + tcx, + identity_args.iter().enumerate().take(cutoff).filter_map(|(index, arg)| { + match arg.kind() { + GenericArgKind::Const(ct) => { + let param_def_id = generics.param_at(index, tcx).def_id; + let ct_ty = + tcx.type_of(param_def_id).instantiate_identity().skip_norm_wip(); + Some(ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx)) + } + _ => None, + } + }), + ); + tcx.all_traits_including_private() .filter(|trait_def_id| { // Consider only traits with the associated type @@ -1896,7 +1928,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } infcx .can_eq( - ty::ParamEnv::empty(), + const_param_env, trait_ref.self_ty(), value, ) && header.polarity != ty::ImplPolarity::Negative diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.rs b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.rs new file mode 100644 index 0000000000000..d6d704395f04f --- /dev/null +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.rs @@ -0,0 +1,57 @@ +// Regression test for issue #163320: probing associated-type suggestions +// must retain const-parameter typing information under the next solver. + +//@ compile-flags: -Znext-solver=globally +//@ check-fail + +#![feature(generic_const_parameter_types)] + +fn where_clause() +where + <[(); N] as IntoIterator>::Item::Item:, + //~^ ERROR ambiguous associated type +{} + +fn nested_where() +where + Option<<[(); N] as IntoIterator>::Item::Item>: Sized, + //~^ ERROR ambiguous associated type +{} + +fn parameter( + _: <[(); N] as IntoIterator>::Item::Item, + //~^ ERROR ambiguous associated type +) {} + +type Alias = + <[(); N] as IntoIterator>::Item::Item; +//~^ ERROR ambiguous associated type + +struct Field { + field: <[(); N] as IntoIterator>::Item::Item, + //~^ ERROR ambiguous associated type +} + +struct Parent; + +impl Parent { + fn inherited() + where + <[(); N] as IntoIterator>::Item::Item:, + //~^ ERROR ambiguous associated type + {} +} + +struct ConstParameter< + const N: usize, + const M: <[(); N] as IntoIterator>::Item::Item, + //~^ ERROR ambiguous associated type +>; + +struct TypeParameterDefault< + const N: usize, + T = <[(); N] as IntoIterator>::Item::Item, + //~^ ERROR ambiguous associated type +>(std::marker::PhantomData); + +fn main() {} diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr new file mode 100644 index 0000000000000..6c8ab9d53e71e --- /dev/null +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr @@ -0,0 +1,123 @@ +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:11:5 + | +LL | <[(); N] as IntoIterator>::Item::Item:, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - <[(); N] as IntoIterator>::Item::Item:, +LL + <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item:, + | +LL - <[(); N] as IntoIterator>::Item::Item:, +LL + <<[(); N] as IntoIterator>::Item as IntoIterator>::Item:, + | + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:17:12 + | +LL | Option<<[(); N] as IntoIterator>::Item::Item>: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - Option<<[(); N] as IntoIterator>::Item::Item>: Sized, +LL + Option<<<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item>: Sized, + | +LL - Option<<[(); N] as IntoIterator>::Item::Item>: Sized, +LL + Option<<<[(); N] as IntoIterator>::Item as IntoIterator>::Item>: Sized, + | + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:22:8 + | +LL | _: <[(); N] as IntoIterator>::Item::Item, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - _: <[(); N] as IntoIterator>::Item::Item, +LL + _: <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item, + | +LL - _: <[(); N] as IntoIterator>::Item::Item, +LL + _: <<[(); N] as IntoIterator>::Item as IntoIterator>::Item, + | + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:27:5 + | +LL | <[(); N] as IntoIterator>::Item::Item; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - <[(); N] as IntoIterator>::Item::Item; +LL + <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item; + | +LL - <[(); N] as IntoIterator>::Item::Item; +LL + <<[(); N] as IntoIterator>::Item as IntoIterator>::Item; + | + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:31:12 + | +LL | field: <[(); N] as IntoIterator>::Item::Item, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - field: <[(); N] as IntoIterator>::Item::Item, +LL + field: <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item, + | +LL - field: <[(); N] as IntoIterator>::Item::Item, +LL + field: <<[(); N] as IntoIterator>::Item as IntoIterator>::Item, + | + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:47:14 + | +LL | const M: <[(); N] as IntoIterator>::Item::Item, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - const M: <[(); N] as IntoIterator>::Item::Item, +LL + const M: <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item, + | +LL - const M: <[(); N] as IntoIterator>::Item::Item, +LL + const M: <<[(); N] as IntoIterator>::Item as IntoIterator>::Item, + | + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:53:9 + | +LL | T = <[(); N] as IntoIterator>::Item::Item, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - T = <[(); N] as IntoIterator>::Item::Item, +LL + T = <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item, + | +LL - T = <[(); N] as IntoIterator>::Item::Item, +LL + T = <<[(); N] as IntoIterator>::Item as IntoIterator>::Item, + | + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:40:9 + | +LL | <[(); N] as IntoIterator>::Item::Item:, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - <[(); N] as IntoIterator>::Item::Item:, +LL + <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item:, + | +LL - <[(); N] as IntoIterator>::Item::Item:, +LL + <<[(); N] as IntoIterator>::Item as IntoIterator>::Item:, + | + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs new file mode 100644 index 0000000000000..d311878942e19 --- /dev/null +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs @@ -0,0 +1,37 @@ +// The const-parameter environment fix must retain applicable associated-type +// suggestions without suggesting an impl for an incompatible projection. + +//@ compile-flags: -Znext-solver=globally +//@ check-fail + +trait Identity { + type Out; +} + +impl Identity for () { + type Out = (u8, u8); +} + +trait Different { + type Out; +} + +impl Different for () { + type Out = (u8, u16); +} + +trait HasItem { + type Item; +} + +impl HasItem for (T, T) { + type Item = (); +} + +type Positive = <<() as Identity>::Out>::Item; +//~^ ERROR ambiguous associated type + +type Negative = <<() as Different>::Out>::Item; +//~^ ERROR ambiguous associated type + +fn main() {} diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr new file mode 100644 index 0000000000000..198cb0ac8b0b2 --- /dev/null +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr @@ -0,0 +1,31 @@ +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-suggestions-issue-163320.rs:31:17 + | +LL | type Positive = <<() as Identity>::Out>::Item; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | type Positive = <<() as Identity>::Out as HasItem>::Item; + | ++++++++++ +LL | type Positive = <<() as Identity>::Out as IntoAsyncIterator>::Item; + | ++++++++++++++++++++ +LL | type Positive = <<() as Identity>::Out as IntoIterator>::Item; + | +++++++++++++++ + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-suggestions-issue-163320.rs:34:17 + | +LL | type Negative = <<() as Different>::Out>::Item; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | type Negative = <<() as Different>::Out as IntoAsyncIterator>::Item; + | ++++++++++++++++++++ +LL | type Negative = <<() as Different>::Out as IntoIterator>::Item; + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0223`. From 26516030333566915aacfe9a8280e6f7d8ddb2ad Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Tue, 29 Sep 2026 21:42:02 +0330 Subject: [PATCH 2/5] avoid type relations during item lowering diagnostics Signed-off-by: Amirhossein Akhlaghpour --- compiler/rustc_hir_analysis/src/collect.rs | 4 + .../src/hir_ty_lowering/mod.rs | 107 +++++++++--------- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 + .../assoc-ty-const-generics-issue-163320.rs | 9 +- ...ssoc-ty-const-generics-issue-163320.stderr | 71 +++++------- ...const-generics-suggestions-issue-163320.rs | 18 ++- ...t-generics-suggestions-issue-163320.stderr | 57 ++++++++-- 7 files changed, 163 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c3cc3bcd6cd0c..8d45c223af0f1 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -717,6 +717,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { None } + fn param_env(&self) -> Option> { + None + } + fn lower_fn_sig( &self, decl: &hir::FnDecl<'_>, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7842bff1ed144..56e9d031a8555 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -37,7 +37,7 @@ use rustc_errors::{ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::InferCtxt; use rustc_infer::traits::DynCompatibilityViolation; use rustc_lint_defs::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -45,8 +45,8 @@ use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{ self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, - Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, - const_lit_matches_ty, fold_regions, + Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, Unnormalized, Upcast, const_lit_matches_ty, + fold_regions, }; use rustc_session::diagnostics::feature_err; use rustc_span::def_id::{LocalModId, ModId}; @@ -232,6 +232,9 @@ pub trait HirTyLowerer<'tcx> { /// The inference context of the lowering context if applicable. fn infcx(&self) -> Option<&InferCtxt<'tcx>>; + /// The parameter environment when lowering in a context with inference. + fn param_env(&self) -> Option>; + /// Convenience method for coercing the lowering context into a trait object type. /// /// Most lowering routines are defined on the trait object type directly @@ -1860,48 +1863,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Vec { let tcx = self.tcx(); - // In contexts that have no inference context, just make a new one. - // We do need a local variable to store it, though. - let infcx_; - let infcx = if let Some(infcx) = self.infcx() { - infcx - } else { - assert!(!qself_ty.has_infer()); - infcx_ = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - &infcx_ - }; + let infcx = self.infcx(); + let param_env = self.param_env(); - // The full param-env isn't available yet but the solver still needs - // const-parameter typing clauses. when lowering a generic parameter - // only include earlier parameters to avoid querying its own type - let (generics_def_id, cutoff) = - if matches!(tcx.def_kind(self.item_def_id()), DefKind::ConstParam | DefKind::TyParam) { - let parent = tcx.local_parent(self.item_def_id()); - let index = tcx - .generics_of(parent) - .param_def_id_to_index(tcx, self.item_def_id().to_def_id()) - .expect("generic parameter must belong to its parent"); - (parent, index as usize) - } else { - (self.item_def_id(), usize::MAX) - }; + // We cannot normalize aliases while lowering item signatures. + // Avoid suggesting traits based on an unresolved projection. + if infcx.is_none() && qself_ty.has_aliases() { + return Vec::new(); + } - let generics = tcx.generics_of(generics_def_id); - let identity_args = ty::GenericArgs::identity_for_item(tcx, generics_def_id); - let const_param_env = ty::ParamEnv::new( - tcx, - identity_args.iter().enumerate().take(cutoff).filter_map(|(index, arg)| { - match arg.kind() { - GenericArgKind::Const(ct) => { - let param_def_id = generics.param_at(index, tcx).def_id; - let ct_ty = - tcx.type_of(param_def_id).instantiate_identity().skip_norm_wip(); - Some(ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx)) - } - _ => None, - } - }), - ); + let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased); + // FIXME: Don't bother dealing with non-lifetime binders here... + if value.has_escaping_bound_vars() { + return Vec::new(); + } tcx.all_traits_including_private() .filter(|trait_def_id| { @@ -1919,19 +1894,47 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { && tcx.all_impls(*trait_def_id) .any(|impl_def_id| { let header = tcx.impl_trait_header(impl_def_id); - let trait_ref = header.trait_ref.instantiate(tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id)).skip_norm_wip(); - - let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased); - // FIXME: Don't bother dealing with non-lifetime binders here... - if value.has_escaping_bound_vars() { + if header.polarity == ty::ImplPolarity::Negative { return false; } - infcx - .can_eq( - const_param_env, + + if let Some(infcx) = infcx { + let trait_ref = header + .trait_ref + .instantiate( + tcx, + infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), + ) + .skip_norm_wip(); + + infcx.can_eq( + param_env.expect("inference requires a parameter environment"), trait_ref.self_ty(), value, - ) && header.polarity != ty::ImplPolarity::Negative + ) + } else { + let impl_ty = header + .trait_ref + .instantiate_identity() + .skip_norm_wip() + .self_ty(); + + // Fast rejection doesn't check that repeated impl + // parameters match the same type. Avoid suggesting + // impls that need that additional equality check. + let mut seen = FxHashSet::default(); + if crate::constrained_generic_params::parameters_for( + tcx, impl_ty, true, + ) + .into_iter() + .any(|param| !seen.insert(param)) + { + return false; + } + + ty::DeepRejectCtxt::relate_rigid_infer(tcx) + .types_may_unify_with_depth(value, impl_ty, usize::MAX) + } }) }) .map(|trait_def_id| tcx.def_path_str(trait_def_id)) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index b2b49dc06b7a6..1a5a65d0f6a85 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -448,6 +448,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { Some(&self.infcx) } + fn param_env(&self) -> Option> { + Some(self.param_env) + } + fn lower_fn_sig( &self, decl: &rustc_hir::FnDecl<'_>, diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.rs b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.rs index d6d704395f04f..cc9084ed37ee9 100644 --- a/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.rs +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.rs @@ -1,5 +1,5 @@ -// Regression test for issue #163320: probing associated-type suggestions -// must retain const-parameter typing information under the next solver. +// Regression test for issue #163320: ambiguous associated-type paths +// involving const generics must not ICE during item lowering or type checking. //@ compile-flags: -Znext-solver=globally //@ check-fail @@ -54,4 +54,9 @@ struct TypeParameterDefault< //~^ ERROR ambiguous associated type >(std::marker::PhantomData); +fn in_body() { + let _: <[(); N] as IntoIterator>::Item::Item; + //~^ ERROR ambiguous associated type +} + fn main() {} diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr index 6c8ab9d53e71e..c1976f534b774 100644 --- a/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr @@ -4,13 +4,10 @@ error[E0223]: ambiguous associated type LL | <[(); N] as IntoIterator>::Item::Item:, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax - | -LL - <[(); N] as IntoIterator>::Item::Item:, -LL + <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item:, +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - <[(); N] as IntoIterator>::Item::Item:, -LL + <<[(); N] as IntoIterator>::Item as IntoIterator>::Item:, +LL + <<[(); N] as IntoIterator>::Item as Example>::Item:, | error[E0223]: ambiguous associated type @@ -19,13 +16,10 @@ error[E0223]: ambiguous associated type LL | Option<<[(); N] as IntoIterator>::Item::Item>: Sized, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax - | -LL - Option<<[(); N] as IntoIterator>::Item::Item>: Sized, -LL + Option<<<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item>: Sized, +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - Option<<[(); N] as IntoIterator>::Item::Item>: Sized, -LL + Option<<<[(); N] as IntoIterator>::Item as IntoIterator>::Item>: Sized, +LL + Option<<<[(); N] as IntoIterator>::Item as Example>::Item>: Sized, | error[E0223]: ambiguous associated type @@ -34,13 +28,10 @@ error[E0223]: ambiguous associated type LL | _: <[(); N] as IntoIterator>::Item::Item, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax - | -LL - _: <[(); N] as IntoIterator>::Item::Item, -LL + _: <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item, +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - _: <[(); N] as IntoIterator>::Item::Item, -LL + _: <<[(); N] as IntoIterator>::Item as IntoIterator>::Item, +LL + _: <<[(); N] as IntoIterator>::Item as Example>::Item, | error[E0223]: ambiguous associated type @@ -49,13 +40,10 @@ error[E0223]: ambiguous associated type LL | <[(); N] as IntoIterator>::Item::Item; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax - | -LL - <[(); N] as IntoIterator>::Item::Item; -LL + <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item; +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - <[(); N] as IntoIterator>::Item::Item; -LL + <<[(); N] as IntoIterator>::Item as IntoIterator>::Item; +LL + <<[(); N] as IntoIterator>::Item as Example>::Item; | error[E0223]: ambiguous associated type @@ -64,13 +52,10 @@ error[E0223]: ambiguous associated type LL | field: <[(); N] as IntoIterator>::Item::Item, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax - | -LL - field: <[(); N] as IntoIterator>::Item::Item, -LL + field: <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item, +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - field: <[(); N] as IntoIterator>::Item::Item, -LL + field: <<[(); N] as IntoIterator>::Item as IntoIterator>::Item, +LL + field: <<[(); N] as IntoIterator>::Item as Example>::Item, | error[E0223]: ambiguous associated type @@ -79,13 +64,10 @@ error[E0223]: ambiguous associated type LL | const M: <[(); N] as IntoIterator>::Item::Item, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - const M: <[(); N] as IntoIterator>::Item::Item, -LL + const M: <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item, - | -LL - const M: <[(); N] as IntoIterator>::Item::Item, -LL + const M: <<[(); N] as IntoIterator>::Item as IntoIterator>::Item, +LL + const M: <<[(); N] as IntoIterator>::Item as Example>::Item, | error[E0223]: ambiguous associated type @@ -94,13 +76,10 @@ error[E0223]: ambiguous associated type LL | T = <[(); N] as IntoIterator>::Item::Item, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax - | -LL - T = <[(); N] as IntoIterator>::Item::Item, -LL + T = <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item, +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - T = <[(); N] as IntoIterator>::Item::Item, -LL + T = <<[(); N] as IntoIterator>::Item as IntoIterator>::Item, +LL + T = <<[(); N] as IntoIterator>::Item as Example>::Item, | error[E0223]: ambiguous associated type @@ -109,15 +88,27 @@ error[E0223]: ambiguous associated type LL | <[(); N] as IntoIterator>::Item::Item:, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - <[(); N] as IntoIterator>::Item::Item:, -LL + <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item:, +LL + <<[(); N] as IntoIterator>::Item as Example>::Item:, | -LL - <[(); N] as IntoIterator>::Item::Item:, -LL + <<[(); N] as IntoIterator>::Item as IntoIterator>::Item:, + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-issue-163320.rs:58:12 + | +LL | let _: <[(); N] as IntoIterator>::Item::Item; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL - let _: <[(); N] as IntoIterator>::Item::Item; +LL + let _: <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item; + | +LL - let _: <[(); N] as IntoIterator>::Item::Item; +LL + let _: <<[(); N] as IntoIterator>::Item as IntoIterator>::Item; | -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs index d311878942e19..5f6a73e308d4e 100644 --- a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs @@ -1,5 +1,5 @@ -// The const-parameter environment fix must retain applicable associated-type -// suggestions without suggesting an impl for an incompatible projection. +// Item lowering should not need trait solving for suggestions, while body +// type checking should retain applicable suggestions. //@ compile-flags: -Znext-solver=globally //@ check-fail @@ -34,4 +34,18 @@ type Positive = <<() as Identity>::Out>::Item; type Negative = <<() as Different>::Out>::Item; //~^ ERROR ambiguous associated type +fn body_positive() { + let _: <<() as Identity>::Out>::Item; + //~^ ERROR ambiguous associated type +} + +fn body_negative() { + let _: <<() as Different>::Out>::Item; + //~^ ERROR ambiguous associated type +} + +// Repeated impl parameters must not produce an incompatible suggestion. +type RepeatedParam = <(u8, u16)>::Item; +//~^ ERROR ambiguous associated type + fn main() {} diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr index 198cb0ac8b0b2..20e9f5e061901 100644 --- a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr @@ -4,14 +4,10 @@ error[E0223]: ambiguous associated type LL | type Positive = <<() as Identity>::Out>::Item; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax +help: if there were a trait named `Example` with associated type `Item` implemented for `<() as Identity>::Out`, you could use the fully-qualified path | -LL | type Positive = <<() as Identity>::Out as HasItem>::Item; +LL | type Positive = <<() as Identity>::Out as Example>::Item; | ++++++++++ -LL | type Positive = <<() as Identity>::Out as IntoAsyncIterator>::Item; - | ++++++++++++++++++++ -LL | type Positive = <<() as Identity>::Out as IntoIterator>::Item; - | +++++++++++++++ error[E0223]: ambiguous associated type --> $DIR/assoc-ty-const-generics-suggestions-issue-163320.rs:34:17 @@ -19,13 +15,52 @@ error[E0223]: ambiguous associated type LL | type Negative = <<() as Different>::Out>::Item; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | +help: if there were a trait named `Example` with associated type `Item` implemented for `<() as Different>::Out`, you could use the fully-qualified path + | +LL | type Negative = <<() as Different>::Out as Example>::Item; + | ++++++++++ + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-suggestions-issue-163320.rs:48:22 + | +LL | type RepeatedParam = <(u8, u16)>::Item; + | ^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | type RepeatedParam = <(u8, u16) as IntoAsyncIterator>::Item; + | ++++++++++++++++++++ +LL | type RepeatedParam = <(u8, u16) as IntoIterator>::Item; + | +++++++++++++++ + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-suggestions-issue-163320.rs:38:12 + | +LL | let _: <<() as Identity>::Out>::Item; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use fully-qualified syntax + | +LL | let _: <<() as Identity>::Out as HasItem>::Item; + | ++++++++++ +LL | let _: <<() as Identity>::Out as IntoAsyncIterator>::Item; + | ++++++++++++++++++++ +LL | let _: <<() as Identity>::Out as IntoIterator>::Item; + | +++++++++++++++ + +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-suggestions-issue-163320.rs:43:12 + | +LL | let _: <<() as Different>::Out>::Item; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | help: use fully-qualified syntax | -LL | type Negative = <<() as Different>::Out as IntoAsyncIterator>::Item; - | ++++++++++++++++++++ -LL | type Negative = <<() as Different>::Out as IntoIterator>::Item; - | +++++++++++++++ +LL | let _: <<() as Different>::Out as IntoAsyncIterator>::Item; + | ++++++++++++++++++++ +LL | let _: <<() as Different>::Out as IntoIterator>::Item; + | +++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0223`. From b3eee237be91bd5312899f6e838f584c3f616f7c Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Tue, 13 Oct 2026 20:55:26 +0330 Subject: [PATCH 3/5] avoid type relations when suggesting associated types Signed-off-by: Amirhossein Akhlaghpour --- compiler/rustc_hir_analysis/src/collect.rs | 4 -- .../src/hir_ty_lowering/errors.rs | 5 +- .../src/hir_ty_lowering/mod.rs | 64 ++++--------------- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 -- ...ssoc-ty-const-generics-issue-163320.stderr | 7 +- ...st-generics-original-repro-issue-163320.rs | 27 ++++++++ ...enerics-original-repro-issue-163320.stderr | 15 +++++ ...const-generics-suggestions-issue-163320.rs | 6 +- ...t-generics-suggestions-issue-163320.stderr | 18 ++---- 9 files changed, 71 insertions(+), 79 deletions(-) create mode 100644 tests/ui/traits/next-solver/assoc-ty-const-generics-original-repro-issue-163320.rs create mode 100644 tests/ui/traits/next-solver/assoc-ty-const-generics-original-repro-issue-163320.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8d45c223af0f1..c3cc3bcd6cd0c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -717,10 +717,6 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { None } - fn param_env(&self) -> Option> { - None - } - fn lower_fn_sig( &self, decl: &hir::FnDecl<'_>, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index bee062b27e0f5..e449e9d7c59a0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -585,6 +585,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &[path_str], item_segment.ident, assoc_tag, + Applicability::MachineApplicable, ) } @@ -698,6 +699,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &traits, ident, assoc_tag, + Applicability::MaybeIncorrect, ) } } @@ -709,6 +711,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { traits: &[String], ident: Ident, assoc_tag: ty::AssocTag, + applicability: Applicability, ) -> ErrorGuaranteed { let kind_str = assoc_tag_str(assoc_tag); let mut err = @@ -807,7 +810,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { sugg_sp, "use fully-qualified syntax", suggestions, - Applicability::MachineApplicable, + applicability, SuggestionStyle::ShowAlways, ); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 56e9d031a8555..cfadf375064b3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -46,12 +46,10 @@ use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{ self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, Unnormalized, Upcast, const_lit_matches_ty, - fold_regions, }; use rustc_session::diagnostics::feature_err; use rustc_span::def_id::{LocalModId, ModId}; -use rustc_span::{DUMMY_SP, Ident, Span, bug, kw, span_bug, sym}; -use rustc_trait_selection::infer::InferCtxtExt; +use rustc_span::{Ident, Span, bug, kw, span_bug, sym}; use rustc_trait_selection::traits::{self, FulfillmentError}; use tracing::{debug, instrument}; @@ -232,9 +230,6 @@ pub trait HirTyLowerer<'tcx> { /// The inference context of the lowering context if applicable. fn infcx(&self) -> Option<&InferCtxt<'tcx>>; - /// The parameter environment when lowering in a context with inference. - fn param_env(&self) -> Option>; - /// Convenience method for coercing the lowering context into a trait object type. /// /// Most lowering routines are defined on the trait object type directly @@ -1863,18 +1858,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Vec { let tcx = self.tcx(); - let infcx = self.infcx(); - let param_env = self.param_env(); - - // We cannot normalize aliases while lowering item signatures. - // Avoid suggesting traits based on an unresolved projection. - if infcx.is_none() && qself_ty.has_aliases() { + // Deep rejection cannot rule out unrelated impls for unresolved aliases. + // Avoid offering misleading suggestions for those types. + if qself_ty.has_aliases() { return Vec::new(); } - let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased); // FIXME: Don't bother dealing with non-lifetime binders here... - if value.has_escaping_bound_vars() { + if qself_ty.has_escaping_bound_vars() { return Vec::new(); } @@ -1898,43 +1889,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return false; } - if let Some(infcx) = infcx { - let trait_ref = header - .trait_ref - .instantiate( - tcx, - infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), - ) - .skip_norm_wip(); - - infcx.can_eq( - param_env.expect("inference requires a parameter environment"), - trait_ref.self_ty(), - value, - ) - } else { - let impl_ty = header - .trait_ref - .instantiate_identity() - .skip_norm_wip() - .self_ty(); - - // Fast rejection doesn't check that repeated impl - // parameters match the same type. Avoid suggesting - // impls that need that additional equality check. - let mut seen = FxHashSet::default(); - if crate::constrained_generic_params::parameters_for( - tcx, impl_ty, true, - ) - .into_iter() - .any(|param| !seen.insert(param)) - { - return false; - } - - ty::DeepRejectCtxt::relate_rigid_infer(tcx) - .types_may_unify_with_depth(value, impl_ty, usize::MAX) - } + let impl_ty = header + .trait_ref + .instantiate_identity() + .skip_norm_wip() + .self_ty(); + + ty::DeepRejectCtxt::relate_rigid_infer(tcx) + .types_may_unify(qself_ty, impl_ty) }) }) .map(|trait_def_id| tcx.def_path_str(trait_def_id)) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 1a5a65d0f6a85..b2b49dc06b7a6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -448,10 +448,6 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { Some(&self.infcx) } - fn param_env(&self) -> Option> { - Some(self.param_env) - } - fn lower_fn_sig( &self, decl: &rustc_hir::FnDecl<'_>, diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr index c1976f534b774..8d87c85a6ac92 100644 --- a/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-issue-163320.stderr @@ -100,13 +100,10 @@ error[E0223]: ambiguous associated type LL | let _: <[(); N] as IntoIterator>::Item::Item; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax - | -LL - let _: <[(); N] as IntoIterator>::Item::Item; -LL + let _: <<[(); N] as IntoIterator>::Item as IntoAsyncIterator>::Item; +help: if there were a trait named `Example` with associated type `Item` implemented for `<[(); N] as IntoIterator>::Item`, you could use the fully-qualified path | LL - let _: <[(); N] as IntoIterator>::Item::Item; -LL + let _: <<[(); N] as IntoIterator>::Item as IntoIterator>::Item; +LL + let _: <<[(); N] as IntoIterator>::Item as Example>::Item; | error: aborting due to 9 previous errors diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-original-repro-issue-163320.rs b/tests/ui/traits/next-solver/assoc-ty-const-generics-original-repro-issue-163320.rs new file mode 100644 index 0000000000000..d53e7908adb77 --- /dev/null +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-original-repro-issue-163320.rs @@ -0,0 +1,27 @@ +// Regression test for the original ICE in issue #163320. +//@ compile-flags: -Znext-solver=globally --crate-type=lib +//@ check-fail + +trait HasStorage { + type Storage; +} + +struct Bits; + +trait TryFromBits { + type Bits; +} + +trait ReadEndian: TryFromBits {} + +struct Zeros; + +impl TryFromBits for Zeros { + type Bits = Bits; +} + +impl ReadEndian for Zeros +where + ::Storage::Bits: Sized, + //~^ ERROR ambiguous associated type +{} diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-original-repro-issue-163320.stderr b/tests/ui/traits/next-solver/assoc-ty-const-generics-original-repro-issue-163320.stderr new file mode 100644 index 0000000000000..544f233dfe8a5 --- /dev/null +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-original-repro-issue-163320.stderr @@ -0,0 +1,15 @@ +error[E0223]: ambiguous associated type + --> $DIR/assoc-ty-const-generics-original-repro-issue-163320.rs:25:5 + | +LL | ::Storage::Bits: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `Bits` implemented for `< as TryFromBits>::Bits as HasStorage>::Storage`, you could use the fully-qualified path + | +LL - ::Storage::Bits: Sized, +LL + << as TryFromBits>::Bits as HasStorage>::Storage as Example>::Bits: Sized, + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs index 5f6a73e308d4e..ae29f307097cc 100644 --- a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.rs @@ -1,5 +1,5 @@ -// Item lowering should not need trait solving for suggestions, while body -// type checking should retain applicable suggestions. +// Suggestions should not need trait solving during either item lowering or +// body type checking. Deep rejection may also admit incompatible impls. //@ compile-flags: -Znext-solver=globally //@ check-fail @@ -44,7 +44,7 @@ fn body_negative() { //~^ ERROR ambiguous associated type } -// Repeated impl parameters must not produce an incompatible suggestion. +// Repeated impl parameters can result in false-positive suggestions. type RepeatedParam = <(u8, u16)>::Item; //~^ ERROR ambiguous associated type diff --git a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr index 20e9f5e061901..4d45070d8192a 100644 --- a/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr +++ b/tests/ui/traits/next-solver/assoc-ty-const-generics-suggestions-issue-163320.stderr @@ -28,6 +28,8 @@ LL | type RepeatedParam = <(u8, u16)>::Item; | help: use fully-qualified syntax | +LL | type RepeatedParam = <(u8, u16) as HasItem>::Item; + | ++++++++++ LL | type RepeatedParam = <(u8, u16) as IntoAsyncIterator>::Item; | ++++++++++++++++++++ LL | type RepeatedParam = <(u8, u16) as IntoIterator>::Item; @@ -39,14 +41,10 @@ error[E0223]: ambiguous associated type LL | let _: <<() as Identity>::Out>::Item; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax +help: if there were a trait named `Example` with associated type `Item` implemented for `<() as Identity>::Out`, you could use the fully-qualified path | -LL | let _: <<() as Identity>::Out as HasItem>::Item; +LL | let _: <<() as Identity>::Out as Example>::Item; | ++++++++++ -LL | let _: <<() as Identity>::Out as IntoAsyncIterator>::Item; - | ++++++++++++++++++++ -LL | let _: <<() as Identity>::Out as IntoIterator>::Item; - | +++++++++++++++ error[E0223]: ambiguous associated type --> $DIR/assoc-ty-const-generics-suggestions-issue-163320.rs:43:12 @@ -54,12 +52,10 @@ error[E0223]: ambiguous associated type LL | let _: <<() as Different>::Out>::Item; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use fully-qualified syntax +help: if there were a trait named `Example` with associated type `Item` implemented for `<() as Different>::Out`, you could use the fully-qualified path | -LL | let _: <<() as Different>::Out as IntoAsyncIterator>::Item; - | ++++++++++++++++++++ -LL | let _: <<() as Different>::Out as IntoIterator>::Item; - | +++++++++++++++ +LL | let _: <<() as Different>::Out as Example>::Item; + | ++++++++++ error: aborting due to 5 previous errors From b84e0479db6b90c7215a64b31499608b1439153c Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Wed, 14 Oct 2026 15:24:47 +0330 Subject: [PATCH 4/5] preserve higher-ranked associated type suggestions Signed-off-by: Amirhossein Akhlaghpour --- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index cfadf375064b3..87f86af28cfd1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1864,11 +1864,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return Vec::new(); } - // FIXME: Don't bother dealing with non-lifetime binders here... - if qself_ty.has_escaping_bound_vars() { - return Vec::new(); - } - tcx.all_traits_including_private() .filter(|trait_def_id| { // Consider only traits with the associated type From 60b099987dca9822b2cadc0cd007aa14d5c63e13 Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Wed, 14 Oct 2026 16:08:51 +0330 Subject: [PATCH 5/5] avoid suggestions for non-lifetime bound variables Signed-off-by: Amirhossein Akhlaghpour --- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 87f86af28cfd1..8e5c33f5d4f16 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1864,6 +1864,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return Vec::new(); } + // FIXME: Support non-lifetime binders without suggesting unrelated traits. + if qself_ty.has_non_region_bound_vars() { + return Vec::new(); + } + tcx.all_traits_including_private() .filter(|trait_def_id| { // Consider only traits with the associated type