Skip to content

Commit bbe5133

Browse files
committed
Syntactically permit attributes on 'if' expressions
Fixes rust-lang#68618 Previously, attributes on 'if' expressions (e.g. `#[attr] if true {}`) were disallowed during parsing. This made it impossible for macros to perform any custom handling of such attributes (e.g. stripping them away), since a compilation error would be emitted before they ever had a chance to run. This PR permits attributes on 'if' expressions ('if-attrs' from here on) syntactically, i.e. during parsing. We instead deny if-attrs during AST validation, which occurs after all macro expansions have run. This is a conservative change which allows more code to be processed by macros. It does not commit us to *semantically* accepting if-attrs. For example, the following code is not allowed even with this PR: ```rust fn builtin_attr() { #[allow(warnings)] if true {} } fn custom_attr() { #[my_proc_macro_attr] if true {} } ``` However, the following code *is* accepted ```rust #[cfg(FALSE)] fn foo() { #[allow(warnings)] if true {} #[my_custom_attr] if true {} } #[my_custom_attr] fn use_within_body() { #[allow(warnings)] if true {} #[my_custom_attr] if true {} } ```
1 parent 9ed29b6 commit bbe5133

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

src/librustc_ast_passes/ast_validation.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,15 @@ impl<'a> AstValidator<'a> {
399399
}
400400
}
401401
}
402+
403+
fn check_attr_on_if_expr(&self, attrs: &[Attribute]) {
404+
if let [a0, ..] = attrs {
405+
// Just point to the first attribute in there...
406+
self.err_handler()
407+
.struct_span_err(a0.span, "attributes are not yet allowed on `if` expressions")
408+
.emit();
409+
}
410+
}
402411
}
403412

404413
enum GenericPosition {
@@ -515,6 +524,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
515524
)
516525
.emit();
517526
}
527+
ExprKind::If(..) => self.check_attr_on_if_expr(&*expr.attrs),
518528
_ => {}
519529
}
520530

src/librustc_parse/parser/expr.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -676,19 +676,11 @@ impl<'a> Parser<'a> {
676676
expr.map(|mut expr| {
677677
attrs.extend::<Vec<_>>(expr.attrs.into());
678678
expr.attrs = attrs;
679-
self.error_attr_on_if_expr(&expr);
680679
expr
681680
})
682681
})
683682
}
684683

685-
fn error_attr_on_if_expr(&self, expr: &Expr) {
686-
if let (ExprKind::If(..), [a0, ..]) = (&expr.kind, &*expr.attrs) {
687-
// Just point to the first attribute in there...
688-
self.struct_span_err(a0.span, "attributes are not yet allowed on `if` expressions")
689-
.emit();
690-
}
691-
}
692684

693685
fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
694686
loop {

0 commit comments

Comments
 (0)