Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,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.
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2052,18 +2052,6 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
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 }
}
Expand Down
178 changes: 3 additions & 175 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -27,7 +26,7 @@ use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State};
use rustc_attr_parsing::validate_attr;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{DiagCtxtHandle, Diagnostic, LintBuffer};
use rustc_errors::{DiagCtxtHandle, LintBuffer, Diagnostic};
use rustc_feature::Features;
use rustc_session::Session;
use rustc_session::lint::builtin::{
Expand All @@ -37,7 +36,6 @@ use rustc_session::lint::builtin::{
use rustc_session::parse::feature_err;
use rustc_span::{Ident, Span, kw, sym};
use rustc_target::spec::{AbiMap, AbiMapping};
use thin_vec::thin_vec;

use crate::errors::{self, TildeConstReason};

Expand Down Expand Up @@ -1576,14 +1574,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}

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) => {
Expand All @@ -1607,7 +1599,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
_ => {}
WherePredicateKind::RegionPredicate(_) => {}
}
self.visit_where_predicate(predicate);
}
Expand Down Expand Up @@ -1939,170 +1931,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}

/// 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 = errors::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(errors::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(errors::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,
Expand Down
43 changes: 0 additions & 43 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -879,49 +879,6 @@ pub(crate) struct PatternInBodiless {
pub span: Span,
}

#[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 {
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,14 +833,6 @@ impl<'a> State<'a> {
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);
}
}
}

Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,8 +396,7 @@ impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> {
self.visit_param_bound(bound, BoundKind::Bound)
}
}
rustc_ast::WherePredicateKind::RegionPredicate(_)
| rustc_ast::WherePredicateKind::EqPredicate(_) => {}
rustc_ast::WherePredicateKind::RegionPredicate(_) => {}
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,24 +1105,20 @@ 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> {
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,
}
}

pub fn bounds(&self) -> GenericBounds<'hir> {
match self {
WherePredicateKind::BoundPredicate(p) => p.bounds,
WherePredicateKind::RegionPredicate(p) => p.bounds,
WherePredicateKind::EqPredicate(_) => &[],
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,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())
Expand All @@ -1217,7 +1216,6 @@ pub(super) fn check_number_of_early_bound_regions<'tcx>(
}
}
}
_ => {}
}
}
if impl_bounds == bounds_span.len() {
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
(pred, span)
}))
}

hir::WherePredicateKind::EqPredicate(..) => {
// FIXME(#20041)
}
}
}

Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -997,12 +997,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, '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);
}
}
}

Expand Down
Loading
Loading