Skip to content
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

Merged
merged 25 commits into from
Oct 11, 2024
Merged

Rust: add macro expansion to the extractor #17659

merged 25 commits into from
Oct 11, 2024

Conversation

aibaars
Copy link
Contributor

@aibaars aibaars commented Oct 3, 2024

No description provided.

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Oct 3, 2024
@aibaars aibaars force-pushed the aibaars/rust-macros branch from c2f9557 to 3286ec7 Compare October 3, 2024 15:23
@aibaars aibaars added the no-change-note-required This PR does not need a change note label Oct 3, 2024
@@ -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

Redundant import, the module is already imported inside
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

Redundant import, the module is already imported inside
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

Redundant import, the module is already imported inside
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
.
@aibaars aibaars force-pushed the aibaars/rust-macros branch 15 times, most recently from 8bd6bee to a86d676 Compare October 8, 2024 15:06
@aibaars aibaars marked this pull request as ready for review October 9, 2024 09:28
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.
Copy link
Contributor

@geoffw0 geoffw0 left a 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!

Copy link
Contributor

@redsun82 redsun82 left a 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...

pub trap: TrapFile,
label: trap::Label,
line_index: LineIndex,
semi: Option<Semantics<'a, RootDatabase>>,
Copy link
Contributor

@redsun82 redsun82 Oct 10, 2024

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 Show resolved Hide resolved
Comment on lines 65 to 68
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())
Copy link
Contributor

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

Comment on lines +188 to +299
pub(crate) fn extract_macro_call_expanded(
&mut self,
mcall: &ast::MacroCall,
label: Label<generated::MacroCall>,
) {
Copy link
Contributor

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?

@aibaars aibaars force-pushed the aibaars/rust-macros branch from 8847599 to 59be922 Compare October 10, 2024 20:10
@redsun82
Copy link
Contributor

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).

@aibaars aibaars force-pushed the aibaars/rust-macros branch from 59be922 to 6ade2a8 Compare October 11, 2024 11:13

override predicate succ(AstNode pred, AstNode succ, Completion c) { none() }

override predicate propagatesAbnormal(AstNode child) { none() }
Copy link
Contributor

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 {
Copy link
Contributor

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() }
}

?

Copy link
Contributor Author

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.

redsun82
redsun82 previously approved these changes Oct 11, 2024
Copy link
Contributor

@redsun82 redsun82 left a 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.

@aibaars aibaars force-pushed the aibaars/rust-macros branch from 6eb0972 to fc298b2 Compare October 11, 2024 14:01
@redsun82 redsun82 merged commit 5b57826 into main Oct 11, 2024
14 checks passed
@redsun82 redsun82 deleted the aibaars/rust-macros branch October 11, 2024 15:29
@@ -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. |
Copy link
Contributor

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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?

Copy link
Contributor

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

Copy link
Contributor

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?

Copy link
Contributor

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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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

Copy link
Contributor Author

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-change-note-required This PR does not need a change note Rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants