Skip to content

Commit

Permalink
Merge pull request #1747 from dtolnay/restrictedtpbound
Browse files Browse the repository at this point in the history
Reject precise captures and ~const in inappropriate syntax positions
  • Loading branch information
dtolnay authored Oct 17, 2024
2 parents e565d5f + ff3325c commit 6afa190
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 23 deletions.
62 changes: 49 additions & 13 deletions src/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ ast_struct! {
#[cfg(feature = "parsing")]
pub(crate) mod parsing {
use crate::attr::Attribute;
use crate::error::Result;
use crate::error::{self, Result};
use crate::ext::IdentExt as _;
use crate::generics::{
BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
Expand Down Expand Up @@ -706,8 +706,15 @@ pub(crate) mod parsing {
if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) {
break;
}
let value: TypeParamBound = input.parse()?;
bounds.push_value(value);
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = true;
TypeParamBound::parse_single(
input,
allow_precise_capture,
allow_tilde_const,
)?
});
if !input.peek(Token![+]) {
break;
}
Expand Down Expand Up @@ -737,14 +744,26 @@ pub(crate) mod parsing {
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for TypeParamBound {
fn parse(input: ParseStream) -> Result<Self> {
let allow_precise_capture = true;
let allow_tilde_const = true;
Self::parse_single(input, allow_precise_capture, allow_tilde_const)
}
}

impl TypeParamBound {
pub(crate) fn parse_single(
input: ParseStream,
allow_precise_capture: bool,
allow_tilde_const: bool,
) -> Result<Self> {
if input.peek(Lifetime) {
return input.parse().map(TypeParamBound::Lifetime);
}

let begin = input.fork();

if cfg!(feature = "full") && input.peek(Token![use]) {
input.parse::<Token![use]>()?;
let use_token: Token![use] = input.parse()?;
input.parse::<Token![<]>()?;
loop {
let lookahead = input.lookahead1();
Expand All @@ -766,8 +785,13 @@ pub(crate) mod parsing {
return Err(lookahead.error());
}
}
input.parse::<Token![>]>()?;
return Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input)));
let gt_token: Token![>] = input.parse()?;
return if allow_precise_capture {
Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input)))
} else {
let msg = "`use<...>` precise capturing syntax is not allowed here";
Err(error::new2(use_token.span, gt_token.span, msg))
};
}

let content;
Expand All @@ -780,8 +804,12 @@ pub(crate) mod parsing {
let is_tilde_const =
cfg!(feature = "full") && content.peek(Token![~]) && content.peek2(Token![const]);
if is_tilde_const {
content.parse::<Token![~]>()?;
content.parse::<Token![const]>()?;
let tilde_token: Token![~] = content.parse()?;
let const_token: Token![const] = content.parse()?;
if !allow_tilde_const {
let msg = "`~const` is not allowed here";
return Err(error::new2(tilde_token.span, const_token.span, msg));
}
}

let mut bound: TraitBound = content.parse()?;
Expand All @@ -793,16 +821,17 @@ pub(crate) mod parsing {
Ok(TypeParamBound::Trait(bound))
}
}
}

