-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust: add macro expansion to the extractor #17659
Conversation
c2f9557
to
3286ec7
Compare
@@ -5,6 +5,7 @@ | |||
|
|||
private import internal.MacroCallImpl | |||
import codeql.rust.elements.AssocItem | |||
import codeql.rust.elements.AstNode |
Check warning
Code scanning / CodeQL
Redundant import Warning
codeql.rust.elements.AssocItem
Redundant import, the module is already imported inside
codeql.rust.elements.Attr
Redundant import, the module is already imported inside
codeql.rust.elements.ExternItem
Redundant import, the module is already imported inside
codeql.rust.elements.Path
Redundant import, the module is already imported inside
codeql.rust.elements.TokenTree
*/ | ||
|
||
private import internal.MacroStmtsImpl | ||
import codeql.rust.elements.AstNode |
Check warning
Code scanning / CodeQL
Redundant import Warning
codeql.rust.elements.Expr
Redundant import, the module is already imported inside
codeql.rust.elements.Stmt
@@ -7,6 +7,7 @@ | |||
private import codeql.rust.elements.internal.generated.Synth | |||
private import codeql.rust.elements.internal.generated.Raw | |||
import codeql.rust.elements.internal.AssocItemImpl::Impl as AssocItemImpl | |||
import codeql.rust.elements.AstNode |
Check warning
Code scanning / CodeQL
Redundant import Warning generated
codeql.rust.elements.Attr
Redundant import, the module is already imported inside
codeql.rust.elements.Path
Redundant import, the module is already imported inside
codeql.rust.elements.TokenTree
8bd6bee
to
a86d676
Compare
This avoids problems with files containing invalid utf-8 data, which may cause panic's like: ``` thread 'main' panicked at external/rules_rust~~_crate~ql~~r~r__ra_ap_salsa-0.0.232/src/input.rs:91:32: no value set for CompressedFileTextQuery(FileId(2429)) stack backtrace: 0: rust_begin_unwind at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:665:5 1: core::panicking::panic_fmt at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:74:14 2: <salsa::input::InputStorage<Q> as salsa::plumbing::QueryStorageOps<Q>>::fetch 3: <DB as ra_ap_base_db::SourceDatabase>::compressed_file_text::__shim 4: <ra_ap_base_db::FileTextQuery as salsa::plumbing::QueryFunction>::execute 5: salsa::Cycle::catch 6: salsa::derived_lru::slot::Slot<Q,MP>::execute 7: salsa::derived_lru::slot::Slot<Q,MP>::read 8: <salsa::derived_lru::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::fetch 9: <DB as ra_ap_base_db::SourceDatabase>::file_text::__shim 10: <DB as ra_ap_base_db::SourceDatabase>::file_text 11: <ra_ap_base_db::ParseQuery as salsa::plumbing::QueryFunction>::execute 12: salsa::Cycle::catch 13: salsa::derived_lru::slot::Slot<Q,MP>::execute 14: salsa::derived_lru::slot::Slot<Q,MP>::read 15: <salsa::derived_lru::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::fetch 16: <DB as ra_ap_base_db::SourceDatabase>::parse::__shim 17: <DB as ra_ap_base_db::SourceDatabase>::parse 18: ra_ap_hir::semantics::SemanticsImpl::parse 19: single_arch_extractor::main ```
The locations are "clipped" to the ranges of the parent node of a token, and the root node of the parse tree for errors.
This way we have only one "project" database in-memory at a time. This should avoid running out of memory when analyzing large mono-repos.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't reviewed this (at this stage), just want to chip in and say that the changes to query-tests
look fantastic!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey, thanks for the tremendous effort here, much appreciated!
Apart from a couple of minor nits I'm slightly worried by the file-to-workspace loading strategy...
rust/extractor/src/translate/base.rs
Outdated
pub trap: TrapFile, | ||
label: trap::Label, | ||
line_index: LineIndex, | ||
semi: Option<Semantics<'a, RootDatabase>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why semi
? maybe semantics
, or sema
? The semi
prefix usually means "half" or "partial"
rust/extractor/src/rust_analyzer.rs
Outdated
while let Some(parent) = p.parent() { | ||
p = parent; | ||
if let Some((vfs, db)) = self.workspace.get(parent) { | ||
if let Some(file_id) = Utf8PathBuf::from_path_buf(path.to_path_buf()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see two problems here:
- I suspect this algorithm can be broken by using a relative path attribute: theoretically with that attribute a source file can be pulled in in a workspace without being beneath the workspace directory. It's dirty and might be rare, but Rob did tell us to beware of what dirty things Rust users have come up with 😅
- if a file ends up in multiple workspaces with different cfg values, we would probably only extract one version of it. Although this case we might want to come back later to, as it's a tricky one which probably requires careful trap keying or maybe using linkage awareness.
In any case I wonder if we shouldn't rather:
- iterate through all source files in the workspaces, ticking them off from the input files and outputting a semantic extraction of them
- after doing that, go through the files that were not ticked off and output a non-semantic extraction of those
pub(crate) fn extract_macro_call_expanded( | ||
&mut self, | ||
mcall: &ast::MacroCall, | ||
label: Label<generated::MacroCall>, | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function is a mouthful... could we maybe split it into smaller ones?
8847599
to
59be922
Compare
also, I think it'd be worth adding to the existing integration tests a query for diagnostics, which should show how the different loading strategy (with semantics and without) applies to files, thanks to the warning when semantics are not available (in one of the integration tests there is a file not in the workspace). |
rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll
Outdated
Show resolved
Hide resolved
59be922
to
6ade2a8
Compare
rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll
Fixed
Show resolved
Hide resolved
|
||
override predicate succ(AstNode pred, AstNode succ, Completion c) { none() } | ||
|
||
override predicate propagatesAbnormal(AstNode child) { none() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
child = super.getExpanded()
.
@@ -391,8 +403,40 @@ class ForExprTree extends LoopingExprTree instanceof ForExpr { | |||
} | |||
} | |||
|
|||
// TODO: replace with expanded macro once the extractor supports it | |||
class MacroExprTree extends LeafTree, MacroExpr { } | |||
class MacroCallTree extends ControlFlowTree instanceof MacroCall { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't this simply be
class MacroCallTree extends StandardPostOrderTree, MacroCall {
override AstNode getChildNode(int i) { i = 0 and result = this.getExpanded() }
}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MacroCalls can also be statements and patterns which are pre-order. By dropping the MacroCall
node altogether it "inherits" the order of the expanded tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing my comments. I agree that the more far-reaching comment about the loading strategy can be addressed later as a follow-up.
6eb0972
to
fc298b2
Compare
@@ -1,10 +1,7 @@ | |||
| main.rs:25:9:25:9 | a | Variable is not used. | | |||
| main.rs:90:13:90:13 | d | Variable is not used. | | |||
| main.rs:114:9:114:9 | k | Variable is not used. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SPURIOUS
comments should be removed in main.rs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@redsun82 let me know if you're already on this, I have a bit of follow-up to do after this PR anyway so I could fix this as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps the comments should be converted to inline test expecations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the fix: #17744
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And there's already an issue for converting them into inline expectations, but that's waiting on having inline expectations for query tests. Is that work finished yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, not finished yet.
@@ -661,7 +704,9 @@ module PatternTrees { | |||
|
|||
class LiteralPatTree extends LeafTree, LiteralPat { } | |||
|
|||
class MacroPatTree extends LeafTree, MacroPat { } // todo | |||
class MacroPatTree extends PreOrderPatTree, MacroPat { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a case for MatroPat
in isIrrefutablePattern
and condPropagateExpr
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this look good for isIrrefutablePattern
? #17746
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't condPropagateExpr
be covered already, MacroPat
because is defined as a PreOrderPatTree
. Or does it need something else?
No description provided.