1
Fork 0

Change syntax for TyAlias where clauses

This commit is contained in:
Jack Huey 2021-10-19 18:45:48 -04:00
parent 379e94f5a4
commit c20b4f5584
46 changed files with 394 additions and 255 deletions

View file

@ -13,11 +13,12 @@ use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, Vari
use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacArgs, MacCall, MacDelimiter};
use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability, ErrorGuaranteed, PResult, StashKey};
use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
use rustc_span::lev_distance::lev_distance;
use rustc_span::source_map::{self, Span};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
use std::convert::TryFrom;
use std::mem;
@ -791,44 +792,6 @@ impl<'a> Parser<'a> {
))
}
/// Emits an error that the where clause at the end of a type alias is not
/// allowed and suggests moving it.
fn error_ty_alias_where(
&self,
before_where_clause_present: bool,
before_where_clause_span: Span,
after_predicates: &[WherePredicate],
after_where_clause_span: Span,
) -> ErrorGuaranteed {
let mut err =
self.struct_span_err(after_where_clause_span, "where clause not allowed here");
if !after_predicates.is_empty() {
let mut state = crate::pprust::State::new();
if !before_where_clause_present {
state.space();
state.word_space("where");
} else {
state.word_space(",");
}
let mut first = true;
for p in after_predicates.iter() {
if !first {
state.word_space(",");
}
first = false;
state.print_where_predicate(p);
}
let suggestion = state.s.eof();
err.span_suggestion(
before_where_clause_span.shrink_to_hi(),
"move it here",
suggestion,
Applicability::MachineApplicable,
);
}
err.emit()
}
/// Parses a `type` alias with the following grammar:
/// ```
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
@ -841,27 +804,40 @@ impl<'a> Parser<'a> {
// Parse optional colon and param bounds.
let bounds =
if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
generics.where_clause = self.parse_where_clause()?;
let before_where_clause = self.parse_where_clause()?;
let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
if self.token.is_keyword(kw::Where) {
let after_where_clause = self.parse_where_clause()?;
let after_where_clause = self.parse_where_clause()?;
self.error_ty_alias_where(
generics.where_clause.has_where_token,
generics.where_clause.span,
&after_where_clause.predicates,
after_where_clause.span,
);
generics.where_clause.predicates.extend(after_where_clause.predicates.into_iter());
}
let where_clauses = (
TyAliasWhereClause(before_where_clause.has_where_token, before_where_clause.span),
TyAliasWhereClause(after_where_clause.has_where_token, after_where_clause.span),
);
let where_predicates_split = before_where_clause.predicates.len();
let mut predicates = before_where_clause.predicates;
predicates.extend(after_where_clause.predicates.into_iter());
let where_clause = WhereClause {
has_where_token: before_where_clause.has_where_token
|| after_where_clause.has_where_token,
predicates,
span: DUMMY_SP,
};
generics.where_clause = where_clause;
self.expect_semi()?;
Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
Ok((
ident,
ItemKind::TyAlias(Box::new(TyAlias {
defaultness,
generics,
where_clauses,
where_predicates_split,
bounds,
ty,
})),
))
}
/// Parses a `UseTree`.