Skip to content

Commit ec09440

Browse files
authored
Merge pull request #21172 from paldepind/rust/dyn-abs
Rust: Avoid unnecessary constraint satisfaction
2 parents c14b869 + 6b3d863 commit ec09440

File tree

6 files changed

+94
-55
lines changed

6 files changed

+94
-55
lines changed

rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
private import rust
99
private import codeql.rust.internal.PathResolution
1010
private import Type
11+
private import TypeAbstraction
1112
private import TypeMention
1213
private import TypeInference
1314
private import FunctionType

rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
private import rust
22
private import codeql.rust.internal.PathResolution
3-
private import TypeInference
43
private import Type
4+
private import TypeAbstraction
55
private import TypeMention
6+
private import TypeInference
67

78
private newtype TFunctionPosition =
89
TArgumentFunctionPosition(ArgumentPosition pos) or

rust/ql/lib/codeql/rust/internal/typeinference/Type.qll

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -569,58 +569,6 @@ class ImplTraitTypeTypeParameter extends ImplTraitType, TypeParameter {
569569
override TypeParameter getPositionalTypeParameter(int i) { none() }
570570
}
571571

572-
/**
573-
* A type abstraction. I.e., a place in the program where type variables are
574-
* introduced.
575-
*
576-
* Example:
577-
* ```rust
578-
* impl<A, B> Foo<A, B> { }
579-
* // ^^^^^^ a type abstraction
580-
* ```
581-
*/
582-
abstract class TypeAbstraction extends AstNode {
583-
abstract TypeParameter getATypeParameter();
584-
}
585-
586-
final class ImplTypeAbstraction extends TypeAbstraction, Impl {
587-
override TypeParamTypeParameter getATypeParameter() {
588-
result.getTypeParam() = this.getGenericParamList().getATypeParam()
589-
}
590-
}
591-
592-
final class DynTypeAbstraction extends TypeAbstraction, DynTraitTypeRepr {
593-
override TypeParameter getATypeParameter() {
594-
result = any(DynTraitTypeParameter tp | tp.getTrait() = this.getTrait()).getTraitTypeParameter()
595-
}
596-
}
597-
598-
final class TraitTypeAbstraction extends TypeAbstraction, Trait {
599-
override TypeParameter getATypeParameter() {
600-
result.(TypeParamTypeParameter).getTypeParam() = this.getGenericParamList().getATypeParam()
601-
or
602-
result.(AssociatedTypeTypeParameter).getTrait() = this
603-
or
604-
result.(SelfTypeParameter).getTrait() = this
605-
}
606-
}
607-
608-
final class TypeBoundTypeAbstraction extends TypeAbstraction, TypeBound {
609-
override TypeParameter getATypeParameter() { none() }
610-
}
611-
612-
final class SelfTypeBoundTypeAbstraction extends TypeAbstraction, Name {
613-
SelfTypeBoundTypeAbstraction() { any(TraitTypeAbstraction trait).getName() = this }
614-
615-
override TypeParameter getATypeParameter() { none() }
616-
}
617-
618-
final class ImplTraitTypeReprAbstraction extends TypeAbstraction, ImplTraitTypeRepr {
619-
override TypeParameter getATypeParameter() {
620-
implTraitTypeParam(this, _, result.(TypeParamTypeParameter).getTypeParam())
621-
}
622-
}
623-
624572
/**
625573
* Holds if `t` is a valid complex [`self` root type][1].
626574
*
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
private import rust
2+
private import codeql.rust.elements.internal.generated.Raw
3+
private import codeql.rust.elements.internal.generated.Synth
4+
private import Type
5+
6+
/**
7+
* A type abstraction. I.e., a place in the program where type variables are
8+
* introduced.
9+
*
10+
* Example:
11+
* ```rust
12+
* impl<A, B> Foo<A, B> { }
13+
* // ^^^^^^ a type abstraction
14+
* ```
15+
*/
16+
abstract class TypeAbstraction extends AstNode {
17+
abstract TypeParameter getATypeParameter();
18+
}
19+
20+
final class ImplTypeAbstraction extends TypeAbstraction, Impl {
21+
override TypeParamTypeParameter getATypeParameter() {
22+
result.getTypeParam() = this.getGenericParamList().getATypeParam()
23+
}
24+
}
25+
26+
private predicate idDynTraitTypeRepr(Raw::DynTraitTypeRepr x, Raw::DynTraitTypeRepr y) { x = y }
27+
28+
private predicate idOfDynTraitTypeRepr(Raw::DynTraitTypeRepr x, int y) =
29+
equivalenceRelation(idDynTraitTypeRepr/2)(x, y)
30+
31+
private int idOfDynTraitTypeRepr(DynTraitTypeRepr node) {
32+
idOfDynTraitTypeRepr(Synth::convertAstNodeToRaw(node), result)
33+
}
34+
35+
/** Holds if `dt` is the (arbitrarily chosen) canonical dyn trait type abstraction for `trait`. */
36+
private predicate canonicalDynTraitTypeAbstraction(DynTraitTypeRepr dt) {
37+
exists(Trait trait |
38+
dt = min(DynTraitTypeRepr d | d.getTrait() = trait | d order by idOfDynTraitTypeRepr(d))
39+
)
40+
}
41+
42+
final class DynTypeAbstraction extends TypeAbstraction, DynTraitTypeRepr {
43+
DynTypeAbstraction() {
44+
// We pick a "canonical" `dyn Trait` in order to avoid including multiple
45+
// entries in `conditionSatisfiesConstraint` with the exact same effect when
46+
// `dyn Trait` occurs multiple times for the same trait.
47+
canonicalDynTraitTypeAbstraction(this)
48+
}
49+
50+
override TypeParameter getATypeParameter() {
51+
result = any(DynTraitTypeParameter tp | tp.getTrait() = this.getTrait()).getTraitTypeParameter()
52+
}
53+
}
54+
55+
final class TraitTypeAbstraction extends TypeAbstraction, Trait {
56+
override TypeParameter getATypeParameter() {
57+
result.(TypeParamTypeParameter).getTypeParam() = this.getGenericParamList().getATypeParam()
58+
or
59+
result.(AssociatedTypeTypeParameter).getTrait() = this
60+
or
61+
result.(SelfTypeParameter).getTrait() = this
62+
}
63+
}
64+
65+
final class TypeBoundTypeAbstraction extends TypeAbstraction, TypeBound {
66+
override TypeParameter getATypeParameter() { none() }
67+
}
68+
69+
final class SelfTypeBoundTypeAbstraction extends TypeAbstraction, Name {
70+
SelfTypeBoundTypeAbstraction() { any(TraitTypeAbstraction trait).getName() = this }
71+
72+
override TypeParameter getATypeParameter() { none() }
73+
}
74+
75+
final class ImplTraitTypeReprAbstraction extends TypeAbstraction, ImplTraitTypeRepr {
76+
override TypeParamTypeParameter getATypeParameter() {
77+
exists(TImplTraitTypeParameter(this, result.getTypeParam()))
78+
}
79+
}

rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ private import codeql.util.Option
55
private import rust
66
private import codeql.rust.internal.PathResolution
77
private import Type
8+
private import TypeAbstraction
9+
private import TypeAbstraction as TA
810
private import Type as T
911
private import TypeMention
1012
private import codeql.rust.internal.typeinference.DerefChain
@@ -37,7 +39,7 @@ private module Input1 implements InputSig1<Location> {
3739

3840
class TypeParameter = T::TypeParameter;
3941

40-
class TypeAbstraction = T::TypeAbstraction;
42+
class TypeAbstraction = TA::TypeAbstraction;
4143

4244
class TypeArgumentPosition extends TTypeArgumentPosition {
4345
int asMethodTypeArgumentPosition() { this = TMethodTypeArgumentPosition(result) }

rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ private import rust
44
private import codeql.rust.internal.PathResolution
55
private import codeql.rust.frameworks.stdlib.Stdlib
66
private import Type
7+
private import TypeAbstraction
78
private import TypeInference
89

910
/** An AST node that may mention a type. */
@@ -563,7 +564,14 @@ class DynTypeBoundListMention extends TypeMention instanceof TypeBoundList {
563564
private Trait trait;
564565

565566
DynTypeBoundListMention() {
566-
exists(DynTraitTypeRepr dyn | this = dyn.getTypeBoundList() and trait = dyn.getTrait())
567+
exists(DynTraitTypeRepr dyn |
568+
// We only need this type mention when the `dyn Trait` is a type
569+
// abstraction, that is, when it's "canonical" and used in
570+
// `conditionSatisfiesConstraint`.
571+
dyn instanceof DynTypeAbstraction and
572+
this = dyn.getTypeBoundList() and
573+
trait = dyn.getTrait()
574+
)
567575
}
568576

569577
override Type resolveTypeAt(TypePath path) {

0 commit comments

Comments
 (0)