1
Fork 0

Refactor where predicates, and reserve for attributes support

This commit is contained in:
Frank King 2024-11-25 16:38:35 +08:00
parent 67a8c64259
commit 161221da9e
44 changed files with 394 additions and 408 deletions

View file

@ -1,6 +1,7 @@
use ast::token::Delimiter;
use rustc_ast::{
self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, token,
self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind,
WhereClause, token,
};
use rustc_errors::{Applicability, PResult};
use rustc_span::Span;
@ -14,8 +15,8 @@ use crate::errors::{
WhereClauseBeforeTupleStructBodySugg,
};
enum PredicateOrStructBody {
Predicate(ast::WherePredicate),
enum PredicateKindOrStructBody {
PredicateKind(ast::WherePredicateKind),
StructBody(ThinVec<ast::FieldDef>),
}
@ -218,10 +219,11 @@ impl<'a> Parser<'a> {
} else if this.token.can_begin_type() {
// Trying to write an associated type bound? (#26271)
let snapshot = this.create_snapshot_for_diagnostic();
match this.parse_ty_where_predicate() {
Ok(where_predicate) => {
let lo = this.token.span;
match this.parse_ty_where_predicate_kind() {
Ok(_) => {
this.dcx().emit_err(errors::BadAssocTypeBounds {
span: where_predicate.span(),
span: lo.to(this.prev_token.span),
});
// FIXME - try to continue parsing other generics?
}
@ -340,31 +342,33 @@ impl<'a> Parser<'a> {
loop {
let where_sp = where_lo.to(self.prev_token.span);
let pred_lo = self.token.span;
if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
let kind = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
let lifetime = self.expect_lifetime();
// Bounds starting with a colon are mandatory, but possibly empty.
self.expect(&token::Colon)?;
let bounds = self.parse_lt_param_bounds();
where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
ast::WhereRegionPredicate {
span: pred_lo.to(self.prev_token.span),
lifetime,
bounds,
},
));
ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
lifetime,
bounds,
})
} else if self.check_type() {
match self.parse_ty_where_predicate_or_recover_tuple_struct_body(
match self.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
struct_, pred_lo, where_sp,
)? {
PredicateOrStructBody::Predicate(pred) => where_clause.predicates.push(pred),
PredicateOrStructBody::StructBody(body) => {
PredicateKindOrStructBody::PredicateKind(kind) => kind,
PredicateKindOrStructBody::StructBody(body) => {
tuple_struct_body = Some(body);
break;
}
}
} else {
break;
}
};
where_clause.predicates.push(ast::WherePredicate {
kind,
id: DUMMY_NODE_ID,
span: pred_lo.to(self.prev_token.span),
});
let prev_token = self.prev_token.span;
let ate_comma = self.eat(&token::Comma);
@ -384,12 +388,12 @@ impl<'a> Parser<'a> {
Ok((where_clause, tuple_struct_body))
}
fn parse_ty_where_predicate_or_recover_tuple_struct_body(
fn parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
&mut self,
struct_: Option<(Ident, Span)>,
pred_lo: Span,
where_sp: Span,
) -> PResult<'a, PredicateOrStructBody> {
) -> PResult<'a, PredicateKindOrStructBody> {
let mut snapshot = None;
if let Some(struct_) = struct_
@ -399,8 +403,8 @@ impl<'a> Parser<'a> {
snapshot = Some((struct_, self.create_snapshot_for_diagnostic()));
};
match self.parse_ty_where_predicate() {
Ok(pred) => Ok(PredicateOrStructBody::Predicate(pred)),
match self.parse_ty_where_predicate_kind() {
Ok(pred) => Ok(PredicateKindOrStructBody::PredicateKind(pred)),
Err(type_err) => {
let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else {
return Err(type_err);
@ -436,7 +440,7 @@ impl<'a> Parser<'a> {
});
self.restore_snapshot(snapshot);
Ok(PredicateOrStructBody::StructBody(body))
Ok(PredicateKindOrStructBody::StructBody(body))
}
Ok(_) => Err(type_err),
Err(body_err) => {
@ -448,8 +452,7 @@ impl<'a> Parser<'a> {
}
}
fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate> {
let lo = self.token.span;
fn parse_ty_where_predicate_kind(&mut self) -> PResult<'a, ast::WherePredicateKind> {
// Parse optional `for<'a, 'b>`.
// This `for` is parsed greedily and applies to the whole predicate,
// the bounded type can have its own `for` applying only to it.
@ -464,8 +467,7 @@ impl<'a> Parser<'a> {
let ty = self.parse_ty_for_where_clause()?;
if self.eat(&token::Colon) {
let bounds = self.parse_generic_bounds()?;
Ok(ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
span: lo.to(self.prev_token.span),
Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
bound_generic_params: lifetime_defs,
bounded_ty: ty,
bounds,
@ -474,11 +476,7 @@ impl<'a> Parser<'a> {
// FIXME: We are just dropping the binders in lifetime_defs on the floor here.
} else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
let rhs_ty = self.parse_ty()?;
Ok(ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
span: lo.to(self.prev_token.span),
lhs_ty: ty,
rhs_ty,
}))
Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty }))
} else {
self.maybe_recover_bounds_doubled_colon(&ty)?;
self.unexpected_any()