diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll
index e67fb05485f5..5814493c3891 100644
--- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll
+++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll
@@ -8,6 +8,7 @@
private import rust
private import codeql.rust.internal.PathResolution
private import Type
+private import TypeAbstraction
private import TypeMention
private import TypeInference
private import FunctionType
diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll
index 8a72c967867d..e32578656195 100644
--- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll
+++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll
@@ -1,8 +1,9 @@
private import rust
private import codeql.rust.internal.PathResolution
-private import TypeInference
private import Type
+private import TypeAbstraction
private import TypeMention
+private import TypeInference
private newtype TFunctionPosition =
TArgumentFunctionPosition(ArgumentPosition pos) or
diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/Type.qll b/rust/ql/lib/codeql/rust/internal/typeinference/Type.qll
index acf20905b6a5..9a31782caf22 100644
--- a/rust/ql/lib/codeql/rust/internal/typeinference/Type.qll
+++ b/rust/ql/lib/codeql/rust/internal/typeinference/Type.qll
@@ -569,58 +569,6 @@ class ImplTraitTypeTypeParameter extends ImplTraitType, TypeParameter {
override TypeParameter getPositionalTypeParameter(int i) { none() }
}
-/**
- * A type abstraction. I.e., a place in the program where type variables are
- * introduced.
- *
- * Example:
- * ```rust
- * impl Foo { }
- * // ^^^^^^ a type abstraction
- * ```
- */
-abstract class TypeAbstraction extends AstNode {
- abstract TypeParameter getATypeParameter();
-}
-
-final class ImplTypeAbstraction extends TypeAbstraction, Impl {
- override TypeParamTypeParameter getATypeParameter() {
- result.getTypeParam() = this.getGenericParamList().getATypeParam()
- }
-}
-
-final class DynTypeAbstraction extends TypeAbstraction, DynTraitTypeRepr {
- override TypeParameter getATypeParameter() {
- result = any(DynTraitTypeParameter tp | tp.getTrait() = this.getTrait()).getTraitTypeParameter()
- }
-}
-
-final class TraitTypeAbstraction extends TypeAbstraction, Trait {
- override TypeParameter getATypeParameter() {
- result.(TypeParamTypeParameter).getTypeParam() = this.getGenericParamList().getATypeParam()
- or
- result.(AssociatedTypeTypeParameter).getTrait() = this
- or
- result.(SelfTypeParameter).getTrait() = this
- }
-}
-
-final class TypeBoundTypeAbstraction extends TypeAbstraction, TypeBound {
- override TypeParameter getATypeParameter() { none() }
-}
-
-final class SelfTypeBoundTypeAbstraction extends TypeAbstraction, Name {
- SelfTypeBoundTypeAbstraction() { any(TraitTypeAbstraction trait).getName() = this }
-
- override TypeParameter getATypeParameter() { none() }
-}
-
-final class ImplTraitTypeReprAbstraction extends TypeAbstraction, ImplTraitTypeRepr {
- override TypeParameter getATypeParameter() {
- implTraitTypeParam(this, _, result.(TypeParamTypeParameter).getTypeParam())
- }
-}
-
/**
* Holds if `t` is a valid complex [`self` root type][1].
*
diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeAbstraction.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeAbstraction.qll
new file mode 100644
index 000000000000..1f9dd0b44b07
--- /dev/null
+++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeAbstraction.qll
@@ -0,0 +1,77 @@
+private import rust
+private import codeql.rust.elements.internal.generated.Raw
+private import codeql.rust.elements.internal.generated.Synth
+private import Type
+
+/**
+ * A type abstraction. I.e., a place in the program where type variables are
+ * introduced.
+ *
+ * Example:
+ * ```rust
+ * impl Foo { }
+ * // ^^^^^^ a type abstraction
+ * ```
+ */
+abstract class TypeAbstraction extends AstNode {
+ abstract TypeParameter getATypeParameter();
+}
+
+final class ImplTypeAbstraction extends TypeAbstraction, Impl {
+ override TypeParamTypeParameter getATypeParameter() {
+ result.getTypeParam() = this.getGenericParamList().getATypeParam()
+ }
+}
+
+private predicate idDynTraitTypeRepr(Raw::DynTraitTypeRepr x, Raw::DynTraitTypeRepr y) { x = y }
+
+private predicate idOfDynTraitTypeRepr(Raw::DynTraitTypeRepr x, int y) =
+ equivalenceRelation(idDynTraitTypeRepr/2)(x, y)
+
+private int idOfDynTraitTypeRepr(DynTraitTypeRepr node) {
+ idOfDynTraitTypeRepr(Synth::convertAstNodeToRaw(node), result)
+}
+
+/** Holds if `dt` is the (arbitrarily chosen) canonical dyn trait type abstraction for `trait`. */
+private predicate canonicalDynTraitTypeAbstraction(DynTraitTypeRepr dt, Trait trait) {
+ dt = min(DynTraitTypeRepr d | d.getTrait() = trait | d order by idOfDynTraitTypeRepr(d))
+}
+
+final class DynTypeAbstraction extends TypeAbstraction, DynTraitTypeRepr {
+ DynTypeAbstraction() {
+ // We pick a "canonical" `dyn Trait` in order to avoid including multiple
+ // entries in `conditionSatisfiesConstraint` with the exact same effect when
+ // `dyn Trait` occurs multiple times for the same trait.
+ canonicalDynTraitTypeAbstraction(this, this.getTrait())
+ }
+
+ override TypeParameter getATypeParameter() {
+ result = any(DynTraitTypeParameter tp | tp.getTrait() = this.getTrait()).getTraitTypeParameter()
+ }
+}
+
+final class TraitTypeAbstraction extends TypeAbstraction, Trait {
+ override TypeParameter getATypeParameter() {
+ result.(TypeParamTypeParameter).getTypeParam() = this.getGenericParamList().getATypeParam()
+ or
+ result.(AssociatedTypeTypeParameter).getTrait() = this
+ or
+ result.(SelfTypeParameter).getTrait() = this
+ }
+}
+
+final class TypeBoundTypeAbstraction extends TypeAbstraction, TypeBound {
+ override TypeParameter getATypeParameter() { none() }
+}
+
+final class SelfTypeBoundTypeAbstraction extends TypeAbstraction, Name {
+ SelfTypeBoundTypeAbstraction() { any(TraitTypeAbstraction trait).getName() = this }
+
+ override TypeParameter getATypeParameter() { none() }
+}
+
+final class ImplTraitTypeReprAbstraction extends TypeAbstraction, ImplTraitTypeRepr {
+ override TypeParamTypeParameter getATypeParameter() {
+ exists(TImplTraitTypeParameter(this, result.getTypeParam()))
+ }
+}
diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll
index 3be7565ebaa1..c579a4168d8f 100644
--- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll
+++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll
@@ -5,6 +5,8 @@ private import codeql.util.Option
private import rust
private import codeql.rust.internal.PathResolution
private import Type
+private import TypeAbstraction
+private import TypeAbstraction as TA
private import Type as T
private import TypeMention
private import codeql.rust.internal.typeinference.DerefChain
@@ -37,7 +39,7 @@ private module Input1 implements InputSig1 {
class TypeParameter = T::TypeParameter;
- class TypeAbstraction = T::TypeAbstraction;
+ class TypeAbstraction = TA::TypeAbstraction;
class TypeArgumentPosition extends TTypeArgumentPosition {
int asMethodTypeArgumentPosition() { this = TMethodTypeArgumentPosition(result) }
diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll
index 840e5198f9cb..25cb28a7ac42 100644
--- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll
+++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll
@@ -4,6 +4,7 @@ private import rust
private import codeql.rust.internal.PathResolution
private import codeql.rust.frameworks.stdlib.Stdlib
private import Type
+private import TypeAbstraction
private import TypeInference
/** An AST node that may mention a type. */
@@ -563,7 +564,14 @@ class DynTypeBoundListMention extends TypeMention instanceof TypeBoundList {
private Trait trait;
DynTypeBoundListMention() {
- exists(DynTraitTypeRepr dyn | this = dyn.getTypeBoundList() and trait = dyn.getTrait())
+ exists(DynTraitTypeRepr dyn |
+ // We only need this type mention when the `dyn Trait` is a type
+ // abstraction, that is, when it's "canonical" and used in
+ // `conditionSatisfiesConstraint`.
+ dyn instanceof DynTypeAbstraction and
+ this = dyn.getTypeBoundList() and
+ trait = dyn.getTrait()
+ )
}
override Type resolveTypeAt(TypePath path) {