Syntactically reject equality predicates
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8a342ac..b8339c7 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs
@@ -509,8 +509,6 @@ pub enum WherePredicateKind { BoundPredicate(WhereBoundPredicate), /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate), - /// An equality predicate (unsupported). - EqPredicate(WhereEqPredicate), } /// A type bound.
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 0e518c1..8ae2f3b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -2111,18 +2111,6 @@ fn lower_where_predicate( in_where_clause: true, }) } - WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => { - hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { - lhs_ty: self.lower_ty_alloc( - lhs_ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ), - rhs_ty: self.lower_ty_alloc( - rhs_ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ), - }) - } }); hir::WherePredicate { hir_id, span, kind } }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index db0c525..081de1a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -17,7 +17,6 @@ //! require name resolution or type checking, or other kinds of complex analysis. use std::mem; -use std::ops::{Deref, DerefMut}; use std::str::FromStr; use itertools::{Either, Itertools}; @@ -37,7 +36,6 @@ }; use rustc_span::{Ident, Span, kw, sym}; use rustc_target::spec::{AbiMap, AbiMapping}; -use thin_vec::thin_vec; use crate::diagnostics::{self, TildeConstReason}; @@ -1593,14 +1591,8 @@ fn visit_generics(&mut self, generics: &Generics) { } validate_generic_param_order(self.dcx(), &generics.params, generics.span); - - for predicate in &generics.where_clause.predicates { - let span = predicate.span; - if let WherePredicateKind::EqPredicate(predicate) = &predicate.kind { - deny_equality_constraints(self, predicate, span, generics); - } - } walk_list!(self, visit_generic_param, &generics.params); + for predicate in &generics.where_clause.predicates { match &predicate.kind { WherePredicateKind::BoundPredicate(bound_pred) => { @@ -1625,7 +1617,7 @@ fn visit_generics(&mut self, generics: &Generics) { } } } - _ => {} + WherePredicateKind::RegionPredicate(_) => {} } self.visit_where_predicate(predicate); } @@ -1962,170 +1954,6 @@ fn visit_anon_const(&mut self, anon_const: &AnonConst) { } } -/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems -/// like it's setting an associated type, provide an appropriate suggestion. -fn deny_equality_constraints( - this: &AstValidator<'_>, - predicate: &WhereEqPredicate, - predicate_span: Span, - generics: &Generics, -) { - let mut err = diagnostics::EqualityInWhere { span: predicate_span, assoc: None, assoc2: None }; - - // Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`. - if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind - && let TyKind::Path(None, path) = &qself.ty.kind - && let [PathSegment { ident, args: None, .. }] = &path.segments[..] - { - for param in &generics.params { - if param.ident == *ident - && let [PathSegment { ident, args, .. }] = &full_path.segments[qself.position..] - { - // Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`. - let mut assoc_path = full_path.clone(); - // Remove `Bar` from `Foo::Bar`. - assoc_path.segments.pop(); - let len = assoc_path.segments.len() - 1; - let gen_args = args.as_deref().cloned(); - // Build `<Bar = RhsTy>`. - let arg = AngleBracketedArg::Constraint(AssocItemConstraint { - id: rustc_ast::node_id::DUMMY_NODE_ID, - ident: *ident, - gen_args, - kind: AssocItemConstraintKind::Equality { - term: predicate.rhs_ty.clone().into(), - }, - span: ident.span, - }); - // Add `<Bar = RhsTy>` to `Foo`. - match &mut assoc_path.segments[len].args { - Some(args) => match args.deref_mut() { - GenericArgs::Parenthesized(_) | GenericArgs::ParenthesizedElided(..) => { - continue; - } - GenericArgs::AngleBracketed(args) => { - args.args.push(arg); - } - }, - empty_args => { - *empty_args = Some( - AngleBracketedArgs { span: ident.span, args: thin_vec![arg] }.into(), - ); - } - } - err.assoc = Some(diagnostics::AssociatedSuggestion { - span: predicate_span, - ident: *ident, - param: param.ident, - path: pprust::path_to_string(&assoc_path), - }) - } - } - } - - let mut suggest = - |poly: &PolyTraitRef, potential_assoc: &PathSegment, predicate: &WhereEqPredicate| { - if let [trait_segment] = &poly.trait_ref.path.segments[..] { - let assoc = pprust::path_to_string(&ast::Path::from_ident(potential_assoc.ident)); - let ty = pprust::ty_to_string(&predicate.rhs_ty); - let (args, span) = match &trait_segment.args { - Some(args) => match args.deref() { - ast::GenericArgs::AngleBracketed(args) => { - let Some(arg) = args.args.last() else { - return; - }; - (format!(", {assoc} = {ty}"), arg.span().shrink_to_hi()) - } - _ => return, - }, - None => (format!("<{assoc} = {ty}>"), trait_segment.span().shrink_to_hi()), - }; - let removal_span = if generics.where_clause.predicates.len() == 1 { - // We're removing th eonly where bound left, remove the whole thing. - generics.where_clause.span - } else { - let mut span = predicate_span; - let mut prev_span: Option<Span> = None; - let mut preds = generics.where_clause.predicates.iter().peekable(); - // Find the predicate that shouldn't have been in the where bound list. - while let Some(pred) = preds.next() { - if let WherePredicateKind::EqPredicate(_) = pred.kind - && pred.span == predicate_span - { - if let Some(next) = preds.peek() { - // This is the first predicate, remove the trailing comma as well. - span = span.with_hi(next.span.lo()); - } else if let Some(prev_span) = prev_span { - // Remove the previous comma as well. - span = span.with_lo(prev_span.hi()); - } - } - prev_span = Some(pred.span); - } - span - }; - err.assoc2 = Some(diagnostics::AssociatedSuggestion2 { - span, - args, - predicate: removal_span, - trait_segment: trait_segment.ident, - potential_assoc: potential_assoc.ident, - }); - } - }; - - if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { - // Given `A: Foo, Foo::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`. - for bounds in generics.params.iter().map(|p| &p.bounds).chain( - generics.where_clause.predicates.iter().filter_map(|pred| match &pred.kind { - WherePredicateKind::BoundPredicate(p) => Some(&p.bounds), - _ => None, - }), - ) { - for bound in bounds { - if let GenericBound::Trait(poly) = bound - && poly.modifiers == TraitBoundModifiers::NONE - { - if full_path.segments[..full_path.segments.len() - 1] - .iter() - .map(|segment| segment.ident.name) - .zip(poly.trait_ref.path.segments.iter().map(|segment| segment.ident.name)) - .all(|(a, b)| a == b) - && let Some(potential_assoc) = full_path.segments.last() - { - suggest(poly, potential_assoc, predicate); - } - } - } - } - // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`. - if let [potential_param, 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); -} - pub fn check_crate( sess: &Session, features: &Features,
diff --git a/compiler/rustc_ast_passes/src/diagnostics.rs b/compiler/rustc_ast_passes/src/diagnostics.rs index a6b75cb..89284ca 100644 --- a/compiler/rustc_ast_passes/src/diagnostics.rs +++ b/compiler/rustc_ast_passes/src/diagnostics.rs
@@ -879,49 +879,6 @@ pub(crate) struct PatternInBodiless { } #[derive(Diagnostic)] -#[diag("equality constraints are not yet supported in `where` clauses")] -#[note("see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information")] -pub(crate) struct EqualityInWhere { - #[primary_span] - #[label("not supported")] - pub span: Span, - #[subdiagnostic] - pub assoc: Option<AssociatedSuggestion>, - #[subdiagnostic] - pub assoc2: Option<AssociatedSuggestion2>, -} - -#[derive(Subdiagnostic)] -#[suggestion( - "if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax", - code = "{param}: {path}", - style = "verbose", - applicability = "maybe-incorrect" -)] -pub(crate) struct AssociatedSuggestion { - #[primary_span] - pub span: Span, - pub ident: Ident, - pub param: Ident, - pub path: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax", - applicability = "maybe-incorrect" -)] -pub(crate) struct AssociatedSuggestion2 { - #[suggestion_part(code = "{args}")] - pub span: Span, - pub args: String, - #[suggestion_part(code = "")] - pub predicate: Span, - pub trait_segment: Ident, - pub potential_assoc: Ident, -} - -#[derive(Diagnostic)] #[diag("`#![feature]` may not be used on the {$channel} release channel", code = E0554)] pub(crate) struct FeatureOnNonNightly { #[primary_span]
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 820c49c..86fb0e6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -869,14 +869,6 @@ pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) { self.print_lifetime_bounds(bounds); } } - ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { - lhs_ty, rhs_ty, .. - }) => { - self.print_type(lhs_ty); - self.space(); - self.word_space("="); - self.print_type(rhs_ty); - } } }
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 43399b6..80296a4 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -396,8 +396,7 @@ fn visit_where_predicate_kind(&mut self, kind: &mut ast::WherePredicateKind) { self.visit_param_bound(bound, BoundKind::Bound) } } - rustc_ast::WherePredicateKind::RegionPredicate(_) - | rustc_ast::WherePredicateKind::EqPredicate(_) => {} + rustc_ast::WherePredicateKind::RegionPredicate(_) => {} } } }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ab2fa55..53141dc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs
@@ -1193,8 +1193,6 @@ pub enum WherePredicateKind<'hir> { BoundPredicate(WhereBoundPredicate<'hir>), /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate<'hir>), - /// An equality predicate (unsupported). - EqPredicate(WhereEqPredicate<'hir>), } impl<'hir> WherePredicateKind<'hir> { @@ -1202,7 +1200,6 @@ pub fn in_where_clause(&self) -> bool { match self { WherePredicateKind::BoundPredicate(p) => p.origin == PredicateOrigin::WhereClause, WherePredicateKind::RegionPredicate(p) => p.in_where_clause, - WherePredicateKind::EqPredicate(_) => false, } } @@ -1210,7 +1207,6 @@ pub fn bounds(&self) -> GenericBounds<'hir> { match self { WherePredicateKind::BoundPredicate(p) => p.bounds, WherePredicateKind::RegionPredicate(p) => p.bounds, - WherePredicateKind::EqPredicate(_) => &[], } } }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 85f0e97..b0c6a13 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs
@@ -1200,10 +1200,6 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( try_visit!(visitor.visit_lifetime(lifetime)); walk_list!(visitor, visit_param_bound, bounds); } - WherePredicateKind::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty }) => { - try_visit!(visitor.visit_ty_unambig(lhs_ty)); - try_visit!(visitor.visit_ty_unambig(rhs_ty)); - } } V::Result::output() }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 234231e..964f801e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1202,7 +1202,6 @@ pub(super) fn check_number_of_early_bound_regions<'tcx>( } } } - _ => {} } } if let Some(impl_node) = tcx.hir_get_if_local(impl_def_id.into()) @@ -1225,7 +1224,6 @@ pub(super) fn check_number_of_early_bound_regions<'tcx>( } } } - _ => {} } } if impl_bounds == bounds_span.len() {
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index cf29a76..01e78fb 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -322,10 +322,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen (pred, span) })) } - - hir::WherePredicateKind::EqPredicate(..) => { - // FIXME(#20041) - } } }
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3e48bfe..adc8be1 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -999,12 +999,6 @@ fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) self.visit_lifetime(lifetime); walk_list!(self, visit_param_bound, bounds); } - &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { - lhs_ty, rhs_ty, .. - }) => { - self.visit_ty_unambig(lhs_ty); - self.visit_ty_unambig(rhs_ty); - } } }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 637ae11..0204c4c 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2530,14 +2530,6 @@ fn print_where_predicate(&mut self, predicate: &hir::WherePredicate<'_>) { } } } - hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { - lhs_ty, rhs_ty, .. - }) => { - self.print_type(lhs_ty); - self.space(); - self.word_space("="); - self.print_type(rhs_ty); - } } }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2c7ccfb..df78f85 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs
@@ -2141,7 +2141,6 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { } } } - _ => continue, }; if relevant_lifetimes.is_empty() { continue;
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 969c854..e2df607 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -2,7 +2,7 @@ self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, token, }; -use rustc_errors::{Applicability, PResult}; +use rustc_errors::{Applicability, Diag, PResult}; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::ThinVec; @@ -592,25 +592,47 @@ fn parse_ty_where_predicate_kind(&mut self) -> PResult<'a, ast::WherePredicateKi // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>` let (bound_vars, _) = self.parse_higher_ranked_binder()?; - // Parse type with mandatory colon and (possibly empty) bounds, - // or with mandatory equality sign and the second type. let ty = self.parse_ty_for_where_clause()?; + if self.eat(exp!(Colon)) { + // The bounds may be empty; we intentionally accept predicates like `Ty:`. let bounds = self.parse_generic_bounds()?; - Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { + + return Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { bound_generic_params: bound_vars, bounded_ty: ty, bounds, - })) - // FIXME: Decide what should be used here, `=` or `==`. - // FIXME: We are just dropping the binders in lifetime_defs on the floor here. - } else if self.eat(exp!(Eq)) || self.eat(exp!(EqEq)) { - let rhs_ty = self.parse_ty()?; - Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty })) - } else { - self.maybe_recover_bounds_doubled_colon(&ty)?; - self.unexpected_any() + })); } + + // NOTE: If we ever end up impl'ing and stabilizing equality predicates (#20041), + // we need to pick between `=` and `==`, both is not an option! + if self.eat(exp!(Eq)) || self.eat(exp!(EqEq)) { + let lhs_ty = ty; + let rhs_ty = self.parse_ty()?; + + // NOTE: If we ever end up impl'ing equality predicates, + // we ought to track the binder in the AST node! + let _ = bound_vars; + + let mut diag = self.dcx().struct_span_err( + lhs_ty.span.to(rhs_ty.span), + "general type equality constraints are not supported", + ); + diag.note( + "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> \ + for more information", + ); + diag.span(lhs_ty.span.to(rhs_ty.span)); + diag.span_label(lhs_ty.span.to(rhs_ty.span), "not supported"); + + suggest_replacing_equality_pred_with_assoc_item_constraint(&mut diag, *lhs_ty, *rhs_ty); + + return Err(diag); + } + + self.maybe_recover_bounds_doubled_colon(&ty)?; + self.unexpected_any() } pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool { @@ -644,3 +666,61 @@ pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool { || self.is_keyword_ahead(start + 1, &[kw::Const])) } } + +fn suggest_replacing_equality_pred_with_assoc_item_constraint( + diag: &mut Diag<'_>, + lhs_ty: ast::Ty, + rhs_ty: ast::Ty, +) { + let TyKind::Path(qself, ast::Path { segments, .. }) = lhs_ty.kind else { return }; + + let mut parts = Vec::new(); + let applicability = match qself { + // We have something like `Ty::Item<i32> = Rhs`. + None if let [self_ty_seg, assoc_item_seg] = &segments[..] + && self_ty_seg.ident.name != kw::PathRoot => + { + parts.push(( + self_ty_seg.span().between(assoc_item_seg.span()), + ": /* Trait */</* ... */".into(), + )); + Applicability::HasPlaceholders + } + Some(qself) if let [assoc_item_seg] = &segments[qself.position..] => { + parts.push((lhs_ty.span.until(qself.ty.span), String::new())); + + // We have something like `<Option<usize> as self::Trait<i32>>::Item = Rhs`. + if let trait_segs @ [.., final_trait_seg] = &segments[..qself.position] { + parts.push((qself.ty.span.between(trait_segs[0].span()), ": ".into())); + let (span, snippet) = match &final_trait_seg.args { + Some(args) => { + let ast::GenericArgs::AngleBracketed(args) = args else { return }; + let Some(args) = args.args.last() else { return }; + (args.span(), ", ") + } + None => (final_trait_seg.span(), "<"), + }; + parts.push((span.between(assoc_item_seg.span()), snippet.into())); + Applicability::MaybeIncorrect + } + // We have something like `<[u8]>::Item == Rhs`. + else { + parts.push(( + qself.ty.span.between(assoc_item_seg.span()), + ": /* Trait */</* ... */".into(), + )); + Applicability::HasPlaceholders + } + } + _ => return, + }; + + parts.push((lhs_ty.span.between(rhs_ty.span), " = ".into())); + parts.push((rhs_ty.span.shrink_to_hi(), ">".into())); + + diag.multipart_suggestion( + "replace it with an associated item constraint if possible", + parts, + applicability, + ); +}
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 9127e49..2f3fbc2 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs
@@ -430,7 +430,7 @@ fn visit_generics(&mut self, g: &'v hir::Generics<'v>) { fn visit_where_predicate(&mut self, p: &'v hir::WherePredicate<'v>) { record_variants!( (self, p, p.kind, Some(p.hir_id), hir, WherePredicate, WherePredicateKind), - [BoundPredicate, RegionPredicate, EqPredicate] + [BoundPredicate, RegionPredicate] ); hir_visit::walk_where_predicate(self, p) } @@ -705,7 +705,7 @@ fn visit_generic_param(&mut self, g: &'v ast::GenericParam) { fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) { record_variants!( (self, p, &p.kind, None, ast, WherePredicate, WherePredicateKind), - [BoundPredicate, RegionPredicate, EqPredicate] + [BoundPredicate, RegionPredicate] ); ast_visit::walk_where_predicate(self, p) }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7442ec99..c2fd72e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs
@@ -417,15 +417,10 @@ fn clean_where_predicate<'tcx>( bound_params, } } - hir::WherePredicateKind::RegionPredicate(wrp) => WherePredicate::RegionPredicate { lifetime: clean_lifetime(wrp.lifetime, cx), bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), }, - - // We should never actually reach this case because these predicates should've already been - // rejected in an earlier compiler pass. This feature isn't fully implemented (#20041). - hir::WherePredicateKind::EqPredicate(_) => bug!("EqPredicate"), }) } @@ -530,7 +525,7 @@ fn clean_projection_predicate<'tcx>( pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, cx: &mut DocContext<'tcx>, ) -> WherePredicate { - WherePredicate::EqPredicate { + WherePredicate::ProjectionPredicate { lhs: clean_projection(pred.map_bound(|p| p.projection_term), cx, None), rhs: clean_middle_term(pred.map_bound(|p| p.term), cx), } @@ -797,8 +792,8 @@ pub(crate) fn clean_generics<'tcx>( } } } - WherePredicate::EqPredicate { lhs, rhs } => { - eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs }); + WherePredicate::ProjectionPredicate { lhs, rhs } => { + eq_predicates.push(WherePredicate::ProjectionPredicate { lhs, rhs }); } } }
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index a5b5660..fecbc91 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs
@@ -40,7 +40,7 @@ pub(crate) fn where_clauses(tcx: TyCtxt<'_>, clauses: ThinVec<WP>) -> ThinVec<WP WP::RegionPredicate { lifetime, bounds } => { lifetimes.push((lifetime, bounds)); } - WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)), + WP::ProjectionPredicate { lhs, rhs } => equalities.push((lhs, rhs)), } } @@ -61,7 +61,7 @@ pub(crate) fn where_clauses(tcx: TyCtxt<'_>, clauses: ThinVec<WP>) -> ThinVec<WP bounds, bound_params, })); - clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs })); + clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::ProjectionPredicate { lhs, rhs })); clauses }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 9c757cf..202727c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs
@@ -1250,7 +1250,7 @@ pub(crate) fn name(self) -> Symbol { pub(crate) enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> }, RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> }, - EqPredicate { lhs: QPathData, rhs: Term }, + ProjectionPredicate { lhs: QPathData, rhs: Term }, } impl WherePredicate {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0b94d2b..8172ef1 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs
@@ -138,7 +138,7 @@ fn print_where_predicate(predicate: &clean::WherePredicate, cx: &Context<'_>) -> } Ok(()) } - clean::WherePredicate::EqPredicate { lhs, rhs } => { + clean::WherePredicate::ProjectionPredicate { lhs, rhs } => { let opts = WithOpts::from(f); write!( f,
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 84faa98..d2bf690 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs
@@ -497,7 +497,7 @@ fn from_clean(predicate: &clean::WherePredicate, renderer: &JsonRenderer<'_>) -> }) .collect(), }, - EqPredicate { lhs, rhs } => WherePredicate::EqPredicate { + ProjectionPredicate { lhs, rhs } => WherePredicate::EqPredicate { // The LHS currently has type `Type` but it should be a `QualifiedPath` since it may // refer to an associated const. However, `EqPredicate` shouldn't exist in the first // place: <https://github.com/rust-lang/rust/141368>.
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index ea99b52..8b50ce2 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -551,14 +551,6 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ } } }, - WherePredicateKind::EqPredicate(ref pred) => { - let mut visitor = RefVisitor::new(cx); - walk_unambig_ty(&mut visitor, pred.lhs_ty); - walk_unambig_ty(&mut visitor, pred.rhs_ty); - if !visitor.lts.is_empty() { - return true; - } - }, } } false
diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs index 5b6b4f1..8b02c48 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
@@ -69,7 +69,6 @@ fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: Node emit_lint(cx, *bound_span, pred.lifetime.ident.span); } }, - WherePredicateKind::EqPredicate(_) => {}, } } }
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index e0a1825..fa93cf2 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -787,7 +787,6 @@ fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { (RegionPredicate(l), RegionPredicate(r)) => { eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound) }, - (EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty), _ => false, } }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 7590090..38724a1 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -301,9 +301,6 @@ fn eq_generics_predicate(&mut self, left: &[WherePredicate<'_>], right: &[WhereP Self::eq_lifetime(l_region.lifetime, r_region.lifetime) && self.eq_generics_bound(l_region.bounds, r_region.bounds) }, - (WherePredicateKind::EqPredicate(l_eq), WherePredicateKind::EqPredicate(r_eq)) => { - self.eq_ty(l_eq.lhs_ty, r_eq.lhs_ty) - }, _ => false, }) }
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index e574a9d..2dfb5e5 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs
@@ -484,16 +484,6 @@ fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteR ref lifetime, ref bounds, }) => rewrite_bounded_lifetime(lifetime, bounds, self.span, context, shape)?, - ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - let lhs_ty_str = lhs_ty - .rewrite_result(context, shape) - .map(|lhs| lhs + " =")?; - rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)? - } }; let mut result = String::with_capacity(attrs_str.len() + pred_str.len() + 1);
diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs index b757521..0072c4c 100644 --- a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs +++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs
@@ -29,12 +29,7 @@ fn paint<C:BoxCar>(c: C, d: C::Color) { //~^ ERROR ambiguous associated type `Color` in bounds of `C` } -fn dent_object_2<COLOR>(c: &dyn BoxCar) where <dyn BoxCar as Vehicle>::Color = COLOR { - //~^ ERROR the value of the associated types - //~| ERROR equality constraints are not yet supported in `where` clauses -} - -fn dent_object_3<X, COLOR>(c: X) +fn dent_object_2<X, COLOR>(c: X) where X: BoxCar, X: Vehicle<Color = COLOR>, X: Box<Color = COLOR>
diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr index 063623e..78a6d02 100644 --- a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr +++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
@@ -1,11 +1,3 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:47 - | -LL | fn dent_object_2<COLOR>(c: &dyn BoxCar) where <dyn BoxCar as Vehicle>::Color = COLOR { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information - error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-from-multiple-supertraits.rs:19:32 | @@ -84,21 +76,7 @@ LL + fn paint<C:BoxCar>(c: C, d: <C as Box>::Color) { | -error[E0191]: the value of the associated types `Color` in `Box`, `Color` in `Vehicle` must be specified - --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:33 - | -LL | type Color; - | ---------- `Vehicle::Color` defined here -... -LL | type Color; - | ---------- `Box::Color` defined here -... -LL | fn dent_object_2<COLOR>(c: &dyn BoxCar) where <dyn BoxCar as Vehicle>::Color = COLOR { - | ^^^^^^ associated types `Color` (from trait `Vehicle`), `Color` (from trait `Box`) must be specified - | - = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0191, E0221, E0222. For more information about an error, try `rustc --explain E0191`.
diff --git a/tests/ui/generic-associated-types/equality-bound.rs b/tests/ui/generic-associated-types/equality-bound.rs deleted file mode 100644 index c136a6d..0000000 --- a/tests/ui/generic-associated-types/equality-bound.rs +++ /dev/null
@@ -1,82 +0,0 @@ -fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 { -//~^ ERROR equality constraints are not yet supported in `where` clauses - panic!() -} -fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 { -//~^ ERROR equality constraints are not yet supported in `where` clauses - panic!() -} -fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 { -//~^ ERROR equality constraints are not yet supported in `where` clauses -//~| ERROR cannot find type `I` - panic!() -} - -use std::iter::FromIterator; - -struct X {} - -impl FromIterator<bool> for X { - fn from_iter<T>(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct Y {} - -impl FromIterator<bool> for Y { - fn from_iter<T>(_: T) -> Self where T: IntoIterator, T::Item = A, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct Z {} - -impl FromIterator<bool> for Z { - fn from_iter<T: IntoIterator>(_: T) -> Self where IntoIterator::Item = A, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct K {} - -impl FromIterator<bool> for K { - fn from_iter<T: IntoIterator>(_: T) -> Self where T::Item = A, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct L {} - -impl FromIterator<bool> for L { - fn from_iter<T>(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct M {} - -impl FromIterator<bool> for M { - fn from_iter<T>(_: T) -> Self where T::Item = A, T: IntoIterator, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} -fn main() {}
diff --git a/tests/ui/generic-associated-types/equality-bound.stderr b/tests/ui/generic-associated-types/equality-bound.stderr deleted file mode 100644 index 0ceb5e3..0000000 --- a/tests/ui/generic-associated-types/equality-bound.stderr +++ /dev/null
@@ -1,218 +0,0 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:1:51 - | -LL | fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 { - | ^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 { -LL + fn sum<I: Iterator<Item = (), Item = i32>>(i: I) -> i32 { - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:5:41 - | -LL | fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 { - | ^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 { -LL + fn sum2<I: Iterator<Item = i32>>(i: I) -> i32 { - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:9:41 - | -LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 { - | ^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:20:58 - | -LL | fn from_iter<T>(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter<T>(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, -LL + fn from_iter<T>(_: T) -> Self where T: IntoIterator<Item = A>, - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:31:58 - | -LL | fn from_iter<T>(_: T) -> Self where T: IntoIterator, T::Item = A, - | ^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter<T>(_: T) -> Self where T: IntoIterator, T::Item = A, -LL + fn from_iter<T>(_: T) -> Self where T: IntoIterator<Item = A>, - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:42:55 - | -LL | fn from_iter<T: IntoIterator>(_: T) -> Self where IntoIterator::Item = A, - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter<T: IntoIterator>(_: T) -> Self where IntoIterator::Item = A, -LL + fn from_iter<T: IntoIterator<Item = A>>(_: T) -> Self - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:53:55 - | -LL | fn from_iter<T: IntoIterator>(_: T) -> Self where T::Item = A, - | ^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter<T: IntoIterator>(_: T) -> Self where T::Item = A, -LL + fn from_iter<T: IntoIterator<Item = A>>(_: T) -> Self - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:64:41 - | -LL | fn from_iter<T>(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter<T>(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, -LL + fn from_iter<T>(_: T) -> Self where T: IntoIterator<Item = A>, - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:75:41 - | -LL | fn from_iter<T>(_: T) -> Self where T::Item = A, T: IntoIterator, - | ^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter<T>(_: T) -> Self where T::Item = A, T: IntoIterator, -LL + fn from_iter<T>(_: T) -> Self where T: IntoIterator<Item = A>, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:20:79 - | -LL | fn from_iter<T>(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, - | ^ -... -LL | struct K {} - | -------- similarly named struct `K` defined here - | -help: a struct with a similar name exists - | -LL - fn from_iter<T>(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, -LL + fn from_iter<T>(_: T) -> Self where T: IntoIterator, IntoIterator::Item = K, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:31:68 - | -LL | fn from_iter<T>(_: T) -> Self where T: IntoIterator, T::Item = A, - | ^ -... -LL | struct K {} - | -------- similarly named struct `K` defined here - | -help: a struct with a similar name exists - | -LL - fn from_iter<T>(_: T) -> Self where T: IntoIterator, T::Item = A, -LL + fn from_iter<T>(_: T) -> Self where T: IntoIterator, T::Item = K, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:42:76 - | -LL | fn from_iter<T: IntoIterator>(_: T) -> Self where IntoIterator::Item = A, - | ^ -... -LL | struct K {} - | -------- similarly named struct `K` defined here - | -help: a struct with a similar name exists - | -LL - fn from_iter<T: IntoIterator>(_: T) -> Self where IntoIterator::Item = A, -LL + fn from_iter<T: IntoIterator>(_: T) -> Self where IntoIterator::Item = K, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:53:65 - | -LL | struct K {} - | -------- similarly named struct `K` defined here -... -LL | fn from_iter<T: IntoIterator>(_: T) -> Self where T::Item = A, - | ^ - | -help: a struct with a similar name exists - | -LL - fn from_iter<T: IntoIterator>(_: T) -> Self where T::Item = A, -LL + fn from_iter<T: IntoIterator>(_: T) -> Self where T::Item = K, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:64:62 - | -LL | struct K {} - | -------- similarly named struct `K` defined here -... -LL | fn from_iter<T>(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, - | ^ - | -help: a struct with a similar name exists - | -LL - fn from_iter<T>(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, -LL + fn from_iter<T>(_: T) -> Self where IntoIterator::Item = K, T: IntoIterator, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:75:51 - | -LL | struct K {} - | -------- similarly named struct `K` defined here -... -LL | fn from_iter<T>(_: T) -> Self where T::Item = A, T: IntoIterator, - | ^ - | -help: a struct with a similar name exists - | -LL - fn from_iter<T>(_: T) -> Self where T::Item = A, T: IntoIterator, -LL + fn from_iter<T>(_: T) -> Self where T::Item = K, T: IntoIterator, - | - -error[E0433]: cannot find type `I` in this scope - --> $DIR/equality-bound.rs:9:41 - | -LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 { - | ^ use of undeclared type `I` - | -help: a type parameter with a similar name exists - | -LL - fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 { -LL + fn sum3<J: Iterator>(i: J) -> i32 where J::Item = i32 { - | - -error: aborting due to 16 previous errors - -Some errors have detailed explanations: E0425, E0433. -For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed index 15cdd44..7735031 100644 --- a/tests/ui/generic-associated-types/missing-bounds.fixed +++ b/tests/ui/generic-associated-types/missing-bounds.fixed
@@ -36,12 +36,11 @@ struct E<B>(B); -impl<B: Add<Output = B>> Add for E<B> where B: Add<Output = B> { - //~^ ERROR equality constraints are not yet supported in `where` clauses +impl<B: Add> Add for E<B> where B: Add<Output = B> { type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) //~ ERROR mismatched types + Self(self.0 + rhs.0) } }
diff --git a/tests/ui/generic-associated-types/missing-bounds.rs b/tests/ui/generic-associated-types/missing-bounds.rs index dad111c..0957674 100644 --- a/tests/ui/generic-associated-types/missing-bounds.rs +++ b/tests/ui/generic-associated-types/missing-bounds.rs
@@ -36,12 +36,11 @@ fn add(self, rhs: Self) -> Self { struct E<B>(B); -impl<B: Add> Add for E<B> where <B as Add>::Output = B { - //~^ ERROR equality constraints are not yet supported in `where` clauses +impl<B: Add> Add for E<B> where B: Add<Output = B> { type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) //~ ERROR mismatched types + Self(self.0 + rhs.0) } }
diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 97b88c2..b930cfb 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr
@@ -1,16 +1,3 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/missing-bounds.rs:39:33 - | -LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B { - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information -help: if `Output` is an associated type you're trying to set, use the associated type binding syntax - | -LL - impl<B: Add> Add for E<B> where <B as Add>::Output = B { -LL + impl<B: Add> Add for E<B> where B: Add<Output = B> { - | - error[E0308]: mismatched types --> $DIR/missing-bounds.rs:13:11 | @@ -77,30 +64,7 @@ LL | impl<B: std::ops::Add<Output = B>> Add for D<B> { | +++++++++++++++++++++++++++ -error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:44:14 - | -LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B { - | - expected this type parameter -... -LL | Self(self.0 + rhs.0) - | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type - | | - | arguments to this function are incorrect - | - = note: expected type parameter `B` - found associated type `<B as Add>::Output` -note: tuple struct defined here - --> $DIR/missing-bounds.rs:37:8 - | -LL | struct E<B>(B); - | ^ -help: consider further restricting this bound - | -LL | impl<B: Add<Output = B>> Add for E<B> where <B as Add>::Output = B { - | ++++++++++++ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0308, E0369. For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/equality-predicates-0.rs b/tests/ui/parser/equality-predicates-0.rs new file mode 100644 index 0000000..a720d96 --- /dev/null +++ b/tests/ui/parser/equality-predicates-0.rs
@@ -0,0 +1,20 @@ +// Test that we syntactically reject *equality predicates*. +// +// It's a feature that was originally proposed as part of accepted RFC 135 (2014). It's never been +// fully implemented and in the meantime design & implementation concerns have been raised. +// Between Feb 2017 and Jun 2026 we accidentally accepted such predicates syntactically +// (indeed, without any pre-expansion feature gate). +// +// We *might* add a more restricted version of this feature to the language in the future. +// See discussions in tracking issue <https://github.com/rust-lang/rust/issues/20041> for details. + +#[cfg(false)] +fn f<T: Iterator>(mut xs: T) -> Option<u8> +where + T::Item = u8 + //~^ ERROR general type equality constraints are not supported +{ + xs.next() +} + +fn main() {}
diff --git a/tests/ui/parser/equality-predicates-0.stderr b/tests/ui/parser/equality-predicates-0.stderr new file mode 100644 index 0000000..f5be5d1 --- /dev/null +++ b/tests/ui/parser/equality-predicates-0.stderr
@@ -0,0 +1,15 @@ +error: general type equality constraints are not supported + --> $DIR/equality-predicates-0.rs:14:5 + | +LL | T::Item = u8 + | ^^^^^^^^^^^^ not supported + | + = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information +help: replace it with an associated item constraint if possible + | +LL - T::Item = u8 +LL + T: /* Trait */</* ... */Item = u8> + | + +error: aborting due to 1 previous error +
diff --git a/tests/ui/parser/equality-predicates-1.rs b/tests/ui/parser/equality-predicates-1.rs new file mode 100644 index 0000000..b5dcc56 --- /dev/null +++ b/tests/ui/parser/equality-predicates-1.rs
@@ -0,0 +1,20 @@ +// Test that we syntactically reject *equality predicates*. +// +// It's a feature that was originally proposed as part of accepted RFC 135 (2014). It's never been +// fully implemented and in the meantime design & implementation concerns have been raised. +// Between Feb 2017 and Jun 2026 we accidentally accepted such predicates syntactically +// (indeed, without any pre-expansion feature gate). +// +// We *might* add a more restricted version of this feature to the language in the future. +// See discussions in tracking issue <https://github.com/rust-lang/rust/issues/20041> for details. + +#[cfg(false)] +fn f<T: Iterator>(mut xs: T) -> Option<u8> +where + <T as Iterator>::Item == u8 + //~^ ERROR general type equality constraints are not supported +{ + xs.next() +} + +fn main() {}
diff --git a/tests/ui/parser/equality-predicates-1.stderr b/tests/ui/parser/equality-predicates-1.stderr new file mode 100644 index 0000000..9e7a0b7 --- /dev/null +++ b/tests/ui/parser/equality-predicates-1.stderr
@@ -0,0 +1,15 @@ +error: general type equality constraints are not supported + --> $DIR/equality-predicates-1.rs:14:5 + | +LL | <T as Iterator>::Item == u8 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information +help: replace it with an associated item constraint if possible + | +LL - <T as Iterator>::Item == u8 +LL + T: Iterator<Item = u8> + | + +error: aborting due to 1 previous error +
diff --git a/tests/ui/where-clauses/where-equality-constraints.rs b/tests/ui/where-clauses/where-equality-constraints.rs deleted file mode 100644 index 8828f09..0000000 --- a/tests/ui/where-clauses/where-equality-constraints.rs +++ /dev/null
@@ -1,6 +0,0 @@ -fn f() where u8 = u16 {} -//~^ ERROR equality constraints are not yet supported in `where` clauses -fn g() where for<'a> &'static (u8,) == u16, {} -//~^ ERROR equality constraints are not yet supported in `where` clauses - -fn main() {}
diff --git a/tests/ui/where-clauses/where-equality-constraints.stderr b/tests/ui/where-clauses/where-equality-constraints.stderr deleted file mode 100644 index 9d8fac0..0000000 --- a/tests/ui/where-clauses/where-equality-constraints.stderr +++ /dev/null
@@ -1,18 +0,0 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/where-equality-constraints.rs:1:14 - | -LL | fn f() where u8 = u16 {} - | ^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/where-equality-constraints.rs:3:14 - | -LL | fn g() where for<'a> &'static (u8,) == u16, {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information - -error: aborting due to 2 previous errors -