Rollup merge of #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
This commit is contained in:
commit
e04e3c89cc
7 changed files with 68 additions and 7 deletions
|
@ -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 @@ 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,
|
||||
}
|
||||
|
|
|
@ -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 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -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() };
|
||||
|
|
|
@ -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 @@ 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(),
|
||||
},
|
||||
|
@ -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
|
||||
|
|
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…
Add table
Reference in a new issue