Skip to content

Commit e04e3c8

Browse files
authored
Rollup merge of rust-lang#73157 - Aaron1011:where-oh-where-has-my-little-span-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
2 parents 0a77c8c + 0fcea2e commit e04e3c8

File tree

7 files changed

+68
-7
lines changed

7 files changed

+68
-7
lines changed

src/librustc_ast/ast.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,11 @@ impl Default for Generics {
362362
fn default() -> Generics {
363363
Generics {
364364
params: Vec::new(),
365-
where_clause: WhereClause { predicates: Vec::new(), span: DUMMY_SP },
365+
where_clause: WhereClause {
366+
has_where_token: false,
367+
predicates: Vec::new(),
368+
span: DUMMY_SP,
369+
},
366370
span: DUMMY_SP,
367371
}
368372
}
@@ -371,6 +375,11 @@ impl Default for Generics {
371375
/// A where-clause in a definition.
372376
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
373377
pub struct WhereClause {
378+
/// `true` if we ate a `where` token: this can happen
379+
/// if we parsed no predicates (e.g. `struct Foo where {}
380+
/// This allows us to accurately pretty-print
381+
/// in `nt_to_tokenstream`
382+
pub has_where_token: bool,
374383
pub predicates: Vec<WherePredicate>,
375384
pub span: Span,
376385
}

src/librustc_ast/mut_visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ pub fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T)
786786
}
787787

788788
pub fn noop_visit_where_clause<T: MutVisitor>(wc: &mut WhereClause, vis: &mut T) {
789-
let WhereClause { predicates, span } = wc;
789+
let WhereClause { has_where_token: _, predicates, span } = wc;
790790
visit_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
791791
vis.visit_span(span);
792792
}

src/librustc_ast_pretty/pprust.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -2593,7 +2593,7 @@ impl<'a> State<'a> {
25932593
}
25942594

25952595
crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
2596-
if where_clause.predicates.is_empty() {
2596+
if where_clause.predicates.is_empty() && !where_clause.has_where_token {
25972597
return;
25982598
}
25992599

@@ -2739,7 +2739,11 @@ impl<'a> State<'a> {
27392739
}
27402740
let generics = ast::Generics {
27412741
params: Vec::new(),
2742-
where_clause: ast::WhereClause { predicates: Vec::new(), span: rustc_span::DUMMY_SP },
2742+
where_clause: ast::WhereClause {
2743+
has_where_token: false,
2744+
predicates: Vec::new(),
2745+
span: rustc_span::DUMMY_SP,
2746+
},
27432747
span: rustc_span::DUMMY_SP,
27442748
};
27452749
let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };

src/librustc_builtin_macros/deriving/generic/ty.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,11 @@ fn mk_ty_param(
216216
}
217217

218218
fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
219-
Generics { params, where_clause: ast::WhereClause { predicates: Vec::new(), span }, span }
219+
Generics {
220+
params,
221+
where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
222+
span,
223+
}
220224
}
221225

222226
/// Lifetimes and bounds on type parameters

src/librustc_parse/parser/generics.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ impl<'a> Parser<'a> {
157157
Ok(ast::Generics {
158158
params,
159159
where_clause: WhereClause {
160+
has_where_token: false,
160161
predicates: Vec::new(),
161162
span: self.prev_token.span.shrink_to_hi(),
162163
},
@@ -170,12 +171,16 @@ impl<'a> Parser<'a> {
170171
/// where T : Trait<U, V> + 'b, 'a : 'b
171172
/// ```
172173
pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
173-
let mut where_clause =
174-
WhereClause { predicates: Vec::new(), span: self.prev_token.span.shrink_to_hi() };
174+
let mut where_clause = WhereClause {
175+
has_where_token: false,
176+
predicates: Vec::new(),
177+
span: self.prev_token.span.shrink_to_hi(),
178+
};
175179

176180
if !self.eat_keyword(kw::Where) {
177181
return Ok(where_clause);
178182
}
183+
where_clause.has_where_token = true;
179184
let lo = self.prev_token.span;
180185

181186
// We are considering adding generics to the `where` keyword as an alternative higher-rank
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// aux-build:test-macros.rs
2+
3+
extern crate test_macros;
4+
use test_macros::recollect_attr;
5+
6+
#[recollect_attr]
7+
struct FieldStruct where {
8+
field: MissingType1 //~ ERROR cannot find
9+
}
10+
11+
#[recollect_attr]
12+
struct TupleStruct(MissingType2) where; //~ ERROR cannot find
13+
14+
enum MyEnum where {
15+
Variant(MissingType3) //~ ERROR cannot find
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0412]: cannot find type `MissingType1` in this scope
2+
--> $DIR/empty-where-clause.rs:8:12
3+
|
4+
LL | field: MissingType1
5+
| ^^^^^^^^^^^^ not found in this scope
6+
7+
error[E0412]: cannot find type `MissingType2` in this scope
8+
--> $DIR/empty-where-clause.rs:12:20
9+
|
10+
LL | struct TupleStruct(MissingType2) where;
11+
| ^^^^^^^^^^^^ not found in this scope
12+
13+
error[E0412]: cannot find type `MissingType3` in this scope
14+
--> $DIR/empty-where-clause.rs:15:13
15+
|
16+
LL | Variant(MissingType3)
17+
| ^^^^^^^^^^^^ not found in this scope
18+
19+
error: aborting due to 3 previous errors
20+
21+
For more information about this error, try `rustc --explain E0412`.

0 commit comments

Comments
 (0)