Allow super in calls

This commit is contained in:
Guillaume Gomez 2025-05-22 23:04:52 +02:00
parent 3ab930ded0
commit 06c32d6d18

View File

@ -34,23 +34,31 @@ macro_rules! expr_prec_layer {
}; };
} }
fn check_expr<'a>( #[derive(Clone, Copy, Default)]
expr: &WithSpan<'a, Expr<'a>>, struct Allowed {
allow_underscore: bool, underscore: bool,
) -> Result<(), ParseErr<'a>> { super_keyword: bool,
}
fn check_expr<'a>(expr: &WithSpan<'a, Expr<'a>>, allowed: Allowed) -> Result<(), ParseErr<'a>> {
match &expr.inner { match &expr.inner {
// List can be found in rust compiler "can_be_raw" function (although in our case, it's also Expr::Var(name) => {
// used in cases like `match`, so `self` is allowed in this case). // List can be found in rust compiler "can_be_raw" function (although in our case, it's
Expr::Var(name @ ("crate" | "super" | "Self")) => { // also used in cases like `match`, so `self` is allowed in this case).
Err(winnow::error::ErrMode::Cut(ErrorContext::new( if (!allowed.super_keyword && *name == "super") || matches!(*name, "crate" | "Self") {
format!("`{name}` cannot be used as an identifier"), Err(winnow::error::ErrMode::Cut(ErrorContext::new(
expr.span, format!("`{name}` cannot be used as an identifier"),
))) expr.span,
)))
} else if !allowed.underscore && *name == "_" {
Err(winnow::error::ErrMode::Cut(ErrorContext::new(
"reserved keyword `_` cannot be used here",
expr.span,
)))
} else {
Ok(())
}
} }
Expr::Var("_") if !allow_underscore => Err(winnow::error::ErrMode::Cut(ErrorContext::new(
"reserved keyword `_` cannot be used here",
expr.span,
))),
Expr::IsDefined(var) | Expr::IsNotDefined(var) => { Expr::IsDefined(var) | Expr::IsNotDefined(var) => {
if *var == "_" { if *var == "_" {
Err(winnow::error::ErrMode::Cut(ErrorContext::new( Err(winnow::error::ErrMode::Cut(ErrorContext::new(
@ -79,35 +87,42 @@ fn check_expr<'a>(
| Expr::Attr(_, _) | Expr::Attr(_, _)
| Expr::Filter(_) | Expr::Filter(_)
| Expr::NamedArgument(_, _) | Expr::NamedArgument(_, _)
| Expr::Var(_)
| Expr::RustMacro(_, _) | Expr::RustMacro(_, _)
| Expr::Try(_) | Expr::Try(_)
| Expr::FilterSource | Expr::FilterSource
| Expr::LetCond(_) => Ok(()), | Expr::LetCond(_) => Ok(()),
Expr::Array(elems) | Expr::Tuple(elems) | Expr::Concat(elems) => { Expr::Array(elems) | Expr::Tuple(elems) | Expr::Concat(elems) => {
for elem in elems { for elem in elems {
check_expr(elem, allow_underscore)?; check_expr(elem, allowed)?;
} }
Ok(()) Ok(())
} }
Expr::Index(elem1, elem2) | Expr::BinOp(_, elem1, elem2) => { Expr::Index(elem1, elem2) | Expr::BinOp(_, elem1, elem2) => {
check_expr(elem1, false)?; check_expr(elem1, Allowed::default())?;
check_expr(elem2, false) check_expr(elem2, Allowed::default())
} }
Expr::Range(_, elem1, elem2) => { Expr::Range(_, elem1, elem2) => {
if let Some(elem1) = elem1 { if let Some(elem1) = elem1 {
check_expr(elem1, false)?; check_expr(elem1, Allowed::default())?;
} }
if let Some(elem2) = elem2 { if let Some(elem2) = elem2 {
check_expr(elem2, false)?; check_expr(elem2, Allowed::default())?;
} }
Ok(()) Ok(())
} }
Expr::As(elem, _) | Expr::Unary(_, elem) | Expr::Group(elem) => check_expr(elem, false), Expr::As(elem, _) | Expr::Unary(_, elem) | Expr::Group(elem) => {
check_expr(elem, Allowed::default())
}
Expr::Call { path, args, .. } => { Expr::Call { path, args, .. } => {
check_expr(path, false)?; check_expr(
path,
Allowed {
underscore: false,
super_keyword: true,
},
)?;
for arg in args { for arg in args {
check_expr(arg, false)?; check_expr(arg, Allowed::default())?;
} }
Ok(()) Ok(())
} }
@ -274,7 +289,13 @@ impl<'a> Expr<'a> {
}), }),
)) ))
.parse_next(i)?; .parse_next(i)?;
check_expr(&expr, allow_underscore)?; check_expr(
&expr,
Allowed {
underscore: allow_underscore,
super_keyword: false,
},
)?;
Ok(expr) Ok(expr)
} }