From 63aac1babb6bc9c7dafca1bbf3954cc58d25d082 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 10 Jun 2025 16:19:34 +0200 Subject: [PATCH 1/6] Rust: Fix bad join in `getCanonicalPath` Before ``` Pipeline standard for PathResolution::ItemNode.getCanonicalPath/1#dispred#f52ac1c6@5132b1w8 was evaluated in 107 iterations totaling 1217ms (delta sizes total: 870557). 568160 ~1% {2} r1 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::AssocItemNode.hasCanonicalPath/1#dispred#120fa1ad_project#PathResolution::ItemNode.__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 564597 ~1% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 68670 ~1% {2} r2 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::VariantItemNode.hasCanonicalPath/1#dispred#12012145_project#PathResolution::ItemNod__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 68670 ~0% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#5` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 49047 ~1% {2} r3 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::StructItemNode.hasCanonicalPath/1#dispred#f482e99c_project#PathResolution::ItemNode__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 49047 ~2% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#2` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 229 ~0% {2} r4 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::UnionItemNode.hasCanonicalPath/1#dispred#f67c4b73_project#PathResolution::ItemNode.__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 229 ~0% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#4` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 12207 ~0% {2} r5 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::EnumItemNode.hasCanonicalPath/1#dispred#03ce35b1_project#PathResolution::ItemNode.g__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 12207 ~0% {3} | JOIN WITH `__PathResolution::EnumItemNode.getName/0#dispred#f21ce0ed_PathResolution::ItemNode.getCanonicalPathP__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 26698 ~2% {2} r6 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::ModuleItemNode.hasCanonicalPath/1#dispred#2fee2540_project#PathResolution::ItemNode__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 26698 ~0% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#1` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 6315 ~1% {2} r7 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::TraitItemNode.hasCanonicalPath/1#dispred#824f98e3_project#PathResolution::ItemNode.__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 6315 ~1% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#3` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 112374 ~0% {3} r8 = JOIN `PathResolution::ImplItemNode.getCanonicalPathTraitPart/1#dispred#009a7fd0#prev_delta` WITH `_PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6_PathResolution::ImplItemNode.hasCanoni__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, _ 112374 ~3% {3} | REWRITE WITH Out.2 := 3 872046 ~1% {2} r9 = SCAN `PathResolution::ItemNode.getCanonicalPath/1#dispred#f52ac1c6#prev_delta` OUTPUT In.1, In.0 777662505 ~2% {3} | JOIN WITH `PathResolution::ImplItemNode.hasCanonicalPath/1#dispred#4e7c51c6_10#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.0 150127 ~1% {3} | JOIN WITH `PathResolution::ImplItemNode.resolveSelfTy/0#dispred#cf157d04` ON FIRST 2 OUTPUT Lhs.0, Lhs.2, _ 150127 ~0% {3} | REWRITE WITH Out.2 := 1 262501 ~1% {3} r10 = r8 UNION r9 230996 ~1% {5} r11 = JOIN r10 WITH `PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6` ON FIRST 1 OUTPUT Lhs.0, Lhs.1, Lhs.2, _, _ 230996 ~0% {5} | REWRITE WITH Out.3 := 4, Out.4 := 0 {3} r12 = r10 AND NOT `PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6_0#antijoin_rhs`(FIRST 1) 31487 ~0% {5} | SCAN OUTPUT In.0, In.1, In.2, _, _ 31487 ~1% {5} | REWRITE WITH Out.3 := 2, Out.4 := 0 262483 ~0% {5} r13 = r11 UNION r12 262483 ~0% {5} | JOIN WITH PRIMITIVE range#bbb ON Lhs.4,Lhs.3,Lhs.2 262483 ~0% {3} | SCAN OUTPUT In.3, In.0, In.1 142807 ~1% {3} | JOIN WITH `__PathResolution::ImplItemNode.getCanonicalPathTraitPart/1#dispred#009a7fd0#prev_PathResolution::Imp__#join_rhs` ON FIRST 3 OUTPUT Lhs.1, Lhs.2, Rhs.3 870570 ~1% {3} r14 = r1 UNION r2 UNION r3 UNION r4 UNION r5 UNION r6 UNION r7 UNION r13 870566 ~1% {3} | AND NOT `PathResolution::ItemNode.getCanonicalPath/1#dispred#f52ac1c6#prev`(FIRST 3) return r14 ``` After ``` Pipeline standard for PathResolution::ItemNode.getCanonicalPath/1#dispred#f52ac1c6@90aba2wd was evaluated in 100 iterations totaling 28ms (delta sizes total: 870531). 568160 ~0% {2} r1 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::AssocItemNode.hasCanonicalPath/1#dispred#120fa1ad_project#PathResolution::ItemNode.__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 564597 ~1% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 68670 ~0% {2} r2 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::VariantItemNode.hasCanonicalPath/1#dispred#12012145_project#PathResolution::ItemNod__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 68670 ~1% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#5` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 49047 ~0% {2} r3 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::StructItemNode.hasCanonicalPath/1#dispred#f482e99c_project#PathResolution::ItemNode__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 49047 ~1% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#2` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 229 ~0% {2} r4 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::UnionItemNode.hasCanonicalPath/1#dispred#f67c4b73_project#PathResolution::ItemNode.__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 229 ~0% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#4` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 12207 ~1% {2} r5 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::EnumItemNode.hasCanonicalPath/1#dispred#03ce35b1_project#PathResolution::ItemNode.g__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 12207 ~0% {3} | JOIN WITH `__PathResolution::EnumItemNode.getName/0#dispred#f21ce0ed_PathResolution::ItemNode.getCanonicalPathP__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 26698 ~0% {2} r6 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::ModuleItemNode.hasCanonicalPath/1#dispred#2fee2540_project#PathResolution::ItemNode__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 26698 ~4% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#1` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 6315 ~1% {2} r7 = JOIN `PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_delta` WITH `_PathResolution::TraitItemNode.hasCanonicalPath/1#dispred#824f98e3_project#PathResolution::ItemNode.__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1 6315 ~2% {3} | JOIN WITH `__PathResolution::ItemNode.getCanonicalPathPrefix/1#dispred#a1d9332d#prev_PathResolution::ItemNode.g__#join_rhs#3` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, Rhs.2 150127 ~0% {3} r8 = JOIN `PathResolution::ImplItemNode.getSelfCanonicalPath/1#dispred#8ed81fbe#prev_delta` WITH `PathResolution::ImplItemNode.hasCanonicalPath/1#dispred#4e7c51c6` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, _ 150127 ~0% {3} | REWRITE WITH Out.2 := 1 112374 ~1% {3} r9 = JOIN `PathResolution::ImplItemNode.getCanonicalPathTraitPart/1#dispred#009a7fd0#prev_delta` WITH `_PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6_PathResolution::ImplItemNode.hasCanoni__#join_rhs` ON FIRST 2 OUTPUT Lhs.0, Lhs.1, _ 112374 ~0% {3} | REWRITE WITH Out.2 := 3 262501 ~0% {3} r10 = r8 UNION r9 230996 ~1% {5} r11 = JOIN r10 WITH `PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6` ON FIRST 1 OUTPUT Lhs.0, Lhs.1, Lhs.2, _, _ 230996 ~1% {5} | REWRITE WITH Out.3 := 4, Out.4 := 0 {3} r12 = r10 AND NOT `PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6_0#antijoin_rhs`(FIRST 1) 31487 ~0% {5} | SCAN OUTPUT In.0, In.1, In.2, _, _ 31487 ~0% {5} | REWRITE WITH Out.3 := 2, Out.4 := 0 262483 ~1% {5} r13 = r11 UNION r12 262483 ~1% {5} | JOIN WITH PRIMITIVE range#bbb ON Lhs.4,Lhs.3,Lhs.2 262483 ~0% {3} | SCAN OUTPUT In.3, In.0, In.1 142772 ~0% {3} | JOIN WITH `__PathResolution::ImplItemNode.getCanonicalPathTraitPart/1#dispred#009a7fd0#prev_PathResolution::Imp__#join_rhs` ON FIRST 3 OUTPUT Lhs.1, Lhs.2, Rhs.3 870535 ~1% {3} r14 = r1 UNION r2 UNION r3 UNION r4 UNION r5 UNION r6 UNION r7 UNION r13 870531 ~1% {3} | AND NOT `PathResolution::ItemNode.getCanonicalPath/1#dispred#f52ac1c6#prev`(FIRST 3) return r14 ``` --- rust/ql/lib/codeql/rust/internal/PathResolution.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 108b8745e44b..4c057c24ee39 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -607,6 +607,9 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl { result = this.resolveTraitTy().getCanonicalPath(c) } + pragma[nomagic] + private string getSelfCanonicalPath(Crate c) { result = this.resolveSelfTy().getCanonicalPath(c) } + pragma[nomagic] private string getCanonicalPathTraitPart(Crate c) { exists(Crate c2 | @@ -621,7 +624,7 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl { result = "<" or i = 1 and - result = this.resolveSelfTy().getCanonicalPath(c) + result = this.getSelfCanonicalPath(c) or if exists(this.getTraitPath()) then From 8c956647dee1292f3e0c82f2a1c6bb9881d75fb8 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 10 Jun 2025 16:28:39 +0200 Subject: [PATCH 2/6] Rust: Fix bad join in `fileImport` Before ``` Evaluated relational algebra for predicate PathResolution::fileImport/2#d9e57816@c790f609 with tuple counts: 241 ~0% {3} r1 = JOIN `_Locatable::Locatable.getFile/0#dispred#f7e24934_PathResolution::isSourceFile/1#803de032#shared` WITH `FileSystem::Folder::Append::append/2#beb8f79a_201#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Rhs.2, Lhs.1 291 ~0% {2} | JOIN WITH `PathResolution::pathAttrImport/3#88463ffa_021#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2 14978 ~8% {2} r2 = SCAN `PathResolution::modImport0/3#03cccf2a` OUTPUT In.0, In.1 14978 ~8% {2} | STREAM DEDUP 14392 ~9% {2} r3 = r2 AND NOT `PathResolution::modImportNested/3#991244df_0#antijoin_rhs`(FIRST 1) 14392 ~0% {3} | JOIN WITH `PathResolution::modImport0/3#03cccf2a` ON FIRST 2 OUTPUT Lhs.1, Rhs.2, Lhs.0 14355 ~0% {4} | JOIN WITH `PathResolution::fileModule/3#d6c6ceef#fbf_120#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.0, Lhs.1, Lhs.2 14978 ~0% {2} r4 = JOIN r2 WITH `PathResolution::modImport0/3#03cccf2a` ON FIRST 2 OUTPUT Lhs.1, Lhs.0 329862 ~0% {5} | JOIN WITH `PathResolution::fileModule/3#d6c6ceef#fbf_102#join_rhs` ON FIRST 1 OUTPUT Lhs.1, Lhs.1, Rhs.2, Lhs.0, Rhs.1 577 ~3% {4} | JOIN WITH `PathResolution::modImportNestedLookup/3#6cc4b913#ffb` ON FIRST 3 OUTPUT Lhs.4, Lhs.3, Lhs.2, Lhs.0 14932 ~0% {4} r5 = r3 UNION r4 14932 ~0% {2} | JOIN WITH `PathResolution::fileModule/3#d6c6ceef#fbf` ON FIRST 3 OUTPUT Lhs.0, Lhs.3 14932 ~0% {2} | JOIN WITH `PathResolution::isSourceFile/1#803de032` ON FIRST 1 OUTPUT Lhs.1, Lhs.0 15223 ~0% {2} r6 = r1 UNION r5 return r6 ``` Afer ``` Evaluated relational algebra for predicate PathResolution::fileImport/2#d9e57816@007bd81i with tuple counts: 241 ~0% {3} r1 = JOIN `_Locatable::Locatable.getFile/0#dispred#f7e24934_PathResolution::isSourceFile/1#803de032#shared` WITH `FileSystem::Folder::Append::append/2#beb8f79a_201#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Rhs.2, Lhs.1 291 ~0% {2} | JOIN WITH `PathResolution::pathAttrImport/3#88463ffa_021#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2 14978 ~8% {2} r2 = SCAN `PathResolution::modImport0/3#03cccf2a` OUTPUT In.0, In.1 14978 ~8% {2} | STREAM DEDUP 14392 ~9% {2} r3 = r2 AND NOT `PathResolution::modImportNested/3#991244df_0#antijoin_rhs`(FIRST 1) 14392 ~0% {3} | JOIN WITH `PathResolution::modImport0/3#03cccf2a` ON FIRST 2 OUTPUT Lhs.1, Rhs.2, Lhs.0 14978 ~9% {3} r4 = JOIN r2 WITH `PathResolution::modImport0/3#03cccf2a` ON FIRST 2 OUTPUT Lhs.0, Lhs.0, Lhs.1 577 ~0% {3} | JOIN WITH `PathResolution::modImportNestedLookup/3#6cc4b913#ffb` ON FIRST 2 OUTPUT Lhs.2, Rhs.2, Lhs.0 14969 ~1% {3} r5 = r3 UNION r4 14932 ~0% {2} | JOIN WITH `PathResolution::fileModule/3#d6c6ceef_120#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2 14932 ~0% {2} | JOIN WITH `PathResolution::isSourceFile/1#803de032` ON FIRST 1 OUTPUT Lhs.1, Lhs.0 15223 ~0% {2} r6 = r1 UNION r5 return r6 ``` --- rust/ql/lib/codeql/rust/internal/PathResolution.qll | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 4c057c24ee39..5e8c991a5820 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -988,6 +988,7 @@ private predicate sourceFileEdge(SourceFile f, string name, ItemNode item) { } /** Holds if `f` is available as `mod name;` inside `folder`. */ +pragma[nomagic] private predicate fileModule(SourceFile f, string name, Folder folder) { exists(File file | file = f.getFile() | file.getBaseName() = name + ".rs" and @@ -1002,6 +1003,12 @@ private predicate fileModule(SourceFile f, string name, Folder folder) { ) } +bindingset[name, folder] +pragma[inline_late] +private predicate fileModuleInlineLate(SourceFile f, string name, Folder folder) { + fileModule(f, name, folder) +} + /** * Gets the `Meta` of the module `m`'s [path attribute][1]. * @@ -1084,7 +1091,7 @@ pragma[nomagic] predicate fileImport(Module m, SourceFile f) { exists(string name, Folder parent | modImport0(m, name, _) and - fileModule(f, name, parent) + fileModuleInlineLate(f, name, parent) | // `m` is not inside a nested module modImport0(m, name, parent) and From bc60d033e540de5851dee34664f94252a3be194d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 10 Jun 2025 18:55:36 +0200 Subject: [PATCH 3/6] Rust: Fix bad join in `inferAccessType` Before ``` Pipeline standard for TypeInference::CallExprBaseMatching::inferAccessType/3#be4695a4@202c46xq was evaluated in 600 iterations totaling 2282ms (delta sizes total: 5827084). 120407742 ~1% {4} r1 = JOIN `TypeInference::CallExprBaseMatchingInput::Access.getTarget/0#dispred#29d66fd1#prev_delta` WITH `TypeInference::CallExprBaseMatchingInput::accessDeclarationPositionMatch/2#6c58c89d` CARTESIAN PRODUCT OUTPUT Lhs.1, Rhs.1, Rhs.0, Lhs.0 6495868 ~109% {4} | JOIN WITH `TypeInference::CallExprBaseMatchingInput::Declaration.getDeclaredType/2#dispred#325b693f` ON FIRST 2 OUTPUT Rhs.3, Lhs.2, Lhs.3, Rhs.2 {4} | AND NOT Type::TypeParameter#f85657da(FIRST 1) 3049994 ~10% {4} | SCAN OUTPUT In.2, In.1, In.3, In.0 7891 ~0% {5} r2 = SCAN `TypeInference::CallExprBaseMatching::explicitTypeMatch/5#98ce2c39#prev_delta` OUTPUT In.1, In.4, In.0, In.2, In.3 4445 ~3% {9} | JOIN WITH `_TypeInference::CallExprBaseMatchingInput::Declaration.getDeclaredType/2#dispred#325b693f_1023#join___#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2, Lhs.4, _, _, Rhs.3, Lhs.3, _, _ {5} | REWRITE WITH Out.3 := (In.5 ++ In.6), Tmp.4 := (In.5 ++ In.6), Tmp.7 := "[0-9]+", Tmp.8 := "", Out.4 := regexpReplaceAll(Tmp.4,Tmp.7,Tmp.8) KEEPING 5 4445 ~3% {7} | SCAN OUTPUT In.0, In.1, In.2, In.3, _, In.4, _ {5} | REWRITE WITH Out.4 := length(In.5), Tmp.6 := 10, TEST Out.4 <= Tmp.6 KEEPING 5 4445 ~5% {4} | SCAN OUTPUT In.1, In.0, In.3, In.2 3553075 ~1% {5} r3 = SCAN `TypeInference::CallExprBaseMatching::directTypeMatch/5#319f8680#prev_delta` OUTPUT In.1, In.4, In.0, In.2, In.3 6860451 ~16% {9} | JOIN WITH `_TypeInference::CallExprBaseMatchingInput::Declaration.getDeclaredType/2#dispred#325b693f_1023#join___#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2, Lhs.4, _, _, Rhs.3, Lhs.3, _, _ {5} | REWRITE WITH Out.3 := (In.5 ++ In.6), Tmp.4 := (In.5 ++ In.6), Tmp.7 := "[0-9]+", Tmp.8 := "", Out.4 := regexpReplaceAll(Tmp.4,Tmp.7,Tmp.8) KEEPING 5 6860451 ~19% {7} | SCAN OUTPUT In.0, In.1, In.2, In.3, _, In.4, _ {5} | REWRITE WITH Out.4 := length(In.5), Tmp.6 := 10, TEST Out.4 <= Tmp.6 KEEPING 5 6211129 ~20% {4} | SCAN OUTPUT In.1, In.0, In.3, In.2 115218 ~1% {5} r4 = SCAN `TypeInference::CallExprBaseMatching::typeConstraintBaseTypeMatch/5#ebeb4216#prev_delta` OUTPUT In.1, In.4, In.0, In.2, In.3 181668 ~2% {9} | JOIN WITH `_TypeInference::CallExprBaseMatchingInput::Declaration.getDeclaredType/2#dispred#325b693f_1023#join___#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2, Lhs.4, _, _, Rhs.3, Lhs.3, _, _ {5} | REWRITE WITH Out.3 := (In.5 ++ In.6), Tmp.4 := (In.5 ++ In.6), Tmp.7 := "[0-9]+", Tmp.8 := "", Out.4 := regexpReplaceAll(Tmp.4,Tmp.7,Tmp.8) KEEPING 5 181668 ~0% {7} | SCAN OUTPUT In.0, In.1, In.2, In.3, _, In.4, _ {5} | REWRITE WITH Out.4 := length(In.5), Tmp.6 := 10, TEST Out.4 <= Tmp.6 KEEPING 5 181668 ~0% {4} | SCAN OUTPUT In.1, In.0, In.3, In.2 9447236 ~16% {4} r5 = r1 UNION r2 UNION r3 UNION r4 5902300 ~4% {4} | AND NOT `TypeInference::CallExprBaseMatching::inferAccessType/3#be4695a4#prev`(FIRST 4) return r5 ``` Afer ``` Pipeline standard for TypeInference::CallExprBaseMatching::inferAccessType/3#be4695a4@061316x0 was evaluated in 600 iterations totaling 1727ms (delta sizes total: 5918371). 1323162 ~0% {2} r1 = SCAN `TypeInference::CallExprBaseMatchingInput::Access.getTarget/0#dispred#29d66fd1#prev_delta` OUTPUT In.1, In.0 5316637 ~152% {4} | JOIN WITH `_Type::TypeParameter#f85657da_TypeInference::CallExprBaseMatchingInput::Declaration.getDeclaredType/__#join_rhs#1` ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Rhs.2, Rhs.3 7891 ~0% {5} r2 = SCAN `TypeInference::CallExprBaseMatching::explicitTypeMatch/5#98ce2c39#prev_delta` OUTPUT In.1, In.4, In.0, In.2, In.3 4445 ~3% {9} | JOIN WITH `_TypeInference::CallExprBaseMatchingInput::Declaration.getDeclaredType/2#dispred#325b693f_1023#join___#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2, Lhs.4, _, _, Rhs.3, Lhs.3, _, _ {5} | REWRITE WITH Out.3 := (In.5 ++ In.6), Tmp.4 := (In.5 ++ In.6), Tmp.7 := "[0-9]+", Tmp.8 := "", Out.4 := regexpReplaceAll(Tmp.4,Tmp.7,Tmp.8) KEEPING 5 4445 ~3% {7} | SCAN OUTPUT In.0, In.1, In.2, In.3, _, In.4, _ {5} | REWRITE WITH Out.4 := length(In.5), Tmp.6 := 10, TEST Out.4 <= Tmp.6 KEEPING 5 4445 ~5% {4} | SCAN OUTPUT In.1, In.0, In.3, In.2 3553075 ~1% {5} r3 = SCAN `TypeInference::CallExprBaseMatching::directTypeMatch/5#319f8680#prev_delta` OUTPUT In.1, In.4, In.0, In.2, In.3 6860451 ~16% {9} | JOIN WITH `_TypeInference::CallExprBaseMatchingInput::Declaration.getDeclaredType/2#dispred#325b693f_1023#join___#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2, Lhs.4, _, _, Rhs.3, Lhs.3, _, _ {5} | REWRITE WITH Out.3 := (In.5 ++ In.6), Tmp.4 := (In.5 ++ In.6), Tmp.7 := "[0-9]+", Tmp.8 := "", Out.4 := regexpReplaceAll(Tmp.4,Tmp.7,Tmp.8) KEEPING 5 6860451 ~19% {7} | SCAN OUTPUT In.0, In.1, In.2, In.3, _, In.4, _ {5} | REWRITE WITH Out.4 := length(In.5), Tmp.6 := 10, TEST Out.4 <= Tmp.6 KEEPING 5 6211129 ~20% {4} | SCAN OUTPUT In.1, In.0, In.3, In.2 115218 ~1% {5} r4 = SCAN `TypeInference::CallExprBaseMatching::typeConstraintBaseTypeMatch/5#ebeb4216#prev_delta` OUTPUT In.1, In.4, In.0, In.2, In.3 181668 ~2% {9} | JOIN WITH `_TypeInference::CallExprBaseMatchingInput::Declaration.getDeclaredType/2#dispred#325b693f_1023#join___#join_rhs` ON FIRST 2 OUTPUT Rhs.2, Lhs.2, Lhs.4, _, _, Rhs.3, Lhs.3, _, _ {5} | REWRITE WITH Out.3 := (In.5 ++ In.6), Tmp.4 := (In.5 ++ In.6), Tmp.7 := "[0-9]+", Tmp.8 := "", Out.4 := regexpReplaceAll(Tmp.4,Tmp.7,Tmp.8) KEEPING 5 181668 ~0% {7} | SCAN OUTPUT In.0, In.1, In.2, In.3, _, In.4, _ {5} | REWRITE WITH Out.4 := length(In.5), Tmp.6 := 10, TEST Out.4 <= Tmp.6 KEEPING 5 181668 ~0% {4} | SCAN OUTPUT In.1, In.0, In.3, In.2 11713879 ~62% {4} r5 = r1 UNION r2 UNION r3 UNION r4 6210333 ~10% {4} | AND NOT `TypeInference::CallExprBaseMatching::inferAccessType/3#be4695a4#prev`(FIRST 4) return r5 ``` --- .../codeql/typeinference/internal/TypeInference.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index ca79740a2ceb..3c984d98e445 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -1289,14 +1289,14 @@ module Make1 Input1> { exists(DeclarationPosition dpos | accessDeclarationPositionMatch(apos, dpos) | // A suffix of `path` leads to a type parameter in the target exists(Declaration target, TypePath prefix, TypeParameter tp, TypePath suffix | - tp = target.getDeclaredType(pragma[only_bind_into](dpos), prefix) and + tp = target.getDeclaredType(dpos, prefix) and path = prefix.append(suffix) and typeMatch(a, target, suffix, result, tp) ) or // `path` corresponds directly to a concrete type in the declaration exists(Declaration target | - result = target.getDeclaredType(pragma[only_bind_into](dpos), path) and + result = target.getDeclaredType(dpos, path) and target = a.getTarget() and not result instanceof TypeParameter ) From f9915e66a788d5f8ec026a5a07a2783333fa2949 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 10 Jun 2025 20:39:10 +0200 Subject: [PATCH 4/6] Rust: Fix bad join in `satisfiesConcreteTypesFromIndex` Before ``` Pipeline standard for TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9@061312x0 was evaluated in 367 iterations totaling 3484ms (delta sizes total: 563408). 66609 ~0% {3} r1 = SCAN `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev_delta` OUTPUT In.1, In.2, In.0 867138261 ~1% {4} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1_210#join_rhs` ON FIRST 2 OUTPUT Lhs.2, Rhs.2, Lhs.0, Lhs.1 29320 ~0% {5} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::IsInstantiationOfInput::potentialInstantiationOf/3#1239e45f#reorder_0_2_1#prev` ON FIRST 2 OUTPUT Rhs.2, Lhs.3, Lhs.0, Lhs.2, Lhs.1 {5} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 29320 ~1% {4} | SCAN OUTPUT In.4, In.3, In.2, In.0 29320 ~0% {5} r2 = JOIN r1 WITH `TypeInference::M2::IsInstantiationOf::getNthPath/2#8b978a80_021#join_rhs` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Rhs.2, _ {4} | REWRITE WITH Tmp.4 := 0, TEST InOut.3 != Tmp.4 KEEPING 4 29320 ~0% {5} | SCAN OUTPUT In.0, In.2, In.1, _, In.3 29320 ~0% {5} | REWRITE WITH Tmp.3 := 1, Out.3 := (InOut.4 - Tmp.3) 29296 ~1% {4} | JOIN WITH `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev` ON FIRST 4 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.4 29320 ~0% {6} r3 = JOIN r1 WITH `TypeInference::M2::IsInstantiationOf::getNthPath/2#8b978a80_021#join_rhs` ON FIRST 2 OUTPUT Lhs.2, Lhs.1, Lhs.0, Lhs.3, Rhs.2, _ {5} | REWRITE WITH Tmp.5 := 0, TEST InOut.4 = Tmp.5 KEEPING 5 0 ~0% {5} | SCAN OUTPUT In.2, _, In.1, In.0, In.3 0 ~0% {5} | REWRITE WITH Out.1 := 0 0 ~0% {4} | JOIN WITH `TypeInference::M2::IsInstantiationOf::getNthPath/2#8b978a80` ON FIRST 3 OUTPUT Lhs.3, Lhs.4, Lhs.0, _ 0 ~0% {4} | REWRITE WITH Out.3 := 0 563353 ~1% {4} r4 = SCAN `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev_delta` OUTPUT In.0, In.2, In.1, In.3 563353 ~1% {6} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::IsInstantiationOfInput::potentialInstantiationOf/3#1239e45f#reorder_0_2_1#prev` ON FIRST 3 OUTPUT Lhs.0, Lhs.2, Lhs.1, _, Lhs.3, _ {4} | REWRITE WITH Tmp.3 := 1, Out.3 := (Tmp.3 + In.4), Tmp.5 := 0, TEST Out.3 != Tmp.5 KEEPING 4 563353 ~0% {4} | SCAN OUTPUT In.2, In.3, In.0, In.1 258647 ~1% {5} r5 = JOIN r4 WITH `TypeInference::M2::IsInstantiationOf::getNthPath/2#8b978a80` ON FIRST 2 OUTPUT Lhs.3, Lhs.2, Lhs.0, Lhs.1, Rhs.2 102998 ~1% {6} | JOIN WITH `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0` ON FIRST 1 OUTPUT Lhs.2, Rhs.1, Lhs.4, Lhs.1, Lhs.0, Lhs.3 52485 ~1% {6} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1` ON FIRST 3 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5 258647 ~0% {5} r6 = JOIN r4 WITH `TypeInference::M2::IsInstantiationOf::getNthPath/2#8b978a80` ON FIRST 2 OUTPUT Lhs.0, Rhs.2, Lhs.2, Lhs.3, Lhs.1 259340 ~1% {6} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1_021#join_rhs` ON FIRST 2 OUTPUT Lhs.2, Lhs.1, Rhs.2, Lhs.3, Lhs.0, Lhs.4 16033 ~0% {6} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 3 OUTPUT Lhs.3, Lhs.2, Lhs.0, Lhs.4, Lhs.5, Lhs.1 {6} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 15992 ~1% {6} | SCAN OUTPUT In.3, In.1, In.5, In.2, In.0, In.4 68477 ~1% {6} r7 = r5 UNION r6 68477 ~0% {4} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1` ON FIRST 3 OUTPUT Lhs.3, Lhs.4, Lhs.0, Lhs.5 465635 ~0% {3} r8 = SCAN `TypeInference::CallExprBaseMatching::AccessConstraint::IsInstantiationOfInput::potentialInstantiationOf/3#1239e45f#reorder_0_2_1#prev_delta` OUTPUT In.1, In.0, In.2 465635 ~0% {5} r9 = JOIN r8 WITH `_TypeInference::M2::IsInstantiationOf::getNthPath/2#8b978a80` ON FIRST 3 OUTPUT Lhs.4, Lhs.0, _, Lhs.2, Lhs.3 465635 ~1% {5} | REWRITE WITH Out.2 := 0 275069 ~0% {5} r11 = JOIN r8 WITH `_TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev` ON FIRST 3 OUTPUT Lhs.2, Lhs.3, Lhs.4, Lhs.0, Lhs.1, Rhs.3, _ 0 ~0% {7} | REWRITE WITH Tmp.6 := 1, Out.6 := (InOut.1 - Tmp.6), TEST Out.6 = InOut.5 0 ~0% {5} r12 = SCAN r11 OUTPUT In.4, In.0, In.1, In.2, In.3 465635 ~1% {5} r13 = r10 UNION r12 94444 ~1% {6} | JOIN WITH `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0` ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Lhs.3, Lhs.2, Lhs.4, Lhs.0 6 ~20% {6} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1` ON FIRST 3 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5 465635 ~0% {5} r14 = JOIN r9 WITH `TypeInference::M2::IsInstantiationOf::getNthPath/2#8b978a80` ON FIRST 3 OUTPUT Lhs.0, Lhs.2, _, Lhs.3, Lhs.4 465635 ~1% {5} | REWRITE WITH Out.2 := 0 0 ~0% {5} r15 = SCAN r11 OUTPUT In.0, In.2, In.1, In.3, In.4 465635 ~1% {5} r16 = r14 UNION r15 465635 ~0% {6} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1_021#join_rhs` ON FIRST 2 OUTPUT Lhs.3, Lhs.1, Rhs.2, Lhs.0, Lhs.2, Lhs.4 465635 ~0% {6} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 3 OUTPUT Lhs.5, Lhs.2, Lhs.3, Lhs.4, Lhs.1, Lhs.0 {6} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 465629 ~1% {6} | SCAN OUTPUT In.2, In.1, In.4, In.3, In.5, In.0 465635 ~1% {6} r17 = r13 UNION r16 465635 ~1% {4} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1` ON FIRST 3 OUTPUT Lhs.4, Lhs.5, Lhs.0, Lhs.3 563408 ~1% {4} r18 = r2 UNION r3 UNION r7 UNION r17 563408 ~1% {4} | AND NOT `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev`(FIRST 4) return r18 ``` After ``` Pipeline standard for TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9@e8671bx7 was evaluated in 376 iterations totaling 245ms (delta sizes total: 563353). 563353 ~1% {6} r1 = SCAN `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev_delta` OUTPUT In.0, In.1, In.2, _, In.3, _ 563353 ~1% {4} | REWRITE WITH Tmp.3 := 1, Out.3 := (Tmp.3 + In.4), Tmp.5 := 0, TEST Out.3 != Tmp.5 KEEPING 4 259340 ~1% {5} r2 = JOIN r1 WITH `TypeInference::M2::IsInstantiationOf::resolveTypeAt/5#77e2181d#prev` ON FIRST 4 OUTPUT Lhs.1, Rhs.5, Lhs.0, Lhs.2, Lhs.3 52485 ~0% {4} | JOIN WITH `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Lhs.4 259340 ~1% {6} r3 = JOIN r1 WITH `TypeInference::M2::IsInstantiationOf::resolveTypeAt/5#77e2181d#prev` ON FIRST 4 OUTPUT Lhs.0, Rhs.4, Rhs.5, Lhs.1, Lhs.2, Lhs.3 16033 ~0% {5} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 3 OUTPUT Lhs.3, Lhs.2, Lhs.0, Lhs.4, Lhs.5 {5} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 15992 ~0% {4} | SCAN OUTPUT In.2, In.0, In.3, In.4 741397 ~1% {7} r4 = SCAN `TypeInference::M2::IsInstantiationOf::resolveTypeAt/5#77e2181d#prev_delta` OUTPUT In.0, In.1, In.2, In.3, In.4, In.5, _ 465635 ~1% {6} | REWRITE WITH Tmp.6 := 0, TEST InOut.3 = Tmp.6 KEEPING 6 465635 ~1% {5} r5 = SCAN r4 OUTPUT In.1, In.5, In.0, In.2, _ 465635 ~0% {5} | REWRITE WITH Out.4 := 0 741397 ~1% {7} r6 = SCAN `TypeInference::M2::IsInstantiationOf::resolveTypeAt/5#77e2181d#prev_delta` OUTPUT In.0, In.1, In.2, In.3, In.4, In.5, _ 275762 ~1% {6} | REWRITE WITH Tmp.6 := 0, TEST InOut.3 != Tmp.6 KEEPING 6 0 ~0% {7} r7 = JOIN r6 WITH `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev` ON FIRST 3 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.3, Lhs.5, Rhs.3, _ {7} | REWRITE WITH Tmp.6 := 1, Out.6 := (InOut.3 - Tmp.6), TEST Out.6 = InOut.5 0 ~0% {5} | SCAN OUTPUT In.1, In.4, In.0, In.2, In.3 465635 ~0% {5} r8 = r5 UNION r7 6 ~0% {4} | JOIN WITH `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0` ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Lhs.3, Lhs.4 29310 ~0% {5} r9 = JOIN `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev_delta` WITH `TypeInference::M2::IsInstantiationOf::resolveTypeAt/5#77e2181d#reorder_0_4_5_1_2_3#prev` ON FIRST 3 OUTPUT Lhs.0, Lhs.2, Rhs.3, Rhs.4, Rhs.5 29310 ~0% {6} r10 = SCAN r9 OUTPUT In.0, In.1, In.2, In.3, In.4, _ {5} | REWRITE WITH Tmp.5 := 0, TEST InOut.4 = Tmp.5 KEEPING 5 0 ~0% {5} | SCAN OUTPUT In.2, In.1, In.0, In.3, _ 0 ~0% {5} | REWRITE WITH Out.4 := 0 29310 ~0% {6} r11 = SCAN r9 OUTPUT In.0, In.1, In.2, In.3, In.4, _ {5} | REWRITE WITH Tmp.5 := 0, TEST InOut.4 != Tmp.5 KEEPING 5 29310 ~1% {6} | SCAN OUTPUT In.0, In.2, In.3, _, In.1, In.4 29310 ~1% {6} | REWRITE WITH Tmp.3 := 1, Out.3 := (InOut.5 - Tmp.3) 29241 ~0% {5} | JOIN WITH `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev` ON FIRST 4 OUTPUT Lhs.1, Lhs.4, Lhs.0, Lhs.2, Lhs.5 29241 ~0% {5} r12 = r10 UNION r11 {5} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 29241 ~1% {4} | SCAN OUTPUT In.2, In.0, In.3, In.4 465635 ~0% {6} r13 = SCAN r4 OUTPUT In.0, In.4, In.5, In.1, In.2, _ 465635 ~1% {6} | REWRITE WITH Out.5 := 0 0 ~0% {8} r14 = JOIN r6 WITH `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev` ON FIRST 3 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Rhs.3, _ {8} | REWRITE WITH Tmp.7 := 1, Out.7 := (InOut.3 - Tmp.7), TEST Out.7 = InOut.6 0 ~0% {6} | SCAN OUTPUT In.0, In.4, In.5, In.1, In.2, In.3 465635 ~1% {6} r15 = r13 UNION r14 465635 ~0% {5} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 3 OUTPUT Lhs.3, Lhs.2, Lhs.0, Lhs.4, Lhs.5 {5} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 465629 ~1% {4} | SCAN OUTPUT In.2, In.0, In.3, In.4 563353 ~1% {4} r16 = r2 UNION r3 UNION r8 UNION r12 UNION r15 563353 ~1% {4} | AND NOT `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypesFromIndex/4#716280b9#prev`(FIRST 4) return r16 ``` --- .../typeinference/internal/TypeInference.qll | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index 3c984d98e445..992f8128837d 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -423,27 +423,23 @@ module Make1 Input1> { ) } - /** - * Holds if `app` is a possible instantiation of `tm` at `path`. That is - * the type at `path` in `tm` is either a type parameter or equal to the - * type at the same path in `app`. - */ - bindingset[app, abs, tm, path] - private predicate satisfiesConcreteTypeAt( - App app, TypeAbstraction abs, TypeMention tm, TypePath path + pragma[nomagic] + private Type resolveNthTypeAt( + App app, TypeAbstraction abs, TypeMention tm, int i, TypePath path ) { - exists(Type t | - tm.resolveTypeAt(path) = t and - if t = abs.getATypeParameter() then any() else app.getTypeAt(path) = t - ) + potentialInstantiationOf(app, abs, tm) and + path = getNthPath(tm, i) and + result = tm.resolveTypeAt(path) } pragma[nomagic] private predicate satisfiesConcreteTypesFromIndex( App app, TypeAbstraction abs, TypeMention tm, int i ) { - potentialInstantiationOf(app, abs, tm) and - satisfiesConcreteTypeAt(app, abs, tm, getNthPath(tm, i)) and + exists(Type t, TypePath path | + t = resolveNthTypeAt(app, abs, tm, i, path) and + if t = abs.getATypeParameter() then any() else app.getTypeAt(path) = t + ) and // Recurse unless we are at the first path if i = 0 then any() else satisfiesConcreteTypesFromIndex(app, abs, tm, i - 1) } From 79e1af04df4cee194deea081f8190b23420b870d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 11 Jun 2025 09:21:58 +0200 Subject: [PATCH 5/6] Rust: Fix bad join in `satisfiesConstraintTypeMention` Before ``` Pipeline standard for TypeInference::CallExprBaseMatching::AccessConstraint::satisfiesConstraintTypeMention/6#69a92324@e8671rw7 was evaluated in 378 iterations totaling 313ms (delta sizes total: 168323). 462477 ~1% {7} r1 = JOIN `TypeInference::CallExprBaseMatching::AccessConstraint::hasConstraintMention/5#8730ee97#prev_delta` WITH TypeInference::CallExprBaseMatching::AccessConstraint::MkRelevantAccess#8a6252ad#reorder_3_0_1_2#prev ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.4, Lhs.3, Rhs.1, Rhs.2, Rhs.3 993561 ~2% {9} | JOIN WITH `TypeInference::M2::BaseTypes::conditionSatisfiesConstraintTypeAt/5#e92dcc7a` ON FIRST 3 OUTPUT Lhs.0, Lhs.1, Lhs.2, Rhs.3, Rhs.4, Lhs.3, Lhs.4, Lhs.5, Lhs.6 993561 ~38% {7} | JOIN WITH `TypeInference::M2::BaseTypes::conditionSatisfiesConstraintTypeAt/5#e92dcc7a` ON FIRST 5 OUTPUT Lhs.0, Lhs.4, Lhs.5, Lhs.6, Lhs.7, Lhs.8, Lhs.3 {7} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 772102 ~427% {6} | SCAN OUTPUT In.3, In.4, In.5, In.2, In.6, In.1 56885 ~1% {4} r2 = SCAN TypeInference::CallExprBaseMatching::AccessConstraint::MkRelevantAccess#8a6252ad#prev_delta OUTPUT In.3, In.0, In.1, In.2 0 ~0% {7} r3 = JOIN r2 WITH `TypeInference::CallExprBaseMatching::AccessConstraint::hasConstraintMention/5#8730ee97#prev` ON FIRST 1 OUTPUT Rhs.1, Rhs.2, Rhs.4, Lhs.1, Lhs.2, Lhs.3, Rhs.3 0 ~0% {9} | JOIN WITH `TypeInference::M2::BaseTypes::conditionSatisfiesConstraintTypeAt/5#e92dcc7a` ON FIRST 3 OUTPUT Lhs.0, Lhs.1, Lhs.2, Rhs.3, Rhs.4, Lhs.3, Lhs.4, Lhs.5, Lhs.6 0 ~0% {7} | JOIN WITH `TypeInference::M2::BaseTypes::conditionSatisfiesConstraintTypeAt/5#e92dcc7a` ON FIRST 5 OUTPUT Lhs.0, Lhs.4, Lhs.5, Lhs.6, Lhs.7, Lhs.8, Lhs.3 {7} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 0 ~0% {6} | SCAN OUTPUT In.2, In.3, In.4, In.5, In.6, In.1 462477 ~1% {8} r4 = JOIN `TypeInference::CallExprBaseMatching::AccessConstraint::hasConstraintMention/5#8730ee97#prev_delta` WITH TypeInference::CallExprBaseMatching::AccessConstraint::MkRelevantAccess#8a6252ad#reorder_3_0_1_2#prev ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.4, Lhs.0, Lhs.3, Rhs.1, Rhs.2, Rhs.3 993561 ~39% {9} | JOIN WITH `TypeInference::M2::BaseTypes::conditionSatisfiesConstraintTypeAt/5#e92dcc7a` ON FIRST 3 OUTPUT Lhs.0, Rhs.4, Lhs.3, Lhs.1, Lhs.4, Lhs.5, Lhs.6, Lhs.7, Rhs.3 23413 ~1% {8} | JOIN WITH `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0` ON FIRST 2 OUTPUT Lhs.3, Lhs.1, Lhs.2, Lhs.4, Lhs.5, Lhs.6, Lhs.7, Lhs.8 2817 ~7% {7} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1` ON FIRST 2 OUTPUT Lhs.2, Lhs.3, Lhs.4, Lhs.5, Lhs.6, Lhs.7, Rhs.2 11550 ~0% {9} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Rhs.2, _, Lhs.6, Rhs.1 {7} | REWRITE WITH Tmp.6 := "", Out.6 := InverseAppend(In.7,Tmp.6,In.8) KEEPING 7 2397 ~1% {11} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.5, _, _, In.4, In.6, _, _ {7} | REWRITE WITH Out.5 := (In.7 ++ In.8), Tmp.6 := (In.7 ++ In.8), Tmp.9 := "[0-9]+", Tmp.10 := "", Out.6 := regexpReplaceAll(Tmp.6,Tmp.9,Tmp.10) KEEPING 7 2397 ~1% {9} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.4, In.5, _, In.6, _ {7} | REWRITE WITH Out.6 := length(In.7), Tmp.8 := 10, TEST Out.6 <= Tmp.8 KEEPING 7 2397 ~1% {6} | SCAN OUTPUT In.1, In.2, In.3, In.0, In.5, In.4 66727 ~0% {6} r5 = JOIN `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev_delta` WITH TypeInference::CallExprBaseMatching::AccessConstraint::MkRelevantAccess#8a6252ad#reorder_3_0_1_2#prev ON FIRST 1 OUTPUT Lhs.0, Lhs.1, Lhs.2, Rhs.1, Rhs.2, Rhs.3 19305359 ~0% {9} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::hasConstraintMention/5#8730ee97#prev` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Rhs.2, Rhs.3, Rhs.4 3454881 ~1% {10} | JOIN WITH `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0` ON FIRST 1 OUTPUT Lhs.0, Lhs.6, Lhs.8, Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Lhs.7 753104 ~1% {9} | JOIN WITH `TypeInference::M2::BaseTypes::conditionSatisfiesConstraintTypeAt/5#e92dcc7a_01243#join_rhs` ON FIRST 4 OUTPUT Lhs.1, Lhs.3, Lhs.4, Lhs.5, Lhs.6, Lhs.7, Lhs.8, Lhs.9, Rhs.4 32040 ~18% {9} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1` ON FIRST 2 OUTPUT Lhs.3, Lhs.4, Lhs.5, Lhs.6, Lhs.7, Lhs.8, _, Rhs.2, Lhs.2 {7} | REWRITE WITH Tmp.6 := "", Out.6 := InverseAppend(In.7,Tmp.6,In.8) KEEPING 7 13192 ~54% {11} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.4, _, _, In.5, In.6, _, _ {7} | REWRITE WITH Out.5 := (In.7 ++ In.8), Tmp.6 := (In.7 ++ In.8), Tmp.9 := "[0-9]+", Tmp.10 := "", Out.6 := regexpReplaceAll(Tmp.6,Tmp.9,Tmp.10) KEEPING 7 13192 ~54% {9} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.4, In.5, _, In.6, _ {7} | REWRITE WITH Out.6 := length(In.7), Tmp.8 := 10, TEST Out.6 <= Tmp.8 KEEPING 7 13192 ~55% {6} | SCAN OUTPUT In.1, In.2, In.3, In.4, In.5, In.0 0 ~0% {8} r6 = JOIN r2 WITH `TypeInference::CallExprBaseMatching::AccessConstraint::hasConstraintMention/5#8730ee97#prev` ON FIRST 1 OUTPUT Rhs.1, Rhs.2, Rhs.4, Lhs.1, Lhs.2, Lhs.3, Lhs.0, Rhs.3 0 ~0% {9} | JOIN WITH `TypeInference::M2::BaseTypes::conditionSatisfiesConstraintTypeAt/5#e92dcc7a` ON FIRST 3 OUTPUT Lhs.0, Rhs.4, Lhs.3, Lhs.4, Lhs.5, Lhs.6, Lhs.1, Lhs.7, Rhs.3 0 ~0% {8} | JOIN WITH `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0` ON FIRST 2 OUTPUT Lhs.6, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Lhs.7, Lhs.8 0 ~0% {7} | JOIN WITH `TypeMention::TypeMention.resolveTypeAt/1#dispred#a125c821#bff#reorder_0_2_1` ON FIRST 2 OUTPUT Lhs.5, Lhs.2, Lhs.3, Lhs.4, Lhs.6, Lhs.7, Rhs.2 0 ~0% {9} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Rhs.2, _, Lhs.6, Rhs.1 {7} | REWRITE WITH Tmp.6 := "", Out.6 := InverseAppend(In.7,Tmp.6,In.8) KEEPING 7 0 ~0% {11} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.5, _, _, In.4, In.6, _, _ {7} | REWRITE WITH Out.5 := (In.7 ++ In.8), Tmp.6 := (In.7 ++ In.8), Tmp.9 := "[0-9]+", Tmp.10 := "", Out.6 := regexpReplaceAll(Tmp.6,Tmp.9,Tmp.10) KEEPING 7 0 ~0% {9} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.4, In.5, _, In.6, _ {7} | REWRITE WITH Out.6 := length(In.7), Tmp.8 := 10, TEST Out.6 <= Tmp.8 KEEPING 7 0 ~0% {6} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.5, In.4 787691 ~403% {6} r7 = r1 UNION r3 UNION r4 UNION r5 UNION r6 212766 ~54% {6} | AND NOT `TypeInference::CallExprBaseMatching::AccessConstraint::satisfiesConstraintTypeMention/6#69a92324#prev`(FIRST 6) return r7 ``` After ``` Pipeline standard for TypeInference::CallExprBaseMatching::AccessConstraint::satisfiesConstraintTypeMention/6#69a92324@9c099xwn was evaluated in 380 iterations totaling 11ms (delta sizes total: 153004). 768937 ~1% {7} r1 = SCAN `TypeInference::CallExprBaseMatching::AccessConstraint::satisfiesConstraintTypeMention0/9#c82a4f76#prev_delta` OUTPUT In.5, In.8, In.1, In.2, In.3, In.4, In.7 {7} | AND NOT `Type::TypeAbstraction.getATypeParameter/0#dispred#030257a0`(FIRST 2) 745524 ~423% {6} | SCAN OUTPUT In.2, In.3, In.4, In.5, In.6, In.1 26916 ~0% {9} r2 = JOIN `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev_delta` WITH `TypeInference::CallExprBaseMatching::AccessConstraint::satisfiesConstraintTypeMention1/7#b265d17e#prev` ON FIRST 1 OUTPUT Lhs.2, Rhs.1, Rhs.2, Rhs.3, Rhs.4, Rhs.5, _, Rhs.6, Lhs.1 {7} | REWRITE WITH Tmp.6 := "", Out.6 := InverseAppend(In.7,Tmp.6,In.8) KEEPING 7 8530 ~1% {11} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.4, _, _, In.5, In.6, _, _ {7} | REWRITE WITH Out.5 := (In.7 ++ In.8), Tmp.6 := (In.7 ++ In.8), Tmp.9 := "[0-9]+", Tmp.10 := "", Out.6 := regexpReplaceAll(Tmp.6,Tmp.9,Tmp.10) KEEPING 7 8530 ~1% {9} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.4, In.5, _, In.6, _ {7} | REWRITE WITH Out.6 := length(In.7), Tmp.8 := 10, TEST Out.6 <= Tmp.8 KEEPING 7 8530 ~1% {6} | SCAN OUTPUT In.1, In.2, In.3, In.4, In.5, In.0 11763 ~1% {9} r3 = JOIN `TypeInference::CallExprBaseMatching::AccessConstraint::satisfiesConstraintTypeMention1/7#b265d17e#prev_delta` WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5, Rhs.2, _, Lhs.6, Rhs.1 {7} | REWRITE WITH Tmp.6 := "", Out.6 := InverseAppend(In.7,Tmp.6,In.8) KEEPING 7 2461 ~1% {11} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.5, _, _, In.4, In.6, _, _ {7} | REWRITE WITH Out.5 := (In.7 ++ In.8), Tmp.6 := (In.7 ++ In.8), Tmp.9 := "[0-9]+", Tmp.10 := "", Out.6 := regexpReplaceAll(Tmp.6,Tmp.9,Tmp.10) KEEPING 7 2461 ~1% {9} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.4, In.5, _, In.6, _ {7} | REWRITE WITH Out.6 := length(In.7), Tmp.8 := 10, TEST Out.6 <= Tmp.8 KEEPING 7 2461 ~1% {6} | SCAN OUTPUT In.0, In.1, In.2, In.3, In.5, In.4 756515 ~396% {6} r4 = r1 UNION r2 UNION r3 155599 ~6% {6} | AND NOT `TypeInference::CallExprBaseMatching::AccessConstraint::satisfiesConstraintTypeMention/6#69a92324#prev`(FIRST 6) return r4 ``` --- .../typeinference/internal/TypeInference.qll | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index 992f8128837d..846ca24e2c97 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -1036,6 +1036,7 @@ module Make1 Input1> { /** * Holds if `at` satisfies `constraint` through `abs`, `sub`, and `constraintMention`. */ + pragma[nomagic] private predicate hasConstraintMention( RelevantAccess at, TypeAbstraction abs, TypeMention sub, Type constraint, TypeMention constraintMention @@ -1059,6 +1060,30 @@ module Make1 Input1> { ) } + pragma[nomagic] + predicate satisfiesConstraintTypeMention0( + RelevantAccess at, Access a, AccessPosition apos, TypePath prefix, Type constraint, + TypeAbstraction abs, TypeMention sub, TypePath path, Type t + ) { + exists(TypeMention constraintMention | + at = MkRelevantAccess(a, apos, prefix) and + hasConstraintMention(at, abs, sub, constraint, constraintMention) and + conditionSatisfiesConstraintTypeAt(abs, sub, constraintMention, path, t) + ) + } + + pragma[nomagic] + predicate satisfiesConstraintTypeMention1( + RelevantAccess at, Access a, AccessPosition apos, TypePath prefix, Type constraint, + TypePath path, TypePath pathToTypeParamInSub + ) { + exists(TypeAbstraction abs, TypeMention sub, TypeParameter tp | + satisfiesConstraintTypeMention0(at, a, apos, prefix, constraint, abs, sub, path, tp) and + tp = abs.getATypeParameter() and + sub.resolveTypeAt(pathToTypeParamInSub) = tp + ) + } + /** * Holds if the type at `a`, `apos`, and `path` satisfies the constraint * `constraint` with the type `t` at `path`. @@ -1067,22 +1092,18 @@ module Make1 Input1> { predicate satisfiesConstraintTypeMention( Access a, AccessPosition apos, TypePath prefix, Type constraint, TypePath path, Type t ) { + exists(TypeAbstraction abs | + satisfiesConstraintTypeMention0(_, a, apos, prefix, constraint, abs, _, path, t) and + not t = abs.getATypeParameter() + ) + or exists( - RelevantAccess at, TypeAbstraction abs, TypeMention sub, Type t0, TypePath prefix0, - TypeMention constraintMention + RelevantAccess at, TypePath prefix0, TypePath pathToTypeParamInSub, TypePath suffix | - at = MkRelevantAccess(a, apos, prefix) and - hasConstraintMention(at, abs, sub, constraint, constraintMention) and - conditionSatisfiesConstraintTypeAt(abs, sub, constraintMention, prefix0, t0) - | - not t0 = abs.getATypeParameter() and t = t0 and path = prefix0 - or - t0 = abs.getATypeParameter() and - exists(TypePath path3, TypePath suffix | - sub.resolveTypeAt(path3) = t0 and - at.getTypeAt(path3.appendInverse(suffix)) = t and - path = prefix0.append(suffix) - ) + satisfiesConstraintTypeMention1(at, a, apos, prefix, constraint, prefix0, + pathToTypeParamInSub) and + at.getTypeAt(pathToTypeParamInSub.appendInverse(suffix)) = t and + path = prefix0.append(suffix) ) } } From 3c9cbf186e1ff3c6a7fd0a439ab4b5b7fd462ce8 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 11 Jun 2025 10:07:37 +0200 Subject: [PATCH 6/6] Rust: Fix bad join in `typeParametersEqualFromIndex` Before ``` Pipeline standard for TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48@9c099swn was evaluated in 375 iterations totaling 154ms (delta sizes total: 0). 16307861 ~1% {5} r1 = JOIN `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev_delta` WITH `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypes/3#3b2e26a8#prev` ON FIRST 1 OUTPUT Rhs.2, Lhs.1, Lhs.0, Lhs.2, Rhs.1 37736 ~1% {7} r2 = JOIN r1 WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789_0312#join_rhs` ON FIRST 2 OUTPUT Lhs.2, Lhs.3, Lhs.4, Lhs.0, Rhs.2, Rhs.3, _ {6} | REWRITE WITH Tmp.6 := 0, TEST InOut.5 != Tmp.6 KEEPING 6 0 ~0% {7} | SCAN OUTPUT In.0, In.2, In.3, In.4, In.1, _, In.5 0 ~0% {7} | REWRITE WITH Tmp.5 := 1, Out.5 := (InOut.6 - Tmp.5) 0 ~0% {6} | JOIN WITH `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48#prev` ON FIRST 6 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.6 0 ~0% {8} r3 = JOIN `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48#prev_delta` WITH `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypes/3#3b2e26a8#prev` ON FIRST 3 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.3, Lhs.4, _, Lhs.5, _ {6} | REWRITE WITH Tmp.5 := 1, Out.5 := (Tmp.5 + In.6), Tmp.7 := 0, TEST Out.5 != Tmp.7 KEEPING 6 0 ~0% {6} | SCAN OUTPUT In.2, In.3, In.5, In.0, In.1, In.4 0 ~0% {7} | JOIN WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789` ON FIRST 3 OUTPUT Lhs.3, Rhs.3, Lhs.5, Lhs.4, Lhs.0, Lhs.1, Lhs.2 0 ~0% {6} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 3 OUTPUT Lhs.0, Lhs.3, Lhs.4, Lhs.5, Lhs.2, Lhs.6 12808446 ~1% {5} r4 = JOIN `TypeInference::M2::IsInstantiationOf::satisfiesConcreteTypes/3#3b2e26a8#prev_delta` WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 1 OUTPUT Lhs.2, Rhs.1, Lhs.0, Lhs.1, Rhs.2 22081 ~1% {7} r5 = JOIN r4 WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789_0312#join_rhs` ON FIRST 2 OUTPUT Lhs.2, Lhs.3, Lhs.0, Lhs.4, Rhs.2, Rhs.3, _ {6} | REWRITE WITH Tmp.6 := 0, TEST InOut.5 != Tmp.6 KEEPING 6 0 ~0% {6} | SCAN OUTPUT In.0, In.1, In.2, In.4, In.3, In.5 0 ~0% {8} | JOIN WITH `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48#prev` ON FIRST 5 OUTPUT Lhs.0, Lhs.1, Lhs.2, Lhs.4, Lhs.3, Lhs.5, Rhs.5, _ {8} | REWRITE WITH Tmp.7 := 1, Out.7 := (InOut.5 - Tmp.7), TEST Out.7 = InOut.6 0 ~0% {6} | SCAN OUTPUT In.0, In.1, In.2, In.4, In.3, In.5 22081 ~1% {8} r6 = JOIN r4 WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789_0312#join_rhs` ON FIRST 2 OUTPUT Lhs.2, Lhs.3, Lhs.0, Lhs.1, Lhs.4, Rhs.2, Rhs.3, _ {7} | REWRITE WITH Tmp.7 := 0, TEST InOut.6 = Tmp.7 KEEPING 7 22081 ~0% {7} | SCAN OUTPUT In.2, In.5, _, In.3, In.0, In.1, In.4 22081 ~0% {7} | REWRITE WITH Out.2 := 0 22081 ~0% {5} | JOIN WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789` ON FIRST 4 OUTPUT Lhs.0, Lhs.1, Lhs.4, Lhs.5, Lhs.6 0 ~0% {6} | JOIN WITH `project#TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789#3` ON FIRST 2 OUTPUT Lhs.2, Lhs.3, Lhs.0, Lhs.1, Lhs.4, _ 0 ~0% {6} | REWRITE WITH Out.5 := 0 37736 ~1% {8} r7 = JOIN r1 WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789_0312#join_rhs` ON FIRST 2 OUTPUT Lhs.2, Lhs.1, Lhs.3, Lhs.4, Lhs.0, Rhs.2, Rhs.3, _ {7} | REWRITE WITH Tmp.7 := 0, TEST InOut.6 = Tmp.7 KEEPING 7 37736 ~0% {7} | SCAN OUTPUT In.4, In.5, _, In.1, In.0, In.2, In.3 37736 ~0% {7} | REWRITE WITH Out.2 := 0 37736 ~1% {5} | JOIN WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789` ON FIRST 4 OUTPUT Lhs.0, Lhs.1, Lhs.4, Lhs.5, Lhs.6 0 ~0% {6} | JOIN WITH `project#TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789#3` ON FIRST 2 OUTPUT Lhs.2, Lhs.4, Lhs.0, Lhs.1, Lhs.3, _ 0 ~0% {6} | REWRITE WITH Out.5 := 0 0 ~0% {6} r8 = r2 UNION r3 UNION r5 UNION r6 UNION r7 0 ~0% {6} | AND NOT `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48#prev`(FIRST 6) return r8 ``` After ``` Pipeline standard for TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48@81728ywe was evaluated in 375 iterations totaling 2ms (delta sizes total: 0). 0 ~0% {6} r1 = JOIN `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndexBase/5#56e8595e#reorder_0_4_1_2_3#prev_delta` WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 2 OUTPUT Lhs.0, Lhs.2, Lhs.3, Lhs.4, Rhs.2, _ 0 ~0% {6} | REWRITE WITH Out.5 := 0 0 ~0% {6} r2 = JOIN `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev_delta` WITH `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndexBase/5#56e8595e#reorder_0_4_1_2_3#prev` ON FIRST 2 OUTPUT Lhs.0, Rhs.2, Rhs.3, Rhs.4, Lhs.2, _ 0 ~0% {6} | REWRITE WITH Out.5 := 0 66609 ~1% {3} r3 = SCAN `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev_delta` OUTPUT In.0, In.2, In.1 0 ~0% {9} | JOIN WITH `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48#reorder_0_4_1_2_3_5#prev` ON FIRST 2 OUTPUT Lhs.0, Lhs.2, Lhs.1, Rhs.2, Rhs.3, Rhs.4, _, Rhs.5, _ {7} | REWRITE WITH Tmp.6 := 1, Out.6 := (Tmp.6 + In.7), Tmp.8 := 0, TEST Out.6 != Tmp.8 KEEPING 7 0 ~0% {7} | SCAN OUTPUT In.4, In.5, In.6, In.1, In.0, In.2, In.3 0 ~0% {6} | JOIN WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789` ON FIRST 4 OUTPUT Lhs.4, Lhs.6, Lhs.0, Lhs.1, Lhs.5, Lhs.2 0 ~0% {8} r4 = SCAN `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48#prev_delta` OUTPUT In.0, In.1, In.2, In.3, In.4, _, In.5, _ {6} | REWRITE WITH Tmp.5 := 1, Out.5 := (Tmp.5 + In.6), Tmp.7 := 0, TEST Out.5 != Tmp.7 KEEPING 6 0 ~0% {6} | SCAN OUTPUT In.2, In.3, In.5, In.0, In.1, In.4 0 ~0% {7} | JOIN WITH `TypeInference::M2::IsInstantiationOf::getNthTypeParameterPath/3#c3ea2789` ON FIRST 3 OUTPUT Lhs.3, Rhs.3, Lhs.5, Lhs.4, Lhs.0, Lhs.1, Lhs.2 0 ~0% {6} | JOIN WITH `TypeInference::CallExprBaseMatching::AccessConstraint::RelevantAccess.getTypeAt/1#dispred#3a89868c#prev` ON FIRST 3 OUTPUT Lhs.0, Lhs.3, Lhs.4, Lhs.5, Lhs.2, Lhs.6 0 ~0% {6} r5 = r1 UNION r2 UNION r3 UNION r4 0 ~0% {6} | AND NOT `TypeInference::M2::IsInstantiationOf::typeParametersEqualFromIndex/6#6471ea48#prev`(FIRST 6) return r5 ``` --- .../typeinference/internal/TypeInference.qll | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index 846ca24e2c97..823459e83bb4 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -463,24 +463,34 @@ module Make1 Input1> { * Gets the path to the `i`th occurrence of `tp` within `tm` per some * arbitrary order, if any. */ + pragma[nomagic] private TypePath getNthTypeParameterPath(TypeMention tm, TypeParameter tp, int i) { result = rank[i + 1](TypePath path | tp = tm.resolveTypeAt(path) and relevantTypeMention(tm) | path) } + pragma[nomagic] + private predicate typeParametersEqualFromIndexBase( + App app, TypeAbstraction abs, TypeMention tm, TypeParameter tp, TypePath path + ) { + path = getNthTypeParameterPath(tm, tp, 0) and + satisfiesConcreteTypes(app, abs, tm) and + // no need to compute this predicate if there is only one path + exists(getNthTypeParameterPath(tm, tp, 1)) + } + pragma[nomagic] private predicate typeParametersEqualFromIndex( App app, TypeAbstraction abs, TypeMention tm, TypeParameter tp, Type t, int i ) { - satisfiesConcreteTypes(app, abs, tm) and exists(TypePath path | - path = getNthTypeParameterPath(tm, tp, i) and t = app.getTypeAt(path) and if i = 0 - then - // no need to compute this predicate if there is only one path - exists(getNthTypeParameterPath(tm, tp, 1)) - else typeParametersEqualFromIndex(app, abs, tm, tp, t, i - 1) + then typeParametersEqualFromIndexBase(app, abs, tm, tp, path) + else ( + typeParametersEqualFromIndex(app, abs, tm, tp, t, i - 1) and + path = getNthTypeParameterPath(tm, tp, i) + ) ) }