Skip to content

Commit

Permalink
Disallow some nonsensical configurations of items
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Mar 24, 2023
1 parent e41f977 commit fd8d37e
Showing 1 changed file with 70 additions and 42 deletions.
112 changes: 70 additions & 42 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,11 @@ pub(crate) mod parsing {
semi_token: Token![;],
}

enum TypeDefaultness {
Optional,
Disallowed,
}

enum WhereClauseLocation {
// type Ty<T> where T: 'static = T;
BeforeEq,
Expand All @@ -1085,9 +1090,16 @@ pub(crate) mod parsing {
}

impl FlexibleItemType {
fn parse(input: ParseStream, where_clause_location: WhereClauseLocation) -> Result<Self> {
fn parse(
input: ParseStream,
allow_defaultness: TypeDefaultness,
where_clause_location: WhereClauseLocation,
) -> Result<Self> {
let vis: Visibility = input.parse()?;
let defaultness: Option<Token![default]> = input.parse()?;
let defaultness: Option<Token![default]> = match allow_defaultness {
TypeDefaultness::Optional => input.parse()?,
TypeDefaultness::Disallowed => None,
};
let type_token: Token![type] = input.parse()?;
let ident: Ident = input.parse()?;
let mut generics: Generics = input.parse()?;
Expand Down Expand Up @@ -1844,17 +1856,21 @@ pub(crate) mod parsing {
fn parse_foreign_item_type(begin: ParseBuffer, input: ParseStream) -> Result<ForeignItem> {
let FlexibleItemType {
vis,
defaultness,
defaultness: _,
type_token,
ident,
generics,
colon_token,
bounds: _,
ty,
semi_token,
} = FlexibleItemType::parse(input, WhereClauseLocation::Both)?;
} = FlexibleItemType::parse(
input,
TypeDefaultness::Disallowed,
WhereClauseLocation::Both,
)?;

if defaultness.is_some() || colon_token.is_some() || ty.is_some() {
if colon_token.is_some() || ty.is_some() {
Ok(ForeignItem::Verbatim(verbatim::between(begin, input)))
} else {
Ok(ForeignItem::Type(ForeignItemType {
Expand Down Expand Up @@ -1909,31 +1925,35 @@ pub(crate) mod parsing {
fn parse_item_type(begin: ParseBuffer, input: ParseStream) -> Result<Item> {
let FlexibleItemType {
vis,
defaultness,
defaultness: _,
type_token,
ident,
generics,
colon_token,
bounds: _,
ty,
semi_token,
} = FlexibleItemType::parse(input, WhereClauseLocation::BeforeEq)?;
} = FlexibleItemType::parse(
input,
TypeDefaultness::Disallowed,
WhereClauseLocation::BeforeEq,
)?;

let (eq_token, ty) = match ty {
Some(ty) if colon_token.is_none() => ty,
_ => return Ok(Item::Verbatim(verbatim::between(begin, input))),
};

if defaultness.is_some() || colon_token.is_some() || ty.is_none() {
Ok(Item::Verbatim(verbatim::between(begin, input)))
} else {
let (eq_token, ty) = ty.unwrap();
Ok(Item::Type(ItemType {
attrs: Vec::new(),
vis,
type_token,
ident,
generics,
eq_token,
ty: Box::new(ty),
semi_token,
}))
}
Ok(Item::Type(ItemType {
attrs: Vec::new(),
vis,
type_token,
ident,
generics,
eq_token,
ty: Box::new(ty),
semi_token,
}))
}

#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
Expand Down Expand Up @@ -2330,17 +2350,21 @@ pub(crate) mod parsing {
fn parse_trait_item_type(begin: ParseBuffer, input: ParseStream) -> Result<TraitItem> {
let FlexibleItemType {
vis,
defaultness,
defaultness: _,
type_token,
ident,
generics,
colon_token,
bounds,
ty,
semi_token,
} = FlexibleItemType::parse(input, WhereClauseLocation::AfterEq)?;
} = FlexibleItemType::parse(
input,
TypeDefaultness::Disallowed,
WhereClauseLocation::AfterEq,
)?;

if defaultness.is_some() || vis.is_some() {
if vis.is_some() {
Ok(TraitItem::Verbatim(verbatim::between(begin, input)))
} else {
Ok(TraitItem::Type(TraitItemType {
Expand Down Expand Up @@ -2669,24 +2693,28 @@ pub(crate) mod parsing {
bounds: _,
ty,
semi_token,
} = FlexibleItemType::parse(input, WhereClauseLocation::AfterEq)?;
} = FlexibleItemType::parse(
input,
TypeDefaultness::Optional,
WhereClauseLocation::AfterEq,
)?;

let (eq_token, ty) = match ty {
Some(ty) if colon_token.is_none() => ty,
_ => return Ok(ImplItem::Verbatim(verbatim::between(begin, input))),
};

if colon_token.is_some() || ty.is_none() {
Ok(ImplItem::Verbatim(verbatim::between(begin, input)))
} else {
let (eq_token, ty) = ty.unwrap();
Ok(ImplItem::Type(ImplItemType {
attrs: Vec::new(),
vis,
defaultness,
type_token,
ident,
generics,
eq_token,
ty,
semi_token,
}))
}
Ok(ImplItem::Type(ImplItemType {
attrs: Vec::new(),
vis,
defaultness,
type_token,
ident,
generics,
eq_token,
ty,
semi_token,
}))
}

#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
Expand Down

0 comments on commit fd8d37e

Please sign in to comment.