Skip to content

Commit

Permalink
Rollup merge of #73157 - Aaron1011:where-oh-where-has-my-little-span-…
Browse files Browse the repository at this point in the history
…gone, r=ecstatic-morse

Don't lose empty `where` clause when pretty-printing

Previously, we would parse `struct Foo where;` and `struct Foo;`
identically, leading to an 'empty' `where` clause being omitted during
pretty printing. This will cause us to lose spans when proc-macros
involved, since we will have a collected `where` token that does not
appear in the pretty-printed item.

We now explicitly track the presence of a `where` token during parsing,
so that we can distinguish between `struct Foo where;` and `struct Foo;`
during pretty-printing
  • Loading branch information
Dylan-DPC committed Jun 10, 2020
2 parents 0a77c8c + 0fcea2e commit e04e3c8
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 7 deletions.
11 changes: 10 additions & 1 deletion src/librustc_ast/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,11 @@ impl Default for Generics {
fn default() -> Generics {
Generics {
params: Vec::new(),
where_clause: WhereClause { predicates: Vec::new(), span: DUMMY_SP },
where_clause: WhereClause {
has_where_token: false,
predicates: Vec::new(),
span: DUMMY_SP,
},
span: DUMMY_SP,
}
}
Expand All @@ -371,6 +375,11 @@ impl Default for Generics {
/// A where-clause in a definition.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct WhereClause {
/// `true` if we ate a `where` token: this can happen
/// if we parsed no predicates (e.g. `struct Foo where {}
/// This allows us to accurately pretty-print
/// in `nt_to_tokenstream`
pub has_where_token: bool,
pub predicates: Vec<WherePredicate>,
pub span: Span,
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_ast/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ pub fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T)
}

pub fn noop_visit_where_clause<T: MutVisitor>(wc: &mut WhereClause, vis: &mut T) {
let WhereClause { predicates, span } = wc;
let WhereClause { has_where_token: _, predicates, span } = wc;
visit_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
vis.visit_span(span);
}
Expand Down
8 changes: 6 additions & 2 deletions src/librustc_ast_pretty/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2593,7 +2593,7 @@ impl<'a> State<'a> {
}

crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
if where_clause.predicates.is_empty() {
if where_clause.predicates.is_empty() && !where_clause.has_where_token {
return;
}

Expand Down Expand Up @@ -2739,7 +2739,11 @@ impl<'a> State<'a> {
}
let generics = ast::Generics {
params: Vec::new(),
where_clause: ast::WhereClause { predicates: Vec::new(), span: rustc_span::DUMMY_SP },
where_clause: ast::WhereClause {
has_where_token: false,
predicates: Vec::new(),
span: rustc_span::DUMMY_SP,
},
span: rustc_span::DUMMY_SP,
};
let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_builtin_macros/deriving/generic/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ fn mk_ty_param(
}

fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
Generics { params, where_clause: ast::WhereClause { predicates: Vec::new(), span }, span }
Generics {
params,
where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
span,
}
}

/// Lifetimes and bounds on type parameters
Expand Down
9 changes: 7 additions & 2 deletions src/librustc_parse/parser/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ impl<'a> Parser<'a> {
Ok(ast::Generics {
params,
where_clause: WhereClause {
has_where_token: false,
predicates: Vec::new(),
span: self.prev_token.span.shrink_to_hi(),
},
Expand All @@ -170,12 +171,16 @@ impl<'a> Parser<'a> {
/// where T : Trait<U, V> + 'b, 'a : 'b
/// ```
pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
let mut where_clause =
WhereClause { predicates: Vec::new(), span: self.prev_token.span.shrink_to_hi() };
let mut where_clause = WhereClause {
has_where_token: false,
predicates: Vec::new(),
span: self.prev_token.span.shrink_to_hi(),
};

if !self.eat_keyword(kw::Where) {
return Ok(where_clause);
}
where_clause.has_where_token = true;
let lo = self.prev_token.span;

// We are considering adding generics to the `where` keyword as an alternative higher-rank
Expand Down
18 changes: 18 additions & 0 deletions src/test/ui/proc-macro/empty-where-clause.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// aux-build:test-macros.rs

extern crate test_macros;
use test_macros::recollect_attr;

#[recollect_attr]
struct FieldStruct where {
field: MissingType1 //~ ERROR cannot find
}

#[recollect_attr]
struct TupleStruct(MissingType2) where; //~ ERROR cannot find

enum MyEnum where {
Variant(MissingType3) //~ ERROR cannot find
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/proc-macro/empty-where-clause.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0412]: cannot find type `MissingType1` in this scope
--> $DIR/empty-where-clause.rs:8:12
|
LL | field: MissingType1
| ^^^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `MissingType2` in this scope
--> $DIR/empty-where-clause.rs:12:20
|
LL | struct TupleStruct(MissingType2) where;
| ^^^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `MissingType3` in this scope
--> $DIR/empty-where-clause.rs:15:13
|
LL | Variant(MissingType3)
| ^^^^^^^^^^^^ not found in this scope

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0412`.

0 comments on commit e04e3c8

Please sign in to comment.