From ff41917147f41cf1ae87133632b2ba17d0753f34 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 5 Mar 2026 21:22:24 +0100 Subject: [PATCH] Rust: More conservative resolution of `>` paths --- .../internal/typeinference/AssociatedType.qll | 13 +++++--- .../internal/typeinference/TypeMention.qll | 32 +++++++++++++------ .../TypeInferenceConsistency.expected | 2 -- .../type-inference/associated_types.rs | 4 +-- .../type-inference/regressions.rs | 2 +- .../type-inference/type-inference.expected | 19 ----------- 6 files changed, 33 insertions(+), 39 deletions(-) delete mode 100644 rust/ql/test/library-tests/type-inference/CONSISTENCY/TypeInferenceConsistency.expected diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/AssociatedType.qll b/rust/ql/lib/codeql/rust/internal/typeinference/AssociatedType.qll index 6bd0db33158..656fd8e7ec8 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/AssociatedType.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/AssociatedType.qll @@ -24,11 +24,14 @@ AssocType getTraitAssocType(Trait trait) { result.getTrait() = trait.getSupertra /** Holds if `path` is of the form `::name` */ pragma[nomagic] -predicate pathTypeAsTraitAssoc(Path path, TypeRepr typeRepr, Path traitPath, string name) { +predicate pathTypeAsTraitAssoc( + Path path, TypeRepr typeRepr, PathTypeRepr traitRepr, Trait trait, string name +) { exists(PathSegment segment | segment = path.getQualifier().getSegment() and typeRepr = segment.getTypeRepr() and - traitPath = segment.getTraitTypeRepr().getPath() and + traitRepr = segment.getTraitTypeRepr() and + trait = resolvePath(traitRepr.getPath()) and name = path.getText() ) } @@ -43,10 +46,10 @@ predicate tpAssociatedType(TypeParam tp, AssocType assoc, Path path) { resolvePath(path.getQualifier()) = tp and resolvePath(path) = assoc or - exists(PathTypeRepr typeRepr, Path traitPath, string name | - pathTypeAsTraitAssoc(path, typeRepr, traitPath, name) and + exists(PathTypeRepr typeRepr, TraitItemNode trait, string name | + pathTypeAsTraitAssoc(path, typeRepr, _, trait, name) and tp = resolvePath(typeRepr.getPath()) and - assoc = resolvePath(traitPath).(TraitItemNode).getAssocItem(name) + assoc = trait.getAssocItem(name) ) } diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll index ef54fe18bb9..631add42d04 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll @@ -701,7 +701,7 @@ class PreTypeMention = PreTypeMention::TypeMention; * concrete type given by `tm`. */ private predicate pathConcreteTypeAssocType( - Path path, PreTypeMention tm, Trait trait, TypeAlias alias + Path path, PreTypeMention tm, TraitItemNode trait, PreTypeMention tmTrait, TypeAlias alias ) { exists(Path qualifier | qualifier = path.getQualifier() and @@ -709,9 +709,8 @@ private predicate pathConcreteTypeAssocType( | // path of the form `::AssocType` // ^^^ tm ^^^^^^^^^ name - exists(string name, Path traitPath | - pathTypeAsTraitAssoc(path, tm, traitPath, name) and - trait = resolvePath(traitPath) and + exists(string name | + pathTypeAsTraitAssoc(path, tm, tmTrait, trait, name) and getTraitAssocType(trait, name) = alias ) or @@ -721,14 +720,15 @@ private predicate pathConcreteTypeAssocType( alias = resolvePath(path) and qualifier = impl.getASelfPath() and tm = impl.(Impl).getSelfTy() and - trait.(TraitItemNode).getAnAssocItem() = alias + trait.getAnAssocItem() = alias and + tmTrait = impl.getTraitPath() ) ) } private module PathSatisfiesConstraintInput implements SatisfiesConstraintInputSig { predicate relevantConstraint(PreTypeMention tm, Type constraint) { - pathConcreteTypeAssocType(_, tm, constraint.(TraitType).getTrait(), _) + pathConcreteTypeAssocType(_, tm, constraint.(TraitType).getTrait(), _, _) } } @@ -740,10 +740,22 @@ private module PathSatisfiesConstraint = * on a concrete type. */ private Type getPathConcreteAssocTypeAt(Path path, TypePath typePath) { - exists(PreTypeMention tm, TraitItemNode t, TypeAlias alias, TypePath path0 | - pathConcreteTypeAssocType(path, tm, t, alias) and - PathSatisfiesConstraint::satisfiesConstraintType(tm, TTrait(t), path0, result) and - path0.isCons(TAssociatedTypeTypeParameter(t, alias), typePath) + exists( + PreTypeMention tm, ImplItemNode impl, TraitItemNode trait, TraitType t, PreTypeMention tmTrait, + TypeAlias alias, TypePath path0 + | + pathConcreteTypeAssocType(path, tm, trait, tmTrait, alias) and + t = TTrait(trait) and + PathSatisfiesConstraint::satisfiesConstraintTypeThrough(tm, impl, t, path0, result) and + path0.isCons(TAssociatedTypeTypeParameter(trait, alias), typePath) + | + tmTrait.getTypeAt(TypePath::nil()) != t + or + not exists(TypePath path1, Type t1 | + t1 = impl.getTraitPath().(PreTypeMention).getTypeAt(path1) and + not t1 instanceof TypeParameter and + t1 != tmTrait.getTypeAt(path1) + ) ) } diff --git a/rust/ql/test/library-tests/type-inference/CONSISTENCY/TypeInferenceConsistency.expected b/rust/ql/test/library-tests/type-inference/CONSISTENCY/TypeInferenceConsistency.expected deleted file mode 100644 index 2dc4ca7791a..00000000000 --- a/rust/ql/test/library-tests/type-inference/CONSISTENCY/TypeInferenceConsistency.expected +++ /dev/null @@ -1,2 +0,0 @@ -nonUniqueCertainType -| associated_types.rs:232:9:234:9 | { ... } | | diff --git a/rust/ql/test/library-tests/type-inference/associated_types.rs b/rust/ql/test/library-tests/type-inference/associated_types.rs index ea050377c21..a678a531f8d 100644 --- a/rust/ql/test/library-tests/type-inference/associated_types.rs +++ b/rust/ql/test/library-tests/type-inference/associated_types.rs @@ -236,8 +236,8 @@ mod concrete_type_as_generic_access_associated_type { pub fn test() { let s = S; - let _a = s.convert(true); // $ target=S::convert type=_a:i32 SPURIOUS: bool - let _b = s.convert(42); // $ target=S::convert type=_b:bool SPURIOUS: i32 + let _a = s.convert(true); // $ target=S::convert $ MISSING: type=_a:i32 + let _b = s.convert(42); // $ target=S::convert $ MISSING: type=_b:bool } } diff --git a/rust/ql/test/library-tests/type-inference/regressions.rs b/rust/ql/test/library-tests/type-inference/regressions.rs index 17a3d121c32..9365588c64a 100644 --- a/rust/ql/test/library-tests/type-inference/regressions.rs +++ b/rust/ql/test/library-tests/type-inference/regressions.rs @@ -71,6 +71,6 @@ mod regression2 { fn foo() { let s1 = S1; let s2 = S2; - let x = s1 - &s2; // $ target=S1SubRefS2 type=x:S2 $ SPURIOUS: type=x:S1 + let x = s1 - &s2; // $ target=S1SubRefS2 type=x:S2 } } diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index fb302784b64..d3ec61e9603 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -105,8 +105,6 @@ inferCertainType | associated_types.rs:229:23:229:27 | SelfParam | | {EXTERNAL LOCATION} | & | | associated_types.rs:229:23:229:27 | SelfParam | TRef | associated_types.rs:10:1:11:9 | S | | associated_types.rs:229:30:229:30 | t | | associated_types.rs:229:20:229:20 | T | -| associated_types.rs:232:9:234:9 | { ... } | | {EXTERNAL LOCATION} | bool | -| associated_types.rs:232:9:234:9 | { ... } | | {EXTERNAL LOCATION} | i32 | | associated_types.rs:233:24:233:24 | t | | associated_types.rs:229:20:229:20 | T | | associated_types.rs:237:19:241:5 | { ... } | | {EXTERNAL LOCATION} | () | | associated_types.rs:239:28:239:31 | true | | {EXTERNAL LOCATION} | bool | @@ -4956,7 +4954,6 @@ inferCertainType | regressions.rs:66:16:66:19 | SelfParam | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:66:22:66:26 | other | | {EXTERNAL LOCATION} | & | | regressions.rs:66:22:66:26 | other | TRef | regressions.rs:41:5:42:14 | S2 | -| regressions.rs:66:61:68:9 | { ... } | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:66:61:68:9 | { ... } | | regressions.rs:41:5:42:14 | S2 | | regressions.rs:67:22:67:25 | self | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:67:29:67:33 | other | | {EXTERNAL LOCATION} | & | @@ -5130,25 +5127,13 @@ inferType | associated_types.rs:229:23:229:27 | SelfParam | | {EXTERNAL LOCATION} | & | | associated_types.rs:229:23:229:27 | SelfParam | TRef | associated_types.rs:10:1:11:9 | S | | associated_types.rs:229:30:229:30 | t | | associated_types.rs:229:20:229:20 | T | -| associated_types.rs:232:9:234:9 | { ... } | | {EXTERNAL LOCATION} | bool | -| associated_types.rs:232:9:234:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| associated_types.rs:233:13:233:25 | ...::through(...) | | {EXTERNAL LOCATION} | bool | -| associated_types.rs:233:13:233:25 | ...::through(...) | | {EXTERNAL LOCATION} | i32 | | associated_types.rs:233:24:233:24 | t | | associated_types.rs:229:20:229:20 | T | | associated_types.rs:237:19:241:5 | { ... } | | {EXTERNAL LOCATION} | () | | associated_types.rs:238:13:238:13 | s | | associated_types.rs:10:1:11:9 | S | | associated_types.rs:238:17:238:17 | S | | associated_types.rs:10:1:11:9 | S | -| associated_types.rs:239:13:239:14 | _a | | {EXTERNAL LOCATION} | bool | -| associated_types.rs:239:13:239:14 | _a | | {EXTERNAL LOCATION} | i32 | | associated_types.rs:239:18:239:18 | s | | associated_types.rs:10:1:11:9 | S | -| associated_types.rs:239:18:239:32 | s.convert(...) | | {EXTERNAL LOCATION} | bool | -| associated_types.rs:239:18:239:32 | s.convert(...) | | {EXTERNAL LOCATION} | i32 | | associated_types.rs:239:28:239:31 | true | | {EXTERNAL LOCATION} | bool | -| associated_types.rs:240:13:240:14 | _b | | {EXTERNAL LOCATION} | bool | -| associated_types.rs:240:13:240:14 | _b | | {EXTERNAL LOCATION} | i32 | | associated_types.rs:240:18:240:18 | s | | associated_types.rs:10:1:11:9 | S | -| associated_types.rs:240:18:240:30 | s.convert(...) | | {EXTERNAL LOCATION} | bool | -| associated_types.rs:240:18:240:30 | s.convert(...) | | {EXTERNAL LOCATION} | i32 | | associated_types.rs:240:28:240:29 | 42 | | {EXTERNAL LOCATION} | i32 | | associated_types.rs:248:30:248:34 | thing | | associated_types.rs:248:19:248:27 | T | | associated_types.rs:248:65:250:5 | { ... } | | associated_types.rs:248:19:248:27 | T::Output[GetSet] | @@ -14816,9 +14801,7 @@ inferType | regressions.rs:66:16:66:19 | SelfParam | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:66:22:66:26 | other | | {EXTERNAL LOCATION} | & | | regressions.rs:66:22:66:26 | other | TRef | regressions.rs:41:5:42:14 | S2 | -| regressions.rs:66:61:68:9 | { ... } | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:66:61:68:9 | { ... } | | regressions.rs:41:5:42:14 | S2 | -| regressions.rs:67:13:67:34 | ...::sub(...) | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:67:13:67:34 | ...::sub(...) | | regressions.rs:41:5:42:14 | S2 | | regressions.rs:67:22:67:25 | self | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:67:28:67:33 | * ... | | regressions.rs:41:5:42:14 | S2 | @@ -14829,10 +14812,8 @@ inferType | regressions.rs:72:18:72:19 | S1 | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:73:13:73:14 | s2 | | regressions.rs:41:5:42:14 | S2 | | regressions.rs:73:18:73:19 | S2 | | regressions.rs:41:5:42:14 | S2 | -| regressions.rs:74:13:74:13 | x | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:74:13:74:13 | x | | regressions.rs:41:5:42:14 | S2 | | regressions.rs:74:17:74:18 | s1 | | regressions.rs:39:5:40:14 | S1 | -| regressions.rs:74:17:74:24 | ... - ... | | regressions.rs:39:5:40:14 | S1 | | regressions.rs:74:17:74:24 | ... - ... | | regressions.rs:41:5:42:14 | S2 | | regressions.rs:74:22:74:24 | &s2 | | {EXTERNAL LOCATION} | & | | regressions.rs:74:22:74:24 | &s2 | TRef | regressions.rs:41:5:42:14 | S2 |