Skip to content

Commit c10d899

Browse files
authored
Merge pull request #19945 from github/redsun82/fix-expansion-in-lib
Rust: fix macro expansion in library code
2 parents 2fffa9d + c70198e commit c10d899

File tree

23 files changed

+240
-70
lines changed

23 files changed

+240
-70
lines changed

rust/extractor/src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ pub struct Config {
7171
pub proc_macro_server: Option<PathBuf>,
7272
pub skip_path_resolution: bool,
7373
pub extract_dependencies_as_source: bool,
74+
pub force_library_mode: bool, // for testing purposes
7475
}
7576

7677
impl Config {

rust/extractor/src/main.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ fn main() -> anyhow::Result<()> {
293293
} else {
294294
(SourceKind::Library, ResolvePaths::No)
295295
};
296+
let (source_mode, source_resolve_paths) = if cfg.force_library_mode {
297+
(library_mode, library_resolve_paths)
298+
} else {
299+
(SourceKind::Source, resolve_paths)
300+
};
296301
let mut processed_files: HashSet<PathBuf, RandomState> =
297302
HashSet::from_iter(files.iter().cloned());
298303
for (manifest, files) in map.values().filter(|(_, files)| !files.is_empty()) {
@@ -311,12 +316,10 @@ fn main() -> anyhow::Result<()> {
311316
file,
312317
&semantics,
313318
vfs,
314-
resolve_paths,
315-
SourceKind::Source,
319+
source_resolve_paths,
320+
source_mode,
316321
),
317-
Err(reason) => {
318-
extractor.extract_without_semantics(file, SourceKind::Source, &reason)
319-
}
322+
Err(reason) => extractor.extract_without_semantics(file, source_mode, &reason),
320323
};
321324
}
322325
for (file_id, file) in vfs.iter() {

rust/extractor/src/qltest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn dump_lib() -> anyhow::Result<()> {
1919
.iter()
2020
.map(|p| p.file_stem().expect("results of glob must have a name"))
2121
.filter(|&p| !["main", "lib", "proc_macro"].map(OsStr::new).contains(&p))
22-
.map(|p| format!("mod {};", p.to_string_lossy()))
22+
.map(|p| format!("pub mod {};", p.to_string_lossy()))
2323
.join("\n");
2424
fs::write("lib.rs", lib).context("writing lib.rs")
2525
}

rust/extractor/src/translate/base.rs

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,33 +24,31 @@ use ra_ap_syntax::{
2424

2525
impl Emission<ast::Item> for Translator<'_> {
2626
fn pre_emit(&mut self, node: &ast::Item) -> Option<Label<generated::Item>> {
27-
self.prepare_item_expansion(node).map(Into::into)
27+
self.item_pre_emit(node).map(Into::into)
2828
}
2929

3030
fn post_emit(&mut self, node: &ast::Item, label: Label<generated::Item>) {
31-
self.emit_item_expansion(node, label);
31+
self.item_post_emit(node, label);
3232
}
3333
}
3434

3535
impl Emission<ast::AssocItem> for Translator<'_> {
3636
fn pre_emit(&mut self, node: &ast::AssocItem) -> Option<Label<generated::AssocItem>> {
37-
self.prepare_item_expansion(&node.clone().into())
38-
.map(Into::into)
37+
self.item_pre_emit(&node.clone().into()).map(Into::into)
3938
}
4039

4140
fn post_emit(&mut self, node: &ast::AssocItem, label: Label<generated::AssocItem>) {
42-
self.emit_item_expansion(&node.clone().into(), label.into());
41+
self.item_post_emit(&node.clone().into(), label.into());
4342
}
4443
}
4544

4645
impl Emission<ast::ExternItem> for Translator<'_> {
4746
fn pre_emit(&mut self, node: &ast::ExternItem) -> Option<Label<generated::ExternItem>> {
48-
self.prepare_item_expansion(&node.clone().into())
49-
.map(Into::into)
47+
self.item_pre_emit(&node.clone().into()).map(Into::into)
5048
}
5149

5250
fn post_emit(&mut self, node: &ast::ExternItem, label: Label<generated::ExternItem>) {
53-
self.emit_item_expansion(&node.clone().into(), label.into());
51+
self.item_post_emit(&node.clone().into(), label.into());
5452
}
5553
}
5654

@@ -849,35 +847,6 @@ impl<'a> Translator<'a> {
849847
})
850848
}
851849

