Skip to content

Commit

Permalink
Update syntax of where-clauses on associated types
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Mar 14, 2022
1 parent 99560af commit 4daa92d
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 38 deletions.
78 changes: 55 additions & 23 deletions src/item.rs
Expand Up @@ -1177,14 +1177,25 @@ pub mod parsing {
semi_token: Token![;],
}

impl Parse for FlexibleItemType {
fn parse(input: ParseStream) -> Result<Self> {
enum WhereClauseLocation {
// type Ty<T> where T: 'static = T;
BeforeEq,
// type Ty<T> = T where T: 'static;
#[allow(dead_code)]
AfterEq,
// TODO: goes away once the migration period on rust-lang/rust#89122 is over
Both,
}

impl FlexibleItemType {
fn parse(input: ParseStream, where_clause_location: WhereClauseLocation) -> Result<Self> {
let vis: Visibility = input.parse()?;
let defaultness: Option<Token![default]> = input.parse()?;
let type_token: Token![type] = input.parse()?;
let ident: Ident = input.parse()?;
let mut generics: Generics = input.parse()?;
let colon_token: Option<Token![:]> = input.parse()?;

let mut bounds = Punctuated::new();
if colon_token.is_some() {
loop {
Expand All @@ -1198,12 +1209,26 @@ pub mod parsing {
bounds.push_punct(input.parse::<Token![+]>()?);
}
}
generics.where_clause = input.parse()?;

if let WhereClauseLocation::BeforeEq | WhereClauseLocation::Both = where_clause_location
{
generics.where_clause = input.parse()?;
}

let ty = if let Some(eq_token) = input.parse()? {
Some((eq_token, input.parse::<Type>()?))
} else {
None
};

if generics.where_clause.is_none() {
if let WhereClauseLocation::AfterEq | WhereClauseLocation::Both =
where_clause_location
{
generics.where_clause = input.parse()?;
}
}

let semi_token: Token![;] = input.parse()?;

Ok(FlexibleItemType {
Expand Down Expand Up @@ -1868,7 +1893,7 @@ pub mod parsing {
bounds: _,
ty,
semi_token,
} = input.parse()?;
} = FlexibleItemType::parse(input, WhereClauseLocation::BeforeEq)?;

if defaultness.is_some()
|| generics.lt_token.is_some()
Expand Down Expand Up @@ -1937,7 +1962,7 @@ pub mod parsing {
bounds: _,
ty,
semi_token,
} = input.parse()?;
} = FlexibleItemType::parse(input, WhereClauseLocation::BeforeEq)?;

if defaultness.is_some() || colon_token.is_some() || ty.is_none() {
Ok(Item::Verbatim(verbatim::between(begin, input)))
Expand Down Expand Up @@ -2328,14 +2353,15 @@ pub mod parsing {
}
}

generics.where_clause = input.parse()?;
let default = if input.peek(Token![=]) {
let eq_token: Token![=] = input.parse()?;
let default: Type = input.parse()?;
Some((eq_token, default))
} else {
None
};

generics.where_clause = input.parse()?;
let semi_token: Token![;] = input.parse()?;

Ok(TraitItemType {
Expand All @@ -2362,7 +2388,7 @@ pub mod parsing {
bounds,
ty,
semi_token,
} = input.parse()?;
} = FlexibleItemType::parse(input, WhereClauseLocation::Both)?;

if defaultness.is_some() || vis.is_some() {
Ok(TraitItem::Verbatim(verbatim::between(begin, input)))
Expand Down Expand Up @@ -2661,20 +2687,26 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for ImplItemType {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let defaultness: Option<Token![default]> = input.parse()?;
let type_token: Token![type] = input.parse()?;
let ident: Ident = input.parse()?;
let mut generics: Generics = input.parse()?;
let eq_token: Token![=] = input.parse()?;
let ty: Type = input.parse()?;
generics.where_clause = input.parse()?;
let semi_token: Token![;] = input.parse()?;
Ok(ImplItemType {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
defaultness: input.parse()?,
type_token: input.parse()?,
ident: input.parse()?,
generics: {
let mut generics: Generics = input.parse()?;
generics.where_clause = input.parse()?;
generics
},
eq_token: input.parse()?,
ty: input.parse()?,
semi_token: input.parse()?,
attrs,
vis,
defaultness,
type_token,
ident,
generics,
eq_token,
ty,
semi_token,
})
}
}
Expand All @@ -2690,7 +2722,7 @@ pub mod parsing {
bounds: _,
ty,
semi_token,
} = input.parse()?;
} = FlexibleItemType::parse(input, WhereClauseLocation::Both)?;

if colon_token.is_some() || ty.is_none() {
Ok(ImplItem::Verbatim(verbatim::between(begin, input)))
Expand Down Expand Up @@ -3106,11 +3138,11 @@ mod printing {
TokensOrDefault(&self.colon_token).to_tokens(tokens);
self.bounds.to_tokens(tokens);
}
self.generics.where_clause.to_tokens(tokens);
if let Some((eq_token, default)) = &self.default {
eq_token.to_tokens(tokens);
default.to_tokens(tokens);
}
self.generics.where_clause.to_tokens(tokens);
self.semi_token.to_tokens(tokens);
}
}
Expand Down Expand Up @@ -3171,9 +3203,9 @@ mod printing {
self.type_token.to_tokens(tokens);
self.ident.to_tokens(tokens);
self.generics.to_tokens(tokens);
self.generics.where_clause.to_tokens(tokens);
self.eq_token.to_tokens(tokens);
self.ty.to_tokens(tokens);
self.generics.where_clause.to_tokens(tokens);
self.semi_token.to_tokens(tokens);
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/common/eq.rs
Expand Up @@ -339,8 +339,8 @@ spanless_eq_struct!(Token; kind span);
spanless_eq_struct!(Trait; unsafety is_auto generics bounds items);
spanless_eq_struct!(TraitRef; path ref_id);
spanless_eq_struct!(Ty; id kind span tokens);
spanless_eq_struct!(TyAlias; defaultness generics where_clauses where_predicates_split bounds ty);
spanless_eq_struct!(TyAliasWhereClause; 0 1);
spanless_eq_struct!(TyAlias; defaultness generics where_clauses !where_predicates_split bounds ty);
spanless_eq_struct!(TyAliasWhereClause; !0 1);
spanless_eq_struct!(UseTree; prefix kind span);
spanless_eq_struct!(Variant; attrs id span !vis ident data disr_expr is_placeholder);
spanless_eq_struct!(Visibility; kind span tokens);
Expand Down
13 changes: 0 additions & 13 deletions tests/repo/mod.rs
Expand Up @@ -14,19 +14,6 @@ const REVISION: &str = "e95b10ba4ac4564ed25f7eef143e3182c33b3902";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
// TODO: trailing where-clause on impl associated type:
// impl<T> Trait for Ty<T> { type Assoc<'a> = T where T: 'a; }
// https://github.com/dtolnay/syn/issues/1071
"src/test/ui/generic-associated-types/collections.rs",
"src/test/ui/generic-associated-types/construct_with_other_type.rs",
"src/test/ui/generic-associated-types/impl_bounds_ok.rs",
"src/test/ui/generic-associated-types/issue-76826.rs",
"src/test/ui/generic-associated-types/issue-88287.rs",
"src/test/ui/generic-associated-types/issue-91139.rs",
"src/test/ui/generic-associated-types/issue-92280.rs",
"src/test/ui/generic-associated-types/iterable.rs",
"src/test/ui/generic-associated-types/streaming_iterator.rs",

// TODO: impl ~const T {}
// https://github.com/dtolnay/syn/issues/1051
"src/test/ui/rfc-2632-const-trait-impl/syntax.rs",
Expand Down

0 comments on commit 4daa92d

Please sign in to comment.