Skip to content

Commit a116932

Browse files
committed
Rust: Avoid duplicated entries in conditionSatisfiesConstraint for dyn trait types
1 parent c0b3569 commit a116932

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,28 @@ final class ImplTypeAbstraction extends TypeAbstraction, Impl {
2323
}
2424
}
2525

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, Trait trait) {
37+
dt = min(DynTraitTypeRepr d | d.getTrait() = trait | d order by idOfDynTraitTypeRepr(d))
38+
}
39+
2640
final class DynTypeAbstraction extends TypeAbstraction, DynTraitTypeRepr {
41+
DynTypeAbstraction() {
42+
// We pick a "canonical" `dyn Trait` in order to avoid including multiple
43+
// entries in `conditionSatisfiesConstraint` with the exact same effect when
44+
// `dyn Trait` occurs multiple times for the same trait.
45+
canonicalDynTraitTypeAbstraction(this, this.getTrait())
46+
}
47+
2748
override TypeParameter getATypeParameter() {
2849
result = any(DynTraitTypeParameter tp | tp.getTrait() = this.getTrait()).getTraitTypeParameter()
2950
}

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)