Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22675 from ChayimFriedman2/cfg-inside-macro-arg
fix: Handle more cases of cfgs in expr store lowering
Shoyu Vanilla (Flint) 11 days ago
parent 8327d55 · parent 433f90e · commit 3d2cdae
-rw-r--r--crates/hir-def/src/expr_store/lower.rs20
-rw-r--r--crates/hir-def/src/expr_store/lower/asm.rs4
-rw-r--r--crates/hir-def/src/expr_store/tests/body.rs45
-rw-r--r--crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs17
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs4
-rw-r--r--crates/parser/test_data/generated/runner.rs4
-rw-r--r--crates/parser/test_data/parser/inline/ok/asm_piece_attr.rast29
-rw-r--r--crates/parser/test_data/parser/inline/ok/asm_piece_attr.rs1
-rw-r--r--crates/syntax/rust.ungram6
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs19
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(&param) {
+ 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 } }