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
This commit is contained in:
parent
fd4b177aab
commit
0fcea2e423
@ -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,
|
||||
}
|
||||
}
|
||||
@ -371,6 +375,11 @@ fn default() -> 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,
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -2593,7 +2593,7 @@ pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::Generic
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2739,7 +2739,11 @@ pub fn print_mutability(&mut self, mutbl: ast::Mutability, print_const: bool) {
|
||||
}
|
||||
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() };
|
||||
|
@ -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
|
||||
|
@ -157,6 +157,7 @@ pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
|
||||
Ok(ast::Generics {
|
||||
params,
|
||||
where_clause: WhereClause {
|
||||
has_where_token: false,
|
||||
predicates: Vec::new(),
|
||||
span: self.prev_token.span.shrink_to_hi(),
|
||||
},
|
||||
@ -170,12 +171,16 @@ pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
|
||||
/// 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
|
||||
|
18
src/test/ui/proc-macro/empty-where-clause.rs
Normal file
18
src/test/ui/proc-macro/empty-where-clause.rs
Normal file
@ -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
src/test/ui/proc-macro/empty-where-clause.stderr
Normal file
21
src/test/ui/proc-macro/empty-where-clause.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user