Unnamed repository; edit this file 'description' to name the repository.
Handle more cases of cfgs in expr store lowering:
- Closure parameters
- Tuple fields
- Inline asm options
- And the cursed of all, macros that expand into a disabled cfg.
Amusingly (and thankfully), unlike expressions patterns do not support cfgs in those places, the only place they do is record fields, and they don't have macros.
| -rw-r--r-- | crates/hir-def/src/expr_store/lower.rs | 20 | ||||
| -rw-r--r-- | crates/hir-def/src/expr_store/lower/asm.rs | 4 | ||||
| -rw-r--r-- | crates/hir-def/src/expr_store/tests/body.rs | 45 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs | 17 | ||||
| -rw-r--r-- | crates/parser/src/grammar/expressions/atom.rs | 4 | ||||
| -rw-r--r-- | crates/parser/test_data/generated/runner.rs | 4 | ||||
| -rw-r--r-- | crates/parser/test_data/parser/inline/ok/asm_piece_attr.rast | 29 | ||||
| -rw-r--r-- | crates/parser/test_data/parser/inline/ok/asm_piece_attr.rs | 1 | ||||
| -rw-r--r-- | crates/syntax/rust.ungram | 6 | ||||
| -rw-r--r-- | crates/syntax/src/ast/generated/nodes.rs | 19 |
10 files changed, 136 insertions, 13 deletions
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index a69755baf6..afbcf4cc84 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -1562,6 +1562,10 @@ impl<'db> ExprCollector<'db> { args.reserve_exact(num_params); arg_types.reserve_exact(num_params); for param in pl.params() { + if !this.check_cfg(¶m) { + continue; + } + let pat = this.collect_pat_top(param.pat()); let type_ref = param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it)); @@ -1666,7 +1670,7 @@ impl<'db> ExprCollector<'db> { } } ast::Expr::TupleExpr(e) => { - let mut exprs: Vec<_> = e.fields().map(|expr| self.collect_expr(expr)).collect(); + let mut exprs: Vec<_> = e.fields().filter_map(|expr| self.maybe_collect_expr(expr)).collect(); // if there is a leading comma, the user is most likely to type out a leading expression // so we insert a missing expression at the beginning for IDE features if comma_follows_token(e.l_paren_token()) { @@ -1681,13 +1685,7 @@ impl<'db> ExprCollector<'db> { match kind { ArrayExprKind::ElementList(e) => { let elements = e - .filter_map(|expr| { - if self.check_cfg(&expr) { - Some(self.collect_expr(expr)) - } else { - None - } - }) + .filter_map(|expr| self.maybe_collect_expr(expr)) .collect(); self.alloc_expr(Expr::Array(Array::ElementList { elements }), syntax_ptr) } @@ -1728,16 +1726,18 @@ impl<'db> ExprCollector<'db> { let e = e.macro_call()?; let macro_ptr = AstPtr::new(&e); let id = self.collect_macro_call(e, macro_ptr, true, |this, expansion| { - expansion.map(|it| this.collect_expr(it)) + expansion.map(|it| this.maybe_collect_expr(it)) }); match id { - Some(id) => { + Some(Some(id)) => { // Make the macro-call point to its expanded expression so we can query // semantics on syntax pointers to the macro let src = self.expander.in_file(syntax_ptr); self.store.expr_map.insert(src, id.into()); id } + // Macro expanded into a disabled cfg (yes, there is such thing, see the weird_cfgs test). + Some(None) => return None, None => self.alloc_expr(Expr::Missing, syntax_ptr), } } diff --git a/crates/hir-def/src/expr_store/lower/asm.rs b/crates/hir-def/src/expr_store/lower/asm.rs index 230d1c9346..63a0594f74 100644 --- a/crates/hir-def/src/expr_store/lower/asm.rs +++ b/crates/hir-def/src/expr_store/lower/asm.rs @@ -27,6 +27,10 @@ impl ExprCollector<'_> { let mut named_args: FxHashMap<Symbol, usize> = Default::default(); let mut reg_args: FxHashSet<usize> = Default::default(); for piece in asm.asm_pieces() { + if !self.check_cfg(&piece) { + continue; + } + let slot = operands.len(); let mut lower_reg = |reg: Option<ast::AsmRegSpec>| { let reg = reg?; diff --git a/crates/hir-def/src/expr_store/tests/body.rs b/crates/hir-def/src/expr_store/tests/body.rs index 98cbcb2450..dda5a8189c 100644 --- a/crates/hir-def/src/expr_store/tests/body.rs +++ b/crates/hir-def/src/expr_store/tests/body.rs @@ -716,3 +716,48 @@ fn foo() -> i64 { }"#]], ); } + +#[test] +fn weird_cfgs() { + pretty_print( + r#" +macro_rules! falsify { + ( $($t:tt)* ) => { #[cfg(false)] $($t)* }; +} + +struct Foo(); + +fn foo() { + foo(falsify!(1)); + (falsify!(1),); + [falsify!(1)]; + Foo(falsify!(1)); + foo(#[cfg(false)] 1); + (#[cfg(false)] 1,); + [#[cfg(false)] 1]; + Foo(#[cfg(false)] 1); + (|#[cfg(false)] a| {})(); + + builtin # asm( + "", + #[cfg(false)] x = const 4, + #[cfg(false)] options(), + #[cfg(false)] clobber_abi("C"), + ); +} + "#, + expect![[r#" + fn foo() { + foo(); + (); + []; + Foo(); + foo(); + (); + []; + Foo(); + (|| {})(); + builtin#asm(_); + }"#]], + ); +} diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index d1c3d1c5df..81ea442e9e 100644 --- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -539,4 +539,21 @@ pub fn repro<T: A>() { "#, ); } + + #[test] + fn cfg_inside_macro_inside_arg() { + check_diagnostics( + r#" +fn foo() {} + +macro_rules! make_X { + () => { #[cfg(false)] X }; +} + +fn main() { + foo(make_X!()); +} + "#, + ); + } } diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index bc7db630d1..7ce1fc2c48 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs @@ -355,6 +355,10 @@ pub(crate) fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedM } let op_n = p.start(); + // test asm_piece_attr + // builtin # global_asm("", #[cfg(false)] options()) + attributes::outer_attrs(p); + // Parse clobber_abi if p.eat_contextual_kw(T![clobber_abi]) { parse_clobber_abi(p); diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs index 26d28ddfc6..4901ece9ca 100644 --- a/crates/parser/test_data/generated/runner.rs +++ b/crates/parser/test_data/generated/runner.rs @@ -25,6 +25,10 @@ mod ok { #[test] fn asm_label() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_label.rs"); } #[test] + fn asm_piece_attr() { + run_and_expect_no_errors("test_data/parser/inline/ok/asm_piece_attr.rs"); + } + #[test] fn asm_sym_paren() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_sym_paren.rs"); } #[test] fn assoc_const_eq() { diff --git a/crates/parser/test_data/parser/inline/ok/asm_piece_attr.rast b/crates/parser/test_data/parser/inline/ok/asm_piece_attr.rast new file mode 100644 index 0000000000..1fa9cd6dd7 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/asm_piece_attr.rast @@ -0,0 +1,29 @@ +SOURCE_FILE + ASM_EXPR + BUILTIN_KW "builtin" + WHITESPACE " " + POUND "#" + WHITESPACE " " + GLOBAL_ASM_KW "global_asm" + L_PAREN "(" + LITERAL + STRING "\"\"" + COMMA "," + WHITESPACE " " + ASM_OPTIONS + ATTR + POUND "#" + L_BRACK "[" + CFG_META + CFG_KW "cfg" + L_PAREN "(" + CFG_ATOM + FALSE_KW "false" + R_PAREN ")" + R_BRACK "]" + WHITESPACE " " + OPTIONS_KW "options" + L_PAREN "(" + R_PAREN ")" + R_PAREN ")" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/asm_piece_attr.rs b/crates/parser/test_data/parser/inline/ok/asm_piece_attr.rs new file mode 100644 index 0000000000..ac9ad101d9 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/asm_piece_attr.rs @@ -0,0 +1 @@ +builtin # global_asm("", #[cfg(false)] options()) diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index e1c91c41e6..05df8b9b14 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -468,17 +468,17 @@ AsmRegSpec = '@string' | NameRef // reg_operand := [ident "="] dir_spec "(" reg_spec ")" operand_expr AsmRegOperand = AsmDirSpec '(' AsmRegSpec ')' AsmOperandExpr // clobber_abi := "clobber_abi(" <abi> *("," <abi>) [","] ")" -AsmClobberAbi = 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')' +AsmClobberAbi = Attr* 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')' // option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" AsmOption = 'pure' | 'nomem' | 'readonly' | 'preserves_flags' | 'noreturn' | 'nostack' | 'att_syntax' | 'raw' | 'may_unwind' // options := "options(" option *("," option) [","] ")" -AsmOptions = 'options' '(' (AsmOption (',' AsmOption)*) ','? ')' +AsmOptions = Attr* 'options' '(' (AsmOption (',' AsmOption)*) ','? ')' AsmLabel = 'label' BlockExpr AsmSym = 'sym' Path AsmConst = 'const' Expr // operand := reg_operand / clobber_abi / options AsmOperand = AsmRegOperand | AsmLabel | AsmSym | AsmConst -AsmOperandNamed = (Name '=')? AsmOperand +AsmOperandNamed = Attr* (Name '=')? AsmOperand AsmPiece = AsmOperandNamed | AsmClobberAbi | AsmOptions FormatArgsExpr = diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index ac1cddf74c..e0992ab9cf 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -59,6 +59,7 @@ impl ArrayType { pub struct AsmClobberAbi { pub(crate) syntax: SyntaxNode, } +impl ast::HasAttrs for AsmClobberAbi {} impl AsmClobberAbi { #[inline] pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } @@ -150,6 +151,7 @@ impl AsmOperandExpr { pub struct AsmOperandNamed { pub(crate) syntax: SyntaxNode, } +impl ast::HasAttrs for AsmOperandNamed {} impl ast::HasName for AsmOperandNamed {} impl AsmOperandNamed { #[inline] @@ -193,6 +195,7 @@ impl AsmOption { pub struct AsmOptions { pub(crate) syntax: SyntaxNode, } +impl ast::HasAttrs for AsmOptions {} impl AsmOptions { #[inline] pub fn asm_options(&self) -> AstChildren<AsmOption> { support::children(&self.syntax) } @@ -2193,6 +2196,7 @@ pub enum AsmPiece { AsmOperandNamed(AsmOperandNamed), AsmOptions(AsmOptions), } +impl ast::HasAttrs for AsmPiece {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AssocItem { @@ -9096,7 +9100,10 @@ impl AstNode for AnyHasAttrs { matches!( kind, ARRAY_EXPR + | ASM_CLOBBER_ABI | ASM_EXPR + | ASM_OPERAND_NAMED + | ASM_OPTIONS | ASSOC_ITEM_LIST | AWAIT_EXPR | BECOME_EXPR @@ -9194,10 +9201,22 @@ impl From<ArrayExpr> for AnyHasAttrs { #[inline] fn from(node: ArrayExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } } +impl From<AsmClobberAbi> for AnyHasAttrs { + #[inline] + fn from(node: AsmClobberAbi) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} impl From<AsmExpr> for AnyHasAttrs { #[inline] fn from(node: AsmExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } } +impl From<AsmOperandNamed> for AnyHasAttrs { + #[inline] + fn from(node: AsmOperandNamed) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From<AsmOptions> for AnyHasAttrs { + #[inline] + fn from(node: AsmOptions) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} impl From<AssocItemList> for AnyHasAttrs { #[inline] fn from(node: AssocItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } |