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) {