852-
pub(crate) fn prepare_item_expansion(
853-
&mut self,
854-
node: &ast::Item,
855-
) -> Option<Label<generated::MacroCall>> {
856-
if self.source_kind == SourceKind::Library {
857-
// if the item expands via an attribute macro, we want to only emit the expansion
858-
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
859-
// we wrap it in a dummy MacroCall to get a single Item label that can replace
860-
// the original Item
861-
let label = self.trap.emit(generated::MacroCall {
862-
id: TrapId::Star,
863-
attrs: vec![],
864-
path: None,
865-
token_tree: None,
866-
});
867-
generated::MacroCall::emit_macro_call_expansion(
868-
label,
869-
expanded.into(),
870-
&mut self.trap.writer,
871-
);
872-
return Some(label);
873-
}
874-
}
875-
if self.is_attribute_macro_target(node) {
876-
self.macro_context_depth += 1;
877-
}
878-
None
879-
}
880-
881850
fn process_item_macro_expansion(
882851
&mut self,
883852
node: &impl ast::AstNode,
@@ -915,10 +884,6 @@ impl<'a> Translator<'a> {
915884
&mut self,
916885
node: &ast::Item,
917886
) -> Option<Label<generated::MacroItems>> {
918-
if !self.is_attribute_macro_target(node) {
919-
return None;
920-
}
921-
self.macro_context_depth -= 1;
922887
if self.macro_context_depth > 0 {
923888
// only expand the outermost attribute macro
924889
return None;
@@ -927,7 +892,49 @@ impl<'a> Translator<'a> {
927892
self.process_item_macro_expansion(node, expansion.map(|x| x.value))
928893
}
929894

930-
pub(crate) fn emit_item_expansion(&mut self, node: &ast::Item, label: Label<generated::Item>) {
895+
pub(crate) fn item_pre_emit(
896+
&mut self,
897+
node: &ast::Item,
898+
) -> Option<Label<generated::MacroCall>> {
899+
if !self.is_attribute_macro_target(node) {
900+
return None;
901+
}
902+
if self.source_kind == SourceKind::Library {
903+
// if the item expands via an attribute macro, we want to only emit the expansion
904+
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
905+
// we wrap it in a dummy MacroCall to get a single Item label that can replace
906+
// the original Item
907+
let label = self.trap.emit(generated::MacroCall {
908+
id: TrapId::Star,
909+
attrs: vec![],
910+
path: None,
911+
token_tree: None,
912+
});
913+
generated::Item::emit_attribute_macro_expansion(
914+
label.into(),
915+
expanded,
916+
&mut self.trap.writer,
917+
);
918+
self.emit_location(label, node);
919+
return Some(label);
920+
}
921+
}
922+
self.macro_context_depth += 1;
923+
None
924+
}
925+
926+
pub(crate) fn item_post_emit(&mut self, node: &ast::Item, label: Label<generated::Item>) {
927+
if !self.is_attribute_macro_target(node) {
928+
return;
929+
}
930+
// see `item_pre_emit`:
931+
// if self.is_attribute_macro_target(node), then we either exited early with `Some(label)`
932+
// and are not here, or we did self.macro_context_depth += 1
933+
assert!(
934+
self.macro_context_depth > 0,
935+
"macro_context_depth should be > 0 for an attribute macro target"
936+
);
937+
self.macro_context_depth -= 1;
931938
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
932939
generated::Item::emit_attribute_macro_expansion(label, expanded, &mut self.trap.writer);
933940
}

rust/ql/lib/codeql/rust/elements/internal/MacroCallImpl.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ module Impl {
3232
* ```
3333
*/
3434
class MacroCall extends Generated::MacroCall {
35-
override string toStringImpl() { result = this.getPath().toAbbreviatedString() + "!..." }
35+
override string toStringImpl() {
36+
if this.hasPath() then result = this.getPath().toAbbreviatedString() + "!..." else result = ""
37+
}
3638

3739
/** Gets an AST node whose location is inside the token tree belonging to this macro call. */
3840
pragma[nomagic]

rust/ql/test/TestUtils.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ predicate toBeTested(Element e) {
66
(
77
not e instanceof Locatable
88
or
9-
e.(Locatable).fromSource()
9+
exists(e.(Locatable).getFile().getRelativePath())
1010
)
1111
}
1212

rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ canonicalPath
22
| anonymous.rs:3:1:32:1 | fn canonicals | test::anonymous::canonicals |
33
| anonymous.rs:34:1:36:1 | fn other | test::anonymous::other |
44
| {EXTERNAL LOCATION} | fn trim | <core::str>::trim |
5-
| lib.rs:1:1:1:14 | mod anonymous | test::anonymous |
6-
| lib.rs:2:1:2:12 | mod regular | test::regular |
5+
| lib.rs:1:1:1:18 | mod anonymous | test::anonymous |
6+
| lib.rs:2:1:2:16 | mod regular | test::regular |
77
| regular.rs:1:1:2:18 | struct Struct | test::regular::Struct |
88
| regular.rs:2:12:2:17 | fn eq | <test::regular::Struct as core::cmp::PartialEq>::eq |
99
| regular.rs:2:12:2:17 | impl ...::Eq for Struct::<...> { ... } | <test::regular::Struct as core::cmp::Eq> |
@@ -42,8 +42,8 @@ canonicalPaths
4242
| anonymous.rs:26:5:31:5 | fn usage | None | None |
4343
| anonymous.rs:34:1:36:1 | fn other | repo::test | crate::anonymous::other |
4444
| anonymous.rs:35:5:35:23 | struct OtherStruct | None | None |
45-
| lib.rs:1:1:1:14 | mod anonymous | repo::test | crate::anonymous |
46-
| lib.rs:2:1:2:12 | mod regular | repo::test | crate::regular |
45+
| lib.rs:1:1:1:18 | mod anonymous | repo::test | crate::anonymous |
46+
| lib.rs:2:1:2:16 | mod regular | repo::test | crate::regular |
4747
| regular.rs:1:1:2:18 | struct Struct | repo::test | crate::regular::Struct |
4848
| regular.rs:2:12:2:17 | fn eq | repo::test | <crate::regular::Struct as crate::cmp::PartialEq>::eq |
4949
| regular.rs:2:12:2:17 | impl ...::Eq for Struct::<...> { ... } | None | None |

rust/ql/test/extractor-tests/canonical_path_disabled/canonical_paths.expected

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ canonicalPath
22
| anonymous.rs:6:1:35:1 | fn canonicals | test::anonymous::canonicals |
33
| anonymous.rs:37:1:39:1 | fn other | test::anonymous::other |
44
| {EXTERNAL LOCATION} | fn trim | <core::str>::trim |
5-
| lib.rs:1:1:1:14 | mod anonymous | test::anonymous |
6-
| lib.rs:2:1:2:12 | mod regular | test::regular |
5+
| lib.rs:1:1:1:18 | mod anonymous | test::anonymous |
6+
| lib.rs:2:1:2:16 | mod regular | test::regular |
77
| regular.rs:4:1:5:18 | struct Struct | test::regular::Struct |
88
| regular.rs:5:12:5:17 | fn eq | <test::regular::Struct as core::cmp::PartialEq>::eq |
99
| regular.rs:5:12:5:17 | impl ...::Eq for Struct::<...> { ... } | <test::regular::Struct as core::cmp::Eq> |
@@ -42,8 +42,8 @@ canonicalPaths
4242
| anonymous.rs:29:5:34:5 | fn usage | None | None |
4343
| anonymous.rs:37:1:39:1 | fn other | None | None |
4444
| anonymous.rs:38:5:38:23 | struct OtherStruct | None | None |
45-
| lib.rs:1:1:1:14 | mod anonymous | None | None |
46-
| lib.rs:2:1:2:12 | mod regular | None | None |
45+
| lib.rs:1:1:1:18 | mod anonymous | None | None |
46+
| lib.rs:2:1:2:16 | mod regular | None | None |
4747
| regular.rs:4:1:5:18 | struct Struct | None | None |
4848
| regular.rs:5:12:5:17 | fn eq | None | None |
4949
| regular.rs:5:12:5:17 | impl ...::Eq for Struct::<...> { ... } | None | None |
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
instances
22
| gen_module.rs:3:1:4:8 | mod foo |
33
| gen_module.rs:5:1:7:1 | mod bar |
4-
| lib.rs:1:1:1:15 | mod gen_module |
4+
| lib.rs:1:1:1:19 | mod gen_module |
55
getExtendedCanonicalPath
66
| gen_module.rs:3:1:4:8 | mod foo | crate::gen_module::foo |
77
| gen_module.rs:5:1:7:1 | mod bar | crate::gen_module::bar |
8-
| lib.rs:1:1:1:15 | mod gen_module | crate::gen_module |
8+
| lib.rs:1:1:1:19 | mod gen_module | crate::gen_module |
99
getCrateOrigin
1010
| gen_module.rs:3:1:4:8 | mod foo | repo::test |
1111
| gen_module.rs:5:1:7:1 | mod bar | repo::test |
12-
| lib.rs:1:1:1:15 | mod gen_module | repo::test |
12+
| lib.rs:1:1:1:19 | mod gen_module | repo::test |
1313
getAttributeMacroExpansion
1414
getAttr
1515
getItemList
1616
| gen_module.rs:5:1:7:1 | mod bar | gen_module.rs:5:9:7:1 | ItemList |
1717
getName
1818
| gen_module.rs:3:1:4:8 | mod foo | gen_module.rs:4:5:4:7 | foo |
1919
| gen_module.rs:5:1:7:1 | mod bar | gen_module.rs:5:5:5:7 | bar |
20-
| lib.rs:1:1:1:15 | mod gen_module | lib.rs:1:5:1:14 | gen_module |
20+
| lib.rs:1:1:1:19 | mod gen_module | lib.rs:1:9:1:18 | gen_module |
2121
getVisibility
22+
| lib.rs:1:1:1:19 | mod gen_module | lib.rs:1:1:1:3 | Visibility |
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
instances
22
| gen_name.rs:3:4:3:12 | test_name |
33
| gen_name.rs:7:9:7:11 | foo |
4-
| lib.rs:1:5:1:12 | gen_name |
4+
| lib.rs:1:9:1:16 | gen_name |
55
getText
66
| gen_name.rs:3:4:3:12 | test_name | test_name |
77
| gen_name.rs:7:9:7:11 | foo | foo |
8-
| lib.rs:1:5:1:12 | gen_name | gen_name |
8+
| lib.rs:1:9:1:16 | gen_name | gen_name |

0 commit comments

Comments
 (0)