impl TypeParamBound {
pub(crate) fn parse_multiple(
input: ParseStream,
allow_plus: bool,
allow_precise_capture: bool,
allow_tilde_const: bool,
) -> Result<Punctuated<Self, Token![+]>> {
let mut bounds = Punctuated::new();
loop {
bounds.push_value(input.parse()?);
let bound = Self::parse_single(input, allow_precise_capture, allow_tilde_const)?;
bounds.push_value(bound);
if !(allow_plus && input.peek(Token![+])) {
break;
}
Expand Down Expand Up @@ -970,8 +999,15 @@ pub(crate) mod parsing {
{
break;
}
let value = input.parse()?;
bounds.push_value(value);
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = true;
TypeParamBound::parse_single(
input,
allow_precise_capture,
allow_tilde_const,
)?
});
if !input.peek(Token![+]) {
break;
}
Expand Down
22 changes: 19 additions & 3 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,15 @@ pub(crate) mod parsing {
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
break;
}
bounds.push_value(input.parse::<TypeParamBound>()?);
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = true;
TypeParamBound::parse_single(
input,
allow_precise_capture,
allow_tilde_const,
)?
});
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
break;
}
Expand Down Expand Up @@ -2184,7 +2192,11 @@ pub(crate) mod parsing {
if input.peek(Token![where]) || input.peek(token::Brace) {
break;
}
supertraits.push_value(input.parse()?);
supertraits.push_value({
let allow_precise_capture = false;
let allow_tilde_const = true;
TypeParamBound::parse_single(input, allow_precise_capture, allow_tilde_const)?
});
if input.peek(Token![where]) || input.peek(token::Brace) {
break;
}
Expand Down Expand Up @@ -2252,7 +2264,11 @@ pub(crate) mod parsing {
if input.peek(Token![where]) || input.peek(Token![;]) {
break;
}
bounds.push_value(input.parse()?);
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = false;
TypeParamBound::parse_single(input, allow_precise_capture, allow_tilde_const)?
});
if input.peek(Token![where]) || input.peek(Token![;]) {
break;
}
Expand Down
11 changes: 9 additions & 2 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,15 @@ pub(crate) mod parsing {
if input.peek(Token![,]) || input.peek(Token![>]) {
break;
}
let value: TypeParamBound = input.parse()?;
bounds.push_value(value);
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = true;
TypeParamBound::parse_single(
input,
allow_precise_capture,
allow_tilde_const,
)?
});
if !input.peek(Token![+]) {
break;
}
Expand Down
48 changes: 43 additions & 5 deletions src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,15 @@ pub(crate) mod parsing {
}));
while let Some(plus) = input.parse()? {
bounds.push_punct(plus);
bounds.push_value(input.parse()?);
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = false;
TypeParamBound::parse_single(
input,
allow_precise_capture,
allow_tilde_const,
)?
});
}
bounds
},
Expand Down Expand Up @@ -469,7 +477,15 @@ pub(crate) mod parsing {
bounds.push_value(first);
while let Some(plus) = input.parse()? {
bounds.push_punct(plus);
bounds.push_value(input.parse()?);
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = false;
TypeParamBound::parse_single(
input,
allow_precise_capture,
allow_tilde_const,
)?
});
}
bounds
},
Expand Down Expand Up @@ -532,7 +548,15 @@ pub(crate) mod parsing {
{
break;
}
bounds.push_value(input.parse()?);
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = false;
TypeParamBound::parse_single(
input,
allow_precise_capture,
allow_tilde_const,
)?
});
}
}
return Ok(Type::TraitObject(TypeTraitObject {
Expand Down Expand Up @@ -823,7 +847,14 @@ pub(crate) mod parsing {
input: ParseStream,
allow_plus: bool,
) -> Result<Punctuated<TypeParamBound, Token![+]>> {
let bounds = TypeParamBound::parse_multiple(input, allow_plus)?;
let allow_precise_capture = false;
let allow_tilde_const = false;
let bounds = TypeParamBound::parse_multiple(
input,
allow_plus,
allow_precise_capture,
allow_tilde_const,
)?;
let mut last_lifetime_span = None;
let mut at_least_one_trait = false;
for bound in &bounds {
Expand Down Expand Up @@ -863,7 +894,14 @@ pub(crate) mod parsing {

pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
let impl_token: Token![impl] = input.parse()?;
let bounds = TypeParamBound::parse_multiple(input, allow_plus)?;
let allow_precise_capture = true;
let allow_tilde_const = false;
let bounds = TypeParamBound::parse_multiple(
input,
allow_plus,
allow_precise_capture,
allow_tilde_const,
)?;
let mut last_lifetime_span = None;
let mut at_least_one_trait = false;
for bound in &bounds {
Expand Down

0 comments on commit 6afa190

Please sign in to comment.