From 5c604fce48df6421995aa6a7bfd8d766340346c6 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 17 Dec 2025 11:52:28 +0100 Subject: [PATCH] Rust: Fix bad join Before ``` Evaluated relational algebra for predicate TypeInference::MethodResolution::MethodCall.getTrait/0#dispred#fc13ba6e@914858bt with tuple counts: 153112 ~2% {2} r1 = SCAN `Operation::Operation.isOverloaded/3#f0e64084` OUTPUT In.0, In.1 153112 ~2% {2} | STREAM DEDUP 18807 ~0% {2} r2 = JOIN `TypeInference::getCallExprTraitQualifier/1#c084fe9f` WITH TypeInference::MethodResolution::MethodCallCallExpr#6eae461f ON FIRST 1 OUTPUT Lhs.0, Lhs.1 65859035 ~3% {3} r3 = JOIN `_IndexExpr::Generated::IndexExpr#9975e37a_TypeInference::MethodResolution::MethodCallIndexExpr.isInM__#shared` WITH Trait::Generated::Trait#ecf50173 CARTESIAN PRODUCT OUTPUT Rhs.0, _, Lhs.0 65859035 ~0% {3} | REWRITE WITH Out.1 := "core::ops::index::Index" 11191 ~0% {2} | JOIN WITH `Addressable::Addressable.getCanonicalPath/0#dispred#6044348f#bb` ON FIRST 2 OUTPUT Lhs.2, Lhs.0 671 ~0% {1} r4 = JOIN IndexExpr::Generated::IndexExpr#9975e37a WITH `TypeInference::MethodResolution::MethodCallIndexExpr.isInMutableContext/0#dispred#8c8ad425` ON FIRST 1 OUTPUT Lhs.0 3948835 ~2% {3} | JOIN WITH Trait::Generated::Trait#ecf50173 CARTESIAN PRODUCT OUTPUT Rhs.0, _, Lhs.0 3948835 ~2% {3} | REWRITE WITH Out.1 := "core::ops::index::IndexMut" 671 ~1% {2} | JOIN WITH `Addressable::Addressable.getCanonicalPath/0#dispred#6044348f#bb` ON FIRST 2 OUTPUT Lhs.2, Lhs.0 183781 ~0% {2} r5 = r1 UNION r2 UNION r3 UNION r4 return r5 ``` After ``` Evaluated relational algebra for predicate TypeInference::MethodResolution::MethodCall.getTrait/0#dispred#fc13ba6e@1b4a55e3 with tuple counts: 153112 ~2% {2} r1 = SCAN `Operation::Operation.isOverloaded/3#f0e64084` OUTPUT In.0, In.1 153112 ~2% {2} | STREAM DEDUP 11191 ~0% {2} r2 = JOIN `_IndexExpr::Generated::IndexExpr#9975e37a_TypeInference::MethodResolution::MethodCallIndexExpr.isInM__#shared` WITH Stdlib::IndexTrait#e80543a5 CARTESIAN PRODUCT OUTPUT Lhs.0, Rhs.0 18807 ~0% {2} r3 = JOIN `TypeInference::getCallExprTraitQualifier/1#c084fe9f` WITH TypeInference::MethodResolution::MethodCallCallExpr#6eae461f ON FIRST 1 OUTPUT Lhs.0, Lhs.1 671 ~0% {1} r4 = JOIN IndexExpr::Generated::IndexExpr#9975e37a WITH `TypeInference::MethodResolution::MethodCallIndexExpr.isInMutableContext/0#dispred#8c8ad425` ON FIRST 1 OUTPUT Lhs.0 671 ~1% {2} | JOIN WITH Stdlib::IndexMutTrait#4d6c31bd CARTESIAN PRODUCT OUTPUT Lhs.0, Rhs.0 183781 ~0% {2} r5 = r1 UNION r2 UNION r3 UNION r4 return r5 ``` --- .../ql/lib/codeql/rust/frameworks/stdlib/Stdlib.qll | 13 +++++++++++++ rust/ql/lib/codeql/rust/internal/TypeInference.qll | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/Stdlib.qll b/rust/ql/lib/codeql/rust/frameworks/stdlib/Stdlib.qll index 00e03053654d..ec0e38f57399 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/Stdlib.qll +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/Stdlib.qll @@ -250,6 +250,19 @@ class IndexTrait extends Trait { } } +/** + * The [`IndexMut` trait][1]. + * + * [1]: https://doc.rust-lang.org/std/ops/trait.IndexMut.html + */ +class IndexMutTrait extends Trait { + pragma[nomagic] + IndexMutTrait() { this.getCanonicalPath() = "core::ops::index::IndexMut" } + + /** Gets the `index_mut` function. */ + Function getIndexMutFunction() { result = this.(TraitItemNode).getAssocItem("index_mut") } +} + /** * The [`Box` struct][1]. * diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 602f964df0f0..488a391150a0 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -1786,8 +1786,8 @@ private module MethodResolution { override Trait getTrait() { if this.isInMutableContext() - then result.getCanonicalPath() = "core::ops::index::IndexMut" - else result.getCanonicalPath() = "core::ops::index::Index" + then result instanceof IndexMutTrait + else result instanceof IndexTrait } }