Skip to content

Rust: Add inline expectations test for type inference #19198

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

Merged
merged 4 commits into from
Apr 3, 2025

Conversation

paldepind
Copy link
Contributor

@paldepind paldepind commented Apr 2, 2025

Adds inline expectations tests for type inference.

The annotations for resolved method calls and field expressions are pretty straightforward and the annotations now subsume what we had in the expected file before.

I've also added annotations for inferred types. We obviously don't want to annotate every single expression, so these annotations are optional and can be used in important places only. These annotations depend on stringifying AST nodes which can be a bit annoying, but I don't think it's too bad is we only use them sparingly and can write the tests with that in mind.

Let's merge at least #19146 before this.

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Apr 2, 2025
@paldepind paldepind force-pushed the rust-ti-inline-expectations branch from 1eca118 to 5c08cd6 Compare April 2, 2025 12:45
@paldepind paldepind marked this pull request as ready for review April 2, 2025 13:45
@paldepind paldepind requested a review from hvitved April 2, 2025 13:45
if this.getArgList().getNumberOfArgs() = 0
then parenthesis = "()"
else parenthesis = "(...)"
) and
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would be better to implement this on ArgList, but that might cause more changes so I'm leaving that for a follow up PR.

@paldepind paldepind force-pushed the rust-ti-inline-expectations branch from 5c08cd6 to 715765a Compare April 3, 2025 06:47
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 think ideally this would have been two PRs, one for the inline expecatation tests change, and one of the changes to comment and type toStringss that cause a lot of noisy changes in the tests. Splitting it into different commits would have helped. It probably isn't worth doing retroactively though.

That aside, the use of inline expectations is an improvement that will pay off if we're expecting a lot of future changes to this test. 👍

}

fn generic_field_access() {
// Explicit type argument
let x = GenericThing::<S> { a: S };
println!("{:?}", x.a);
let x = GenericThing::<S> { a: S }; // $ type=x:A.S
Copy link
Contributor

Choose a reason for hiding this comment

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

What does this annotation mean exactly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This means that x has a type which at parameter position A contains S. In this case x has the type GenericThing<S> and GenericThing has a type parameter called A, hence x has S at A. For this line we could also add $ type=x:GenericThing since the "root" of x's type is GenericThing.

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.

Can I ask you to (force push) a change that moves all ToString changes into a separate commit before continuing my review, please?

then parenthesis = "()"
else parenthesis = "(...)"
) and
result = base + separator + this.getIdentifier().toStringImpl() + parenthesis
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be better to use the toStringPart pattern here instead, to avoid computing intermediate strings

@@ -43,10 +43,15 @@ module Impl {
}

override string toStringImpl() {
Copy link
Contributor

Choose a reason for hiding this comment

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

It would have been nice to have all toString changes (including changes in .expected files) in a separate commit.

@paldepind paldepind force-pushed the rust-ti-inline-expectations branch from 715765a to d5d61dd Compare April 3, 2025 10:49
@paldepind
Copy link
Contributor Author

Can I ask you to (force push) a change that moves all ToString changes into a separate commit before continuing my review, please?

Done, now split in two commits :)

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.

LGTM, minor suggestions

@@ -9,6 +9,6 @@ trait T1<T>: T2<S<T>> {

trait T2<T>: T1<S<T>> {
fn bar(self) {
self.foo()
self.foo() // $ method=foo
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should change this to using canonical paths, once that PR lands, because the comment as-is doesn't really tell us anything about the target.

Copy link
Contributor Author

@paldepind paldepind Apr 3, 2025

Choose a reason for hiding this comment

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

Yes, that is a good idea if they're not too cumbersome to write.

But this also works reasonably well. We only use just the name in the cases where there's a single method of a given name in scope, and then the method resolution would have to do something very wrong to find another method with the same name.

println!("{:?}", x1);

let mut x2 = MyOption::new();
x2.set(S);
x2.set(S); // $ method=MyOption::set
println!("{:?}", x2);

let mut x3 = MyOption::new(); // missing type `S` from `MyOption<S>` (but can resolve `MyTrait<S>`)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this comment be updated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question. I left this in place because the x3 is stringified as "mut x3". I think it might make more sense to just print it as "x3" and I'd prefer to not write too many "unstable" stringifications in the annotations.

f.getPrecedingComment().getCommentText() = value
or
not exists(f.getPrecedingComment()) and
value = f.getName().getText()
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps add a TODO comment to use canonical name instead (if it exists)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done 👍

@paldepind paldepind merged commit 04d37c3 into github:main Apr 3, 2025
17 checks passed
@paldepind paldepind deleted the rust-ti-inline-expectations branch April 3, 2025 13:20
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.

3 participants