From fd7cadd986cb342de80a14b6857323e0f33e83cd Mon Sep 17 00:00:00 2001 From: lapla Date: Sun, 8 Feb 2026 22:45:08 +0900 Subject: [PATCH] Fix ICE in `deny_equality_constraints` with bare qualified self types --- .../rustc_ast_passes/src/ast_validation.rs | 30 +++++++++++++++++++ .../equality-constraint-with-bare-qself.rs | 12 ++++++++ ...equality-constraint-with-bare-qself.stderr | 25 ++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 tests/ui/where-clauses/equality-constraint-with-bare-qself.rs create mode 100644 tests/ui/where-clauses/equality-constraint-with-bare-qself.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2457e0a777e44..4fbf26e1dfe93 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1838,6 +1838,7 @@ fn deny_equality_constraints( // Given `::Bar = RhsTy`, suggest `A: Foo`. if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind + && qself.position > 0 // `::AssocTy` is handled further down && let TyKind::Path(None, path) = &qself.ty.kind && let [PathSegment { ident, args: None, .. }] = &path.segments[..] { @@ -1987,6 +1988,35 @@ fn deny_equality_constraints( } } } + // Given `A: Foo, ::Bar = RhsTy`, suggest `A: Foo`. + if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind + && qself.position == 0 + && let TyKind::Path(None, path) = &qself.ty.kind + && let [potential_param] = &path.segments[..] + && let [potential_assoc] = &full_path.segments[..] + { + for (ident, bounds) in generics.params.iter().map(|p| (p.ident, &p.bounds)).chain( + generics.where_clause.predicates.iter().filter_map(|pred| match &pred.kind { + WherePredicateKind::BoundPredicate(p) + if let ast::TyKind::Path(None, path) = &p.bounded_ty.kind + && let [segment] = &path.segments[..] => + { + Some((segment.ident, &p.bounds)) + } + _ => None, + }), + ) { + if ident == potential_param.ident { + for bound in bounds { + if let ast::GenericBound::Trait(poly) = bound + && poly.modifiers == TraitBoundModifiers::NONE + { + suggest(poly, potential_assoc, predicate); + } + } + } + } + } this.dcx().emit_err(err); } diff --git a/tests/ui/where-clauses/equality-constraint-with-bare-qself.rs b/tests/ui/where-clauses/equality-constraint-with-bare-qself.rs new file mode 100644 index 0000000000000..659bf31290c94 --- /dev/null +++ b/tests/ui/where-clauses/equality-constraint-with-bare-qself.rs @@ -0,0 +1,12 @@ +// issue: + +use std::iter::Iterator; + +struct Ty +//~^ ERROR type parameter `T` is never used +where + T: Iterator, + ::Item = i32, {} +//~^ ERROR equality constraints are not yet supported in `where` clauses + +fn main() {} diff --git a/tests/ui/where-clauses/equality-constraint-with-bare-qself.stderr b/tests/ui/where-clauses/equality-constraint-with-bare-qself.stderr new file mode 100644 index 0000000000000..eaf1927c40f9b --- /dev/null +++ b/tests/ui/where-clauses/equality-constraint-with-bare-qself.stderr @@ -0,0 +1,25 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-constraint-with-bare-qself.rs:9:5 + | +LL | ::Item = i32, {} + | ^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - T: Iterator, +LL - ::Item = i32, {} +LL + T: Iterator, {} + | + +error[E0392]: type parameter `T` is never used + --> $DIR/equality-constraint-with-bare-qself.rs:5:11 + | +LL | struct Ty + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`.