Skip to content
Open
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
53 changes: 15 additions & 38 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3633,49 +3633,26 @@ pub struct Trait {
pub items: ThinVec<Box<AssocItem>>,
}

/// The location of a where clause on a `TyAlias` (`Span`) and whether there was
/// a `where` keyword (`bool`). This is split out from `WhereClause`, since there
/// are two locations for where clause on type aliases, but their predicates
/// are concatenated together.
///
/// Take this example:
/// ```ignore (only-for-syntax-highlight)
/// trait Foo {
/// type Assoc<'a, 'b> where Self: 'a, Self: 'b;
/// }
/// impl Foo for () {
/// type Assoc<'a, 'b> where Self: 'a = () where Self: 'b;
/// // ^^^^^^^^^^^^^^ first where clause
/// // ^^^^^^^^^^^^^^ second where clause
/// }
/// ```
///
/// If there is no where clause, then this is `false` with `DUMMY_SP`.
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default, Walkable)]
pub struct TyAliasWhereClause {
pub has_where_token: bool,
pub span: Span,
}

/// The span information for the two where clauses on a `TyAlias`.
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default, Walkable)]
pub struct TyAliasWhereClauses {
/// Before the equals sign.
pub before: TyAliasWhereClause,
/// After the equals sign.
pub after: TyAliasWhereClause,
/// The index in `TyAlias.generics.where_clause.predicates` that would split
/// into predicates from the where clause before the equals sign and the ones
/// from the where clause after the equals sign.
pub split: usize,
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct TyAlias {
pub defaultness: Defaultness,
pub ident: Ident,
pub generics: Generics,
pub where_clauses: TyAliasWhereClauses,
/// There are two locations for where clause on type aliases. This represents the second
/// where clause, before the semicolon. The first where clause is stored inside `generics`.
///
/// Take this example:
/// ```ignore (only-for-syntax-highlight)
/// trait Foo {
/// type Assoc<'a, 'b> where Self: 'a, Self: 'b;
/// }
/// impl Foo for () {
/// type Assoc<'a, 'b> where Self: 'a = () where Self: 'b;
/// // ^^^^^^^^^^^^^^ before where clause
/// // ^^^^^^^^^^^^^^ after where clause
/// }
/// ```
pub after_where_clause: WhereClause,
#[visitable(extra = BoundKind::Bound)]
pub bounds: GenericBounds,
pub ty: Option<Box<Ty>>,
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,6 @@ macro_rules! common_visitor_and_walkers {
TraitBoundModifiers,
TraitObjectSyntax,
TyAlias,
TyAliasWhereClause,
TyAliasWhereClauses,
TyKind,
TyPatKind,
UnOp,
Expand Down
37 changes: 21 additions & 16 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,18 @@ pub(super) struct ItemLowerer<'a, 'hir> {
/// clause if it exists.
fn add_ty_alias_where_clause(
generics: &mut ast::Generics,
mut where_clauses: TyAliasWhereClauses,
after_where_clause: &ast::WhereClause,
prefer_first: bool,
) {
generics.where_clause.predicates.extend_from_slice(&after_where_clause.predicates);

let mut before = (generics.where_clause.has_where_token, generics.where_clause.span);
let mut after = (after_where_clause.has_where_token, after_where_clause.span);
if !prefer_first {
(where_clauses.before, where_clauses.after) = (where_clauses.after, where_clauses.before);
(before, after) = (after, before);
}
let where_clause =
if where_clauses.before.has_where_token || !where_clauses.after.has_where_token {
where_clauses.before
} else {
where_clauses.after
};
generics.where_clause.has_where_token = where_clause.has_where_token;
generics.where_clause.span = where_clause.span;
(generics.where_clause.has_where_token, generics.where_clause.span) =
if before.0 || !after.0 { before } else { after };
}

impl<'a, 'hir> ItemLowerer<'a, 'hir> {
Expand Down Expand Up @@ -271,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));
hir::ItemKind::GlobalAsm { asm, fake_body }
}
ItemKind::TyAlias(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
ItemKind::TyAlias(box TyAlias { ident, generics, after_where_clause, ty, .. }) => {
// We lower
//
// type Foo = impl Trait
Expand All @@ -282,7 +280,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// opaque type Foo1: Trait
let ident = self.lower_ident(*ident);
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, true);
add_ty_alias_where_clause(&mut generics, after_where_clause, true);
let (generics, ty) = self.lower_generics(
&generics,
id,
Expand Down Expand Up @@ -901,10 +899,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
}
AssocItemKind::Type(box TyAlias {
ident, generics, where_clauses, bounds, ty, ..
ident,
generics,
after_where_clause,
bounds,
ty,
..
}) => {
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
add_ty_alias_where_clause(&mut generics, after_where_clause, false);
let (generics, kind) = self.lower_generics(
&generics,
i.id,
Expand Down Expand Up @@ -1070,9 +1073,11 @@ impl<'hir> LoweringContext<'_, 'hir> {

(*ident, (generics, hir::ImplItemKind::Fn(sig, body_id)))
}
AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
AssocItemKind::Type(box TyAlias {
ident, generics, after_where_clause, ty, ..
}) => {
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
add_ty_alias_where_clause(&mut generics, after_where_clause, false);
(
*ident,
self.lower_generics(
Expand Down
39 changes: 17 additions & 22 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,25 +145,24 @@ impl<'a> AstValidator<'a> {
&mut self,
ty_alias: &TyAlias,
) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
if ty_alias.ty.is_none() || !ty_alias.where_clauses.before.has_where_token {
if ty_alias.ty.is_none() || !ty_alias.generics.where_clause.has_where_token {
return Ok(());
}

let (before_predicates, after_predicates) =
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_clauses.split);
let span = ty_alias.where_clauses.before.span;
let span = ty_alias.generics.where_clause.span;

let sugg = if !before_predicates.is_empty() || !ty_alias.where_clauses.after.has_where_token
let sugg = if !ty_alias.generics.where_clause.predicates.is_empty()
|| !ty_alias.after_where_clause.has_where_token
{
let mut state = State::new();

if !ty_alias.where_clauses.after.has_where_token {
if !ty_alias.after_where_clause.has_where_token {
state.space();
state.word_space("where");
}

let mut first = after_predicates.is_empty();
for p in before_predicates {
let mut first = ty_alias.after_where_clause.predicates.is_empty();
for p in &ty_alias.generics.where_clause.predicates {
if !first {
state.word_space(",");
}
Expand All @@ -174,7 +173,7 @@ impl<'a> AstValidator<'a> {
errors::WhereClauseBeforeTypeAliasSugg::Move {
left: span,
snippet: state.s.eof(),
right: ty_alias.where_clauses.after.span.shrink_to_hi(),
right: ty_alias.after_where_clause.span.shrink_to_hi(),
}
} else {
errors::WhereClauseBeforeTypeAliasSugg::Remove { span }
Expand Down Expand Up @@ -566,11 +565,7 @@ impl<'a> AstValidator<'a> {
self.dcx().emit_err(errors::BoundInContext { span, ctx });
}

fn check_foreign_ty_genericless(
&self,
generics: &Generics,
where_clauses: &TyAliasWhereClauses,
) {
fn check_foreign_ty_genericless(&self, generics: &Generics, after_where_clause: &WhereClause) {
let cannot_have = |span, descr, remove_descr| {
self.dcx().emit_err(errors::ExternTypesCannotHave {
span,
Expand All @@ -584,14 +579,14 @@ impl<'a> AstValidator<'a> {
cannot_have(generics.span, "generic parameters", "generic parameters");
}

let check_where_clause = |where_clause: TyAliasWhereClause| {
let check_where_clause = |where_clause: &WhereClause| {
if where_clause.has_where_token {
cannot_have(where_clause.span, "`where` clauses", "`where` clause");
}
};

check_where_clause(where_clauses.before);
check_where_clause(where_clauses.after);
check_where_clause(&generics.where_clause);
check_where_clause(&after_where_clause);
}

fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body_span: Option<Span>) {
Expand Down Expand Up @@ -1261,7 +1256,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_item(self, item);
}
ItemKind::TyAlias(
ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. },
ty_alias @ box TyAlias { defaultness, bounds, after_where_clause, ty, .. },
) => {
self.check_defaultness(item.span, *defaultness);
if ty.is_none() {
Expand All @@ -1276,9 +1271,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
self.dcx().emit_err(err);
}
} else if where_clauses.after.has_where_token {
} else if after_where_clause.has_where_token {
self.dcx().emit_err(errors::WhereClauseAfterTypeAlias {
span: where_clauses.after.span,
span: after_where_clause.span,
help: self.sess.is_nightly_build(),
});
}
Expand Down Expand Up @@ -1308,15 +1303,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
defaultness,
ident,
generics,
where_clauses,
after_where_clause,
bounds,
ty,
..
}) => {
self.check_defaultness(fi.span, *defaultness);
self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span));
self.check_type_no_bounds(bounds, "`extern` blocks");
self.check_foreign_ty_genericless(generics, where_clauses);
self.check_foreign_ty_genericless(generics, after_where_clause);
self.check_foreign_item_ascii_only(*ident);
}
ForeignItemKind::Static(box StaticItem { ident, safety, expr, .. }) => {
Expand Down
29 changes: 10 additions & 19 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ impl<'a> State<'a> {
defaultness,
ident,
generics,
where_clauses,
after_where_clause,
bounds,
ty,
}) => {
self.print_associated_type(
*ident,
generics,
*where_clauses,
after_where_clause,
bounds,
ty.as_deref(),
vis,
Expand Down Expand Up @@ -127,14 +127,12 @@ impl<'a> State<'a> {
&mut self,
ident: Ident,
generics: &ast::Generics,
where_clauses: ast::TyAliasWhereClauses,
after_where_clause: &ast::WhereClause,
bounds: &ast::GenericBounds,
ty: Option<&ast::Ty>,
vis: &ast::Visibility,
defaultness: ast::Defaultness,
) {
let (before_predicates, after_predicates) =
generics.where_clause.predicates.split_at(where_clauses.split);
let (cb, ib) = self.head("");
self.print_visibility(vis);
self.print_defaultness(defaultness);
Expand All @@ -145,13 +143,13 @@ impl<'a> State<'a> {
self.word_nbsp(":");
self.print_type_bounds(bounds);
}
self.print_where_clause_parts(where_clauses.before.has_where_token, before_predicates);
self.print_where_clause(&generics.where_clause);
if let Some(ty) = ty {
self.space();
self.word_space("=");
self.print_type(ty);
}
self.print_where_clause_parts(where_clauses.after.has_where_token, after_predicates);
self.print_where_clause(&after_where_clause);
self.word(";");
self.end(ib);
self.end(cb);
Expand Down Expand Up @@ -283,14 +281,14 @@ impl<'a> State<'a> {
defaultness,
ident,
generics,
where_clauses,
after_where_clause,
bounds,
ty,
}) => {
self.print_associated_type(
*ident,
generics,
*where_clauses,
after_where_clause,
bounds,
ty.as_deref(),
&item.vis,
Expand Down Expand Up @@ -585,14 +583,14 @@ impl<'a> State<'a> {
defaultness,
ident,
generics,
where_clauses,
after_where_clause,
bounds,
ty,
}) => {
self.print_associated_type(
*ident,
generics,
*where_clauses,
after_where_clause,
bounds,
ty.as_deref(),
vis,
Expand Down Expand Up @@ -759,14 +757,7 @@ impl<'a> State<'a> {
}

fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
self.print_where_clause_parts(where_clause.has_where_token, &where_clause.predicates);
}

fn print_where_clause_parts(
&mut self,
has_where_token: bool,
predicates: &[ast::WherePredicate],
) {
let ast::WhereClause { has_where_token, ref predicates, span: _ } = *where_clause;
if predicates.is_empty() && !has_where_token {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ impl<'a> TraitDef<'a> {
defaultness: ast::Defaultness::Final,
ident,
generics: Generics::default(),
where_clauses: ast::TyAliasWhereClauses::default(),
after_where_clause: ast::WhereClause::default(),
bounds: Vec::new(),
ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
})),
Expand Down
Loading
Loading