From 6ed469c806c600078ae08f3703e4f7f7ae2f5de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 9 Nov 2025 22:18:08 +0100 Subject: [PATCH] IAT: Reinstate early bailout --- .../src/hir_ty_lowering/mod.rs | 18 ++++++++--- .../fall-back-to-trait-candidate.rs | 25 +++++++++++++++ ...-self-type-differs-shadowing-trait-item.rs | 31 ------------------- ...ffers-shadowing-trait-item.shadowed.stderr | 15 --------- ...fers-shadowing-trait-item.uncovered.stderr | 15 --------- .../prefer-inherent-over-trait.rs | 28 +++++++++++++++++ 6 files changed, 66 insertions(+), 66 deletions(-) create mode 100644 tests/ui/associated-inherent-types/fall-back-to-trait-candidate.rs delete mode 100644 tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs delete mode 100644 tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr delete mode 100644 tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr create mode 100644 tests/ui/associated-inherent-types/prefer-inherent-over-trait.rs 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 c1eb277b1380b..10ee5714ba104 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1481,11 +1481,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match assoc_tag { // Don't attempt to look up inherent associated types when the feature is not // enabled. Theoretically it'd be fine to do so since we feature-gate their - // definition site. However, due to current limitations of the implementation - // (caused by us performing selection during HIR ty lowering instead of in the - // trait solver), IATs can lead to cycle errors (#108491) which mask the - // feature-gate error, needlessly confusing users who use IATs by accident - // (#113265). + // definition site. However, the current implementation of inherent associated + // items is somewhat brittle, so let's not run it by default. ty::AssocTag::Type => return Ok(None), ty::AssocTag::Const => { // We also gate the mgca codepath for type-level uses of inherent consts @@ -1514,9 +1511,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) .collect(); + // At the moment, we actually bail out with a hard error if the selection of an inherent + // associated item fails (see below). This means we never consider trait associated items + // as potential fallback candidates (#142006). To temporarily mask that issue, let's not + // select at all if there are no early inherent candidates. + if candidates.is_empty() { + return Ok(None); + } + let (applicable_candidates, fulfillment_errors) = self.select_inherent_assoc_candidates(span, self_ty, candidates.clone()); + // FIXME(#142006): Don't eagerly error here, there might be applicable trait candidates. let InherentAssocCandidate { impl_, assoc_item, scope: def_scope } = match &applicable_candidates[..] { &[] => Err(self.report_unresolved_inherent_assoc_item( @@ -1537,6 +1543,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )), }?; + // FIXME(#142006): Don't eagerly validate here, there might be trait candidates that are + // accessible (visible and stable) contrary to the inherent candidate. self.check_assoc_item(assoc_item, name, def_scope, block, span); // FIXME(fmease): Currently creating throwaway `parent_args` to please diff --git a/tests/ui/associated-inherent-types/fall-back-to-trait-candidate.rs b/tests/ui/associated-inherent-types/fall-back-to-trait-candidate.rs new file mode 100644 index 0000000000000..6c3eee0f7ec74 --- /dev/null +++ b/tests/ui/associated-inherent-types/fall-back-to-trait-candidate.rs @@ -0,0 +1,25 @@ +// Ensure that IAT selection doesn't hard error on associated type paths that could refer to +// an inherent associated type if we can't find an applicable inherent candidate since there +// might still be valid trait associated type candidates. +// +// FIXME(#142006): This only covers the bare minimum, we also need to disqualify inherent +// candidates if they're inaccessible or if the impl headers don't match / apply. +// +// issue: +//@ check-pass + +#![feature(inherent_associated_types)] +#![expect(incomplete_features)] + +struct Type; +trait Trait { type AssocTy; fn scope(); } + +impl Trait for Type { + type AssocTy = (); + + fn scope() { + let (): Self::AssocTy; + } +} + +fn main() { ::scope(); } diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs deleted file mode 100644 index 337fd8fa00c55..0000000000000 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![feature(inherent_associated_types)] -#![allow(incomplete_features)] - -// Check that it's okay to report “[inherent] associated type […] not found” for inherent associated -// type candidates that are not applicable (due to unsuitable Self type) even if there exists a -// “shadowed” associated type from a trait with the same name since its use would be ambiguous -// anyway if the IAT didn't exist. -// FIXME(inherent_associated_types): Figure out which error would be more helpful here. - -//@ revisions: shadowed uncovered - -struct S(T); - -trait Tr { - type Pr; -} - -impl Tr for S { - type Pr = (); -} - -#[cfg(shadowed)] -impl S<()> { - type Pr = i32; -} - -fn main() { - let _: S::::Pr = (); - //[shadowed]~^ ERROR associated type `Pr` not found - //[uncovered]~^^ ERROR associated type `Pr` not found -} diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr deleted file mode 100644 index a247d6d5b45bd..0000000000000 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0220]: associated type `Pr` not found for `S` in the current scope - --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:23 - | -LL | struct S(T); - | ----------- associated type `Pr` not found for this struct -... -LL | let _: S::::Pr = (); - | ^^ associated item not found in `S` - | - = note: the associated type was found for - - `S<()>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr deleted file mode 100644 index f35158c5b4101..0000000000000 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0220]: associated type `Pr` not found for `S` in the current scope - --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:23 - | -LL | struct S(T); - | ----------- associated type `Pr` not found for this struct -... -LL | let _: S::::Pr = (); - | ^^ associated item not found in `S` - | - = note: the associated type was found for - - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-inherent-types/prefer-inherent-over-trait.rs b/tests/ui/associated-inherent-types/prefer-inherent-over-trait.rs new file mode 100644 index 0000000000000..6c81ef7409d4a --- /dev/null +++ b/tests/ui/associated-inherent-types/prefer-inherent-over-trait.rs @@ -0,0 +1,28 @@ +#![feature(inherent_associated_types)] +#![expect(incomplete_features)] + +// Ensure that prefer inherent associated types over trait associated types +// (assuming the impl headers match and they're accessible). +//@ check-pass + +struct Adt; + +impl Adt { + type Ty = (); +} + +trait Trait { + type Ty; + fn scope(); +} + +impl Trait for Adt { + type Ty = i32; + fn scope() { + // We prefer the inherent assoc ty `Adt::Ty` (`()`) over the + // trait assoc ty `::Ty` (`i32`). + let (): Self::Ty; + } +} + +fn main() {}