Skip to content

Conversation

@paldepind
Copy link
Contributor

@paldepind paldepind commented Mar 19, 2025

This PR improves type inference for trait bounds on type parameters. For instance

fn call_first_trait_per_bound<T: ATrait<Foo, Bar>>(x: T) {
    x.method(); // <- We can now infer the type of this method call
}

where method is a trait method.

This is done by implementing getABaseTypeMention on type parameter types s.t. their bounds are base type mentions and by a small tweak to baseTypeMentionHasNonTypeParameterAt.

To explain and motivate the change to baseTypeMentionHasNonTypeParameterAt consider the C# example below.
I'm not sure if this can actually happen in C#, but we suppose that T is some type parameter in scope and we have:

forall<T> { // <- `T` is in scope, i.e., a fixed type inside this block
  // ..
  class Sub<S> : Super<T, S, Int> { }
}

Here the meaning of S and T in Super are different. T is a fixed type at the class declaration and S is a type parameter of the class and the subclassing (Rust makes this more clear as the type quantification is explicit). Hence the T should actually be handled just like Int, but baseTypeMentionHasNonTypeParameterAt which gives us the "concrete" types in the type mention, would only produce Int and not S, due to not t instanceof TypeParameter.

The above can maybe not happen in C#, but in Rust it does in the following, if we consider SecondTrait<I> to be a base type mention of T:

trait MyTrait<A> { ... }
fn call_first_trait_per_bound<I: Debug, T: MyTrait<I>>(x: T) { ... }

Here we'd like T and it's mention SecondTrait<I> to have at the path A the type I. We make this possible only excluding type parameters of the "subtype" and not all type parameters.

The PR also adds some comments and some tests for type aliases, that are unrelated to the above.

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Mar 19, 2025
@paldepind paldepind marked this pull request as ready for review March 19, 2025 15:25
Copilot AI review requested due to automatic review settings March 19, 2025 15:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR improves type inference for trait bounds on type parameters by refining the handling of base type mentions and tweaking the evaluation of type parameters in trait bounds. It also adds new test modules to validate the changes in trait bound resolution and type alias handling.

  • Introduces the module "type_parameter_bounds" with various functions to test trait method resolution.
  • Adds the module "type_aliases" to test generic and non-generic type alias inference.
Files not reviewed (3)
  • rust/ql/lib/codeql/rust/internal/Type.qll: Language not supported
  • rust/ql/lib/codeql/rust/internal/TypeInference.qll: Language not supported
  • shared/typeinference/codeql/typeinference/internal/TypeInference.qll: Language not supported
Comments suppressed due to low confidence (1)

rust/ql/test/library-tests/type-inference/main.rs:546

  • The variable 'p3' is declared twice in the same scope in function 'f'; using distinct names may clarify the test cases.
let p3: AnotherPair<S3> = PairOption::PairNone(); // type for `Snd` missing, spurious `S3` for `Fst`

Tip: Leave feedback on Copilot's review comments with the 👎 and 👍 buttons to help improve review quality. Learn more

type AnotherPair<Thr> = PairOption<S2, Thr>;

pub fn f() {
// Type can be infered from the constructor
Copy link

Copilot AI Mar 19, 2025

Choose a reason for hiding this comment

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

The word 'infered' appears in this comment; it should be spelled 'inferred'.

Suggested change
// Type can be infered from the constructor
// Type can be inferred from the constructor

Copilot uses AI. Check for mistakes.
let p1: MyPair = PairOption::PairBoth(S1, S2);
println!("{:?}", p1);

// Type can be only infered from the type alias
Copy link

Copilot AI Mar 19, 2025

Choose a reason for hiding this comment

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

The word 'infered' appears in this comment; it should be spelled 'inferred'.

Suggested change
// Type can be only infered from the type alias
// Type can be only inferred from the type alias

Copilot uses AI. Check for mistakes.
@paldepind paldepind requested a review from hvitved March 19, 2025 15:30
@paldepind paldepind added the no-change-note-required This PR does not need a change note label Mar 19, 2025
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.

Very nice! Let's wait for DCA before merging.

@paldepind
Copy link
Contributor Author

DCA is looking fine.

@paldepind paldepind merged commit 6590777 into github:main Mar 20, 2025
38 checks passed
@paldepind paldepind deleted the rust-ti-1 branch March 20, 2025 13:38
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.

2 participants