mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
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 {
|
fn default() -> Generics {
|
||||||
Generics {
|
Generics {
|
||||||
params: Vec::new(),
|
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,
|
span: DUMMY_SP,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -371,6 +375,11 @@ impl Default for Generics {
|
|||||||
/// A where-clause in a definition.
|
/// A where-clause in a definition.
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct WhereClause {
|
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 predicates: Vec<WherePredicate>,
|
||||||
pub span: Span,
|
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) {
|
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));
|
visit_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
}
|
}
|
||||||
|
@ -2593,7 +2593,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2739,7 +2739,11 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
let generics = ast::Generics {
|
let generics = ast::Generics {
|
||||||
params: Vec::new(),
|
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,
|
span: rustc_span::DUMMY_SP,
|
||||||
};
|
};
|
||||||
let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
|
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 {
|
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
|
/// Lifetimes and bounds on type parameters
|
||||||
|
@ -157,6 +157,7 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(ast::Generics {
|
Ok(ast::Generics {
|
||||||
params,
|
params,
|
||||||
where_clause: WhereClause {
|
where_clause: WhereClause {
|
||||||
|
has_where_token: false,
|
||||||
predicates: Vec::new(),
|
predicates: Vec::new(),
|
||||||
span: self.prev_token.span.shrink_to_hi(),
|
span: self.prev_token.span.shrink_to_hi(),
|
||||||
},
|
},
|
||||||
@ -170,12 +171,16 @@ impl<'a> Parser<'a> {
|
|||||||
/// where T : Trait<U, V> + 'b, 'a : 'b
|
/// where T : Trait<U, V> + 'b, 'a : 'b
|
||||||
/// ```
|
/// ```
|
||||||
pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
|
pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
|
||||||
let mut where_clause =
|
let mut where_clause = WhereClause {
|
||||||
WhereClause { predicates: Vec::new(), span: self.prev_token.span.shrink_to_hi() };
|
has_where_token: false,
|
||||||
|
predicates: Vec::new(),
|
||||||
|
span: self.prev_token.span.shrink_to_hi(),
|
||||||
|
};
|
||||||
|
|
||||||
if !self.eat_keyword(kw::Where) {
|
if !self.eat_keyword(kw::Where) {
|
||||||
return Ok(where_clause);
|
return Ok(where_clause);
|
||||||
}
|
}
|
||||||
|
where_clause.has_where_token = true;
|
||||||
let lo = self.prev_token.span;
|
let lo = self.prev_token.span;
|
||||||
|
|
||||||
// We are considering adding generics to the `where` keyword as an alternative higher-rank
|
// 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