Skip to content

Conversation

@paldepind
Copy link
Contributor

@paldepind paldepind commented Jan 14, 2026

This PR adds support for specifying associated type from a supertrait in a trait bound that uses a subtrait.

The Problem

Suppose we have a supertrait and a subtrait as follows:

trait GetSet {
    type Output;
    // ..
}
trait AnotherGet: GetSet {
    type AnotherOutput;
    // ...
}

Now trait bounds that use AnotherGet can mention the Output associated type like this

SomeTP: AnotherGet<Output = SomeType, AnotherOutput = SomeOtherType>

Additionally, dyn types for AnotherGet have to specify Output from the supertrait:

&dyn<AnotherGet<Output = Foo, AnotherOutput = Bar>

The Solution

To support the above, this PR makes associated types in supertraits (which are already turned into type parameters of the supertrait) induce type parameters in any subtraits (transitively). This seemed like the simplest implementation, given how we currently treat associated types as type parameters.

So in the above example, the trait AnotherGet gets a type parameter for Output, written as Output[AnotherGet]. For a bound AnotherGet<Output = ..> the equality will instantiate Output[AnotherGet].

The new type parameters are accounted for in the sub-trait "inheritance" relation such that type parameters that correspond to the same associated type are matched up to each other.

Dyn trait types also receive the new type parameters in the same way as traits, such that
dyn Foo still has a set of type parameters that correspond 1-to-1 to those of Foo.

About the change to the consistency check:
Previously, for something like

fn param_add<T: Add>(a: T, b: T) -> T::Output {

the path T::Output would in resolvePathTypeAt resolve to the type alias for Output but would then be filtered away inside PathTypeMention::resolvePathTypeAt at the check that prevents type parameters from escaping their scope.

Now resolvePathTypeAt won't resolve to anything for T::Output since T doesn't resolve to a trait. This means that the current exemption doesn't apply and thus I added an additional one.

Future Work

This should enable us to improve type inference for closures as well as support the Fn and FnMut traits (which now inherits the Result associated type from their FnOnce supertrait).

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Jan 14, 2026
@paldepind paldepind force-pushed the rust/associated-types branch from 401495b to a19ad5e Compare January 14, 2026 13:44
override Location getLocation() { result = typeAlias.getLocation() }
}

/** Gets the associated type type parameter corresponding directly to `typeAlias`. */

Check warning

Code scanning / CodeQL

Comment has repeated word Warning

The comment repeats type.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, but it's the "associated-type" "type-parameter".

result.isDirect() and result.getTypeAlias() = typeAlias
}

/** Gets the dyn type type parameter corresponding directly to `typeAlias`. */

Check warning

Code scanning / CodeQL

Comment has repeated word Warning

The comment repeats type.
@paldepind paldepind force-pushed the rust/associated-types branch from 2215712 to 8cbe17a Compare January 15, 2026 06:23
@paldepind paldepind marked this pull request as ready for review January 15, 2026 08:16
@paldepind paldepind requested a review from a team as a code owner January 15, 2026 08:16
Copilot AI review requested due to automatic review settings January 15, 2026 08:16
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 adds support for associated types from supertraits being inherited by subtraits and dyn traits as type parameters. The implementation treats these inherited associated types as type parameters to enable trait bounds and dyn types to specify values for associated types defined in supertraits.

Changes:

  • Modified TAssociatedTypeTypeParameter and TDynTraitTypeParameter to include the owning trait as a parameter
  • Added logic to propagate associated type parameters from supertraits to subtraits
  • Updated type parameter sorting to account for the new trait parameter
  • Reorganized test code by extracting associated type tests into a separate file
  • Updated consistency checks to handle the new type parameter structure

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
rust/ql/lib/codeql/rust/internal/typeinference/Type.qll Modified type parameter constructors to include trait parameter, added helper predicates for retrieving associated type parameters
rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll Updated type parameter resolution logic to handle inherited associated types from supertraits
rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll Updated type parameter ID calculation to include trait IDs for proper ordering
rust/ql/lib/codeql/rust/internal/typeinference/TypeInferenceConsistency.qll Added check to ensure NonAliasPathTypeMention doesn't resolve to TypeAlias
rust/ql/lib/codeql/rust/elements/internal/TraitImpl.qll Added getSupertrait() method to navigate trait hierarchy
rust/ql/test/library-tests/type-inference/main.rs Removed associated type tests and added module reference to new file
rust/ql/test/library-tests/type-inference/associated_types.rs New comprehensive test file for associated type scenarios
rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected Updated line number reference due to code reorganization

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


override ItemNode getDeclaringItem() { result = this.getTrait() }
/**
* Holds if this associated type type parameter corresponds directly its
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

Corrected grammar: 'corresponds directly its trait' should be 'corresponds directly to its trait'.

Suggested change
* Holds if this associated type type parameter corresponds directly its
* Holds if this associated type type parameter corresponds directly to its

Copilot uses AI. Check for mistakes.
name = result.getName().getText()
}

pragma[nomagic]
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

The method getAssocTypeArg is renamed from returning TypeRepr to returning TypeMention, but the name still suggests it returns a type argument. Consider renaming to getAssocTypeMention or updating the documentation to clarify the return type change.

Suggested change
pragma[nomagic]
pragma[nomagic]
/**
* Gets the associated type argument with the given `name` as a type mention.
*/

Copilot uses AI. Check for mistakes.
@hvitved
Copy link
Contributor

hvitved commented Jan 15, 2026

To support the above, this PR makes associated types in supertraits (which are already turned into type parameters of the supertrait) induce type parameters in any subtraits (transitively). This seemed like the simplest implementation, given how we currently treat associated types as type parameters.

This is also how I envisioned it should be modeled 👍

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.

2 participants