From a11693268ba01ba2120dc53dd4237ed9f8ccaeea Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Fri, 16 Jan 2026 10:36:24 +0100 Subject: [PATCH] Rust: Avoid duplicated entries in `conditionSatisfiesConstraint` for dyn trait types --- .../typeinference/TypeAbstraction.qll | 21 +++++++++++++++++++ .../internal/typeinference/TypeMention.qll | 10 ++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeAbstraction.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeAbstraction.qll index 6a9dba92b83..1f9dd0b44b0 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeAbstraction.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeAbstraction.qll @@ -23,7 +23,28 @@ final class ImplTypeAbstraction extends TypeAbstraction, Impl { } } +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() } diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll index 840e5198f9c..25cb28a7ac4 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) {