1038: Add WherePred to allow predicate access in WhereClause r=matklad a=vipentti

Lifetime bounds in where predicates are now also parsed into `TYPE_BOUND_LIST` to allow unified access to bounds.

Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>
This commit is contained in:
bors[bot] 2019-03-31 10:43:50 +00:00
commit dec9bde108
5 changed files with 132 additions and 8 deletions

View file

@ -165,7 +165,7 @@ fn where_predicate(p: &mut Parser) {
LIFETIME => { LIFETIME => {
p.bump(); p.bump();
if p.at(COLON) { if p.at(COLON) {
lifetime_bounds(p); bounds(p);
} else { } else {
p.error("expected colon"); p.error("expected colon");
} }

View file

@ -799,3 +799,70 @@ fn test_doc_comment_preserves_indents() {
let module = file.syntax().descendants().find_map(Module::cast).unwrap(); let module = file.syntax().descendants().find_map(Module::cast).unwrap();
assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap()); assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap());
} }
#[test]
fn test_where_predicates() {
fn assert_bound(text: &str, bound: Option<&TypeBound>) {
assert_eq!(text, bound.unwrap().syntax().text().to_string());
}
let file = SourceFile::parse(
r#"
fn foo()
where
T: Clone + Copy + Debug + 'static,
'a: 'b + 'c,
Iterator::Item: 'a + Debug,
Iterator::Item: Debug + 'a,
<T as Iterator>::Item: Debug + 'a,
for<'a> F: Fn(&'a str)
{}
"#,
);
let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap();
let mut predicates = where_clause.predicates();
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
assert_eq!("T", pred.type_ref().unwrap().syntax().text().to_string());
assert_bound("Clone", bounds.next());
assert_bound("Copy", bounds.next());
assert_bound("Debug", bounds.next());
assert_bound("'static", bounds.next());
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
assert_eq!("'a", pred.lifetime().unwrap().syntax().text().to_string());
assert_bound("'b", bounds.next());
assert_bound("'c", bounds.next());
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string());
assert_bound("'a", bounds.next());
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
assert_eq!("Iterator::Item", pred.type_ref().unwrap().syntax().text().to_string());
assert_bound("Debug", bounds.next());
assert_bound("'a", bounds.next());
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
assert_eq!("<T as Iterator>::Item", pred.type_ref().unwrap().syntax().text().to_string());
assert_bound("Debug", bounds.next());
assert_bound("'a", bounds.next());
let pred = predicates.next().unwrap();
let mut bounds = pred.type_bound_list().unwrap().bounds();
assert_eq!("for<'a> F", pred.type_ref().unwrap().syntax().text().to_string());
assert_bound("Fn(&'a str)", bounds.next());
}

View file

@ -4810,7 +4810,48 @@ impl ToOwned for WhereClause {
} }
impl WhereClause {} impl WhereClause {
pub fn predicates(&self) -> impl Iterator<Item = &WherePred> {
super::children(self)
}
}
// WherePred
#[derive(Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct WherePred {
pub(crate) syntax: SyntaxNode,
}
unsafe impl TransparentNewType for WherePred {
type Repr = rowan::SyntaxNode<RaTypes>;
}
impl AstNode for WherePred {
fn cast(syntax: &SyntaxNode) -> Option<&Self> {
match syntax.kind() {
WHERE_PRED => Some(WherePred::from_repr(syntax.into_repr())),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl ToOwned for WherePred {
type Owned = TreeArc<WherePred>;
fn to_owned(&self) -> TreeArc<WherePred> { TreeArc::cast(self.syntax.to_owned()) }
}
impl ast::TypeBoundsOwner for WherePred {}
impl WherePred {
pub fn type_ref(&self) -> Option<&TypeRef> {
super::child_opt(self)
}
pub fn lifetime(&self) -> Option<&Lifetime> {
super::child_opt(self)
}
}
// WhileExpr // WhileExpr
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]

View file

@ -595,7 +595,20 @@ Grammar(
["bounds", "TypeBound"], ["bounds", "TypeBound"],
] ]
), ),
"WhereClause": (), "WherePred": (
options: [
"TypeRef",
"Lifetime",
],
traits: [
"TypeBoundsOwner",
],
),
"WhereClause": (
collections: [
["predicates", "WherePred"],
],
),
"ExprStmt": ( "ExprStmt": (
options: [ ["expr", "Expr"] ] options: [ ["expr", "Expr"] ]
), ),

View file

@ -15,11 +15,14 @@ SOURCE_FILE@[0; 116)
LIFETIME@[18; 20) "'a" LIFETIME@[18; 20) "'a"
COLON@[20; 21) COLON@[20; 21)
WHITESPACE@[21; 22) WHITESPACE@[21; 22)
LIFETIME@[22; 24) "'b" TYPE_BOUND_LIST@[22; 29)
WHITESPACE@[24; 25) TYPE_BOUND@[22; 24)
PLUS@[25; 26) LIFETIME@[22; 24) "'b"
WHITESPACE@[26; 27) WHITESPACE@[24; 25)
LIFETIME@[27; 29) "'c" PLUS@[25; 26)
WHITESPACE@[26; 27)
TYPE_BOUND@[27; 29)
LIFETIME@[27; 29) "'c"
COMMA@[29; 30) COMMA@[29; 30)
WHITESPACE@[30; 34) WHITESPACE@[30; 34)
WHERE_PRED@[34; 59) WHERE_PRED@[34; 59)