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 some toString implementations #18035

Merged
merged 18 commits into from
Nov 25, 2024
Merged

Rust: add some toString implementations #18035

merged 18 commits into from
Nov 25, 2024

Conversation

redsun82
Copy link
Contributor

@redsun82 redsun82 commented Nov 19, 2024

This sets up better toString implementations to give more meaningful test expectations and AST printing results.

This is by no means systematic and complete. Most notably almost all type representations are still missing, and some less frequent Exprs, but it should get us started.

The strategy is to make toString as close as possible to the rust syntax, but

  • skipping things like attributes altogether
  • replacing "complex" subnodes with ...

What is considered a "simple" subnode (causing it to be part of the parent toString) can be tweaked by implementing toAbbreviatedString(), which returns ... by default. Currently simple subnodes are:

  • literal expressions and patterns
  • _ expressions and patterns
  • path expressions and patterns (i.e. name references)

This means for example that

  • a call with an identifier target will have that identifier in its toString (i.e. source(...))
  • same goes for operations (i.e. x + ....) or statements (if cond {...})

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Nov 19, 2024
import codeql.rust.elements.Item
import codeql.rust.elements.ItemList
import codeql.rust.elements.Label
import codeql.rust.elements.LabelableExpr

Check warning

Code scanning / CodeQL

Redundant import Warning

Redundant import, the module is already imported inside
codeql.rust.elements.BlockExpr
.
Redundant import, the module is already imported inside
codeql.rust.elements.LoopingExpr
.
@@ -74,6 +75,7 @@
import codeql.rust.elements.LiteralPat
import codeql.rust.elements.Locatable
import codeql.rust.elements.LoopExpr
import codeql.rust.elements.LoopingExpr

Check warning

Code scanning / CodeQL

Redundant import Warning

Redundant import, the module is already imported inside
codeql.rust.elements.ForExpr
.
Redundant import, the module is already imported inside
codeql.rust.elements.LoopExpr
.
Redundant import, the module is already imported inside
codeql.rust.elements.WhileExpr
.

private import internal.LoopingExprImpl
import codeql.rust.elements.BlockExpr
import codeql.rust.elements.LabelableExpr

Check warning

Code scanning / CodeQL

Redundant import Warning

Redundant import, the module is already imported inside
codeql.rust.elements.BlockExpr
.
@redsun82 redsun82 marked this pull request as ready for review November 20, 2024 16:00
@@ -27,5 +27,7 @@ module Impl {
*/
class LiteralExpr extends Generated::LiteralExpr {
override string toString() { result = this.getTextValue() }

override string toAbbreviatedString() { result = this.getTextValue() }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now thought we might want to trim long literals here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

| variables.rs:332:9:332:9 | v | variables.rs:332:13:332:41 | RefExpr |
| variables.rs:155:9:155:10 | p2 | variables.rs:155:14:155:37 | Point {...} |
| variables.rs:169:9:169:11 | msg | variables.rs:169:15:169:38 | Message::Hello {...} |
| variables.rs:189:9:189:14 | either | variables.rs:189:18:189:33 | Either::Left(...) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm probably not the right person to review the extractor changes right now but I will say this: these look good, much better than before.

Copy link
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for taking on this task! My main concern is that ideally toString should not be recursive, since (a) it takes longer to evaluate, (b) the DIL becomes more complex, and (c) it prevents magic sets optimizations.

@@ -102,5 +103,15 @@ module Impl {
isLabelled(result, label)
)
}

override string toString() { result = concat(int i | | this.toStringPart(i), " " order by i) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May as well use strictconcat.

class CastExpr extends Generated::CastExpr { }
class CastExpr extends Generated::CastExpr {
override string toString() {
result = this.getExpr().toAbbreviatedString() + " as " + this.getTy().toString()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid, if possible, to make toString recursive. Could we instead have a predicate, getName, on TypeRef?

private string toStringPart(int index) {
index = 0 and result = "continue"
or
index = 1 and result = this.getLifetime().toString()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, better if we can avoid recursion.

/**
* A Enum. For example:
* ```rust
* todo!()
* ```
*/
class Enum extends Generated::Enum { }
class Enum extends Generated::Enum {
override string toString() { result = "enum " + this.getName().toString() }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getText instead of toString.

override string toString() {
exists(string abbr, string name |
abbr = this.getExpr().toAbbreviatedString() and
name = this.getNameRef().toString() and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, better if we can avoid recursion.

override string toString() { result = concat(int i | | this.toStringPart(i) order by i) }

private string toStringPart(int index) {
index = 0 and result = this.getNameRef().toString()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion.

@@ -21,5 +21,7 @@ module Impl {
* Foo { .. } = second;
* ```
*/
class RecordExpr extends Generated::RecordExpr { }
class RecordExpr extends Generated::RecordExpr {
override string toString() { result = this.getPath().toString() + " {...}" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion.

@@ -21,5 +21,7 @@ module Impl {
* }
* ```
*/
class RecordPat extends Generated::RecordPat { }
class RecordPat extends Generated::RecordPat {
override string toString() { result = this.getPath().toString() + " {...}" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion.

@@ -24,5 +24,7 @@ module Impl {
* pub trait Foo<T: Frobinizable> where T::Frobinator: Eq {}
* ```
*/
class Trait extends Generated::Trait { }
class Trait extends Generated::Trait {
override string toString() { result = "trait " + this.getName() }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion.

/**
* A Union. For example:
* ```rust
* todo!()
* ```
*/
class Union extends Generated::Union { }
class Union extends Generated::Union {
override string toString() { result = "union " + this.getName().toString() }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursion.

Copy link
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on making toString non-recursive, thanks!

@hvitved hvitved merged commit 4b0b038 into main Nov 25, 2024
15 checks passed
@hvitved hvitved deleted the redsun82/rust-str branch November 25, 2024 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants