diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e8eed93499f..0f2906dab31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,9 +7,9 @@ repos: rev: v3.2.0 hooks: - id: trailing-whitespace - exclude: /test/.*$(? bar.md\n | .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | sed -f config foo.md > bar.md\n | .github/workflows/artifactpoisoning71.yml:4:5:4:16 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | python test.py | .github/workflows/artifactpoisoning81.yml:3:5:3:23 | pull_request_target | pull_request_target | -| .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | Uses Step | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | make snapshot | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | npm install | .github/workflows/artifactpoisoning96.yml:2:3:2:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | .github/workflows/artifactpoisoning101.yml:4:3:4:21 | pull_request_target | pull_request_target | -| .github/workflows/test18.yml:36:15:40:58 | Uses Step | .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Uses Step | .github/workflows/test18.yml:3:5:3:16 | workflow_run | workflow_run | -| .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | ./gradlew buildScanPublishPrevious\n | .github/workflows/test25.yml:2:3:2:14 | workflow_run | workflow_run | +| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run | +| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning11.yml:38:11:38:77 | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning11.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning12.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning12.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning12.yml:38:11:38:25 | python foo/x.py | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning12.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning21.yml:19:14:20:21 | sh foo/cmd\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning21.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning22.yml:13:9:17:6 | Uses Step | .github/workflows/artifactpoisoning22.yml:13:9:17:6 | Uses Step | .github/workflows/artifactpoisoning22.yml:18:14:18:19 | sh cmd | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning22.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning31.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning31.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning31.yml:19:14:19:22 | ./foo/cmd | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning31.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning32.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning32.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning32.yml:17:14:18:20 | ./bar/cmd\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning32.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning33.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning33.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning33.yml:17:14:18:20 | ./bar/cmd\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning33.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning34.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning34.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning34.yml:20:14:22:23 | npm install\nnpm run lint\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning34.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning41.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning41.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning41.yml:22:14:22:22 | ./foo/cmd | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning41.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning42.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning71.yml:4:5:4:16 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning81.yml:3:5:3:23 | pull_request_target | pull_request_target | +| .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning96.yml:2:3:2:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning101.yml:4:3:4:21 | pull_request_target | pull_request_target | +| .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/test18.yml:3:5:3:16 | workflow_run | workflow_run | +| .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/test25.yml:2:3:2:14 | workflow_run | workflow_run | diff --git a/cpp/ql/lib/change-notes/2026-04-07-autoconf.md b/cpp/ql/lib/change-notes/2026-04-07-autoconf.md new file mode 100644 index 00000000000..9f04417b8e2 --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-04-07-autoconf.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added a subclass `AutoconfConfigureTestFile` of `ConfigurationTestFile` that represents files created by GNU autoconf configure scripts to test the build configuration. diff --git a/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll b/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll index b39c1009f07..ae90caa0e63 100644 --- a/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll +++ b/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll @@ -42,3 +42,10 @@ class MesonPrivateTestFile extends ConfigurationTestFile { ) } } + +/** + * A file created by a GNU autoconf configure script to test the system configuration. + */ +class AutoconfConfigureTestFile extends ConfigurationTestFile { + AutoconfConfigureTestFile() { this.getBaseName().regexpMatch("conftest[0-9]*\\.c(pp)?") } +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.expected b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.expected new file mode 100644 index 00000000000..a87d2ddbd1b --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.expected @@ -0,0 +1,2 @@ +| conftest.c.c:4:3:4:8 | call to strlen | This expression has no effect (because $@ has no external side effects). | conftest.h:3:8:3:13 | strlen | strlen | +| conftest_abc.c:4:3:4:8 | call to strlen | This expression has no effect (because $@ has no external side effects). | conftest.h:3:8:3:13 | strlen | strlen | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.qlref b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.qlref new file mode 100644 index 00000000000..82a90f5413a --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.qlref @@ -0,0 +1 @@ +Likely Bugs/Likely Typos/ExprHasNoEffect.ql diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c new file mode 100644 index 00000000000..2e067f5c433 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main2() { + strlen(""); // GOOD: conftest files are ignored + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c.c new file mode 100644 index 00000000000..4ff7c225335 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c.c @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main3() { + strlen(""); // BAD: not a `conftest` file, as `conftest` is not directly followed by the extension or a sequence of numbers. + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.cpp b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.cpp new file mode 100644 index 00000000000..7b8edf64261 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.cpp @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main4() { + strlen(""); // GOOD: conftest files are ignored + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.h b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.h new file mode 100644 index 00000000000..9cf6f7e0d9f --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.h @@ -0,0 +1,3 @@ +typedef long long size_t; + +size_t strlen(const char *s); diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest123.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest123.c new file mode 100644 index 00000000000..b227d53ad2a --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest123.c @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main5() { + strlen(""); // GOOD: conftest files are ignored + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest_abc.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest_abc.c new file mode 100644 index 00000000000..88215d7434c --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest_abc.c @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main1() { + strlen(""); // BAD: not a `conftest` file, as `conftest` is not directly followed by the extension or a sequence of numbers. + return 0; +} diff --git a/csharp/ql/lib/Linq/Helpers.qll b/csharp/ql/lib/Linq/Helpers.qll index d490868f453..912b12b9457 100644 --- a/csharp/ql/lib/Linq/Helpers.qll +++ b/csharp/ql/lib/Linq/Helpers.qll @@ -77,7 +77,7 @@ predicate missedAllOpportunity(ForeachStmtGenericEnumerable fes) { // The then case of the if assigns false to something and breaks out of the loop. exists(Assignment a, BoolLiteral bl | a = is.getThen().getAChild*() and - bl = a.getRValue() and + bl = a.getRightOperand() and bl.toString() = "false" ) and is.getThen().getAChild*() instanceof BreakStmt diff --git a/csharp/ql/lib/change-notes/2026-04-01-getlrvalue.md b/csharp/ql/lib/change-notes/2026-04-01-getlrvalue.md new file mode 100644 index 00000000000..da1a3d62148 --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-04-01-getlrvalue.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The predicates `get[L|R]Value` in the class `Assignment` have been deprecated. Use `get[Left|Right]Operand` instead. diff --git a/csharp/ql/lib/definitions.qll b/csharp/ql/lib/definitions.qll index 4feaf20629c..d4f2540bbef 100644 --- a/csharp/ql/lib/definitions.qll +++ b/csharp/ql/lib/definitions.qll @@ -96,7 +96,7 @@ private class MethodUse extends Use, QualifiableExpr { private class AccessUse extends Access, Use { AccessUse() { not this.getTarget().(Parameter).getCallable() instanceof Accessor and - not this = any(LocalVariableDeclAndInitExpr d).getLValue() and + not this = any(LocalVariableDeclAndInitExpr d).getLeftOperand() and not this.isImplicit() and not this instanceof MethodAccess and // handled by `MethodUse` not this instanceof TypeAccess and // handled by `TypeMentionUse` diff --git a/csharp/ql/lib/semmle/code/csharp/Assignable.qll b/csharp/ql/lib/semmle/code/csharp/Assignable.qll index a0e575218ad..7075626aa3b 100644 --- a/csharp/ql/lib/semmle/code/csharp/Assignable.qll +++ b/csharp/ql/lib/semmle/code/csharp/Assignable.qll @@ -235,7 +235,7 @@ private class RefArg extends AssignableAccess { module AssignableInternal { private predicate tupleAssignmentDefinition(AssignExpr ae, Expr leaf) { exists(TupleExpr te | - ae.getLValue() = te and + ae.getLeftOperand() = te and te.getAnArgument+() = leaf and // `leaf` is either an assignable access or a local variable declaration not leaf instanceof TupleExpr @@ -249,8 +249,8 @@ module AssignableInternal { */ private predicate tupleAssignmentPair(AssignExpr ae, Expr left, Expr right) { tupleAssignmentDefinition(ae, _) and - left = ae.getLValue() and - right = ae.getRValue() + left = ae.getLeftOperand() and + right = ae.getRightOperand() or exists(TupleExpr l, TupleExpr r, int i | tupleAssignmentPair(ae, l, r) | left = l.getArgument(i) and @@ -291,7 +291,7 @@ module AssignableInternal { cached newtype TAssignableDefinition = TAssignmentDefinition(Assignment a) { - not a.getLValue() instanceof TupleExpr and + not a.getLeftOperand() instanceof TupleExpr and not a instanceof AssignCallOperation and not a instanceof AssignCoalesceExpr } or @@ -358,7 +358,7 @@ module AssignableInternal { // Not defined by dispatch in order to avoid too conservative negative recursion error cached AssignableAccess getTargetAccess(AssignableDefinition def) { - def = TAssignmentDefinition(any(Assignment a | a.getLValue() = result)) + def = TAssignmentDefinition(any(Assignment a | a.getLeftOperand() = result)) or def = TTupleAssignmentDefinition(_, result) or @@ -381,8 +381,8 @@ module AssignableInternal { tupleAssignmentPair(ae, ac, result) ) or - exists(Assignment ass | ac = ass.getLValue() | - result = ass.getRValue() and + exists(Assignment ass | ac = ass.getLeftOperand() | + result = ass.getRightOperand() and not ass instanceof AssignOperation ) or @@ -527,7 +527,7 @@ module AssignableDefinitions { Assignment getAssignment() { result = a } override Expr getSource() { - result = a.getRValue() and + result = a.getRightOperand() and not a instanceof AddOrRemoveEventExpr } diff --git a/csharp/ql/lib/semmle/code/csharp/Conversion.qll b/csharp/ql/lib/semmle/code/csharp/Conversion.qll index ec7ef9cac95..fd2c680e9c7 100644 --- a/csharp/ql/lib/semmle/code/csharp/Conversion.qll +++ b/csharp/ql/lib/semmle/code/csharp/Conversion.qll @@ -232,14 +232,9 @@ private module Identity { */ pragma[nomagic] private predicate convTypeArguments(Type fromTypeArgument, Type toTypeArgument, int i) { - exists(int j | - fromTypeArgument = getTypeArgumentRanked(_, _, i) and - toTypeArgument = getTypeArgumentRanked(_, _, j) and - i <= j and - j <= i - | - convIdentity(fromTypeArgument, toTypeArgument) - ) + fromTypeArgument = getTypeArgumentRanked(_, _, pragma[only_bind_into](i)) and + toTypeArgument = getTypeArgumentRanked(_, _, pragma[only_bind_into](i)) and + convIdentity(fromTypeArgument, toTypeArgument) } pragma[nomagic] @@ -929,19 +924,16 @@ private module Variance { private predicate convTypeArguments( TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i, TVariance v ) { - exists(int j | - fromTypeArgument = getTypeArgumentRanked(_, _, i, _) and - toTypeArgument = getTypeArgumentRanked(_, _, j, _) and - i <= j and - j <= i - | + fromTypeArgument = getTypeArgumentRanked(_, _, pragma[only_bind_into](i), _) and + toTypeArgument = getTypeArgumentRanked(_, _, pragma[only_bind_into](i), _) and + ( convIdentity(fromTypeArgument, toTypeArgument) and v = TNone() or - convRefTypeTypeArgumentOut(fromTypeArgument, toTypeArgument, j) and + convRefTypeTypeArgumentOut(fromTypeArgument, toTypeArgument, i) and v = TOut() or - convRefTypeTypeArgumentIn(toTypeArgument, fromTypeArgument, j) and + convRefTypeTypeArgumentIn(toTypeArgument, fromTypeArgument, i) and v = TIn() ) } diff --git a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll index 1ac96c85e78..1fab6b0f8c4 100644 --- a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll +++ b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll @@ -343,10 +343,10 @@ final class AssignmentNode extends ControlFlowElementNode { result.(TypeMentionNode).getTarget() = controlFlowElement or childIndex = 0 and - result.(ElementNode).getElement() = assignment.getLValue() + result.(ElementNode).getElement() = assignment.getLeftOperand() or childIndex = 1 and - result.(ElementNode).getElement() = assignment.getRValue() + result.(ElementNode).getElement() = assignment.getRightOperand() } } diff --git a/csharp/ql/lib/semmle/code/csharp/Property.qll b/csharp/ql/lib/semmle/code/csharp/Property.qll index bbd4fdd9d8e..c9a338d0359 100644 --- a/csharp/ql/lib/semmle/code/csharp/Property.qll +++ b/csharp/ql/lib/semmle/code/csharp/Property.qll @@ -535,8 +535,8 @@ class Setter extends Accessor, @setter { exists(AssignExpr assign | this.getStatementBody().getNumberOfStmts() = 1 and assign.getParent() = this.getStatementBody().getAChild() and - assign.getLValue() = result.getAnAccess() and - assign.getRValue() = accessToValue() + assign.getLeftOperand() = result.getAnAccess() and + assign.getRightOperand() = accessToValue() ) } diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll index 03a5aa7e2b7..6c1eb8c06eb 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll @@ -136,7 +136,7 @@ private module GuardsInput implements IdExpr() { this instanceof AssignExpr or this instanceof CastExpr } Expr getEqualChildExpr() { - result = this.(AssignExpr).getRValue() + result = this.(AssignExpr).getRightOperand() or result = this.(CastExpr).getExpr() } @@ -836,7 +836,7 @@ module Internal { /** Holds if expression `e2` is a `null` value whenever `e1` is. */ predicate nullValueImpliedUnary(Expr e1, Expr e2) { - e1 = e2.(AssignExpr).getRValue() + e1 = e2.(AssignExpr).getRightOperand() or e1 = e2.(Cast).getExpr() or @@ -923,7 +923,7 @@ module Internal { /** Holds if expression `e2` is a non-`null` value whenever `e1` is. */ predicate nonNullValueImpliedUnary(Expr e1, Expr e2) { e1 = e2.(CastExpr).getExpr() or - e1 = e2.(AssignExpr).getRValue() or + e1 = e2.(AssignExpr).getRightOperand() or e1 = e2.(NullCoalescingOperation).getAnOperand() } diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index e29e92d26eb..dc2c7477a35 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -521,7 +521,7 @@ module Expressions { // ``` // need special treatment, because the accesses `[0]`, `[1]`, and `[2]` // have no qualifier. - this = any(MemberInitializer mi).getLValue() + this = any(MemberInitializer mi).getLeftOperand() ) and not exists(AssignableDefinitions::OutRefDefinition def | def.getTargetAccess() = this) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll index a82779eaa5d..3d690ee1ac4 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll @@ -31,7 +31,7 @@ private Expr maybeNullExpr(Expr reason) { or result instanceof AsExpr and reason = result or - result.(AssignExpr).getRValue() = maybeNullExpr(reason) + result.(AssignExpr).getRightOperand() = maybeNullExpr(reason) or result.(CastExpr).getExpr() = maybeNullExpr(reason) or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll index af104d777b8..ab1e75b3d0f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll @@ -29,4 +29,8 @@ module CsharpDataFlow implements InputSig { predicate neverSkipInPathGraph(Node n) { exists(n.(AssignableDefinitionNode).getDefinition().getTargetAccess()) } + + DataFlowType getSourceContextParameterNodeType(Node p) { + exists(p) and result.isSourceContextParameterType() + } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 109c27de67b..ae530b2d451 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -528,7 +528,7 @@ module LocalFlow { e2 = any(AssignExpr ae | ae.getParent() = any(ControlFlowElement cfe | not cfe instanceof ExprStmt) and - e1 = ae.getRValue() + e1 = ae.getRightOperand() ) or e1 = e2.(ObjectCreation).getInitializer() @@ -554,7 +554,7 @@ module LocalFlow { e2 = we ) or - exists(AssignExpr ae | ae.getLValue().(TupleExpr) = e2 and ae.getRValue() = e1) + exists(AssignExpr ae | ae.getLeftOperand().(TupleExpr) = e2 and ae.getRightOperand() = e1) or exists(ControlFlowElement cfe | cfe = e2.(TupleExpr).(PatternExpr).getPatternMatch() | cfe.(IsExpr).getExpr() = e1 @@ -795,7 +795,7 @@ private predicate fieldOrPropertyStore(ContentSet c, Expr src, Expr q, boolean p q = we and mi = we.getInitializer().getAMemberInitializer() and f = mi.getInitializedMember() and - src = mi.getRValue() and + src = mi.getRightOperand() and postUpdate = false ) or @@ -804,7 +804,7 @@ private predicate fieldOrPropertyStore(ContentSet c, Expr src, Expr q, boolean p mi = q.(ObjectInitializer).getAMemberInitializer() and q.getParent() instanceof ObjectCreation and f = mi.getInitializedMember() and - src = mi.getRValue() and + src = mi.getRightOperand() and postUpdate = false ) or @@ -879,8 +879,8 @@ private predicate arrayStore(Expr src, Expr a, boolean postUpdate) { // Member initializer, `new C { Array = { [i] = src } }` exists(MemberInitializer mi | mi = a.(ObjectInitializer).getAMemberInitializer() and - mi.getLValue() instanceof ArrayAccess and - mi.getRValue() = src and + mi.getLeftOperand() instanceof ArrayAccess and + mi.getRightOperand() = src and postUpdate = false ) } @@ -1179,7 +1179,8 @@ private module Cached { cached newtype TDataFlowType = TGvnDataFlowType(Gvn::GvnType t) or - TDelegateDataFlowType(Callable lambda) { lambdaCreationExpr(_, lambda) } + TDelegateDataFlowType(Callable lambda) { lambdaCreationExpr(_, lambda) } or + TSourceContextParameterType() } import Cached @@ -2394,6 +2395,8 @@ class DataFlowType extends TDataFlowType { Callable asDelegate() { this = TDelegateDataFlowType(result) } + predicate isSourceContextParameterType() { this = TSourceContextParameterType() } + /** * Gets an expression that creates a delegate of this type. * @@ -2412,6 +2415,9 @@ class DataFlowType extends TDataFlowType { result = this.asGvnType().toString() or result = this.asDelegate().toString() + or + this.isSourceContextParameterType() and + result = "" } } @@ -2469,6 +2475,11 @@ private predicate compatibleTypesDelegateLeft(DataFlowType dt1, DataFlowType dt2 ) } +pragma[nomagic] +private predicate compatibleTypesSourceContextParameterTypeLeft(DataFlowType dt1, DataFlowType dt2) { + dt1.isSourceContextParameterType() and not exists(dt2.asDelegate()) +} + /** * Holds if `t1` and `t2` are compatible, that is, whether data can flow from * a node of type `t1` to a node of type `t2`. @@ -2499,6 +2510,10 @@ predicate compatibleTypes(DataFlowType dt1, DataFlowType dt2) { compatibleTypesDelegateLeft(dt2, dt1) or dt1.asDelegate() = dt2.asDelegate() + or + compatibleTypesSourceContextParameterTypeLeft(dt1, dt2) + or + compatibleTypesSourceContextParameterTypeLeft(dt2, dt1) } pragma[nomagic] @@ -2511,6 +2526,8 @@ predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { uselessTypebound(t2) or compatibleTypesDelegateLeft(t1, t2) + or + compatibleTypesSourceContextParameterTypeLeft(t1, t2) } /** @@ -2582,7 +2599,7 @@ module PostUpdateNodes { call.getExpr() = init.(CollectionInitializer).getAnElementInitializer() or // E.g. `new Dictionary() { [0] = "a", [1] = "b" }` - call.getExpr() = init.(ObjectInitializer).getAMemberInitializer().getLValue() + call.getExpr() = init.(ObjectInitializer).getAMemberInitializer().getLeftOperand() ) } @@ -2795,7 +2812,7 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves preservesValue = true or exists(AddEventExpr aee | - nodeFrom.asExpr() = aee.getRValue() and + nodeFrom.asExpr() = aee.getRightOperand() and nodeTo.asExpr().(EventRead).getTarget() = aee.getTarget() and preservesValue = false ) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll index 2809f8187b9..83593a5df36 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll @@ -337,7 +337,7 @@ private module CallGraph { pred = succ.(DelegateCreation).getArgument() or exists(AddEventExpr ae | succ.(EventAccess).getTarget() = ae.getTarget() | - pred = ae.getRValue() + pred = ae.getRightOperand() ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll index 46153f18dae..171f2d2f59e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll @@ -21,7 +21,7 @@ private module Impl { /** Holds if SSA definition `def` equals `e + delta`. */ predicate ssaUpdateStep(ExplicitDefinition def, ExprNode e, int delta) { exists(ControlFlow::Node cfn | cfn = def.getControlFlowNode() | - e = cfn.(ExprNode::Assignment).getRValue() and + e = cfn.(ExprNode::Assignment).getRightOperand() and delta = 0 and not cfn instanceof ExprNode::AssignOperation or @@ -39,7 +39,7 @@ private module Impl { /** Holds if `e1 + delta` equals `e2`. */ predicate valueFlowStep(ExprNode e2, ExprNode e1, int delta) { - e2.(ExprNode::AssignExpr).getRValue() = e1 and delta = 0 + e2.(ExprNode::AssignExpr).getRightOperand() = e1 and delta = 0 or e2.(ExprNode::UnaryPlusExpr).getOperand() = e1 and delta = 0 or @@ -207,13 +207,13 @@ module ExprNode { override CS::Assignment e; /** Gets the left operand of this assignment. */ - ExprNode getLValue() { - result = unique(ExprNode res | hasChild(e, e.getLValue(), this, res) | res) + ExprNode getLeftOperand() { + result = unique(ExprNode res | hasChild(e, e.getLeftOperand(), this, res) | res) } /** Gets the right operand of this assignment. */ - ExprNode getRValue() { - result = unique(ExprNode res | hasChild(e, e.getRValue(), this, res) | res) + ExprNode getRightOperand() { + result = unique(ExprNode res | hasChild(e, e.getRightOperand(), this, res) | res) } } @@ -225,6 +225,10 @@ module ExprNode { /** A compound assignment operation. */ class AssignOperation extends Assignment, BinaryOperation { override CS::AssignOperation e; + + override ExprNode getLeftOperand() { result = Assignment.super.getLeftOperand() } + + override ExprNode getRightOperand() { result = Assignment.super.getRightOperand() } } /** A unary operation. */ diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index d59d7958765..f64eceda134 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -168,7 +168,7 @@ private module Impl { /** Returned an expression that is assigned to `f`. */ ExprNode getAssignedValueToField(Field f) { result.getExpr() in [ - f.getAnAssignedValue(), any(AssignOperation a | a.getLValue() = f.getAnAccess()) + f.getAnAssignedValue(), any(AssignOperation a | a.getLeftOperand() = f.getAnAccess()) ] } @@ -231,7 +231,7 @@ private module Impl { /** Returns a sub expression of `e` for expression types where the sign depends on the child. */ ExprNode getASubExprWithSameSign(ExprNode e) { exists(Expr e_, Expr child | hasChild(e_, child, e, result) | - child = e_.(AssignExpr).getRValue() or + child = e_.(AssignExpr).getRightOperand() or child = e_.(UnaryPlusExpr).getOperand() or child = e_.(PostIncrExpr).getOperand() or child = e_.(PostDecrExpr).getOperand() or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaUtils.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaUtils.qll index 89117d90ba7..cf4b44239e9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaUtils.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaUtils.qll @@ -55,5 +55,5 @@ ExprNode ssaRead(Definition v, int delta) { or v.(ExplicitDefinition).getControlFlowNode().(ExprNode::Assignment) = result and delta = 0 or - result.(ExprNode::AssignExpr).getRValue() = ssaRead(v, delta) + result.(ExprNode::AssignExpr).getRightOperand() = ssaRead(v, delta) } diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index f7f6c7a50be..770fab65f54 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -1348,7 +1348,7 @@ private module Internal { any(DynamicMemberAccess dma | this = TDispatchDynamicEventAccess(_, dma, _)).getQualifier() } - override Expr getArgument(int i) { i = 0 and result = this.getCall().getRValue() } + override Expr getArgument(int i) { i = 0 and result = this.getCall().getRightOperand() } } /** A call to a constructor using dynamic types. */ diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll index 84375bc7013..d9fb16f0974 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll @@ -112,7 +112,7 @@ class BaseAccess extends Access, @base_access_expr { class MemberAccess extends Access, QualifiableExpr, @member_access_expr { override predicate hasImplicitThisQualifier() { QualifiableExpr.super.hasImplicitThisQualifier() and - not exists(MemberInitializer mi | mi.getLValue() = this) + not exists(MemberInitializer mi | mi.getLeftOperand() = this) } override Member getQualifiedDeclaration() { result = this.getTarget() } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll index 467149011d2..8c7dd80da24 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll @@ -20,14 +20,22 @@ class Assignment extends BinaryOperation, @assign_expr { expr_parent(_, 1, this) } - /** Gets the left operand of this assignment. */ - Expr getLValue() { result = this.getLeftOperand() } + /** + * DEPRECATED: Use `getLeftOperand` instead. + * + * Gets the left operand of this assignment. + */ + deprecated Expr getLValue() { result = this.getLeftOperand() } - /** Gets the right operand of this assignment. */ - Expr getRValue() { result = this.getRightOperand() } + /** + * DEPRECATED: Use `getRightOperand` instead. + * + * Gets the right operand of this assignment. + */ + deprecated Expr getRValue() { result = this.getRightOperand() } /** Gets the variable being assigned to, if any. */ - Variable getTargetVariable() { result.getAnAccess() = this.getLValue() } + Variable getTargetVariable() { result.getAnAccess() = this.getLeftOperand() } override string getOperator() { none() } } @@ -40,7 +48,12 @@ class LocalVariableDeclAndInitExpr extends LocalVariableDeclExpr, Assignment { override LocalVariable getTargetVariable() { result = this.getVariable() } - override LocalVariableAccess getLValue() { result = Assignment.super.getLValue() } + /** + * DEPRECATED: Use `getLeftOperand` instead. + */ + deprecated override LocalVariableAccess getLValue() { result = this.getLeftOperand() } + + override LocalVariableAccess getLeftOperand() { result = Assignment.super.getLeftOperand() } override string toString() { result = LocalVariableDeclExpr.super.toString() + " = ..." } @@ -223,9 +236,12 @@ deprecated class AssignUnsighedRightShiftExpr = AssignUnsignedRightShiftExpr; */ class AddOrRemoveEventExpr extends AssignOperation, @assign_event_expr { /** Gets the event targeted by this event assignment. */ - Event getTarget() { result = this.getLValue().getTarget() } + Event getTarget() { result = this.getLeftOperand().getTarget() } - override EventAccess getLValue() { result = this.getChild(0) } + /** + * DEPRECATED: Use `getLeftOperand` instead. + */ + deprecated override EventAccess getLValue() { result = this.getLeftOperand() } override EventAccess getLeftOperand() { result = this.getChild(0) } } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll index 0d9e414a5c4..272a8e0caae 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll @@ -773,7 +773,7 @@ class EventCall extends AccessorCall, EventAccessExpr { override EventAccessor getTarget() { exists(Event e, AddOrRemoveEventExpr aoree | e = this.getEvent() and - aoree.getLValue() = this + aoree.getLeftOperand() = this | aoree instanceof AddEventExpr and result = e.getAddEventAccessor() or @@ -784,8 +784,8 @@ class EventCall extends AccessorCall, EventAccessExpr { override Expr getArgument(int i) { i = 0 and exists(AddOrRemoveEventExpr aoree | - aoree.getLValue() = this and - result = aoree.getRValue() + aoree.getLeftOperand() = this and + result = aoree.getRightOperand() ) } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll index 0e16e0da9c3..19ff9fac53b 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll @@ -95,7 +95,7 @@ class MemberInitializer extends AssignExpr { MemberInitializer() { this.getParent() instanceof ObjectInitializer } /** Gets the initialized member. */ - Member getInitializedMember() { result.getAnAccess() = this.getLValue() } + Member getInitializedMember() { result.getAnAccess() = this.getLeftOperand() } override string getAPrimaryQlClass() { result = "MemberInitializer" } } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll index 66764d06479..36eda82531c 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll @@ -1099,7 +1099,7 @@ class QualifiableExpr extends Expr, @qualifiable_expr { } private Expr getAnAssignOrForeachChild() { - result = any(AssignExpr e).getLValue() + result = any(AssignExpr e).getLeftOperand() or result = any(ForeachStmt fs).getVariableDeclTuple() or diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll index 9ab9a026fd2..0beec9a84b2 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll @@ -41,6 +41,6 @@ class ReturnedByMockObject extends ObjectCreation { * Gets a value used to initialize a member of this object creation. */ Expr getAMemberInitializationValue() { - result = this.getInitializer().(ObjectInitializer).getAMemberInitializer().getRValue() + result = this.getInitializer().(ObjectInitializer).getAMemberInitializer().getRightOperand() } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Sql.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Sql.qll index 6b1eb7b67fb..58d6d68bf0e 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Sql.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Sql.qll @@ -17,14 +17,14 @@ abstract class SqlExpr extends Expr { class CommandTextAssignmentSqlExpr extends SqlExpr, AssignExpr { CommandTextAssignmentSqlExpr() { exists(Property p, SystemDataIDbCommandInterface i, Property text | - p = this.getLValue().(PropertyAccess).getTarget() and + p = this.getLeftOperand().(PropertyAccess).getTarget() and text = i.getCommandTextProperty() | p.overridesOrImplementsOrEquals(text) ) } - override Expr getSql() { result = this.getRValue() } + override Expr getSql() { result = this.getRightOperand() } } /** A construction of an unknown `IDbCommand` object. */ diff --git a/csharp/ql/lib/semmle/code/csharp/security/auth/SecureCookies.qll b/csharp/ql/lib/semmle/code/csharp/security/auth/SecureCookies.qll index 56b6294949b..e7cb6d8e308 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/auth/SecureCookies.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/auth/SecureCookies.qll @@ -100,20 +100,20 @@ Expr getAValueForCookiePolicyProp(string prop) { Expr getAValueForProp(ObjectCreation create, Assignment a, string prop) { // values set in object init exists(MemberInitializer init, Expr src, PropertyAccess pa | - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName(prop) and init = create.getInitializer().(ObjectInitializer).getAMemberInitializer() and - init.getLValue() = pa and - DataFlow::localExprFlow(src, init.getRValue()) and + init.getLeftOperand() = pa and + DataFlow::localExprFlow(src, init.getRightOperand()) and result = src ) or // values set on var that create is assigned to exists(Expr src, PropertyAccess pa | - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName(prop) and DataFlow::localExprFlow(create, pa.getQualifier()) and - DataFlow::localExprFlow(src, a.getRValue()) and + DataFlow::localExprFlow(src, a.getRightOperand()) and result = src ) } @@ -138,15 +138,15 @@ private module OnAppendCookieTrackingConfig impl exists(PropertyWrite pw, Assignment delegateAssign, Callable c | pw.getProperty().getName() = "OnAppendCookie" and pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreBuilderCookiePolicyOptions and - delegateAssign.getLValue() = pw and + delegateAssign.getLeftOperand() = pw and ( exists(LambdaExpr lambda | - delegateAssign.getRValue() = lambda and + delegateAssign.getRightOperand() = lambda and lambda = c ) or exists(DelegateCreation delegate | - delegateAssign.getRValue() = delegate and + delegateAssign.getRightOperand() = delegate and delegate.getArgument().(CallableAccess).getTarget() = c ) ) and @@ -159,9 +159,9 @@ private module OnAppendCookieTrackingConfig impl exists(PropertyWrite pw, Assignment a | pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieOptions and pw.getProperty().getName() = getPropertyName() and - a.getLValue() = pw and + a.getLeftOperand() = pw and exists(Expr val | - DataFlow::localExprFlow(val, a.getRValue()) and + DataFlow::localExprFlow(val, a.getRightOperand()) and val.getValue() = "true" ) and sink.asExpr() = pw.getQualifier() diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll index 5b2bd407a5c..3c8911ef807 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll @@ -126,16 +126,16 @@ private module TypeNameTrackingConfig implements DataFlow::ConfigSig { or node1.getType() instanceof TypeNameHandlingEnum and exists(PropertyWrite pw, Property p, Assignment a | - a.getLValue() = pw and + a.getLeftOperand() = pw and pw.getProperty() = p and p.getDeclaringType() instanceof JsonSerializerSettingsClass and p.hasName("TypeNameHandling") and ( - node1.asExpr() = a.getRValue() and + node1.asExpr() = a.getRightOperand() and node2.asExpr() = pw.getQualifier() or exists(ObjectInitializer oi | - node1.asExpr() = oi.getAMemberInitializer().getRValue() and + node1.asExpr() = oi.getAMemberInitializer().getRightOperand() and node2.asExpr() = oi ) ) diff --git a/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll index 1abeaf797b0..765dc2adf54 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll @@ -84,15 +84,15 @@ private Expr getAValueForProp(ObjectCreation create, string prop) { // values set in object init exists(MemberInitializer init | init = create.getInitializer().(ObjectInitializer).getAMemberInitializer() and - init.getLValue().(PropertyAccess).getTarget().hasName(prop) and - result = init.getRValue() + init.getLeftOperand().(PropertyAccess).getTarget().hasName(prop) and + result = init.getRightOperand() ) or // values set on var that create is assigned to exists(Assignment propAssign | - DataFlow::localExprFlow(create, propAssign.getLValue().(PropertyAccess).getQualifier()) and - propAssign.getLValue().(PropertyAccess).getTarget().hasName(prop) and - result = propAssign.getRValue() + DataFlow::localExprFlow(create, propAssign.getLeftOperand().(PropertyAccess).getQualifier()) and + propAssign.getLeftOperand().(PropertyAccess).getTarget().hasName(prop) and + result = propAssign.getRightOperand() ) } diff --git a/csharp/ql/src/Dead Code/NonAssignedFields.ql b/csharp/ql/src/Dead Code/NonAssignedFields.ql index 83aa889b77c..b9e86809749 100644 --- a/csharp/ql/src/Dead Code/NonAssignedFields.ql +++ b/csharp/ql/src/Dead Code/NonAssignedFields.ql @@ -84,9 +84,9 @@ where not f.getDeclaringType() instanceof Enum and not f.getType() instanceof Struct and not exists(Assignment ae, Field g | - ae.getLValue().(FieldAccess).getTarget() = g and + ae.getLeftOperand().(FieldAccess).getTarget() = g and g.getUnboundDeclaration() = f and - not ae.getRValue() instanceof NullLiteral + not ae.getRightOperand() instanceof NullLiteral ) and not exists(MethodCall mc, int i, Field g | exists(Parameter p | mc.getTarget().getParameter(i) = p | p.isOut() or p.isRef()) and @@ -101,7 +101,7 @@ where not init instanceof NullLiteral ) and not exists(AssignOperation ua, Field g | - ua.getLValue().(FieldAccess).getTarget() = g and + ua.getLeftOperand().(FieldAccess).getTarget() = g and g.getUnboundDeclaration() = f ) and not exists(MutatorOperation op | diff --git a/csharp/ql/src/Language Abuse/ForeachCapture.ql b/csharp/ql/src/Language Abuse/ForeachCapture.ql index 03f1f99a044..2ed24b42eba 100644 --- a/csharp/ql/src/Language Abuse/ForeachCapture.ql +++ b/csharp/ql/src/Language Abuse/ForeachCapture.ql @@ -60,16 +60,16 @@ module LambdaDataFlow { } Element getAssignmentTarget(Expr e) { - exists(Assignment a | a.getRValue() = e | - result = a.getLValue().(PropertyAccess).getTarget() or - result = a.getLValue().(FieldAccess).getTarget() or - result = a.getLValue().(LocalVariableAccess).getTarget() or - result = a.getLValue().(EventAccess).getTarget() + exists(Assignment a | a.getRightOperand() = e | + result = a.getLeftOperand().(PropertyAccess).getTarget() or + result = a.getLeftOperand().(FieldAccess).getTarget() or + result = a.getLeftOperand().(LocalVariableAccess).getTarget() or + result = a.getLeftOperand().(EventAccess).getTarget() ) or exists(AddEventExpr aee | - e = aee.getRValue() and - result = aee.getLValue().getTarget() + e = aee.getRightOperand() and + result = aee.getLeftOperand().getTarget() ) or result = getCollectionAssignmentTarget(e) @@ -97,8 +97,8 @@ Element getCollectionAssignmentTarget(Expr e) { // Store values using indexer exists(IndexerAccess ia, AssignExpr ae | ia.getQualifier() = result.(Variable).getAnAccess() and - ia = ae.getLValue() and - e = ae.getRValue() + ia = ae.getLeftOperand() and + e = ae.getRightOperand() ) } diff --git a/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql b/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql index bd7492b8583..01d6baa9573 100644 --- a/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql +++ b/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql @@ -15,7 +15,7 @@ import csharp import semmle.code.csharp.commons.StructuralComparison private Expr getAssignedExpr(Stmt stmt) { - result = stmt.stripSingletonBlocks().(ExprStmt).getExpr().(AssignExpr).getLValue() + result = stmt.stripSingletonBlocks().(ExprStmt).getExpr().(AssignExpr).getLeftOperand() } from IfStmt is, string what diff --git a/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql b/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql index 5fcb140e679..046099213cc 100644 --- a/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql +++ b/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql @@ -23,9 +23,10 @@ where ) and forex(Access a | a = v.getAnAccess() | a = any(ModifierMethodCall m).getQualifier() or - a = any(AssignExpr ass | ass.getRValue() instanceof ObjectCreation).getLValue() or + a = any(AssignExpr ass | ass.getRightOperand() instanceof ObjectCreation).getLeftOperand() or a = - any(LocalVariableDeclAndInitExpr ass | ass.getRValue() instanceof ObjectCreation).getLValue() + any(LocalVariableDeclAndInitExpr ass | ass.getRightOperand() instanceof ObjectCreation) + .getLeftOperand() ) and not v = any(ForeachStmt fs).getVariable() and not v = any(BindingPatternExpr vpe).getVariableDeclExpr().getVariable() and diff --git a/csharp/ql/src/Likely Bugs/SelfAssignment.ql b/csharp/ql/src/Likely Bugs/SelfAssignment.ql index f01a1378242..6e51b87a779 100644 --- a/csharp/ql/src/Likely Bugs/SelfAssignment.ql +++ b/csharp/ql/src/Likely Bugs/SelfAssignment.ql @@ -19,7 +19,7 @@ private predicate candidate(AssignExpr ae) { not ae instanceof MemberInitializer and // Enum field initializers are never self assignments. `enum E { A = 42 }` not ae.getParent().(Field).getDeclaringType() instanceof Enum and - forall(Expr e | e = ae.getLValue().getAChildExpr*() | + forall(Expr e | e = ae.getLeftOperand().getAChildExpr*() | // Non-trivial property accesses may have side-effects, // so these are not considered e instanceof PropertyAccess implies e instanceof TrivialPropertyAccess @@ -28,7 +28,7 @@ private predicate candidate(AssignExpr ae) { private predicate selfAssignExpr(AssignExpr ae) { candidate(ae) and - sameGvn(ae.getLValue(), ae.getRValue()) + sameGvn(ae.getLeftOperand(), ae.getRightOperand()) } private Declaration getDeclaration(Expr e) { @@ -40,5 +40,5 @@ private Declaration getDeclaration(Expr e) { } from AssignExpr ae, Declaration target -where selfAssignExpr(ae) and target = getDeclaration(ae.getLValue()) +where selfAssignExpr(ae) and target = getDeclaration(ae.getLeftOperand()) select ae, "This assignment assigns $@ to itself.", target, target.getName() diff --git a/csharp/ql/src/Linq/BadMultipleIteration.ql b/csharp/ql/src/Linq/BadMultipleIteration.ql index 8146bbf167d..0f9e335e225 100644 --- a/csharp/ql/src/Linq/BadMultipleIteration.ql +++ b/csharp/ql/src/Linq/BadMultipleIteration.ql @@ -50,7 +50,7 @@ predicate potentiallyConsumingAccess(VariableAccess va) { Expr sequenceSource(IEnumerableSequence seq) { result = seq.getInitializer() or - exists(Assignment a | a.getLValue() = seq.getAnAccess() and result = a.getRValue()) + exists(Assignment a | a.getLeftOperand() = seq.getAnAccess() and result = a.getRightOperand()) } from IEnumerableSequence seq, VariableAccess va diff --git a/csharp/ql/src/Performance/StringConcatenationInLoop.ql b/csharp/ql/src/Performance/StringConcatenationInLoop.ql index 3b3228588a4..d27b99e7bdd 100644 --- a/csharp/ql/src/Performance/StringConcatenationInLoop.ql +++ b/csharp/ql/src/Performance/StringConcatenationInLoop.ql @@ -24,7 +24,7 @@ class StringCat extends AddExpr { */ predicate isSelfConcatAssignExpr(AssignExpr e, Variable v) { exists(VariableAccess use | - stringCatContains(e.getRValue(), use) and + stringCatContains(e.getRightOperand(), use) and use.getTarget() = e.getTargetVariable() and v = use.getTarget() ) @@ -41,7 +41,7 @@ predicate stringCatContains(StringCat expr, Expr child) { * where `v` is a simple variable (and not, for example, a property). */ predicate isConcatExpr(AssignAddExpr e, Variable v) { - e.getLValue().getType() instanceof StringType and + e.getLeftOperand().getType() instanceof StringType and v = e.getTargetVariable() } diff --git a/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql b/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql index dcc520540bb..f72de01b5db 100644 --- a/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql +++ b/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql @@ -27,8 +27,8 @@ predicate cookieAppendHttpOnlyByDefault() { predicate httpOnlyFalse(ObjectCreation oc) { exists(Assignment a | - getAValueForProp(oc, a, "HttpOnly") = a.getRValue() and - a.getRValue().getValue() = "false" + getAValueForProp(oc, a, "HttpOnly") = a.getRightOperand() and + a.getRightOperand().getValue() = "false" ) } @@ -100,8 +100,8 @@ predicate nonHttpOnlyCookieBuilderAssignment(Assignment a, Expr val) { MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions ) and pw.getProperty().getName() = "HttpOnly" and - a.getLValue() = pw and - DataFlow::localExprFlow(val, a.getRValue()) + a.getLeftOperand() = pw and + DataFlow::localExprFlow(val, a.getRightOperand()) ) } @@ -111,7 +111,7 @@ where nonHttpOnlyCookieCall(httpOnlySink) or exists(Assignment a | - httpOnlySink = a.getRValue() and + httpOnlySink = a.getRightOperand() and nonHttpOnlyCookieBuilderAssignment(a, _) ) ) diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql index 330ad1c1c32..a1dd249faba 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql @@ -35,8 +35,8 @@ module InsecureSqlConnectionConfig implements DataFlow::ConfigSig { ) and not exists(MemberInitializer mi | mi = oc.getInitializer().(ObjectInitializer).getAMemberInitializer() and - mi.getLValue().(PropertyAccess).getTarget().getName() = "Encrypt" and - mi.getRValue().(BoolLiteral).getValue() = "true" + mi.getLeftOperand().(PropertyAccess).getTarget().getName() = "Encrypt" and + mi.getRightOperand().(BoolLiteral).getValue() = "true" ) ) } diff --git a/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql b/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql index ce1f75d627c..1149b4bcad2 100644 --- a/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql +++ b/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql @@ -31,8 +31,8 @@ predicate cookieAppendSecureByDefault() { predicate secureFalse(ObjectCreation oc) { exists(Assignment a | - getAValueForProp(oc, a, "Secure") = a.getRValue() and - a.getRValue().getValue() = "false" + getAValueForProp(oc, a, "Secure") = a.getRightOperand() and + a.getRightOperand().getValue() = "false" ) } @@ -96,8 +96,8 @@ predicate insecureSecurePolicyAssignment(Assignment a, Expr val) { MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions ) and pw.getProperty().getName() = "SecurePolicy" and - a.getLValue() = pw and - DataFlow::localExprFlow(val, a.getRValue()) and + a.getLeftOperand() = pw and + DataFlow::localExprFlow(val, a.getRightOperand()) and val.getValue() = "2" // None ) } @@ -107,7 +107,7 @@ where insecureCookieCall(secureSink) or exists(Assignment a | - secureSink = a.getRValue() and + secureSink = a.getRightOperand() and insecureSecurePolicyAssignment(a, _) ) select secureSink, "Cookie attribute 'Secure' is not set to true." diff --git a/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql b/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql index 9c6e6935186..59a6340104a 100644 --- a/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql +++ b/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql @@ -14,11 +14,11 @@ import csharp from Assignment a, PropertyAccess pa where - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName("Domain") and pa.getTarget().getDeclaringType().hasFullyQualifiedName("System.Web", "HttpCookie") and ( - a.getRValue().getValue().regexpReplaceAll("[^.]", "").length() < 2 or - a.getRValue().getValue().matches(".%") + a.getRightOperand().getValue().regexpReplaceAll("[^.]", "").length() < 2 or + a.getRightOperand().getValue().matches(".%") ) select a, "Overly broad domain for cookie." diff --git a/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql b/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql index 6690cac47d2..d659f7c8dc5 100644 --- a/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql +++ b/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql @@ -14,8 +14,8 @@ import csharp from Assignment a, PropertyAccess pa where - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName("Path") and pa.getTarget().getDeclaringType().hasFullyQualifiedName("System.Web", "HttpCookie") and - a.getRValue().getValue() = "/" + a.getRightOperand().getValue() = "/" select a, "Overly broad path for cookie." diff --git a/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql b/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql index 7a3a5fdc4f2..bc9bf289c2d 100644 --- a/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql +++ b/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql @@ -17,12 +17,12 @@ from Element l where // header checking is disabled programmatically in the code exists(Assignment a, PropertyAccess pa | - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName("EnableHeaderChecking") and pa.getTarget() .getDeclaringType() .hasFullyQualifiedName("System.Web.Configuration", "HttpRuntimeSection") and - a.getRValue().getValue() = "false" and + a.getRightOperand().getValue() = "false" and a = l ) or diff --git a/csharp/ql/src/Security Features/InsecureRandomness.ql b/csharp/ql/src/Security Features/InsecureRandomness.ql index 8237afdff13..649969a2778 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.ql +++ b/csharp/ql/src/Security Features/InsecureRandomness.ql @@ -89,10 +89,10 @@ module Random { e = any(SensitiveLibraryParameter v).getAnAssignedArgument() or // Assignment operation, e.g. += or similar - exists(AssignOperation ao | ao.getRValue() = e | - ao.getLValue() = any(SensitiveVariable v).getAnAccess() or - ao.getLValue() = any(SensitiveProperty v).getAnAccess() or - ao.getLValue() = any(SensitiveLibraryParameter v).getAnAccess() + exists(AssignOperation ao | ao.getRightOperand() = e | + ao.getLeftOperand() = any(SensitiveVariable v).getAnAccess() or + ao.getLeftOperand() = any(SensitiveProperty v).getAnAccess() or + ao.getLeftOperand() = any(SensitiveLibraryParameter v).getAnAccess() ) ) } diff --git a/csharp/ql/src/Security Features/InsufficientKeySize.ql b/csharp/ql/src/Security Features/InsufficientKeySize.ql index 94ae6b9286f..02be9125835 100644 --- a/csharp/ql/src/Security Features/InsufficientKeySize.ql +++ b/csharp/ql/src/Security Features/InsufficientKeySize.ql @@ -20,7 +20,7 @@ predicate incorrectUseOfRC2(Assignment e, string msg) { .getDeclaringType() .hasFullyQualifiedName("System.Security.Cryptography", "RC2CryptoServiceProvider") ) and - e.getRValue().getValue().toInt() < 128 and + e.getRightOperand().getValue().toInt() < 128 and msg = "Key size should be at least 128 bits for RC2 encryption." } diff --git a/csharp/ql/src/Security Features/PersistentCookie.ql b/csharp/ql/src/Security Features/PersistentCookie.ql index 7f9861213fc..edc97b464e5 100644 --- a/csharp/ql/src/Security Features/PersistentCookie.ql +++ b/csharp/ql/src/Security Features/PersistentCookie.ql @@ -52,8 +52,8 @@ class FutureDateExpr extends MethodCall { from Assignment a, PropertyAccess pa, FutureDateExpr fde where - a.getLValue() = pa and - a.getRValue() = fde and + a.getLeftOperand() = pa and + a.getRightOperand() = fde and pa.getTarget().hasName("Expires") and pa.getTarget().getDeclaringType().hasFullyQualifiedName("System.Web", "HttpCookie") and (fde.timeIsNotClear() or fde.getTimeInSecond() > 300) // 5 minutes max diff --git a/csharp/ql/src/Telemetry/DatabaseQuality.qll b/csharp/ql/src/Telemetry/DatabaseQuality.qll index ca2ab3e7e16..ad7ac682bf5 100644 --- a/csharp/ql/src/Telemetry/DatabaseQuality.qll +++ b/csharp/ql/src/Telemetry/DatabaseQuality.qll @@ -27,7 +27,7 @@ module CallTargetStats implements StatsSig { p = c.getProperty() and not p.getAnAccessor() instanceof Setter and assign = c.getParent() and - assign.getLValue() = c and + assign.getLeftOperand() = c and assign.getParent() instanceof Property ) } @@ -36,7 +36,7 @@ module CallTargetStats implements StatsSig { exists(Property p, AssignExpr assign | p = c.getProperty() and assign = c.getParent() and - assign.getLValue() = c and + assign.getLeftOperand() = c and assign.getParent() instanceof ObjectInitializer and assign.getParent().getParent() instanceof AnonymousObjectCreation ) @@ -46,8 +46,8 @@ module CallTargetStats implements StatsSig { exists(Property p, AssignExpr assign | p = c.getProperty() and assign = c.getParent() and - assign.getLValue() = c and - assign.getRValue() instanceof ObjectOrCollectionInitializer + assign.getLeftOperand() = c and + assign.getRightOperand() instanceof ObjectOrCollectionInitializer ) } diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql index d43050c2deb..0dc8fc362d6 100644 --- a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql +++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql @@ -187,10 +187,10 @@ module HashWithoutSaltConfig implements DataFlow::ConfigSig { or // a salt or key is included in subclasses of `KeyedHashAlgorithm` exists(MethodCall mc, Assignment a, ObjectCreation oc | - a.getRValue() = oc and + a.getRightOperand() = oc and oc.getObjectType().getABaseType+() instanceof KeyedHashAlgorithm and mc.getTarget() instanceof HashMethod and - a.getLValue() = mc.getQualifier().(VariableAccess).getTarget().getAnAccess() and + a.getLeftOperand() = mc.getQualifier().(VariableAccess).getTarget().getAnAccess() and mc.getArgument(0) = node.asExpr() ) } diff --git a/csharp/ql/test/library-tests/assignments/AssignOperation.ql b/csharp/ql/test/library-tests/assignments/AssignOperation.ql index 2ca3b11a831..2fa23ed0a9f 100644 --- a/csharp/ql/test/library-tests/assignments/AssignOperation.ql +++ b/csharp/ql/test/library-tests/assignments/AssignOperation.ql @@ -1,4 +1,4 @@ import csharp from AssignOperation ao -select ao, ao.getLValue(), ao.getRValue() +select ao, ao.getLeftOperand(), ao.getRightOperand() diff --git a/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql b/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql index 69e7db8c1cf..450ed9940a8 100644 --- a/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql +++ b/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql @@ -1,5 +1,5 @@ import csharp from Assignment a -select a.getLocation(), a.getLValue().getType().toString(), a.getRValue().getType().toString(), - a.getRValue().toString() +select a.getLocation(), a.getLeftOperand().getType().toString(), + a.getRightOperand().getType().toString(), a.getRightOperand().toString() diff --git a/csharp/ql/test/library-tests/csharp10/lambda.ql b/csharp/ql/test/library-tests/csharp10/lambda.ql index 3cfec302b52..55c7faac049 100644 --- a/csharp/ql/test/library-tests/csharp10/lambda.ql +++ b/csharp/ql/test/library-tests/csharp10/lambda.ql @@ -3,7 +3,7 @@ import csharp private predicate getLambda( LocalVariableDeclAndInitExpr e, string type, LocalVariable v, LambdaExpr lexp ) { - lexp = e.getRValue() and + lexp = e.getRightOperand() and v = e.getTargetVariable() and type = e.getType().toStringWithTypes() } diff --git a/csharp/ql/test/library-tests/csharp11/operators.ql b/csharp/ql/test/library-tests/csharp11/operators.ql index 607efac0c26..f1543e2d744 100644 --- a/csharp/ql/test/library-tests/csharp11/operators.ql +++ b/csharp/ql/test/library-tests/csharp11/operators.ql @@ -14,8 +14,8 @@ query predicate assignbitwise( AssignBitwiseOperation op, Expr left, Expr right, string name, string qlclass ) { op.getFile().getStem() = "Operators" and - left = op.getLValue() and - right = op.getRValue() and + left = op.getLeftOperand() and + right = op.getRightOperand() and name = op.getOperator() and qlclass = op.getAPrimaryQlClass() } diff --git a/csharp/ql/test/library-tests/csharp6/MemberInitializer.ql b/csharp/ql/test/library-tests/csharp6/MemberInitializer.ql index f3ef63fe225..1895792f07c 100644 --- a/csharp/ql/test/library-tests/csharp6/MemberInitializer.ql +++ b/csharp/ql/test/library-tests/csharp6/MemberInitializer.ql @@ -12,7 +12,7 @@ query predicate indexerCalls(IndexerCall indexer, int arg, Expr value) { query predicate elementAssignments( ElementWrite write, Assignment assignment, int index, Expr indexer ) { - write = assignment.getLValue() and indexer = write.getIndex(index) + write = assignment.getLeftOperand() and indexer = write.getIndex(index) } query predicate arrayQualifiers(ElementAccess access, Expr qualifier) { diff --git a/csharp/ql/test/library-tests/enums/Enums11.ql b/csharp/ql/test/library-tests/enums/Enums11.ql index 36b2c005a21..f6133517f7d 100644 --- a/csharp/ql/test/library-tests/enums/Enums11.ql +++ b/csharp/ql/test/library-tests/enums/Enums11.ql @@ -6,7 +6,7 @@ import csharp from Expr e where - exists(Assignment a | a.getRValue() = e | + exists(Assignment a | a.getRightOperand() = e | a.getParent().(Field).getDeclaringType() instanceof Enum ) select e, e.getValue() diff --git a/csharp/ql/test/library-tests/expressions/AddEventExpr1.ql b/csharp/ql/test/library-tests/expressions/AddEventExpr1.ql index 48f6b41e19d..e3c1530fb1a 100644 --- a/csharp/ql/test/library-tests/expressions/AddEventExpr1.ql +++ b/csharp/ql/test/library-tests/expressions/AddEventExpr1.ql @@ -9,5 +9,5 @@ where c.hasName("LoginDialog") and e.getEnclosingCallable() = c and e.getTarget().hasName("Click") and - e.getLValue().getQualifier().(FieldAccess).getTarget().hasName("OkButton") + e.getLeftOperand().getQualifier().(FieldAccess).getTarget().hasName("OkButton") select c, e diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod1.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod1.ql index 2c8268e87e1..74e9d3cb1ff 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod1.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod1.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f7") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f7") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod2.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod2.ql index e9fbbf01a10..8f0390b0f82 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod2.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod2.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e, Parameter p, ParameterAccess pa where - assign.getLValue().(VariableAccess).getTarget().hasName("f7") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f7") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and p = e.getParameter(0) and diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod3.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod3.ql index e4c2e9ae9ba..46d8907319d 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod3.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod3.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f7") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f7") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getType().(DelegateType).getReturnType() instanceof IntType diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod4.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod4.ql index 4d424b65b84..cca81c6b04e 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod4.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod4.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f8") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f8") and e.getParent+() = assign and e.hasNoParameters() select e, e diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod5.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod5.ql index cbc6ac82ca7..577d810dfad 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod5.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod5.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e, LocalVariableAccess va where - assign.getLValue().(VariableAccess).getTarget().hasName("f8") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f8") and e.getParent+() = assign and e.hasNoParameters() and va.getEnclosingStmt().getParent+() = e.getBody() and diff --git a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation1.ql b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation1.ql index 74d8cd27a94..c717aa260e0 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation1.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation1.ql @@ -6,11 +6,11 @@ import csharp from Assignment assign, AnonymousObjectCreation o, Assignment a, Property p where - assign.getLValue().(VariableAccess).getTarget().hasName("list2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("list2") and o.getParent+() = assign and o.getInitializer().getMemberInitializer(0) = a and - a.getRValue().getValue() = "2" and - p = a.getLValue().(PropertyAccess).getTarget() and + a.getRightOperand().getValue() = "2" and + p = a.getLeftOperand().(PropertyAccess).getTarget() and p.hasName("i") and p.getDeclaringType() = o.getObjectType() select o diff --git a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation2.ql b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation2.ql index 5f9e16564b4..d55bf89d606 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation2.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation2.ql @@ -6,11 +6,11 @@ import csharp from Assignment assign, AnonymousObjectCreation o, Assignment a, Property p where - assign.getLValue().(VariableAccess).getTarget().hasName("contacts2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("contacts2") and o.getParent+() = assign and o.getInitializer().getMemberInitializer(0) = a and - a.getRValue().getValue() = "Chris Smith" and - p = a.getLValue().(PropertyAccess).getTarget() and + a.getRightOperand().getValue() = "Chris Smith" and + p = a.getLeftOperand().(PropertyAccess).getTarget() and p.hasName("Name") and p.getDeclaringType() = o.getObjectType() select o, p.getType().toString() diff --git a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation3.ql b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation3.ql index afa9ca0d3b2..6033bfed38a 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation3.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation3.ql @@ -6,11 +6,11 @@ import csharp from Assignment assign, AnonymousObjectCreation o, Assignment a, Property p where - assign.getLValue().(VariableAccess).getTarget().hasName("contacts2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("contacts2") and o.getParent+() = assign and o.getInitializer().getMemberInitializer(1) = a and - a.getRValue() instanceof ArrayCreation and - p = a.getLValue().(PropertyAccess).getTarget() and + a.getRightOperand() instanceof ArrayCreation and + p = a.getLeftOperand().(PropertyAccess).getTarget() and p.hasName("PhoneNumbers") and p.getDeclaringType() = o.getObjectType() select o, p.getType().getName() diff --git a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation4.ql b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation4.ql index b6354d1f493..a52278839f2 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation4.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation4.ql @@ -8,7 +8,7 @@ from Assignment assign, AnonymousObjectCreation o, Assignment a, AnonymousObjectCreation p, Assignment b where - assign.getLValue().(VariableAccess).getTarget().hasName("contacts2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("contacts2") and o.getParent+() = assign and o.getInitializer().getMemberInitializer(1) = a and p.getParent+() = assign and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation1.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation1.ql index fba7a403615..6f728347bff 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation1.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation1.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e, ArrayInitializer i where - a.getLValue().(VariableAccess).getTarget().hasName("is1") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is1") and + e = a.getRightOperand() and not e.isImplicitlyTyped() and i = e.getInitializer() and e.isImplicitlySized() and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation10.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation10.ql index d8a1df12867..951ca22c0c2 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation10.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation10.ql @@ -6,9 +6,9 @@ import csharp from Assignment a, ArrayCreation e, CastExpr cast where - a.getLValue().(VariableAccess).getTarget().hasName("os") and + a.getLeftOperand().(VariableAccess).getTarget().hasName("os") and e.getEnclosingCallable().hasName("MainElementAccess") and - e = a.getRValue() and + e = a.getRightOperand() and not e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation2.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation2.ql index ae56d579839..88ce79bc91e 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation2.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation2.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e, ArrayInitializer i where - a.getLValue().(VariableAccess).getTarget().hasName("is2") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is2") and + e = a.getRightOperand() and not e.isImplicitlyTyped() and i = e.getInitializer() and e.getNumberOfLengthArguments() = 2 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation3.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation3.ql index efe626dab08..0da55f86479 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation3.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation3.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("is3") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is3") and + e = a.getRightOperand() and not e.isImplicitlyTyped() and not e.hasInitializer() and e.getNumberOfLengthArguments() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation4.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation4.ql index 2a0dd531283..b79ec3f7bd6 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation4.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation4.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("is4") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is4") and + e = a.getRightOperand() and not e.isImplicitlyTyped() and not e.hasInitializer() and e.getNumberOfLengthArguments() = 2 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation5.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation5.ql index 04c29cafba8..88df5bef175 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation5.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation5.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e, int i where - a.getLValue().(VariableAccess).getTarget().hasName("is5") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is5") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation6.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation6.ql index 7ca6bbe9668..237900bbe7c 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation6.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation6.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("is6") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is6") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation7.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation7.ql index e34253a4f02..a466195a0b1 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation7.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation7.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("is7") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is7") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation8.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation8.ql index cc1fd366db1..8eb810247c0 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation8.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation8.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("contacts2") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("contacts2") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation9.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation9.ql index fc4b561c170..55ba1d1edb1 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation9.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation9.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("t") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("t") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/Lambda1.ql b/csharp/ql/test/library-tests/expressions/Lambda1.ql index f4787c584f3..4e4d17b9d24 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda1.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda1.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f1") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f1") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof ShortType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda2.ql b/csharp/ql/test/library-tests/expressions/Lambda2.ql index 5fff4bd2cf6..ff5c06ec670 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda2.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda2.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f2") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda3.ql b/csharp/ql/test/library-tests/expressions/Lambda3.ql index 32aa919cd20..46d3a411b36 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda3.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda3.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f3") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f3") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda4.ql b/csharp/ql/test/library-tests/expressions/Lambda4.ql index ca7eb7a4207..69ac40ad932 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda4.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda4.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f4") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f4") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda5.ql b/csharp/ql/test/library-tests/expressions/Lambda5.ql index cc577aa85cb..3836ca4effd 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda5.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda5.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f5") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f5") and e.getParent+() = assign and e.getNumberOfParameters() = 2 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda6.ql b/csharp/ql/test/library-tests/expressions/Lambda6.ql index c584e4f6c09..4a6ee312834 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda6.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda6.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f6") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f6") and e.getParent+() = assign and e.getNumberOfParameters() = 0 and e.getType().(DelegateType).hasName("Unit") and diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation10.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation10.ql index abd4a9d6ec6..971654a95b3 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation10.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation10.ql @@ -6,7 +6,7 @@ import csharp from Assignment a, CollectionInitializer i where - a.getLValue().(VariableAccess).getTarget().hasName("list1") and + a.getLeftOperand().(VariableAccess).getTarget().hasName("list1") and i.getParent+() = a and i.getElementInitializer(0).getArgument(0) instanceof AssignExpr select i.getAChild+() diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation11.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation11.ql index c874735c300..0265579ff67 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation11.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation11.ql @@ -6,7 +6,7 @@ import csharp from Assignment a, CollectionInitializer i, AnonymousObjectCreation o where - a.getLValue().(VariableAccess).getTarget().hasName("list2") and + a.getLeftOperand().(VariableAccess).getTarget().hasName("list2") and i.getParent+() = a and i.getElementInitializer(0).getArgument(0) = o select i, o diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation4.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation4.ql index 5812397b11b..6ec3e2ec327 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation4.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation4.ql @@ -15,9 +15,9 @@ where cc.hasName("Point") and i = e.getInitializer() and a = i.getMemberInitializer(0) and - a.getLValue().(PropertyAccess).getTarget().hasName("X") and - a.getRValue().getValue() = "0" and + a.getLeftOperand().(PropertyAccess).getTarget().hasName("X") and + a.getRightOperand().getValue() = "0" and b = i.getMemberInitializer(1) and - b.getLValue().(PropertyAccess).getTarget().hasName("Y") and - b.getRValue().getValue() = "1" + b.getLeftOperand().(PropertyAccess).getTarget().hasName("Y") and + b.getRightOperand().getValue() = "1" select e, i, a, b diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation5.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation5.ql index cf31f518ec7..e130da484d7 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation5.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation5.ql @@ -15,10 +15,10 @@ where cc.hasName("Point") and i = e.getInitializer() and a = i.getMemberInitializer(0) and - a.getLValue().(PropertyAccess).getTarget().hasName("X") and - a.getRValue().getValue() = "2" and + a.getLeftOperand().(PropertyAccess).getTarget().hasName("X") and + a.getRightOperand().getValue() = "2" and b = i.getMemberInitializer(1) and - b.getLValue().(PropertyAccess).getTarget().hasName("Y") and - b.getRValue().getValue() = "3" and + b.getLeftOperand().(PropertyAccess).getTarget().hasName("Y") and + b.getRightOperand().getValue() = "3" and i.getNumberOfMemberInitializers() = 2 select i, a, b diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation6.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation6.ql index 11e771890ca..529607c8d4b 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation6.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation6.ql @@ -15,10 +15,10 @@ where cc.hasName("Rectangle") and i = e.getInitializer() and a = i.getMemberInitializer(0) and - a.getLValue().(PropertyAccess).getTarget().hasName("P1") and - a.getRValue() instanceof ObjectCreation and + a.getLeftOperand().(PropertyAccess).getTarget().hasName("P1") and + a.getRightOperand() instanceof ObjectCreation and b = i.getMemberInitializer(1) and - b.getLValue().(PropertyAccess).getTarget().hasName("P2") and - b.getRValue() instanceof ObjectCreation and + b.getLeftOperand().(PropertyAccess).getTarget().hasName("P2") and + b.getRightOperand() instanceof ObjectCreation and i.getNumberOfMemberInitializers() = 2 select i, a, b diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation7.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation7.ql index ccb17515525..404011f1896 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation7.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation7.ql @@ -15,10 +15,10 @@ where cc.hasName("Rectangle2") and i = e.getInitializer() and a = i.getMemberInitializer(0) and - a.getLValue().(PropertyAccess).getTarget().hasName("P1") and - a.getRValue() instanceof ObjectInitializer and + a.getLeftOperand().(PropertyAccess).getTarget().hasName("P1") and + a.getRightOperand() instanceof ObjectInitializer and b = i.getMemberInitializer(1) and - b.getLValue().(PropertyAccess).getTarget().hasName("P2") and - b.getRValue() instanceof ObjectInitializer and + b.getLeftOperand().(PropertyAccess).getTarget().hasName("P2") and + b.getRightOperand() instanceof ObjectInitializer and i.getNumberOfMemberInitializers() = 2 select m, e diff --git a/csharp/ql/test/library-tests/expressions/RemoveEventExpr1.ql b/csharp/ql/test/library-tests/expressions/RemoveEventExpr1.ql index 95b223ed6f4..991fdd6e492 100644 --- a/csharp/ql/test/library-tests/expressions/RemoveEventExpr1.ql +++ b/csharp/ql/test/library-tests/expressions/RemoveEventExpr1.ql @@ -9,5 +9,5 @@ where c.hasName("LoginDialog") and e.getEnclosingCallable() = c and e.getTarget().hasName("Click") and - e.getLValue().getQualifier().(FieldAccess).getTarget().hasName("CancelButton") + e.getLeftOperand().getQualifier().(FieldAccess).getTarget().hasName("CancelButton") select c, e diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs b/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs index b59513504d9..4c85b397ac1 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs +++ b/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs @@ -536,6 +536,12 @@ public class HigherOrderParameters { a(o); } + + private void CallApply() + { + // Test that this call to `Apply` does not interfere with the flow summaries generated for `Apply` + Apply(x => x, null); + } } public static class HigherOrderExtensionMethods diff --git a/docs/codeql/reusables/supported-versions-compilers.rst b/docs/codeql/reusables/supported-versions-compilers.rst index 566238658f3..3891332f457 100644 --- a/docs/codeql/reusables/supported-versions-compilers.rst +++ b/docs/codeql/reusables/supported-versions-compilers.rst @@ -11,23 +11,23 @@ Microsoft extensions (up to VS 2022), Arm Compiler 5 [5]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``" - C#,C# up to 13,"Microsoft Visual Studio up to 2019 with .NET up to 4.8, + C#,C# up to 14 [6]_,"Microsoft Visual Studio up to 2019 with .NET up to 4.8, .NET Core up to 3.1 - .NET 5, .NET 6, .NET 7, .NET 8, .NET 9","``.sln``, ``.slnx``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" + .NET 5, .NET 6, .NET 7, .NET 8, .NET 9, .NET 10 [6]_","``.sln``, ``.slnx``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" GitHub Actions,"Not applicable",Not applicable,"``.github/workflows/*.yml``, ``.github/workflows/*.yaml``, ``**/action.yml``, ``**/action.yaml``" Go (aka Golang), "Go up to 1.26", "Go 1.11 or more recent", ``.go`` - Java,"Java 7 to 26 [6]_","javac (OpenJDK and Oracle JDK), + Java,"Java 7 to 26 [7]_","javac (OpenJDK and Oracle JDK), - Eclipse compiler for Java (ECJ) [7]_",``.java`` - Kotlin,"Kotlin 1.8.0 to 2.3.0\ *x*","kotlinc",``.kt`` - JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_" - Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py`` - Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" - Rust [11]_,"Rust editions 2021 and 2024","Rust compiler","``.rs``, ``Cargo.toml``" - Swift [12]_ [13]_,"Swift 5.4-6.2","Swift compiler","``.swift``" - TypeScript [14]_,"2.6-5.9",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``" + Eclipse compiler for Java (ECJ) [8]_",``.java`` + Kotlin,"Kotlin 1.8.0 to 2.3.2\ *x*","kotlinc",``.kt`` + JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [9]_" + Python [10]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py`` + Ruby [11]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" + Rust [12]_,"Rust editions 2021 and 2024","Rust compiler","``.rs``, ``Cargo.toml``" + Swift [13]_ [14]_,"Swift 5.4-6.2","Swift compiler","``.swift``" + TypeScript [15]_,"2.6-5.9",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``" .. container:: footnote-group @@ -36,12 +36,13 @@ .. [3] Objective-C, Objective-C++, C++/CLI, and C++/CX are not supported. .. [4] Support for the clang-cl compiler is preliminary. .. [5] Support for the Arm Compiler (armcc) is preliminary. - .. [6] Builds that execute on Java 7 to 26 can be analyzed. The analysis understands standard language features in Java 8 to 26; "preview" and "incubator" features are not supported. Source code using Java language versions older than Java 8 are analyzed as Java 8 code. - .. [7] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. - .. [8] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. - .. [9] The extractor requires Python 3 to run. To analyze Python 2.7 you should install both versions of Python. - .. [10] Requires glibc 2.17. - .. [11] Requires ``rustup`` and ``cargo`` to be installed. Features from nightly toolchains are not supported. - .. [12] Support for the analysis of Swift requires macOS. - .. [13] Embedded Swift is not supported. - .. [14] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default. + .. [6] Support for .NET 10 is preliminary and code that uses language features new to C# 14 is not yet fully supported for extraction and analysis. + .. [7] Builds that execute on Java 7 to 26 can be analyzed. The analysis understands standard language features in Java 8 to 26; "preview" and "incubator" features are not supported. Source code using Java language versions older than Java 8 are analyzed as Java 8 code. + .. [8] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. + .. [9] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. + .. [10] The extractor requires Python 3 to run. To analyze Python 2.7 you should install both versions of Python. + .. [11] Requires glibc 2.17. + .. [12] Requires ``rustup`` and ``cargo`` to be installed. Features from nightly toolchains are not supported. + .. [13] Support for the analysis of Swift requires macOS. + .. [14] Embedded Swift is not supported. + .. [15] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default. diff --git a/go/extractor/registries/registryproxy_test.go b/go/extractor/registries/registryproxy_test.go index c564040ff1b..2f0b34bcb03 100644 --- a/go/extractor/registries/registryproxy_test.go +++ b/go/extractor/registries/registryproxy_test.go @@ -75,3 +75,59 @@ func TestParseRegistryConfigsMultiple(t *testing.T) { t.Fatalf("Expected `URL` to be `https://proxy.example.com/mod`, but got `%s`", second.URL) } } + +func TestParseRegistryConfigsMultipleGitSources(t *testing.T) { + multiple := parseRegistryConfigsSuccess(t, "[{ \"type\": \"git_source\", \"url\": \"https://github.com/github\" }, { \"type\": \"git_source\", \"url\": \"https://go.googlesource.com/go\" }]") + + if len(multiple) != 2 { + t.Fatalf("Expected `parseRegistryConfigs` to return two configurations, but got %d.", len(multiple)) + } + + first := multiple[0] + + if first.Type != "git_source" { + t.Fatalf("Expected `Type` to be `git_source`, but got `%s`", first.Type) + } + + if first.URL != "https://github.com/github" { + t.Fatalf("Expected `URL` to be `https://github.com/github`, but got `%s`", first.URL) + } + + second := multiple[1] + + if second.Type != "git_source" { + t.Fatalf("Expected `Type` to be `git_source`, but got `%s`", second.Type) + } + + if second.URL != "https://go.googlesource.com/go" { + t.Fatalf("Expected `URL` to be `https://go.googlesource.com/go`, but got `%s`", second.URL) + } +} + +func TestParseRegistryConfigsMultipleGoProxyServers(t *testing.T) { + multiple := parseRegistryConfigsSuccess(t, "[{ \"type\": \"goproxy_server\", \"url\": \"https://proxy.example.com/mod\" }, { \"type\": \"goproxy_server\", \"url\": \"https://goproxy.io\" }]") + + if len(multiple) != 2 { + t.Fatalf("Expected `parseRegistryConfigs` to return two configurations, but got %d.", len(multiple)) + } + + first := multiple[0] + + if first.Type != "goproxy_server" { + t.Fatalf("Expected `Type` to be `goproxy_server`, but got `%s`", first.Type) + } + + if first.URL != "https://proxy.example.com/mod" { + t.Fatalf("Expected `URL` to be `https://proxy.example.com/mod`, but got `%s`", first.URL) + } + + second := multiple[1] + + if second.Type != "goproxy_server" { + t.Fatalf("Expected `Type` to be `goproxy_server`, but got `%s`", second.Type) + } + + if second.URL != "https://goproxy.io" { + t.Fatalf("Expected `URL` to be `https://goproxy.io`, but got `%s`", second.URL) + } +} diff --git a/java/kotlin-extractor/deps/kotlin-compiler-2.3.20.jar b/java/kotlin-extractor/deps/kotlin-compiler-2.3.20.jar new file mode 100644 index 00000000000..60eae6cb5ed --- /dev/null +++ b/java/kotlin-extractor/deps/kotlin-compiler-2.3.20.jar @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4198518f6d840f2f665b2e3c8319a854281f6af43790aca563e3f6b9c46bca68 +size 61256493 diff --git a/java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.3.20.jar b/java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.3.20.jar new file mode 100644 index 00000000000..a19f1cf3400 --- /dev/null +++ b/java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.3.20.jar @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:976f989d0b5f5d80e8e8a8ad4b73da0bfc27fdd965b9fa38362b2be79ecc1337 +size 59718536 diff --git a/java/kotlin-extractor/deps/kotlin-stdlib-2.3.20.jar b/java/kotlin-extractor/deps/kotlin-stdlib-2.3.20.jar new file mode 100644 index 00000000000..59297c653b7 --- /dev/null +++ b/java/kotlin-extractor/deps/kotlin-stdlib-2.3.20.jar @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ae12504a5040ebaf37703908483420d1a5624dd1d93f357665f8c77c848a01e +size 1804720 diff --git a/java/kotlin-extractor/dev/wrapper.py b/java/kotlin-extractor/dev/wrapper.py index 8aa5b55ee67..6fc51aded79 100755 --- a/java/kotlin-extractor/dev/wrapper.py +++ b/java/kotlin-extractor/dev/wrapper.py @@ -27,7 +27,7 @@ import shutil import io import os -DEFAULT_VERSION = "2.3.10" +DEFAULT_VERSION = "2.3.20" def options(): diff --git a/java/kotlin-extractor/src/main/kotlin/utils/GetByFqName.kt b/java/kotlin-extractor/src/main/kotlin/utils/GetByFqName.kt index 8f85ca7ebd3..14fadbcb6c0 100644 --- a/java/kotlin-extractor/src/main/kotlin/utils/GetByFqName.kt +++ b/java/kotlin-extractor/src/main/kotlin/utils/GetByFqName.kt @@ -1,3 +1,6 @@ +// referenceClass, referenceFunctions, referenceProperties are deprecated since Kotlin 2.3.20 +@file:Suppress("DEPRECATION") + package com.github.codeql.utils import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext diff --git a/java/kotlin-extractor/versions.bzl b/java/kotlin-extractor/versions.bzl index 33fca7a37f8..cea5d649025 100644 --- a/java/kotlin-extractor/versions.bzl +++ b/java/kotlin-extractor/versions.bzl @@ -10,6 +10,7 @@ VERSIONS = [ "2.2.0-Beta1", "2.2.20-Beta2", "2.3.0", + "2.3.20", ] def _version_to_tuple(v): diff --git a/java/ql/integration-tests/kotlin/all-platforms/annotation-id-consistency/PrintAst.expected b/java/ql/integration-tests/kotlin/all-platforms/annotation-id-consistency/PrintAst.expected index 07722d53b1e..bbf6b186e1f 100644 --- a/java/ql/integration-tests/kotlin/all-platforms/annotation-id-consistency/PrintAst.expected +++ b/java/ql/integration-tests/kotlin/all-platforms/annotation-id-consistency/PrintAst.expected @@ -281,7 +281,12 @@ test.kt: # 40| 11: [Class] HasKotlinDeprecatedAnnotationUsedByJava #-----| -3: (Annotations) # 40| 1: [Annotation] Deprecated -# 40| 1: [StringLiteral] "Kotlin deprecation message 1" +# 0| 1: [Annotation] ReplaceWith +# 0| 1: [StringLiteral] "" +# 0| 2: [ArrayInit] {...} +# 0| 2: [VarAccess] DeprecationLevel.WARNING +# 0| -1: [TypeAccess] DeprecationLevel +# 40| 3: [StringLiteral] "Kotlin deprecation message 1" # 40| 1: [Constructor] HasKotlinDeprecatedAnnotationUsedByJava # 40| 5: [BlockStmt] { ... } # 40| 0: [SuperConstructorInvocationStmt] super(...) @@ -298,7 +303,12 @@ test.kt: # 46| 13: [Class] HasKotlinDeprecatedAnnotationUsedByKotlin #-----| -3: (Annotations) # 46| 1: [Annotation] Deprecated -# 46| 1: [StringLiteral] "Kotlin deprecation message 2" +# 0| 1: [Annotation] ReplaceWith +# 0| 1: [StringLiteral] "" +# 0| 2: [ArrayInit] {...} +# 0| 2: [VarAccess] DeprecationLevel.WARNING +# 0| -1: [TypeAccess] DeprecationLevel +# 46| 3: [StringLiteral] "Kotlin deprecation message 2" # 46| 1: [Constructor] HasKotlinDeprecatedAnnotationUsedByKotlin # 46| 5: [BlockStmt] { ... } # 46| 0: [SuperConstructorInvocationStmt] super(...) diff --git a/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected b/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected index bbc580f1e48..2720daff0b2 100644 --- a/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected +++ b/java/ql/integration-tests/kotlin/all-platforms/diagnostics/kotlin-version-too-new/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.3.20.", + "markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.3.30.", "severity": "error", "source": { "extractorName": "java", diff --git a/java/ql/lib/change-notes/2026-03-26-kotlin-2.3.20.md b/java/ql/lib/change-notes/2026-03-26-kotlin-2.3.20.md new file mode 100644 index 00000000000..b18cff45704 --- /dev/null +++ b/java/ql/lib/change-notes/2026-03-26-kotlin-2.3.20.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Kotlin versions up to 2.3.20 are now supported. diff --git a/java/ql/test-kotlin1/library-tests/java-kotlin-collection-type-generic-methods/test.expected b/java/ql/test-kotlin1/library-tests/java-kotlin-collection-type-generic-methods/test.expected index a56980d10ac..a55e73e283f 100644 --- a/java/ql/test-kotlin1/library-tests/java-kotlin-collection-type-generic-methods/test.expected +++ b/java/ql/test-kotlin1/library-tests/java-kotlin-collection-type-generic-methods/test.expected @@ -196,6 +196,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -222,6 +224,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -248,6 +252,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -280,6 +286,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | K | | Map | put | V | | Map | putAll | Map | @@ -310,6 +318,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | Identity | | Map | put | Object | | Map | putAll | Map | @@ -341,6 +351,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | K | | Map | put | V | | Map | putAll | Map | @@ -370,6 +382,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | Object | | Map | putAll | Map | | Map | putIfAbsent | Object | @@ -397,6 +411,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | String | | Map | putAll | Map | | Map | putIfAbsent | String | diff --git a/java/ql/test-kotlin2/library-tests/java-kotlin-collection-type-generic-methods/test.expected b/java/ql/test-kotlin2/library-tests/java-kotlin-collection-type-generic-methods/test.expected index 2495c1fc157..3237c89c8c7 100644 --- a/java/ql/test-kotlin2/library-tests/java-kotlin-collection-type-generic-methods/test.expected +++ b/java/ql/test-kotlin2/library-tests/java-kotlin-collection-type-generic-methods/test.expected @@ -191,6 +191,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -216,6 +218,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -242,6 +246,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -274,6 +280,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | K | | Map | put | V | | Map | putAll | Map | @@ -303,6 +311,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | Identity | | Map | put | Object | | Map | putAll | Map | @@ -333,6 +343,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | K | | Map | put | V | | Map | putAll | Map | @@ -361,6 +373,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | Object | | Map | putAll | Map | | Map | putIfAbsent | Object | @@ -388,6 +402,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | String | | Map | putAll | Map | | Map | putIfAbsent | String | diff --git a/java/ql/test-kotlin2/library-tests/reflection/reflection.expected b/java/ql/test-kotlin2/library-tests/reflection/reflection.expected index b5de2b1adea..2c0bee11a9e 100644 --- a/java/ql/test-kotlin2/library-tests/reflection/reflection.expected +++ b/java/ql/test-kotlin2/library-tests/reflection/reflection.expected @@ -266,6 +266,7 @@ compGenerated | file:///AccessFlag$Location.class:0:0:0:0 | getEntries | Default property accessor | | file:///AccessFlag.class:0:0:0:0 | getEntries | Default property accessor | | file:///AccessMode.class:0:0:0:0 | getEntries | Default property accessor | +| file:///ByteOrder.class:0:0:0:0 | getEntries | Default property accessor | | file:///CharProgression.class:0:0:0:0 | forEach | Forwarder for a Kotlin class inheriting an interface default method | | file:///CharProgression.class:0:0:0:0 | spliterator | Forwarder for a Kotlin class inheriting an interface default method | | file:///CharRange.class:0:0:0:0 | forEach | Forwarder for a Kotlin class inheriting an interface default method | diff --git a/java/ql/test/library-tests/compact-source-files/CompactSourceAnalysis.expected b/java/ql/test/library-tests/compact-source-files/CompactSourceAnalysis.expected index 05db00aa26d..0e1dd647e41 100644 --- a/java/ql/test/library-tests/compact-source-files/CompactSourceAnalysis.expected +++ b/java/ql/test/library-tests/compact-source-files/CompactSourceAnalysis.expected @@ -1 +1 @@ -| Test.java:0:0:0:0 | Test | Test.java:1:1:1:1 | Test | Compact source file 'Test' contains implicit class 'Test' | +| Test.java:0:0:0:0 | Test | Test.java:1:1:29:1 | Test | Compact source file 'Test' contains implicit class 'Test' | diff --git a/java/ql/test/library-tests/compact-source-files/ImplicitClassDetection.expected b/java/ql/test/library-tests/compact-source-files/ImplicitClassDetection.expected index 61dcdd8a17f..9bfaaecbbcb 100644 --- a/java/ql/test/library-tests/compact-source-files/ImplicitClassDetection.expected +++ b/java/ql/test/library-tests/compact-source-files/ImplicitClassDetection.expected @@ -1,2 +1,2 @@ -| Test.java:1:1:1:1 | Test | implicit | +| Test.java:1:1:29:1 | Test | implicit | | Test.java:25:7:25:16 | NotCompact | not implicit | diff --git a/java/ql/test/library-tests/compact-source-files/MethodInCompactSource.expected b/java/ql/test/library-tests/compact-source-files/MethodInCompactSource.expected index 3c7b45f500e..d4b41c61441 100644 --- a/java/ql/test/library-tests/compact-source-files/MethodInCompactSource.expected +++ b/java/ql/test/library-tests/compact-source-files/MethodInCompactSource.expected @@ -1,5 +1,5 @@ -| Test.java:1:1:1:1 | | in compact source | -| Test.java:1:1:1:1 | | in compact source | +| Test.java:1:1:29:1 | | in compact source | +| Test.java:1:1:29:1 | | in compact source | | Test.java:5:6:5:9 | main | in compact source | | Test.java:11:6:11:16 | processData | in compact source | | Test.java:16:14:16:31 | updatePrivateField | in compact source | diff --git a/java/ql/test/library-tests/compact-source-files/options b/java/ql/test/library-tests/compact-source-files/options index db1dc01e53b..3d6e630aa73 100644 --- a/java/ql/test/library-tests/compact-source-files/options +++ b/java/ql/test/library-tests/compact-source-files/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --release 25 --enable-preview +//semmle-extractor-options: --javac-args --release 25 diff --git a/java/ql/test/library-tests/dataflow/kdf/options b/java/ql/test/library-tests/dataflow/kdf/options index f4edc64c017..801b81e0752 100644 --- a/java/ql/test/library-tests/dataflow/kdf/options +++ b/java/ql/test/library-tests/dataflow/kdf/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --enable-preview --release 25 \ No newline at end of file +//semmle-extractor-options: --javac-args --release 25 \ No newline at end of file diff --git a/java/ql/test/library-tests/dataflow/scoped-values/options b/java/ql/test/library-tests/dataflow/scoped-values/options index c793109355a..2d42b8d2cd8 100644 --- a/java/ql/test/library-tests/dataflow/scoped-values/options +++ b/java/ql/test/library-tests/dataflow/scoped-values/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -source 25 -target 25 --enable-preview \ No newline at end of file +//semmle-extractor-options: --javac-args -source 25 -target 25 \ No newline at end of file diff --git a/java/ql/test/library-tests/errorexpr/Test.java b/java/ql/test/library-tests/errorexpr/Test.java index af314e5ced6..068690e7bb2 100644 --- a/java/ql/test/library-tests/errorexpr/Test.java +++ b/java/ql/test/library-tests/errorexpr/Test.java @@ -13,6 +13,5 @@ public class Test { } // Diagnostic Matches: Erroneous node in tree: (ERROR) -// Diagnostic Matches: In file Test.java:8:15 no end location for JCMethodInvocation : yield(x) // Diagnostic Matches: 1 errors during annotation processing // Diagnostic Matches: Unknown or erroneous type for expression of kind ErrorExpr diff --git a/java/ql/test/library-tests/flexible-constructors/options b/java/ql/test/library-tests/flexible-constructors/options index db1dc01e53b..3d6e630aa73 100644 --- a/java/ql/test/library-tests/flexible-constructors/options +++ b/java/ql/test/library-tests/flexible-constructors/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --release 25 --enable-preview +//semmle-extractor-options: --javac-args --release 25 diff --git a/java/ql/test/library-tests/module-import-declarations/options b/java/ql/test/library-tests/module-import-declarations/options index b510fdce0df..801b81e0752 100644 --- a/java/ql/test/library-tests/module-import-declarations/options +++ b/java/ql/test/library-tests/module-import-declarations/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --release 25 --enable-preview \ No newline at end of file +//semmle-extractor-options: --javac-args --release 25 \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-676/semmle/tests/options b/java/ql/test/query-tests/security/CWE-676/semmle/tests/options new file mode 100644 index 00000000000..3d6e630aa73 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-676/semmle/tests/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args --release 25 diff --git a/python/ql/lib/semmle/python/frameworks/Eventlet.model.yml b/python/ql/lib/semmle/python/frameworks/Eventlet.model.yml new file mode 100644 index 00000000000..f60b9218819 --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Eventlet.model.yml @@ -0,0 +1,9 @@ +extensions: + - addsTo: + pack: codeql/python-all + extensible: typeModel + data: + # See https://eventlet.readthedocs.io/en/latest/patching.html + - ['socket.socket', 'eventlet', 'Member[green].Member[socket].Member[socket].ReturnValue'] + # eventlet also re-exports as eventlet.socket for convenience + - ['socket.socket', 'eventlet', 'Member[socket].Member[socket].ReturnValue'] diff --git a/python/ql/lib/semmle/python/frameworks/Gevent.model.yml b/python/ql/lib/semmle/python/frameworks/Gevent.model.yml new file mode 100644 index 00000000000..974ecedd073 --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Gevent.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/python-all + extensible: typeModel + data: + # See https://www.gevent.org/api/gevent.socket.html + - ['socket.socket', 'gevent', 'Member[socket].Member[socket].ReturnValue'] diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.model.yml b/python/ql/lib/semmle/python/frameworks/Stdlib.model.yml index a01bf1b40ba..5b50dff313e 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.model.yml +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.model.yml @@ -27,6 +27,8 @@ extensions: extensible: sinkModel data: - ["zipfile.ZipFile","Member[extractall].Argument[0,path:]", "path-injection"] + # See https://docs.python.org/3/library/socket.html#socket.socket.bind + - ["socket.socket", "Member[bind].Argument[0,address:]", "bind-socket-all-interfaces"] - addsTo: pack: codeql/python-all @@ -184,6 +186,8 @@ extensions: pack: codeql/python-all extensible: typeModel data: + # See https://docs.python.org/3/library/socket.html#socket.socket + - ['socket.socket', 'socket', 'Member[socket].ReturnValue'] # See https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlparse - ["urllib.parse.ParseResult~Subclass", 'urllib', 'Member[parse].Member[urlparse]'] diff --git a/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql b/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql index 5e2e27b3bf4..14c17edc359 100644 --- a/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql +++ b/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql @@ -2,7 +2,7 @@ * @name Binding a socket to all network interfaces * @description Binding a socket to all interfaces opens it up to traffic from any IPv4 address * and is therefore associated with security risks. - * @kind problem + * @kind path-problem * @tags security * external/cwe/cwe-200 * @problem.severity error @@ -14,7 +14,9 @@ import python import semmle.python.dataflow.new.DataFlow -import semmle.python.ApiGraphs +import semmle.python.dataflow.new.TaintTracking +private import semmle.python.frameworks.data.ModelsAsData +import BindToAllInterfacesFlow::PathGraph /** Gets a hostname that can be used to bind to all interfaces. */ private string vulnerableHostname() { @@ -26,45 +28,26 @@ private string vulnerableHostname() { ] } -/** Gets a reference to a hostname that can be used to bind to all interfaces. */ -private DataFlow::TypeTrackingNode vulnerableHostnameRef(DataFlow::TypeTracker t, string hostname) { - t.start() and - exists(StringLiteral allInterfacesStringLiteral | hostname = vulnerableHostname() | - allInterfacesStringLiteral.getText() = hostname and - result.asExpr() = allInterfacesStringLiteral - ) - or - exists(DataFlow::TypeTracker t2 | result = vulnerableHostnameRef(t2, hostname).track(t2, t)) +private module BindToAllInterfacesConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source.asExpr().(StringLiteral).getText() = vulnerableHostname() + } + + predicate isSink(DataFlow::Node sink) { + ModelOutput::sinkNode(sink, "bind-socket-all-interfaces") and + // Network socket addresses are tuples like (host, port), so we require + // the bind() argument to originate from a tuple expression. This excludes + // AF_UNIX sockets, which pass a plain string path to bind(). + any(DataFlow::LocalSourceNode n | n.asExpr() instanceof Tuple).flowsTo(sink) + } } -/** Gets a reference to a hostname that can be used to bind to all interfaces. */ -DataFlow::Node vulnerableHostnameRef(string hostname) { - vulnerableHostnameRef(DataFlow::TypeTracker::end(), hostname).flowsTo(result) -} +private module BindToAllInterfacesFlow = TaintTracking::Global; -/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */ -private DataFlow::TypeTrackingNode vulnerableAddressTuple(DataFlow::TypeTracker t, string hostname) { - t.start() and - result.asExpr() = any(Tuple tup | tup.getElt(0) = vulnerableHostnameRef(hostname).asExpr()) - or - exists(DataFlow::TypeTracker t2 | result = vulnerableAddressTuple(t2, hostname).track(t2, t)) -} +private import BindToAllInterfacesFlow -/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */ -DataFlow::Node vulnerableAddressTuple(string hostname) { - vulnerableAddressTuple(DataFlow::TypeTracker::end(), hostname).flowsTo(result) -} - -/** - * Gets an instance of `socket.socket` using _some_ address family. - * - * See https://docs.python.org/3/library/socket.html - */ -API::Node socketInstance() { result = API::moduleImport("socket").getMember("socket").getReturn() } - -from DataFlow::CallCfgNode bindCall, DataFlow::Node addressArg, string hostname -where - bindCall = socketInstance().getMember("bind").getACall() and - addressArg = bindCall.getArg(0) and - addressArg = vulnerableAddressTuple(hostname) -select bindCall.asExpr(), "'" + hostname + "' binds a socket to all interfaces." +from PathNode source, PathNode sink +where flowPath(source, sink) +select sink.getNode(), source, sink, + "Binding a socket to all interfaces (using $@) is a security risk.", source.getNode(), + "'" + source.getNode().asExpr().(StringLiteral).getText() + "'" diff --git a/python/ql/src/Statements/ShouldUseWithStatement.ql b/python/ql/src/Statements/ShouldUseWithStatement.ql index eb5cf9237d5..20bf053f6da 100644 --- a/python/ql/src/Statements/ShouldUseWithStatement.ql +++ b/python/ql/src/Statements/ShouldUseWithStatement.ql @@ -13,7 +13,7 @@ */ import python -private import LegacyPointsTo +private import semmle.python.dataflow.new.internal.DataFlowDispatch predicate calls_close(Call c) { exists(Attribute a | c.getFunc() = a and a.getName() = "close") } @@ -23,18 +23,12 @@ predicate only_stmt_in_finally(Try t, Call c) { ) } -predicate points_to_context_manager(ControlFlowNodeWithPointsTo f, ClassValue cls) { - forex(Value v | f.pointsTo(v) | v.getClass() = cls) and - cls.isContextManager() -} - -from Call close, Try t, ClassValue cls +from Call close, Try t, Class cls where only_stmt_in_finally(t, close) and calls_close(close) and - exists(ControlFlowNode f | f = close.getFunc().getAFlowNode().(AttrNode).getObject() | - points_to_context_manager(f, cls) - ) + classInstanceTracker(cls).asExpr() = close.getFunc().(Attribute).getObject() and + DuckTyping::isContextManager(cls) select close, "Instance of context-manager class $@ is closed in a finally block. Consider using 'with' statement.", cls, cls.getName() diff --git a/python/ql/src/change-notes/2026-03-26-improve-bind-all-interfaces-query.md b/python/ql/src/change-notes/2026-03-26-improve-bind-all-interfaces-query.md new file mode 100644 index 00000000000..bc78b2b6f77 --- /dev/null +++ b/python/ql/src/change-notes/2026-03-26-improve-bind-all-interfaces-query.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +- The `py/bind-socket-all-network-interfaces` query now uses the global data-flow library, leading to better precision and more results. Also, wrappers of `socket.socket` in the `eventlet` and `gevent` libraries are now also recognized as socket binding operations. diff --git a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.expected b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.expected index 86c67af4eae..0b96b2df650 100644 --- a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.expected +++ b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.expected @@ -1,5 +1,63 @@ -| BindToAllInterfaces_test.py:5:1:5:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. | -| BindToAllInterfaces_test.py:9:1:9:18 | Attribute() | '' binds a socket to all interfaces. | -| BindToAllInterfaces_test.py:17:1:17:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. | -| BindToAllInterfaces_test.py:21:1:21:11 | Attribute() | '0.0.0.0' binds a socket to all interfaces. | -| BindToAllInterfaces_test.py:26:1:26:20 | Attribute() | '::' binds a socket to all interfaces. | +#select +| BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | '' | +| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | '::' | +| BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | '0.0.0.0' | +edges +| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | provenance | | +| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | provenance | | +| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | provenance | | +| BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | provenance | | +| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | provenance | dict.get | +| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +nodes +| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | semmle.label | ControlFlowNode for ALL_LOCALS | +| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup | +| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup | +| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Return] [Attribute bind_addr] | +| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | semmle.label | [post] ControlFlowNode for self [Attribute bind_addr] | +| BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Attribute bind_addr] | +| BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Attribute bind_addr] | +| BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | semmle.label | ControlFlowNode for server [Attribute bind_addr] | +| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | semmle.label | ControlFlowNode for Server() [Attribute bind_addr] | +| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | semmle.label | ControlFlowNode for server [Attribute bind_addr] | +| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | semmle.label | ControlFlowNode for host | +| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +subpaths diff --git a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.qlref b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.qlref index f06cc3d869d..6396fd91863 100644 --- a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.qlref +++ b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.qlref @@ -1 +1,2 @@ -Security/CVE-2018-1281/BindToAllInterfaces.ql \ No newline at end of file +query: Security/CVE-2018-1281/BindToAllInterfaces.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql \ No newline at end of file diff --git a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py index bbab44d8103..27ba6642b64 100644 --- a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py +++ b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py @@ -2,25 +2,61 @@ import socket # binds to all interfaces, insecure s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(('0.0.0.0', 31137)) +s.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces] # binds to all interfaces, insecure s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(('', 4040)) +s.bind(('', 4040)) # $ Alert[py/bind-socket-all-network-interfaces] # binds only to a dedicated interface, secure s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('84.68.10.12', 8080)) # binds to all interfaces, insecure -ALL_LOCALS = "0.0.0.0" -s.bind((ALL_LOCALS, 9090)) +ALL_LOCALS = "0.0.0.0" # $ Source +s.bind((ALL_LOCALS, 9090)) # $ Alert[py/bind-socket-all-network-interfaces] # binds to all interfaces, insecure tup = (ALL_LOCALS, 8080) -s.bind(tup) +s.bind(tup) # $ Alert[py/bind-socket-all-network-interfaces] # IPv6 s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) -s.bind(("::", 8080)) # NOT OK +s.bind(("::", 8080)) # $ Alert[py/bind-socket-all-network-interfaces] + + +# FN cases from https://github.com/github/codeql/issues/21582 + +# Address stored in a class attribute +class Server: + def __init__(self): + self.bind_addr = '0.0.0.0' # $ Source + self.port = 31137 + + def start(self): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((self.bind_addr, self.port)) # $ Alert[py/bind-socket-all-network-interfaces] + +server = Server() +server.start() + +# os.environ.get with insecure default +import os +host = os.environ.get('APP_HOST', '0.0.0.0') # $ Source +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.bind((host, 8080)) # $ Alert[py/bind-socket-all-network-interfaces] + +# gevent.socket (alternative socket module) +from gevent import socket as gsocket +gs = gsocket.socket(gsocket.AF_INET, gsocket.SOCK_STREAM) +gs.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces] + +# eventlet.green.socket (another alternative socket module) +from eventlet.green import socket as esocket +es = esocket.socket(esocket.AF_INET, esocket.SOCK_STREAM) +es.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces] + +# AF_UNIX socket binding should not be flagged +us = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +us.bind('') diff --git a/python/ql/test/query-tests/Statements/general/ShouldUseWithStatement.expected b/python/ql/test/query-tests/Statements/general/ShouldUseWithStatement.expected index d062717bbf2..50ff6cc1f91 100644 --- a/python/ql/test/query-tests/Statements/general/ShouldUseWithStatement.expected +++ b/python/ql/test/query-tests/Statements/general/ShouldUseWithStatement.expected @@ -1 +1 @@ -| test.py:168:9:168:17 | Attribute() | Instance of context-manager class $@ is closed in a finally block. Consider using 'with' statement. | test.py:151:1:151:17 | class CM | CM | +| test.py:168:9:168:17 | Attribute() | Instance of context-manager class $@ is closed in a finally block. Consider using 'with' statement. | test.py:151:1:151:17 | Class CM | CM | diff --git a/rust/ql/lib/codeql/files/FileSystem.qll b/rust/ql/lib/codeql/files/FileSystem.qll index cfab33b9a44..93ff7be604e 100644 --- a/rust/ql/lib/codeql/files/FileSystem.qll +++ b/rust/ql/lib/codeql/files/FileSystem.qll @@ -45,13 +45,16 @@ extensible predicate additionalExternalFile(string relativePath); /** A file. */ class File extends Container, Impl::File { + pragma[nomagic] + private predicate isAdditionalExternalFile() { additionalExternalFile(this.getRelativePath()) } + /** * Holds if this file was extracted from the source code of the target project * (rather than another location such as inside a dependency). */ predicate fromSource() { exists(ExtractorStep s | s.getAction() = "Extract" and s.getFile() = this) and - not additionalExternalFile(this.getRelativePath()) + not this.isAdditionalExternalFile() } /** diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll b/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll index 97dbf2d8f3a..26e8bdea4e0 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll @@ -134,7 +134,7 @@ module SatisfiesBlanketConstraint< exists(ArgumentTypeAndBlanketOffset ato, Trait traitBound | ato = MkArgumentTypeAndBlanketOffset(at, _) and SatisfiesBlanketConstraintInput::relevantConstraint(ato, impl, traitBound) and - SatisfiesBlanketConstraint::satisfiesConstraintType(ato, TTrait(traitBound), _, _) + SatisfiesBlanketConstraint::satisfiesConstraint(ato, TTrait(traitBound), _, _) ) or exists(TypeParam blanketTypeParam | diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index 0f9afcd06bb..c6a268be126 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -467,6 +467,41 @@ private predicate isPanicMacroCall(MacroExpr me) { me.getMacroCall().resolveMacro().(MacroRules).getName().getText() = "panic" } +// Due to "binding modes" the type of the pattern is not necessarily the +// same as the type of the initializer. However, when the pattern is an +// identifier pattern, its type is guaranteed to be the same as the type of the +// initializer. +private predicate identLetStmt(LetStmt let, IdentPat lhs, Expr rhs) { + let.getPat() = lhs and + let.getInitializer() = rhs +} + +/** + * Gets the root type of a closure. + * + * We model closures as `dyn Fn` trait object types. A closure might implement + * only `Fn`, `FnMut`, or `FnOnce`. But since `Fn` is a subtrait of the others, + * giving closures the type `dyn Fn` works well in practice -- even if not + * entirely accurate. + */ +private DynTraitType closureRootType() { + result = TDynTraitType(any(FnTrait t)) // always exists because of the mention in `builtins/mentions.rs` +} + +/** Gets the path to a closure's return type. */ +private TypePath closureReturnPath() { + result = + TypePath::singleton(TDynTraitTypeParameter(any(FnTrait t), any(FnOnceTrait t).getOutputType())) +} + +/** Gets the path to a closure's `index`th parameter type, where the arity is `arity`. */ +pragma[nomagic] +private TypePath closureParameterPath(int arity, int index) { + result = + TypePath::cons(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam()), + TypePath::singleton(getTupleTypeParameter(arity, index))) +} + /** Module for inferring certain type information. */ module CertainTypeInference { pragma[nomagic] @@ -544,11 +579,7 @@ module CertainTypeInference { // is not a certain type equality. exists(LetStmt let | not let.hasTypeRepr() and - // Due to "binding modes" the type of the pattern is not necessarily the - // same as the type of the initializer. The pattern being an identifier - // pattern is sufficient to ensure that this is not the case. - let.getPat().(IdentPat) = n1 and - let.getInitializer() = n2 + identLetStmt(let, n1, n2) ) or exists(LetExpr let | @@ -572,6 +603,21 @@ module CertainTypeInference { ) else prefix2.isEmpty() ) + or + exists(CallExprImpl::DynamicCallExpr dce, TupleType tt, int i | + n1 = dce.getArgList() and + tt.getArity() = dce.getNumberOfSyntacticArguments() and + n2 = dce.getSyntacticPositionalArgument(i) and + prefix1 = TypePath::singleton(tt.getPositionalTypeParameter(i)) and + prefix2.isEmpty() + ) + or + exists(ClosureExpr ce, int index | + n1 = ce and + n2 = ce.getParam(index).getPat() and + prefix1 = closureParameterPath(ce.getNumberOfParams(), index) and + prefix2.isEmpty() + ) } pragma[nomagic] @@ -636,6 +682,10 @@ module CertainTypeInference { path.isEmpty() and result instanceof NeverType or + n instanceof ClosureExpr and + path.isEmpty() and + result = closureRootType() + or infersCertainTypeAt(n, path, result.getATypeParameter()) } @@ -835,17 +885,6 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat n1.(ArrayRepeatExpr).getRepeatOperand() = n2 and prefix1 = TypePath::singleton(getArrayTypeParameter()) and prefix2.isEmpty() - or - exists(ClosureExpr ce, int index | - n1 = ce and - n2 = ce.getParam(index).getPat() and - prefix1 = closureParameterPath(ce.getNumberOfParams(), index) and - prefix2.isEmpty() - ) - or - n1.(ClosureExpr).getClosureBody() = n2 and - prefix1 = closureReturnPath() and - prefix2.isEmpty() } /** @@ -881,6 +920,9 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) { strictcount(Expr e | bodyReturns(parent, e)) > 1 and prefix.isEmpty() or + parent = any(ClosureExpr ce | not ce.hasRetType() and ce.getClosureBody() = child) and + prefix = closureReturnPath() + or exists(Struct s | child = [parent.(RangeExpr).getStart(), parent.(RangeExpr).getEnd()] and prefix = TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and @@ -888,6 +930,19 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) { ) } +private Type inferUnknownTypeFromAnnotation(AstNode n, TypePath path) { + inferType(n, path) = TUnknownType() and + // Normally, these are coercion sites, but in case a type is unknown we + // allow for type information to flow from the type annotation. + exists(TypeMention tm | result = tm.getTypeAt(path) | + tm = any(LetStmt let | identLetStmt(let, _, n)).getTypeRepr() + or + tm = any(ClosureExpr ce | n = ce.getBody()).getRetType().getTypeRepr() + or + tm = getReturnTypeMention(any(Function f | n = f.getBody())) + ) +} + /** * Holds if the type tree of `n1` at `prefix1` should be equal to the type tree * of `n2` at `prefix2`, but type information should only propagate from `n1` to @@ -1545,12 +1600,14 @@ private module AssocFunctionResolution { * * This is either: * - * 1. `AssocFunctionCallMethodCallExpr`: a method call, `x.m()`; - * 2. `AssocFunctionCallIndexExpr`: an index expression, `x[i]`, which is [syntactic sugar][1] + * 1. `MethodCallExprAssocFunctionCall`: a method call, `x.m()`; + * 2. `IndexExprAssocFunctionCall`: an index expression, `x[i]`, which is [syntactic sugar][1] * for `*x.index(i)`; - * 3. `AssocFunctionCallCallExpr`: a qualified function call, `Q::f(x)`; or - * 4. `AssocFunctionCallOperation`: an operation expression, `x + y`, which is syntactic sugar + * 3. `CallExprAssocFunctionCall`: a qualified function call, `Q::f(x)`; or + * 4. `OperationAssocFunctionCall`: an operation expression, `x + y`, which is syntactic sugar * for `Add::add(x, y)`. + * 5. `DynamicAssocFunctionCall`: a call to a closure, `c(x)`, which is syntactic sugar for + * `c.call_once(x)`, `c.call_mut(x)`, or `c.call(x)`. * * Note that only in case 1 and 2 is auto-dereferencing and borrowing allowed. * @@ -1567,7 +1624,7 @@ private module AssocFunctionResolution { pragma[nomagic] abstract predicate hasNameAndArity(string name, int arity); - abstract Expr getNonReturnNodeAt(FunctionPosition pos); + abstract AstNode getNonReturnNodeAt(FunctionPosition pos); AstNode getNodeAt(FunctionPosition pos) { result = this.getNonReturnNodeAt(pos) @@ -2101,7 +2158,7 @@ private module AssocFunctionResolution { } } - private class AssocFunctionCallMethodCallExpr extends AssocFunctionCall instanceof MethodCallExpr { + private class MethodCallExprAssocFunctionCall extends AssocFunctionCall instanceof MethodCallExpr { override predicate hasNameAndArity(string name, int arity) { name = super.getIdentifier().getText() and arity = super.getNumberOfSyntacticArguments() @@ -2121,7 +2178,7 @@ private module AssocFunctionResolution { override Trait getTrait() { none() } } - private class AssocFunctionCallIndexExpr extends AssocFunctionCall, IndexExpr { + private class IndexExprAssocFunctionCall extends AssocFunctionCall, IndexExpr { private predicate isInMutableContext() { // todo: does not handle all cases yet VariableImpl::assignmentOperationDescendant(_, this) @@ -2151,8 +2208,8 @@ private module AssocFunctionResolution { } } - private class AssocFunctionCallCallExpr extends AssocFunctionCall, CallExpr { - AssocFunctionCallCallExpr() { + private class CallExprAssocFunctionCall extends AssocFunctionCall, CallExpr { + CallExprAssocFunctionCall() { exists(getCallExprPathQualifier(this)) and // even if a target cannot be resolved by path resolution, it may still // be possible to resolve a blanket implementation (so not `forex`) @@ -2184,7 +2241,7 @@ private module AssocFunctionResolution { override Trait getTrait() { result = getCallExprTraitQualifier(this) } } - final class AssocFunctionCallOperation extends AssocFunctionCall, Operation { + final class OperationAssocFunctionCall extends AssocFunctionCall, Operation { override predicate hasNameAndArity(string name, int arity) { this.isOverloaded(_, name, _) and arity = this.getNumberOfOperands() @@ -2242,6 +2299,29 @@ private module AssocFunctionResolution { override Trait getTrait() { this.isOverloaded(result, _, _) } } + private class DynamicAssocFunctionCall extends AssocFunctionCall instanceof CallExprImpl::DynamicCallExpr + { + pragma[nomagic] + override predicate hasNameAndArity(string name, int arity) { + name = "call_once" and // todo: handle call_mut and call + arity = 2 // args are passed in a tuple + } + + override predicate hasReceiver() { any() } + + override AstNode getNonReturnNodeAt(FunctionPosition pos) { + pos.asPosition() = 0 and + result = super.getFunction() + or + pos.asPosition() = 1 and + result = super.getArgList() + } + + override predicate supportsAutoDerefAndBorrow() { any() } + + override Trait getTrait() { result instanceof AnyFnTrait } + } + pragma[nomagic] private AssocFunctionDeclaration getAssocFunctionSuccessor( ImplOrTraitItemNode i, string name, int arity @@ -2445,7 +2525,7 @@ private module AssocFunctionResolution { ) { exists(CallDerefCand cdc, TypePath exprPath | cdc = MkCallDerefCand(afc, selfPos, derefChain) and - CallSatisfiesDerefConstraint::satisfiesConstraintTypeThrough(cdc, impl, _, exprPath, result) and + CallSatisfiesDerefConstraint::satisfiesConstraintThrough(cdc, impl, _, exprPath, result) and exprPath.isCons(getDerefTargetTypeParameter(), path) ) } @@ -3198,7 +3278,7 @@ private module OperationMatchingInput implements MatchingInputSig { } } - class Access extends AssocFunctionResolution::AssocFunctionCallOperation { + class Access extends AssocFunctionResolution::OperationAssocFunctionCall { Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() } pragma[nomagic] @@ -3566,7 +3646,7 @@ private module AwaitSatisfiesType = SatisfiesType type of pattern (loop variable) exists(ForExpr fe, TypePath exprPath, AssociatedTypeTypeParameter tp | n = fe.getPat() and - ForIterableSatisfiesType::satisfiesConstraintType(fe.getIterable(), _, exprPath, result) and + ForIterableSatisfiesType::satisfiesConstraint(fe.getIterable(), _, exprPath, result) and exprPath.isCons(tp, path) | tp = getIntoIteratorItemTypeParameter() @@ -3744,130 +3824,36 @@ private Type inferForLoopExprType(AstNode n, TypePath path) { ) } -/** - * An invoked expression, the target of a call that is either a local variable - * or a non-path expression. This means that the expression denotes a - * first-class function. - */ -final private class InvokedClosureExpr extends Expr { - private CallExprImpl::DynamicCallExpr call; - - InvokedClosureExpr() { call.getFunction() = this } - - Type getTypeAt(TypePath path) { result = inferType(this, path) } - - CallExpr getCall() { result = call } -} - -private module InvokedClosureSatisfiesTypeInput implements SatisfiesTypeInputSig -{ - predicate relevantConstraint(InvokedClosureExpr term, Type constraint) { - exists(term) and - constraint.(TraitType).getTrait() instanceof FnOnceTrait - } -} - -private module InvokedClosureSatisfiesType = - SatisfiesType; - -/** Gets the type of `ce` when viewed as an implementation of `FnOnce`. */ -private Type invokedClosureFnTypeAt(InvokedClosureExpr ce, TypePath path) { - InvokedClosureSatisfiesType::satisfiesConstraintType(ce, _, path, result) -} - -/** - * Gets the root type of a closure. - * - * We model closures as `dyn Fn` trait object types. A closure might implement - * only `Fn`, `FnMut`, or `FnOnce`. But since `Fn` is a subtrait of the others, - * giving closures the type `dyn Fn` works well in practice -- even if not - * entirely accurate. - */ -private DynTraitType closureRootType() { - result = TDynTraitType(any(FnTrait t)) // always exists because of the mention in `builtins/mentions.rs` -} - -/** Gets the path to a closure's return type. */ -private TypePath closureReturnPath() { - result = - TypePath::singleton(TDynTraitTypeParameter(any(FnTrait t), any(FnOnceTrait t).getOutputType())) -} - -/** Gets the path to a closure with arity `arity`'s `index`th parameter type. */ pragma[nomagic] -private TypePath closureParameterPath(int arity, int index) { - result = - TypePath::cons(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam()), - TypePath::singleton(getTupleTypeParameter(arity, index))) -} - -/** Gets the path to the return type of the `FnOnce` trait. */ -private TypePath fnReturnPath() { - result = TypePath::singleton(getAssociatedTypeTypeParameter(any(FnOnceTrait t).getOutputType())) -} - -/** - * Gets the path to the parameter type of the `FnOnce` trait with arity `arity` - * and index `index`. - */ -pragma[nomagic] -private TypePath fnParameterPath(int arity, int index) { - result = - TypePath::cons(TTypeParamTypeParameter(any(FnOnceTrait t).getTypeParam()), - TypePath::singleton(getTupleTypeParameter(arity, index))) -} - -pragma[nomagic] -private Type inferDynamicCallExprType(Expr n, TypePath path) { - exists(InvokedClosureExpr ce | - // Propagate the function's return type to the call expression - exists(TypePath path0 | result = invokedClosureFnTypeAt(ce, path0) | - n = ce.getCall() and - path = path0.stripPrefix(fnReturnPath()) +private Type inferClosureExprType(AstNode n, TypePath path) { + exists(ClosureExpr ce | + n = ce and + ( + path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and + result.(TupleType).getArity() = ce.getNumberOfParams() or - // Propagate the function's parameter type to the arguments - exists(int index | - n = ce.getCall().getSyntacticPositionalArgument(index) and - path = - path0.stripPrefix(fnParameterPath(ce.getCall().getArgList().getNumberOfArgs(), index)) + exists(TypePath path0 | + result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(path0) and + path = closureReturnPath().append(path0) ) ) or - // _If_ the invoked expression has the type of a closure, then we propagate - // the surrounding types into the closure. - exists(int arity, TypePath path0 | ce.getTypeAt(TypePath::nil()) = closureRootType() | - // Propagate the type of arguments to the parameter types of closure - exists(int index, ArgList args | - n = ce and - args = ce.getCall().getArgList() and - arity = args.getNumberOfArgs() and - result = inferType(args.getArg(index), path0) and - path = closureParameterPath(arity, index).append(path0) - ) - or - // Propagate the type of the call expression to the return type of the closure - n = ce and - arity = ce.getCall().getArgList().getNumberOfArgs() and - result = inferType(ce.getCall(), path0) and - path = closureReturnPath().append(path0) + exists(Param p | + p = ce.getAParam() and + not p.hasTypeRepr() and + n = p.getPat() and + result = TUnknownType() and + path.isEmpty() ) ) } pragma[nomagic] -private Type inferClosureExprType(AstNode n, TypePath path) { - exists(ClosureExpr ce | - n = ce and - path.isEmpty() and - result = closureRootType() - or - n = ce and - path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and - result.(TupleType).getArity() = ce.getNumberOfParams() - or - // Propagate return type annotation to body - n = ce.getClosureBody() and - result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(path) +private TupleType inferArgList(ArgList args, TypePath path) { + exists(CallExprImpl::DynamicCallExpr dce | + args = dce.getArgList() and + result.getArity() = dce.getNumberOfSyntacticArguments() and + path.isEmpty() ) } @@ -3915,7 +3901,8 @@ private module Cached { or i instanceof ImplItemNode and dispatch = false | - result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) + result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) and + not call instanceof CallExprImpl::DynamicCallExpr ) } @@ -4023,11 +4010,13 @@ private module Cached { or result = inferForLoopExprType(n, path) or - result = inferDynamicCallExprType(n, path) - or result = inferClosureExprType(n, path) or + result = inferArgList(n, path) + or result = inferDeconstructionPatType(n, path) + or + result = inferUnknownTypeFromAnnotation(n, path) ) } } diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll index 70dfbeda848..c4650f97c34 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll @@ -769,7 +769,7 @@ private Type getPathConcreteAssocTypeAt(Path path, TypePath typePath) { TypeAlias alias, TypePath path0 | pathConcreteTypeAssocType(path, tm, trait, traitOrTmTrait, alias) and - PathSatisfiesConstraint::satisfiesConstraintTypeThrough(tm, impl, traitOrTmTrait, path0, result) and + PathSatisfiesConstraint::satisfiesConstraintThrough(tm, impl, traitOrTmTrait, path0, result) and path0.isCons(TAssociatedTypeTypeParameter(trait, alias), typePath) ) } diff --git a/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected index 2ac439e085b..ffc2576a05e 100644 --- a/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected +++ b/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected @@ -2,3 +2,4 @@ multipleResolvedTargets | main.rs:2223:9:2223:31 | ... .my_add(...) | | main.rs:2225:9:2225:29 | ... .my_add(...) | | main.rs:2740:13:2740:17 | x.f() | +| regressions.rs:179:17:179:27 | ... + ... | diff --git a/rust/ql/test/library-tests/type-inference/closure.rs b/rust/ql/test/library-tests/type-inference/closure.rs index cc756a6b267..fbef401bb08 100644 --- a/rust/ql/test/library-tests/type-inference/closure.rs +++ b/rust/ql/test/library-tests/type-inference/closure.rs @@ -63,7 +63,7 @@ mod fn_once_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -100,7 +100,7 @@ mod fn_mut_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -137,7 +137,7 @@ mod fn_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -152,3 +152,90 @@ mod dyn_fn_once { let _r2 = apply_boxed(Box::new(|_: i64| true), 3); // $ target=apply_boxed target=new type=_r2:bool } } + +mod closure_infer_param { + fn apply1 i64>(f: F, a: i64) -> i64 { + f(a) + } + + fn apply2(f: impl Fn(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply3(f: &dyn Fn(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply4 i64>(mut f: F, a: i64) -> i64 { + f(a) + } + + fn apply5(f: &mut dyn FnMut(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply6(f: impl Fn(T) -> i64, a: T) -> i64 { + f(a) + } + + fn apply7 i64>(mut f: F, a: T) -> i64 { + f(a) + } + + fn test() { + let f = |x| x; // $ type=x:i64 + let _r = apply1(f, 1i64); // $ target=apply1 + + let f = |x| x; // $ type=x:i64 + let _r = apply2(f, 2i64); // $ target=apply2 + + let f = |x| x; // $ type=x:i64 + let _r = apply3(&f, 3i64); // $ target=apply3 + + let f = |x| x; // $ type=x:i64 + let _r = apply4(f, 4i64); // $ target=apply4 + + let mut f = |x| x; // $ MISSING: type=x:i64 + let _r = apply5(&mut f, 5i64); // $ target=apply5 + + let f = |x| x; // $ type=x:i64 + let _r = apply6(f, 6i64); // $ target=apply6 + + let f = |x| x; // $ type=x:i64 + let _r = apply7(f, 7i64); // $ target=apply7 + } +} + +mod implicit_deref { + use std::ops::Deref; + + struct S(T); + + impl Deref for S { + type Target = dyn Fn(T) -> bool; + + fn deref(&self) -> &Self::Target { + &|_| false + } + } + + pub fn test() { + let x = 0i64; + let v = Default::default(); // $ type=v:i64 target=default + let s = S(v); + let _ret = s(x); // $ type=_ret:bool + + let x = 0i32; + let v = Default::default(); // $ type=v:i32 target=default + let s = S(v); + let s_ref = &s; + let _ret = s_ref(x); // $ type=_ret:bool + + // The call below is not an implicit deref, instead it will target + // `impl FnOnce for &F` from + // https://doc.rust-lang.org/std/ops/trait.FnOnce.html#impl-FnOnce%3CA%3E-for-%26F + // and we currently cannot handle inferring the output type + let c = |x| x; // $ MISSING: type=x:i64 + (&c)(x); // $ MISSING: type=_:i64 + } +} diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 6c9f2c801d5..ecb4816ebb0 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -2259,7 +2259,7 @@ mod loops { // for loops with arrays for i in [1, 2, 3] {} // $ type=i:i32 - for i in [1, 2, 3].map(|x| x + 1) {} // $ target=map MISSING: type=i:i32 + for i in [1, 2, 3].map(|x| x + 1) {} // $ target=map target=add type=i:i32 for i in [1, 2, 3].into_iter() {} // $ target=into_iter type=i:i32 let vals1 = [1u8, 2, 3]; // $ type=vals1:TArray.u8 @@ -2759,6 +2759,30 @@ mod dereference; mod dyn_type; mod regressions; +mod arg_trait_bounds { + struct Gen(T); + + trait Container { + fn get_input(&self) -> T; + } + + fn my_get>(c: &T) -> bool { + c.get_input() == 42 // $ target=get_input target=eq + } + + impl Container for Gen { + fn get_input(&self) -> GT { + self.0 // $ fieldof=Gen + } + } + + fn test() { + let v = Default::default(); // $ type=v:i64 target=default + let g = Gen(v); + let _ = my_get(&g); // $ target=my_get + } +} + fn main() { field_access::f(); // $ target=f method_impl::f(); // $ target=f diff --git a/rust/ql/test/library-tests/type-inference/regressions.rs b/rust/ql/test/library-tests/type-inference/regressions.rs index e1b47479f5d..5c830bb3db2 100644 --- a/rust/ql/test/library-tests/type-inference/regressions.rs +++ b/rust/ql/test/library-tests/type-inference/regressions.rs @@ -130,3 +130,52 @@ mod regression4 { } } } + +mod regression5 { + struct S1; + struct S2(T2); + + impl From<&S1> for S2 { + fn from(_: &S1) -> Self { + S2(S1) + } + } + + impl From for S2 { + fn from(t: T) -> Self { + S2(t) + } + } + + fn foo() -> S2 { + let x = S1.into(); // $ target=into + x // $ SPURIOUS: type=x:T2.TRef.S1 -- happens because we currently do not consider the two `impl` blocks to be siblings + } +} + +mod regression6 { + use std::ops::Add; + struct S(T); + + impl Add for S { + type Output = Self; + + // add1 + fn add(self, _rhs: Self) -> Self::Output { + self + } + } + + impl Add for S { + type Output = Self; + + // add2 + fn add(self, _rhs: T) -> Self::Output { + self + } + } + + fn foo() { + let x = S(0) + S(1); // $ target=add1 $ SPURIOUS: target=add2 type=x:T.T.i32 + } +} 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 1e2c753b242..4be70359842 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -545,6 +545,14 @@ inferCertainType | blanket_impl.rs:299:47:299:67 | "SELECT * FROM users" | | {EXTERNAL LOCATION} | & | | blanket_impl.rs:299:47:299:67 | "SELECT * FROM users" | TRef | {EXTERNAL LOCATION} | str | | closure.rs:4:19:31:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:6:13:6:22 | my_closure | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:6:13:6:22 | my_closure | dyn(Args) | {EXTERNAL LOCATION} | (T_2) | +| closure.rs:6:13:6:22 | my_closure | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:13:6:22 | my_closure | dyn(Args).T1 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:26:6:38 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_2) | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args).T1 | {EXTERNAL LOCATION} | bool | | closure.rs:6:27:6:27 | a | | {EXTERNAL LOCATION} | bool | | closure.rs:6:30:6:30 | b | | {EXTERNAL LOCATION} | bool | | closure.rs:6:33:6:33 | a | | {EXTERNAL LOCATION} | bool | @@ -552,19 +560,47 @@ inferCertainType | closure.rs:6:38:6:38 | b | | {EXTERNAL LOCATION} | bool | | closure.rs:8:13:8:13 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:8:22:8:25 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:9:13:9:19 | add_one | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:9:23:9:34 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:9:31:9:34 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:10:18:10:24 | add_one | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:10:25:10:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:10:25:10:27 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:26:10:26 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:14:13:14:20 | add_zero | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:14:13:14:20 | add_zero | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:14:13:14:20 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:14:24:14:33 | \|...\| n | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:14:24:14:33 | \|...\| n | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:14:24:14:33 | \|...\| n | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:14:25:14:25 | n | | {EXTERNAL LOCATION} | i64 | | closure.rs:14:33:14:33 | n | | {EXTERNAL LOCATION} | i64 | +| closure.rs:15:18:15:25 | add_zero | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:15:18:15:25 | add_zero | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:15:18:15:25 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:17:13:17:21 | _get_bool | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:17:25:21:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:24:13:24:14 | id | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:24:18:24:22 | \|...\| b | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:25:18:25:19 | id | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:25:20:25:25 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:25:20:25:25 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:21:25:24 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:28:13:28:15 | id2 | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:28:19:28:23 | \|...\| b | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:30:13:30:15 | _b2 | | {EXTERNAL LOCATION} | bool | +| closure.rs:30:25:30:27 | id2 | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:35:44:35:44 | f | | closure.rs:35:20:35:41 | F | | closure.rs:35:50:37:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:36:23:36:23 | f | | closure.rs:35:20:35:41 | F | +| closure.rs:36:24:36:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:36:24:36:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:36:25:36:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:39:45:39:45 | f | | closure.rs:39:28:39:42 | F | | closure.rs:39:51:41:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:40:23:40:23 | f | | closure.rs:39:28:39:42 | F | +| closure.rs:40:24:40:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:40:24:40:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:40:25:40:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:43:46:43:46 | f | | closure.rs:43:22:43:43 | F | | closure.rs:43:52:46:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -573,23 +609,41 @@ inferCertainType | closure.rs:48:45:48:45 | a | | closure.rs:48:14:48:14 | A | | closure.rs:48:56:50:5 | { ... } | | closure.rs:48:17:48:17 | B | | closure.rs:49:9:49:9 | f | | closure.rs:48:20:48:36 | F | +| closure.rs:49:10:49:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:49:10:49:12 | ArgList | T0 | closure.rs:48:14:48:14 | A | | closure.rs:49:11:49:11 | a | | closure.rs:48:14:48:14 | A | | closure.rs:52:18:52:18 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:52:53:54:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:53:9:53:9 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:56:15:68:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:57:13:57:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:57:13:57:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:57:13:57:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:57:17:63:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:57:17:63:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:57:17:63:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:57:18:57:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:58:16:58:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:64:24:64:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:64:24:64:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:64:24:64:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:64:27:64:30 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:66:13:66:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:66:17:66:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:67:13:67:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:19:67:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:67:29:67:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:72:47:72:47 | f | | closure.rs:72:20:72:40 | F | | closure.rs:72:53:74:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:73:23:73:23 | f | | closure.rs:72:20:72:40 | F | +| closure.rs:73:24:73:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:73:24:73:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:73:25:73:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:76:48:76:48 | f | | closure.rs:76:28:76:41 | F | | closure.rs:76:54:78:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:77:23:77:23 | f | | closure.rs:76:28:76:41 | F | +| closure.rs:77:24:77:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:77:24:77:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:77:25:77:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:80:49:80:49 | f | | closure.rs:80:22:80:42 | F | | closure.rs:80:55:83:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -598,23 +652,41 @@ inferCertainType | closure.rs:85:48:85:48 | a | | closure.rs:85:14:85:14 | A | | closure.rs:85:59:87:5 | { ... } | | closure.rs:85:17:85:17 | B | | closure.rs:86:9:86:9 | f | | closure.rs:85:20:85:35 | F | +| closure.rs:86:10:86:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:86:10:86:12 | ArgList | T0 | closure.rs:85:14:85:14 | A | | closure.rs:86:11:86:11 | a | | closure.rs:85:14:85:14 | A | | closure.rs:89:22:89:22 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:89:56:91:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:90:9:90:9 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:93:15:105:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:94:13:94:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:94:13:94:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:94:13:94:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:94:17:100:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:94:17:100:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:94:17:100:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:94:18:94:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:95:16:95:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:101:24:101:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:101:24:101:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:101:24:101:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:101:27:101:30 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:103:13:103:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:103:17:103:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:104:13:104:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:19:104:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:104:29:104:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:109:40:109:40 | f | | closure.rs:109:20:109:37 | F | | closure.rs:109:46:111:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:110:23:110:23 | f | | closure.rs:109:20:109:37 | F | +| closure.rs:110:24:110:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:110:24:110:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:110:25:110:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:113:41:113:41 | f | | closure.rs:113:28:113:38 | F | | closure.rs:113:47:115:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:114:23:114:23 | f | | closure.rs:113:28:113:38 | F | +| closure.rs:114:24:114:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:114:24:114:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:114:25:114:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:117:42:117:42 | f | | closure.rs:117:22:117:39 | F | | closure.rs:117:48:120:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -623,16 +695,30 @@ inferCertainType | closure.rs:122:41:122:41 | a | | closure.rs:122:14:122:14 | A | | closure.rs:122:52:124:5 | { ... } | | closure.rs:122:17:122:17 | B | | closure.rs:123:9:123:9 | f | | closure.rs:122:20:122:32 | F | +| closure.rs:123:10:123:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:123:10:123:12 | ArgList | T0 | closure.rs:122:14:122:14 | A | | closure.rs:123:11:123:11 | a | | closure.rs:122:14:122:14 | A | | closure.rs:126:18:126:18 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:126:49:128:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:127:9:127:9 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:130:15:142:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:131:13:131:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:131:13:131:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:131:13:131:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:131:17:137:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:131:17:137:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:131:17:137:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:131:18:131:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:132:16:132:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:138:24:138:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:138:24:138:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:138:24:138:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:138:27:138:30 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:140:13:140:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:140:17:140:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:141:13:141:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:19:141:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:141:29:141:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:146:54:146:54 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:146:54:146:54 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:146:54:146:54 | f | T | closure.rs:146:26:146:51 | F | @@ -641,6 +727,8 @@ inferCertainType | closure.rs:147:9:147:9 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:147:9:147:9 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:147:9:147:9 | f | T | closure.rs:146:26:146:51 | F | +| closure.rs:147:10:147:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:147:10:147:14 | ArgList | T0 | closure.rs:146:20:146:20 | A | | closure.rs:147:11:147:13 | arg | | closure.rs:146:20:146:20 | A | | closure.rs:150:30:150:30 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:150:30:150:30 | f | A | {EXTERNAL LOCATION} | Global | @@ -659,8 +747,154 @@ inferCertainType | closure.rs:151:34:151:36 | arg | | closure.rs:150:24:150:24 | A | | closure.rs:152:31:152:53 | ...::new(...) | | {EXTERNAL LOCATION} | Box | | closure.rs:152:31:152:53 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| closure.rs:152:40:152:52 | \|...\| true | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:152:40:152:52 | \|...\| true | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:152:40:152:52 | \|...\| true | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:152:41:152:41 | _ | | {EXTERNAL LOCATION} | i64 | | closure.rs:152:49:152:52 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:157:34:157:34 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:157:40:157:40 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:157:55:159:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:9:158:9 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:158:10:158:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:158:10:158:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:11:158:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:15:161:15 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:161:39:161:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:54:163:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:9:162:9 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:162:10:162:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:162:10:162:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:11:162:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:165:15:165:15 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:39:165:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:54:167:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:166:9:166:9 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:10:166:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:10:166:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:11:166:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:41:169:41 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:169:47:169:47 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:62:171:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:9:170:9 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:170:10:170:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:170:10:170:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:11:170:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:173:15:173:15 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:46:173:46 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:61:175:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:174:9:174:9 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:10:174:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:10:174:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:11:174:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:177:18:177:18 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:177:40:177:40 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:177:53:179:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:9:178:9 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:178:10:178:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:178:10:178:12 | ArgList | T0 | closure.rs:177:15:177:15 | T | +| closure.rs:178:11:178:11 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:181:42:181:42 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:181:48:181:48 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:181:61:183:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:9:182:9 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:182:10:182:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:182:10:182:12 | ArgList | T0 | closure.rs:181:15:181:15 | T | +| closure.rs:182:11:182:11 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:185:15:206:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:186:13:186:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:186:17:186:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:187:13:187:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:18:187:32 | apply1(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:25:187:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:187:28:187:31 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:13:189:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:189:17:189:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:190:13:190:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:18:190:32 | apply2(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:25:190:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:190:28:190:31 | 2i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:13:192:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:192:17:192:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:13:193:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:18:193:33 | apply3(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | | {EXTERNAL LOCATION} | & | +| closure.rs:193:26:193:26 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:29:193:32 | 3i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:13:195:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:195:17:195:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:196:13:196:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:18:196:32 | apply4(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:25:196:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:196:28:196:31 | 4i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:198:17:198:17 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:198:21:198:25 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:13:199:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:18:199:37 | apply5(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:25:199:30 | &mut f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:199:30:199:30 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:33:199:36 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:13:201:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:201:17:201:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:202:13:202:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:18:202:32 | apply6(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:25:202:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:202:28:202:31 | 6i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:13:204:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:204:17:204:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:205:13:205:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:18:205:32 | apply7(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:25:205:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:205:28:205:31 | 7i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:217:18:217:22 | SelfParam | | {EXTERNAL LOCATION} | & | +| closure.rs:217:18:217:22 | SelfParam | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:217:18:217:22 | SelfParam | TRef.T | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | | {EXTERNAL LOCATION} | & | +| closure.rs:217:42:219:9 | { ... } | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:13:218:22 | &... | | {EXTERNAL LOCATION} | & | +| closure.rs:218:14:218:22 | \|...\| false | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:18:218:22 | false | | {EXTERNAL LOCATION} | bool | +| closure.rs:222:19:240:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:223:13:223:13 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:223:17:223:20 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:21:226:23 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:226:21:226:23 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:22:226:22 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:228:13:228:13 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:228:17:228:20 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:13:231:17 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:231:21:231:22 | &s | | {EXTERNAL LOCATION} | & | +| closure.rs:232:20:232:24 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:232:25:232:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:232:25:232:27 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:26:232:26 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:13:238:13 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:238:17:238:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:9:239:12 | (...) | | {EXTERNAL LOCATION} | & | +| closure.rs:239:10:239:11 | &c | | {EXTERNAL LOCATION} | & | +| closure.rs:239:11:239:11 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:13:239:15 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:13:239:15 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:14:239:14 | x | | {EXTERNAL LOCATION} | i32 | | dereference.rs:13:14:13:18 | SelfParam | | {EXTERNAL LOCATION} | & | | dereference.rs:13:14:13:18 | SelfParam | TRef | dereference.rs:5:1:7:1 | MyIntPointer | | dereference.rs:13:29:15:5 | { ... } | | {EXTERNAL LOCATION} | & | @@ -2259,6 +2493,7 @@ inferCertainType | main.rs:1340:40:1345:5 | { ... } | | {EXTERNAL LOCATION} | Result | | main.rs:1340:40:1345:5 | { ... } | E | main.rs:1320:5:1321:14 | S2 | | main.rs:1340:40:1345:5 | { ... } | T | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:24:1343:28 | \|...\| s | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1349:30:1349:34 | input | | {EXTERNAL LOCATION} | Result | | main.rs:1349:30:1349:34 | input | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1349:30:1349:34 | input | T | main.rs:1349:20:1349:27 | T | @@ -2268,6 +2503,7 @@ inferCertainType | main.rs:1350:21:1350:25 | input | | {EXTERNAL LOCATION} | Result | | main.rs:1350:21:1350:25 | input | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1350:21:1350:25 | input | T | main.rs:1349:20:1349:27 | T | +| main.rs:1351:49:1354:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1352:22:1352:27 | "{:?}\\n" | | {EXTERNAL LOCATION} | & | | main.rs:1352:22:1352:27 | "{:?}\\n" | TRef | {EXTERNAL LOCATION} | str | | main.rs:1352:22:1352:30 | ...::_print(...) | | {EXTERNAL LOCATION} | () | @@ -3182,6 +3418,7 @@ inferCertainType | main.rs:2261:28:2261:29 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2262:9:2262:44 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2262:18:2262:26 | [...] | | {EXTERNAL LOCATION} | [;] | +| main.rs:2262:32:2262:40 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:2262:43:2262:44 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2263:9:2263:41 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2263:18:2263:26 | [...] | | {EXTERNAL LOCATION} | [;] | @@ -3715,48 +3952,65 @@ inferCertainType | main.rs:2747:21:2747:21 | y | | {EXTERNAL LOCATION} | & | | main.rs:2750:13:2750:13 | y | | {EXTERNAL LOCATION} | usize | | main.rs:2751:23:2751:23 | y | | {EXTERNAL LOCATION} | usize | -| main.rs:2762:11:2797:1 | { ... } | | {EXTERNAL LOCATION} | () | -| main.rs:2763:5:2763:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2764:5:2764:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:5:2765:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:20:2765:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:41:2765:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2766:5:2766:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2767:5:2767:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2768:5:2768:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2769:5:2769:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2770:5:2770:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2771:5:2771:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2772:5:2772:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2773:5:2773:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2774:5:2774:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2775:5:2775:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2776:5:2776:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2777:5:2777:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2778:5:2778:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2779:5:2779:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2780:5:2780:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2781:5:2781:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | -| main.rs:2781:5:2781:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | -| main.rs:2782:5:2782:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2783:5:2783:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2784:5:2784:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2785:5:2785:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2786:5:2786:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2787:5:2787:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2788:5:2788:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2789:5:2789:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2790:5:2790:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2791:5:2791:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2792:5:2792:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2793:5:2793:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2794:5:2794:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2795:5:2795:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | -| main.rs:2795:5:2795:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2795:5:2795:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | -| main.rs:2795:5:2795:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | -| main.rs:2795:16:2795:19 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:2796:5:2796:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2766:22:2766:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2766:22:2766:26 | SelfParam | TRef | main.rs:2765:5:2767:5 | Self [trait Container] | +| main.rs:2769:34:2769:34 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2769:34:2769:34 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2769:49:2771:5 | { ... } | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:9:2770:9 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2770:9:2770:9 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2774:22:2774:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2774:22:2774:26 | SelfParam | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2774:22:2774:26 | SelfParam | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2774:35:2776:9 | { ... } | | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:16 | self | | {EXTERNAL LOCATION} | & | +| main.rs:2775:13:2775:16 | self | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2775:13:2775:16 | self | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2779:15:2783:5 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2782:17:2782:26 | my_get(...) | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:24:2782:25 | &g | | {EXTERNAL LOCATION} | & | +| main.rs:2786:11:2821:1 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2787:5:2787:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2788:5:2788:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:5:2789:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:20:2789:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:41:2789:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2790:5:2790:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2791:5:2791:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2792:5:2792:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2793:5:2793:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2794:5:2794:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2795:5:2795:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2796:5:2796:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2797:5:2797:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2798:5:2798:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2799:5:2799:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2800:5:2800:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2801:5:2801:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2802:5:2802:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2803:5:2803:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2804:5:2804:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2805:5:2805:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | +| main.rs:2805:5:2805:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | +| main.rs:2806:5:2806:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2807:5:2807:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2808:5:2808:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2809:5:2809:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2810:5:2810:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2811:5:2811:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2812:5:2812:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2813:5:2813:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2814:5:2814:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2815:5:2815:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2816:5:2816:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2817:5:2817:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2818:5:2818:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2819:5:2819:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2819:5:2819:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2819:5:2819:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | +| main.rs:2819:5:2819:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | +| main.rs:2819:16:2819:19 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:2820:5:2820:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | | overloading.rs:4:19:4:23 | SelfParam | | {EXTERNAL LOCATION} | & | | overloading.rs:4:19:4:23 | SelfParam | TRef | overloading.rs:2:5:11:5 | Self [trait FirstTrait] | | overloading.rs:4:34:6:9 | { ... } | | {EXTERNAL LOCATION} | bool | @@ -5092,6 +5346,32 @@ inferCertainType | regressions.rs:127:9:130:9 | { ... } | | {EXTERNAL LOCATION} | () | | regressions.rs:128:24:128:27 | self | | regressions.rs:121:5:121:19 | S | | regressions.rs:128:24:128:27 | self | T | regressions.rs:123:10:123:10 | T | +| regressions.rs:139:17:139:17 | _ | | {EXTERNAL LOCATION} | & | +| regressions.rs:139:17:139:17 | _ | TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:139:33:141:9 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:139:33:141:9 | { ... } | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:145:17:145:17 | t | | regressions.rs:144:10:144:10 | T | +| regressions.rs:145:31:147:9 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:145:31:147:9 | { ... } | T2 | regressions.rs:144:10:144:10 | T | +| regressions.rs:146:16:146:16 | t | | regressions.rs:144:10:144:10 | T | +| regressions.rs:150:24:153:5 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:150:24:153:5 | { ... } | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:164:16:164:19 | SelfParam | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:16:164:19 | SelfParam | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:164:22:164:25 | _rhs | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:22:164:25 | _rhs | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:164:50:166:9 | { ... } | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:50:166:9 | { ... } | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:165:13:165:16 | self | | regressions.rs:158:5:158:19 | S | +| regressions.rs:165:13:165:16 | self | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:173:16:173:19 | SelfParam | | regressions.rs:158:5:158:19 | S | +| regressions.rs:173:16:173:19 | SelfParam | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:173:22:173:25 | _rhs | | regressions.rs:169:10:169:10 | T | +| regressions.rs:173:47:175:9 | { ... } | | regressions.rs:158:5:158:19 | S | +| regressions.rs:173:47:175:9 | { ... } | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:174:13:174:16 | self | | regressions.rs:158:5:158:19 | S | +| regressions.rs:174:13:174:16 | self | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:178:14:180:5 | { ... } | | {EXTERNAL LOCATION} | () | inferType | associated_types.rs:5:15:5:18 | SelfParam | | associated_types.rs:1:1:2:21 | Wrapper | | associated_types.rs:5:15:5:18 | SelfParam | A | associated_types.rs:4:6:4:6 | A | @@ -6051,6 +6331,8 @@ inferType | closure.rs:10:18:10:24 | add_one | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:18:10:24 | add_one | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:10:18:10:27 | add_one(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:10:25:10:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:10:25:10:27 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:26:10:26 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:13:13:13:13 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:13:17:13:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | @@ -6070,6 +6352,8 @@ inferType | closure.rs:15:18:15:25 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:15:18:15:25 | add_zero | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:15:18:15:28 | add_zero(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:15:26:15:28 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:15:26:15:28 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:15:27:15:27 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:17:13:17:21 | _get_bool | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:17:13:17:21 | _get_bool | dyn(Args) | {EXTERNAL LOCATION} | () | @@ -6097,6 +6381,8 @@ inferType | closure.rs:25:18:25:19 | id | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:18:25:19 | id | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:25:18:25:25 | id(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:25:20:25:25 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:25:20:25:25 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:21:25:24 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:28:13:28:15 | id2 | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:28:13:28:15 | id2 | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | @@ -6116,18 +6402,24 @@ inferType | closure.rs:30:25:30:27 | id2 | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:30:25:30:27 | id2 | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:30:25:30:32 | id2(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:30:28:30:32 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:30:28:30:32 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:30:29:30:31 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:35:44:35:44 | f | | closure.rs:35:20:35:41 | F | | closure.rs:35:50:37:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:36:13:36:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:36:23:36:23 | f | | closure.rs:35:20:35:41 | F | | closure.rs:36:23:36:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:36:24:36:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:36:24:36:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:36:25:36:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:39:45:39:45 | f | | closure.rs:39:28:39:42 | F | | closure.rs:39:51:41:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:40:13:40:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:40:23:40:23 | f | | closure.rs:39:28:39:42 | F | | closure.rs:40:23:40:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:40:24:40:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:40:24:40:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:40:25:40:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:43:46:43:46 | f | | closure.rs:43:22:43:43 | F | | closure.rs:43:52:46:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6135,74 +6427,77 @@ inferType | closure.rs:44:19:44:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:45:9:45:9 | f | | closure.rs:43:22:43:43 | F | | closure.rs:45:9:45:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:45:10:45:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:45:10:45:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:45:11:45:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:48:39:48:39 | f | | closure.rs:48:20:48:36 | F | | closure.rs:48:45:48:45 | a | | closure.rs:48:14:48:14 | A | | closure.rs:48:56:50:5 | { ... } | | closure.rs:48:17:48:17 | B | | closure.rs:49:9:49:9 | f | | closure.rs:48:20:48:36 | F | | closure.rs:49:9:49:12 | f(...) | | closure.rs:48:17:48:17 | B | +| closure.rs:49:10:49:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:49:10:49:12 | ArgList | T0 | closure.rs:48:14:48:14 | A | | closure.rs:49:11:49:11 | a | | closure.rs:48:14:48:14 | A | | closure.rs:52:18:52:18 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:52:53:54:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:53:9:53:9 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:53:9:53:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:53:10:53:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:53:10:53:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:53:11:53:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:53:11:53:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:56:15:68:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:57:13:57:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:57:13:57:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:57:13:57:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:57:13:57:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:57:13:57:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:57:17:63:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:57:17:63:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:57:18:57:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:57:34:63:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:57:34:63:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:58:13:62:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:58:13:62:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:58:16:58:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:58:18:60:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:58:18:60:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:59:17:59:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:59:17:59:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:60:20:62:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:60:20:62:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:61:17:61:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:61:17:61:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:64:13:64:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:64:13:64:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:64:18:64:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:64:18:64:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:64:24:64:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:64:24:64:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:64:24:64:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:64:24:64:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:64:24:64:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:64:27:64:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:66:13:66:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:66:13:66:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:66:13:66:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:66:17:66:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:66:17:66:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:66:17:66:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:66:18:66:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:66:21:66:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:66:25:66:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:67:13:67:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:19:67:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:29:67:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:67:29:67:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:67:29:67:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:72:47:72:47 | f | | closure.rs:72:20:72:40 | F | | closure.rs:72:53:74:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:73:13:73:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:73:23:73:23 | f | | closure.rs:72:20:72:40 | F | | closure.rs:73:23:73:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:73:24:73:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:73:24:73:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:73:25:73:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:76:48:76:48 | f | | closure.rs:76:28:76:41 | F | | closure.rs:76:54:78:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:77:13:77:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:77:23:77:23 | f | | closure.rs:76:28:76:41 | F | | closure.rs:77:23:77:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:77:24:77:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:77:24:77:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:77:25:77:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:80:49:80:49 | f | | closure.rs:80:22:80:42 | F | | closure.rs:80:55:83:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6210,74 +6505,77 @@ inferType | closure.rs:81:19:81:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:82:9:82:9 | f | | closure.rs:80:22:80:42 | F | | closure.rs:82:9:82:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:82:10:82:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:82:10:82:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:82:11:82:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:85:42:85:42 | f | | closure.rs:85:20:85:35 | F | | closure.rs:85:48:85:48 | a | | closure.rs:85:14:85:14 | A | | closure.rs:85:59:87:5 | { ... } | | closure.rs:85:17:85:17 | B | | closure.rs:86:9:86:9 | f | | closure.rs:85:20:85:35 | F | | closure.rs:86:9:86:12 | f(...) | | closure.rs:85:17:85:17 | B | +| closure.rs:86:10:86:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:86:10:86:12 | ArgList | T0 | closure.rs:85:14:85:14 | A | | closure.rs:86:11:86:11 | a | | closure.rs:85:14:85:14 | A | | closure.rs:89:22:89:22 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:89:56:91:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:90:9:90:9 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:90:9:90:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:90:10:90:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:90:10:90:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:90:11:90:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:90:11:90:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:93:15:105:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:94:13:94:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:94:13:94:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:94:13:94:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:94:13:94:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:94:13:94:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:94:17:100:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:94:17:100:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:94:18:94:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:94:34:100:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:94:34:100:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:95:13:99:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:95:13:99:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:95:16:95:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:95:18:97:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:95:18:97:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:96:17:96:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:96:17:96:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:97:20:99:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:97:20:99:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:98:17:98:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:98:17:98:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:101:13:101:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:101:13:101:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:101:18:101:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:101:18:101:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:101:24:101:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:101:24:101:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:101:24:101:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:101:24:101:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:101:24:101:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:101:27:101:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:103:13:103:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:103:13:103:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:103:13:103:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:103:17:103:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:103:17:103:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:103:17:103:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:103:18:103:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:103:21:103:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:103:25:103:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:104:13:104:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:19:104:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:29:104:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:104:29:104:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:104:29:104:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:109:40:109:40 | f | | closure.rs:109:20:109:37 | F | | closure.rs:109:46:111:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:110:13:110:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:110:23:110:23 | f | | closure.rs:109:20:109:37 | F | | closure.rs:110:23:110:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:110:24:110:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:110:24:110:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:110:25:110:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:113:41:113:41 | f | | closure.rs:113:28:113:38 | F | | closure.rs:113:47:115:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:114:13:114:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:114:23:114:23 | f | | closure.rs:113:28:113:38 | F | | closure.rs:114:23:114:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:114:24:114:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:114:24:114:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:114:25:114:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:117:42:117:42 | f | | closure.rs:117:22:117:39 | F | | closure.rs:117:48:120:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6285,63 +6583,62 @@ inferType | closure.rs:118:19:118:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:119:9:119:9 | f | | closure.rs:117:22:117:39 | F | | closure.rs:119:9:119:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:119:10:119:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:119:10:119:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:119:11:119:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:122:35:122:35 | f | | closure.rs:122:20:122:32 | F | | closure.rs:122:41:122:41 | a | | closure.rs:122:14:122:14 | A | | closure.rs:122:52:124:5 | { ... } | | closure.rs:122:17:122:17 | B | | closure.rs:123:9:123:9 | f | | closure.rs:122:20:122:32 | F | | closure.rs:123:9:123:12 | f(...) | | closure.rs:122:17:122:17 | B | +| closure.rs:123:10:123:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:123:10:123:12 | ArgList | T0 | closure.rs:122:14:122:14 | A | | closure.rs:123:11:123:11 | a | | closure.rs:122:14:122:14 | A | | closure.rs:126:18:126:18 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:126:49:128:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:127:9:127:9 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:127:9:127:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:127:10:127:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:127:10:127:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:127:11:127:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:127:11:127:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:130:15:142:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:131:13:131:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:131:13:131:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:131:13:131:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:131:13:131:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:131:13:131:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:131:17:137:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:131:17:137:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:131:18:131:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:131:34:137:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:131:34:137:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:132:13:136:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:132:13:136:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:132:16:132:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:132:18:134:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:132:18:134:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:133:17:133:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:133:17:133:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:134:20:136:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:134:20:136:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:135:17:135:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:135:17:135:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:138:13:138:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:138:13:138:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:138:18:138:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:138:18:138:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:138:24:138:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:138:24:138:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:138:24:138:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:138:24:138:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:138:24:138:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:138:27:138:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:140:13:140:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:140:13:140:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:140:13:140:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:140:17:140:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:140:17:140:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:140:17:140:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:140:18:140:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:140:21:140:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:140:25:140:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:141:13:141:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:19:141:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:29:141:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:141:29:141:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:141:29:141:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:146:54:146:54 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:146:54:146:54 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:146:54:146:54 | f | T | closure.rs:146:26:146:51 | F | @@ -6351,7 +6648,8 @@ inferType | closure.rs:147:9:147:9 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:147:9:147:9 | f | T | closure.rs:146:26:146:51 | F | | closure.rs:147:9:147:14 | f(...) | | closure.rs:146:23:146:23 | B | -| closure.rs:147:9:147:14 | f(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:147:10:147:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:147:10:147:14 | ArgList | T0 | closure.rs:146:20:146:20 | A | | closure.rs:147:11:147:13 | arg | | closure.rs:146:20:146:20 | A | | closure.rs:150:30:150:30 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:150:30:150:30 | f | A | {EXTERNAL LOCATION} | Global | @@ -6385,6 +6683,287 @@ inferType | closure.rs:152:41:152:41 | _ | | {EXTERNAL LOCATION} | i64 | | closure.rs:152:49:152:52 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:152:56:152:56 | 3 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:157:34:157:34 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:157:40:157:40 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:157:55:159:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:9:158:9 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:158:9:158:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:10:158:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:158:10:158:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:11:158:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:15:161:15 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:161:39:161:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:54:163:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:9:162:9 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:162:9:162:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:10:162:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:162:10:162:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:11:162:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:165:15:165:15 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:39:165:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:54:167:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:166:9:166:9 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:10:166:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:10:166:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:11:166:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:41:169:41 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:169:47:169:47 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:62:171:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:9:170:9 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:170:9:170:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:10:170:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:170:10:170:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:11:170:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:173:15:173:15 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:46:173:46 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:61:175:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:174:9:174:9 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:10:174:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:10:174:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:11:174:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:177:18:177:18 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:177:40:177:40 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:177:53:179:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:9:178:9 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:178:9:178:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:10:178:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:178:10:178:12 | ArgList | T0 | closure.rs:177:15:177:15 | T | +| closure.rs:178:11:178:11 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:181:42:181:42 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:181:48:181:48 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:181:61:183:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:9:182:9 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:182:9:182:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:10:182:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:182:10:182:12 | ArgList | T0 | closure.rs:181:15:181:15 | T | +| closure.rs:182:11:182:11 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:185:15:206:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:186:13:186:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:186:13:186:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:186:13:186:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:13:186:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:17:186:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:18:186:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:21:186:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:13:187:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:18:187:32 | apply1(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:25:187:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:187:25:187:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:187:25:187:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:25:187:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:28:187:31 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:13:189:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:189:13:189:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:189:13:189:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:13:189:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:17:189:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:18:189:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:21:189:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:13:190:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:18:190:32 | apply2(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:25:190:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:190:25:190:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:190:25:190:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:25:190:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:28:190:31 | 2i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:13:192:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:192:13:192:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:192:13:192:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:13:192:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:17:192:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:18:192:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:21:192:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:13:193:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:18:193:33 | apply3(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | | {EXTERNAL LOCATION} | & | +| closure.rs:193:25:193:26 | &f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:26:193:26 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:26:193:26 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:26:193:26 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:26:193:26 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:29:193:32 | 3i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:13:195:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:195:13:195:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:195:13:195:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:13:195:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:17:195:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:18:195:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:21:195:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:13:196:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:18:196:32 | apply4(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:25:196:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:196:25:196:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:196:25:196:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:25:196:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:28:196:31 | 4i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:198:17:198:17 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:198:17:198:17 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:198:21:198:25 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:198:21:198:25 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:13:199:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:18:199:37 | apply5(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:25:199:30 | &mut f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:199:25:199:30 | &mut f | TRefMut | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:25:199:30 | &mut f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:30:199:30 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:30:199:30 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:33:199:36 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:13:201:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:201:13:201:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:201:13:201:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:13:201:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:17:201:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:18:201:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:21:201:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:13:202:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:18:202:32 | apply6(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:25:202:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:202:25:202:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:202:25:202:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:25:202:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:28:202:31 | 6i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:13:204:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:204:13:204:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:204:13:204:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:13:204:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:17:204:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:18:204:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:21:204:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:13:205:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:18:205:32 | apply7(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:25:205:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:205:25:205:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:205:25:205:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:25:205:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:28:205:31 | 7i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:217:18:217:22 | SelfParam | | {EXTERNAL LOCATION} | & | +| closure.rs:217:18:217:22 | SelfParam | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:217:18:217:22 | SelfParam | TRef.T | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | | {EXTERNAL LOCATION} | & | +| closure.rs:217:42:219:9 | { ... } | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:13:218:22 | &... | | {EXTERNAL LOCATION} | & | +| closure.rs:218:13:218:22 | &... | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:14:218:22 | \|...\| false | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:15:218:15 | _ | | closure.rs:214:10:214:10 | T | +| closure.rs:218:18:218:22 | false | | {EXTERNAL LOCATION} | bool | +| closure.rs:222:19:240:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:223:13:223:13 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:223:17:223:20 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:224:13:224:13 | v | | {EXTERNAL LOCATION} | i64 | +| closure.rs:224:17:224:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:225:13:225:13 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:225:13:225:13 | s | T | {EXTERNAL LOCATION} | i64 | +| closure.rs:225:17:225:20 | S(...) | | closure.rs:212:5:212:19 | S | +| closure.rs:225:17:225:20 | S(...) | T | {EXTERNAL LOCATION} | i64 | +| closure.rs:225:19:225:19 | v | | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:13:226:16 | _ret | | {EXTERNAL LOCATION} | bool | +| closure.rs:226:20:226:20 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:226:20:226:20 | s | T | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:20:226:23 | s(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:226:21:226:23 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:226:21:226:23 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:22:226:22 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:228:13:228:13 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:228:17:228:20 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:229:13:229:13 | v | | {EXTERNAL LOCATION} | i32 | +| closure.rs:229:17:229:34 | ...::default(...) | | {EXTERNAL LOCATION} | i32 | +| closure.rs:230:13:230:13 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:230:13:230:13 | s | T | {EXTERNAL LOCATION} | i32 | +| closure.rs:230:17:230:20 | S(...) | | closure.rs:212:5:212:19 | S | +| closure.rs:230:17:230:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| closure.rs:230:19:230:19 | v | | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:13:231:17 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:231:13:231:17 | s_ref | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:231:13:231:17 | s_ref | TRef.T | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:21:231:22 | &s | | {EXTERNAL LOCATION} | & | +| closure.rs:231:21:231:22 | &s | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:231:21:231:22 | &s | TRef.T | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:22:231:22 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:231:22:231:22 | s | T | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:13:232:16 | _ret | | {EXTERNAL LOCATION} | bool | +| closure.rs:232:20:232:24 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:232:20:232:24 | s_ref | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:232:20:232:24 | s_ref | TRef.T | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:20:232:27 | s_ref(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:232:25:232:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:232:25:232:27 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:26:232:26 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:13:238:13 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:238:13:238:13 | c | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:238:13:238:13 | c | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:13:238:13 | c | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:17:238:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:18:238:18 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:21:238:21 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:12 | (...) | | {EXTERNAL LOCATION} | & | +| closure.rs:239:9:239:12 | (...) | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:15 | ...(...) | | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:10:239:11 | &c | | {EXTERNAL LOCATION} | & | +| closure.rs:239:10:239:11 | &c | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:11:239:11 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:11:239:11 | c | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:11:239:11 | c | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:11:239:11 | c | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:13:239:15 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:13:239:15 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:14:239:14 | x | | {EXTERNAL LOCATION} | i32 | | dereference.rs:13:14:13:18 | SelfParam | | {EXTERNAL LOCATION} | & | | dereference.rs:13:14:13:18 | SelfParam | TRef | dereference.rs:5:1:7:1 | MyIntPointer | | dereference.rs:13:29:15:5 | { ... } | | {EXTERNAL LOCATION} | & | @@ -9458,14 +10037,21 @@ inferType | main.rs:1341:28:1341:41 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1341:28:1341:41 | ...::Ok(...) | T | main.rs:1317:5:1318:14 | S1 | | main.rs:1341:39:1341:40 | S1 | | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:13:1343:13 | y | | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:17 | x | | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:17 | x | T | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:17 | x | T.T | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:18 | TryExpr | | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:18 | TryExpr | T | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:29 | ... .map(...) | | {EXTERNAL LOCATION} | Result | +| main.rs:1343:17:1343:29 | ... .map(...) | T | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:17:1343:30 | TryExpr | | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:24:1343:28 | \|...\| s | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1343:24:1343:28 | \|...\| s | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:1343:24:1343:28 | \|...\| s | dyn(Args).T0 | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:24:1343:28 | \|...\| s | dyn(Output) | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:25:1343:25 | s | | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:28:1343:28 | s | | main.rs:1317:5:1318:14 | S1 | | main.rs:1344:9:1344:22 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1344:9:1344:22 | ...::Ok(...) | E | main.rs:1320:5:1321:14 | S2 | | main.rs:1344:9:1344:22 | ...::Ok(...) | T | main.rs:1317:5:1318:14 | S1 | @@ -9481,26 +10067,36 @@ inferType | main.rs:1350:21:1350:25 | input | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1350:21:1350:25 | input | T | main.rs:1349:20:1349:27 | T | | main.rs:1350:21:1350:26 | TryExpr | | main.rs:1349:20:1349:27 | T | +| main.rs:1351:13:1351:18 | mapped | | main.rs:1349:20:1349:27 | T | | main.rs:1351:22:1351:38 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1351:22:1351:38 | ...::Ok(...) | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1351:22:1351:38 | ...::Ok(...) | T | main.rs:1349:20:1349:27 | T | | main.rs:1351:22:1354:10 | ... .and_then(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1351:22:1354:10 | ... .and_then(...) | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:22:1354:10 | ... .and_then(...) | T | main.rs:1349:20:1349:27 | T | +| main.rs:1351:22:1354:11 | TryExpr | | main.rs:1349:20:1349:27 | T | | main.rs:1351:33:1351:37 | value | | main.rs:1349:20:1349:27 | T | | main.rs:1351:49:1354:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:1351:49:1354:9 | \|...\| ... | dyn(Args).T0 | main.rs:1349:20:1349:27 | T | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | Result | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output).E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output).T | main.rs:1349:20:1349:27 | T | +| main.rs:1351:50:1351:50 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1351:53:1354:9 | { ... } | | {EXTERNAL LOCATION} | Result | | main.rs:1351:53:1354:9 | { ... } | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:53:1354:9 | { ... } | T | main.rs:1349:20:1349:27 | T | | main.rs:1352:13:1352:31 | MacroExpr | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:27 | "{:?}\\n" | | {EXTERNAL LOCATION} | & | | main.rs:1352:22:1352:27 | "{:?}\\n" | TRef | {EXTERNAL LOCATION} | str | | main.rs:1352:22:1352:30 | ...::_print(...) | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:30 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:30 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:1352:30:1352:30 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | T | main.rs:1349:20:1349:27 | T | +| main.rs:1353:33:1353:33 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1355:9:1355:23 | ...::Err(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1355:9:1355:23 | ...::Err(...) | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1355:9:1355:23 | ...::Err(...) | T | main.rs:1349:20:1349:27 | T | @@ -11071,14 +11667,21 @@ inferType | main.rs:2261:25:2261:25 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2261:28:2261:29 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2262:9:2262:44 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2262:13:2262:13 | i | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:18:2262:26 | [...] | | {EXTERNAL LOCATION} | [;] | | main.rs:2262:18:2262:26 | [...] | TArray | {EXTERNAL LOCATION} | i32 | | main.rs:2262:18:2262:41 | ... .map(...) | | {EXTERNAL LOCATION} | [;] | +| main.rs:2262:18:2262:41 | ... .map(...) | TArray | {EXTERNAL LOCATION} | i32 | | main.rs:2262:19:2262:19 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:22:2262:22 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:25:2262:25 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:32:2262:40 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:2262:32:2262:40 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:2262:32:2262:40 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:32:2262:40 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:33:2262:33 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:36:2262:36 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:36:2262:40 | ... + ... | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:40:2262:40 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:43:2262:44 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2263:9:2263:41 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | @@ -12316,48 +12919,81 @@ inferType | main.rs:2751:17:2751:17 | x | | {EXTERNAL LOCATION} | i32 | | main.rs:2751:17:2751:24 | x.max(...) | | {EXTERNAL LOCATION} | i32 | | main.rs:2751:23:2751:23 | y | | {EXTERNAL LOCATION} | usize | -| main.rs:2762:11:2797:1 | { ... } | | {EXTERNAL LOCATION} | () | -| main.rs:2763:5:2763:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2764:5:2764:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:5:2765:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:20:2765:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:41:2765:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2766:5:2766:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2767:5:2767:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2768:5:2768:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2769:5:2769:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2770:5:2770:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2771:5:2771:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2772:5:2772:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2773:5:2773:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2774:5:2774:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2775:5:2775:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2776:5:2776:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2777:5:2777:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2778:5:2778:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2779:5:2779:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2780:5:2780:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2781:5:2781:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | -| main.rs:2781:5:2781:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | -| main.rs:2782:5:2782:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2783:5:2783:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2784:5:2784:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2785:5:2785:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2786:5:2786:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2787:5:2787:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2788:5:2788:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2789:5:2789:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2790:5:2790:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2791:5:2791:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2792:5:2792:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2793:5:2793:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2794:5:2794:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2795:5:2795:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | -| main.rs:2795:5:2795:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2795:5:2795:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | -| main.rs:2795:5:2795:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | -| main.rs:2795:16:2795:19 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:2796:5:2796:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2766:22:2766:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2766:22:2766:26 | SelfParam | TRef | main.rs:2765:5:2767:5 | Self [trait Container] | +| main.rs:2769:34:2769:34 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2769:34:2769:34 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2769:49:2771:5 | { ... } | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:9:2770:9 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2770:9:2770:9 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2770:9:2770:21 | c.get_input() | | {EXTERNAL LOCATION} | i64 | +| main.rs:2770:9:2770:27 | ... == ... | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:26:2770:27 | 42 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2774:22:2774:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2774:22:2774:26 | SelfParam | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2774:22:2774:26 | SelfParam | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2774:35:2776:9 | { ... } | | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:16 | self | | {EXTERNAL LOCATION} | & | +| main.rs:2775:13:2775:16 | self | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2775:13:2775:16 | self | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:18 | self.0 | | main.rs:2773:10:2773:17 | GT | +| main.rs:2779:15:2783:5 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2780:13:2780:13 | v | | {EXTERNAL LOCATION} | i64 | +| main.rs:2780:17:2780:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | +| main.rs:2781:13:2781:13 | g | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2781:13:2781:13 | g | T | {EXTERNAL LOCATION} | i64 | +| main.rs:2781:17:2781:22 | Gen(...) | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2781:17:2781:22 | Gen(...) | T | {EXTERNAL LOCATION} | i64 | +| main.rs:2781:21:2781:21 | v | | {EXTERNAL LOCATION} | i64 | +| main.rs:2782:13:2782:13 | _ | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:17:2782:26 | my_get(...) | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:24:2782:25 | &g | | {EXTERNAL LOCATION} | & | +| main.rs:2782:24:2782:25 | &g | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2782:24:2782:25 | &g | TRef.T | {EXTERNAL LOCATION} | i64 | +| main.rs:2782:25:2782:25 | g | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2782:25:2782:25 | g | T | {EXTERNAL LOCATION} | i64 | +| main.rs:2786:11:2821:1 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2787:5:2787:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2788:5:2788:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:5:2789:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:20:2789:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:41:2789:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2790:5:2790:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2791:5:2791:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2792:5:2792:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2793:5:2793:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2794:5:2794:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2795:5:2795:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2796:5:2796:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2797:5:2797:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2798:5:2798:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2799:5:2799:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2800:5:2800:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2801:5:2801:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2802:5:2802:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2803:5:2803:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2804:5:2804:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2805:5:2805:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | +| main.rs:2805:5:2805:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | +| main.rs:2806:5:2806:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2807:5:2807:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2808:5:2808:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2809:5:2809:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2810:5:2810:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2811:5:2811:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2812:5:2812:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2813:5:2813:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2814:5:2814:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2815:5:2815:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2816:5:2816:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2817:5:2817:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2818:5:2818:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2819:5:2819:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2819:5:2819:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2819:5:2819:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | +| main.rs:2819:5:2819:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | +| main.rs:2819:16:2819:19 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:2820:5:2820:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | | overloading.rs:4:19:4:23 | SelfParam | | {EXTERNAL LOCATION} | & | | overloading.rs:4:19:4:23 | SelfParam | TRef | overloading.rs:2:5:11:5 | Self [trait FirstTrait] | | overloading.rs:4:34:6:9 | { ... } | | {EXTERNAL LOCATION} | bool | @@ -15158,4 +15794,62 @@ inferType | regressions.rs:128:24:128:27 | self | T | regressions.rs:123:10:123:10 | T | | regressions.rs:129:13:129:13 | s | | regressions.rs:123:10:123:10 | T | | regressions.rs:129:13:129:17 | s.m() | | {EXTERNAL LOCATION} | () | +| regressions.rs:139:17:139:17 | _ | | {EXTERNAL LOCATION} | & | +| regressions.rs:139:17:139:17 | _ | TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:139:33:141:9 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:139:33:141:9 | { ... } | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:140:13:140:18 | S2(...) | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:140:13:140:18 | S2(...) | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:140:16:140:17 | S1 | | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:145:17:145:17 | t | | regressions.rs:144:10:144:10 | T | +| regressions.rs:145:31:147:9 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:145:31:147:9 | { ... } | T2 | regressions.rs:144:10:144:10 | T | +| regressions.rs:146:13:146:17 | S2(...) | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:146:13:146:17 | S2(...) | T2 | regressions.rs:144:10:144:10 | T | +| regressions.rs:146:16:146:16 | t | | regressions.rs:144:10:144:10 | T | +| regressions.rs:150:24:153:5 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:150:24:153:5 | { ... } | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:13:151:13 | x | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:151:13:151:13 | x | T2 | {EXTERNAL LOCATION} | & | +| regressions.rs:151:13:151:13 | x | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:13:151:13 | x | T2.TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:17:151:18 | S1 | | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:17:151:25 | S1.into() | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:151:17:151:25 | S1.into() | T2 | {EXTERNAL LOCATION} | & | +| regressions.rs:151:17:151:25 | S1.into() | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:17:151:25 | S1.into() | T2.TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:152:9:152:9 | x | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:152:9:152:9 | x | T2 | {EXTERNAL LOCATION} | & | +| regressions.rs:152:9:152:9 | x | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:152:9:152:9 | x | T2.TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:164:16:164:19 | SelfParam | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:16:164:19 | SelfParam | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:164:22:164:25 | _rhs | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:22:164:25 | _rhs | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:164:50:166:9 | { ... } | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:50:166:9 | { ... } | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:165:13:165:16 | self | | regressions.rs:158:5:158:19 | S | +| regressions.rs:165:13:165:16 | self | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:173:16:173:19 | SelfParam | | regressions.rs:158:5:158:19 | S | +| regressions.rs:173:16:173:19 | SelfParam | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:173:22:173:25 | _rhs | | regressions.rs:169:10:169:10 | T | +| regressions.rs:173:47:175:9 | { ... } | | regressions.rs:158:5:158:19 | S | +| regressions.rs:173:47:175:9 | { ... } | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:174:13:174:16 | self | | regressions.rs:158:5:158:19 | S | +| regressions.rs:174:13:174:16 | self | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:178:14:180:5 | { ... } | | {EXTERNAL LOCATION} | () | +| regressions.rs:179:13:179:13 | x | | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:13:179:13 | x | T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:13:179:13 | x | T | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:13:179:13 | x | T.T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:17:179:20 | S(...) | | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:17:179:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:17:179:27 | ... + ... | | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:17:179:27 | ... + ... | T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:17:179:27 | ... + ... | T | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:17:179:27 | ... + ... | T.T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:19:179:19 | 0 | | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:24:179:27 | S(...) | | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:24:179:27 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:26:179:26 | 1 | | {EXTERNAL LOCATION} | i32 | testFailures diff --git a/rust/ql/test/utils-tests/modelgenerator/option.rs b/rust/ql/test/utils-tests/modelgenerator/option.rs index 701073564b1..afe76e2088e 100644 --- a/rust/ql/test/utils-tests/modelgenerator/option.rs +++ b/rust/ql/test/utils-tests/modelgenerator/option.rs @@ -149,6 +149,8 @@ impl MyOption { // summary=::map;Argument[0].ReturnValue;ReturnValue.Field[test::option::MyOption::MySome(0)];value;dfc-generated // summary=::map;Argument[self].Field[test::option::MyOption::MySome(0)];Argument[0].Parameter[0];value;dfc-generated + // The spurious model below happens because `f` incorrectly resolves to the closure passed in from `as_deref` + // SPURIOUS-summary=::map;Argument[self].Field[test::option::MyOption::MySome(0)].Reference;ReturnValue.Field[test::option::MyOption::MySome(0)].Reference;taint;dfc-generated pub fn map(self, f: F) -> MyOption where F: FnOnce(T) -> U, @@ -217,7 +219,7 @@ impl MyOption { } } - // MISSING: `Deref` trait + // summary=::as_deref;Argument[self].Reference.Field[test::option::MyOption::MySome(0)];ReturnValue.Field[test::option::MyOption::MySome(0)].Reference;taint;dfc-generated pub fn as_deref(&self) -> MyOption<&T::Target> where T: Deref, diff --git a/shared/dataflow/codeql/dataflow/DataFlow.qll b/shared/dataflow/codeql/dataflow/DataFlow.qll index 7f9c0194374..cacd52cf839 100644 --- a/shared/dataflow/codeql/dataflow/DataFlow.qll +++ b/shared/dataflow/codeql/dataflow/DataFlow.qll @@ -63,6 +63,35 @@ signature module InputSig { DataFlowType getNodeType(Node node); + /** + * Gets a special type to use for parameter node `p` belonging to callables with a + * source node where a source call context `FlowFeature` is used, if any. + * + * This can be used to prevent lambdas from being resolved, when a concrete call + * context is needed. Example: + * + * ```csharp + * void Foo(Action a) + * { + * var x = Source(); + * a(x); // (1) + * a = s => Sink(s); // (2) + * a(x); // (3) + * } + * + * void Bar() + * { + * Foo(s => Sink(s)); // (4) + * } + * ``` + * + * If a source call context flow feature is used, `a` can be assigned a special + * type that is incompatible with the type of _any_ lambda expression, which will + * prevent the call edge from (1) to (4). Note that the call edge from (3) to (2) + * will still be valid. + */ + default DataFlowType getSourceContextParameterNodeType(Node p) { none() } + predicate nodeIsHidden(Node node); class DataFlowExpr; diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 506774857d8..ed0412d1cd4 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1103,6 +1103,16 @@ module MakeImpl Lang> { private module FwdTypeFlowInput implements TypeFlowInput { predicate enableTypeFlow = Param::enableTypeFlow/0; + pragma[nomagic] + predicate isParameterNodeInSourceCallContext(ParamNode p) { + hasSourceCallCtx() and + exists(Node source, DataFlowCallable c | + Config::isSource(pragma[only_bind_into](source), _) and + nodeEnclosingCallable(source, c) and + nodeEnclosingCallable(p, c) + ) + } + predicate relevantCallEdgeIn = PrevStage::relevantCallEdgeIn/2; predicate relevantCallEdgeOut = PrevStage::relevantCallEdgeOut/2; @@ -1410,6 +1420,8 @@ module MakeImpl Lang> { private module RevTypeFlowInput implements TypeFlowInput { predicate enableTypeFlow = Param::enableTypeFlow/0; + predicate isParameterNodeInSourceCallContext(ParamNode p) { none() } + predicate relevantCallEdgeIn(Call call, Callable c) { flowOutOfCallAp(call, c, _, _, _, _, _) } diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll index 51ebb3f8a73..962a58c26f9 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll @@ -1893,6 +1893,9 @@ module MakeImplCommon Lang> { signature module TypeFlowInput { predicate enableTypeFlow(); + /** Holds if `p` is a parameter of a callable with a source node that has a call context. */ + predicate isParameterNodeInSourceCallContext(ParamNode p); + /** Holds if the edge is possibly needed in the direction `call` to `c`. */ predicate relevantCallEdgeIn(Call call, Callable c); @@ -1953,6 +1956,9 @@ module MakeImplCommon Lang> { /** * Holds if a sequence of calls may propagate the value of `arg` to some * argument-to-parameter call edge that strengthens the static type. + * + * This predicate is a reverse flow computation, starting at calls that + * strengthen the type and then following relevant call edges backwards. */ pragma[nomagic] private predicate trackedArgTypeCand(ArgNode arg) { @@ -1987,6 +1993,9 @@ module MakeImplCommon Lang> { * Holds if `p` is part of a value-propagating call path where the * end-points have stronger types than the intermediate parameter and * argument nodes. + * + * This predicate is a forward flow computation, intersecting with the + * reverse flow computation done in `trackedArgTypeCand`. */ private predicate trackedParamType(ParamNode p) { exists(Call call1, Callable c1, ArgNode argOut, Call call2, Callable c2, ArgNode argIn | @@ -2013,6 +2022,8 @@ module MakeImplCommon Lang> { typeStrongerThanFilter(at, pt) ) or + Input::isParameterNodeInSourceCallContext(p) + or exists(ArgNode arg | trackedArgType(arg) and relevantCallEdge(_, _, arg, p) and @@ -2104,8 +2115,12 @@ module MakeImplCommon Lang> { * context. */ private predicate typeFlowParamType(ParamNode p, Type t, boolean cc) { - exists(Callable c | - Input::dataFlowNonCallEntry(c, cc) and + exists(Callable c | Input::dataFlowNonCallEntry(c, cc) | + cc = true and + nodeEnclosingCallable(p, c) and + t = getSourceContextParameterNodeType(p) + or + (cc = false or not exists(getSourceContextParameterNodeType(p))) and trackedParamWithType(p, t, c) ) or diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll index 426576d3ace..b7a45a67b56 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll @@ -86,6 +86,8 @@ module MakeImplStage1 Lang> { bindingset[p, kind] predicate parameterFlowThroughAllowed(ParamNd p, ReturnKindExt kind); + predicate fwdFlow(Nd node); + // begin StageSig class Ap; @@ -634,7 +636,7 @@ module MakeImplStage1 Lang> { ) } - private predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } + predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } pragma[nomagic] private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc) { @@ -1291,6 +1293,8 @@ module MakeImplStage1 Lang> { import Stage1 import Stage1Common + predicate fwdFlow(Nd node) { Stage1::fwdFlow(node) } + predicate revFlow(NodeEx node, Ap ap) { Stage1::revFlow(node) and exists(ap) } predicate toNormalSinkNode = toNormalSinkNodeEx/1; @@ -1395,6 +1399,8 @@ module MakeImplStage1 Lang> { import Stage1Common + predicate fwdFlow(Nd node) { Stage1::fwdFlow(node.getNodeEx()) } + predicate revFlow(Nd node) { Stage1::revFlow(node.getNodeEx()) } predicate revFlow(Nd node, Ap ap) { Stage1::revFlow(node.getNodeEx()) and exists(ap) } diff --git a/shared/mad/codeql/mad/ModelValidation.qll b/shared/mad/codeql/mad/ModelValidation.qll index 042fb4200dd..5eaa78626ab 100644 --- a/shared/mad/codeql/mad/ModelValidation.qll +++ b/shared/mad/codeql/mad/ModelValidation.qll @@ -48,7 +48,7 @@ module KindValidation { // CPP-only currently "remote-sink", // Python-only currently, but may be shared in the future - "prompt-injection" + "bind-socket-all-interfaces", "prompt-injection" ] or this.matches([ diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index 0b23b08aad6..888ca65fa98 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -964,7 +964,7 @@ module Make1 Input1> { /** * Holds if `term` does not satisfy `constraint`. * - * This predicate is an approximation of `not hasConstraintMention(term, constraint)`. + * This predicate is an approximation of `not hasConstraintMention(term, _, _, constraint, _, _)`. */ pragma[nomagic] private predicate hasNotConstraintMention( @@ -1072,7 +1072,7 @@ module Make1 Input1> { } pragma[nomagic] - private predicate satisfiesConstraintTypeMention1( + private predicate satisfiesConstraint0( Term term, Constraint constraint, TypeAbstraction abs, TypeMention sub, TypePath path, Type t ) { @@ -1100,37 +1100,55 @@ module Make1 Input1> { } pragma[inline] - private predicate satisfiesConstraintTypeMentionInline( - Term term, Constraint constraint, TypeAbstraction abs, TypePath path, - TypePath pathToTypeParamInSub + private predicate satisfiesConstraintInline( + Term term, Constraint constraint, TypeAbstraction abs, TypePath pathToTypeParamInConstraint, + TypePath pathToTypeParamInSub, TypeParameter tp ) { - exists(TypeMention sub, TypeParameter tp | - satisfiesConstraintTypeMention1(term, constraint, abs, sub, path, tp) and + exists(TypeMention sub | + satisfiesConstraint0(term, constraint, abs, sub, pathToTypeParamInConstraint, tp) and tp = abs.getATypeParameter() and sub.getTypeAt(pathToTypeParamInSub) = tp ) } + /** + * Holds if `term` satisfies the constraint `constraint` with _some_ type + * parameter at `pathToTypeParamInConstraint`, and the type parameter occurs + * at `pathToTypeParamInSub` in a satisfying condition. + * + * Example: + * + * ```rust + * struct MyThing { ... } + * + * trait MyTrait { ... } + * + * impl MyTrait for MyThing { ... } + * + * fn foo>(x: T) { ... } + * + * let x = MyThing(Default::default()); + * foo(x); + * ``` + * + * At `term` = `foo(x)`, we have `constraint = MyTrait`, and because of the + * `impl` block, `pathToTypeParamInConstraint` = `"B"`, and + * `pathToTypeParamInSub` = `"A"`. + */ pragma[nomagic] - private predicate satisfiesConstraintTypeMention( - Term term, Constraint constraint, TypePath path, TypePath pathToTypeParamInSub - ) { - satisfiesConstraintTypeMentionInline(term, constraint, _, path, pathToTypeParamInSub) - } - - pragma[nomagic] - private predicate satisfiesConstraintTypeMentionThrough( - Term term, Constraint constraint, TypeAbstraction abs, TypePath path, + predicate satisfiesConstraintAtTypeParameter( + Term term, Constraint constraint, TypePath pathToTypeParamInConstraint, TypePath pathToTypeParamInSub ) { - satisfiesConstraintTypeMentionInline(term, constraint, abs, path, pathToTypeParamInSub) + satisfiesConstraintInline(term, constraint, _, pathToTypeParamInConstraint, + pathToTypeParamInSub, _) } pragma[inline] - private predicate satisfiesConstraintTypeNonTypeParamInline( + private predicate satisfiesConstraintNonTypeParamInline( Term term, TypeAbstraction abs, Constraint constraint, TypePath path, Type t ) { - satisfiesConstraintTypeMention1(term, constraint, abs, _, path, t) and + satisfiesConstraint0(term, constraint, abs, _, path, t) and not t = abs.getATypeParameter() } @@ -1142,15 +1160,14 @@ module Make1 Input1> { } /** - * Holds if the type tree at `term` satisfies the constraint `constraint` - * with the type `t` at `path`. + * Holds if `term` satisfies the constraint `constraint` with the type `t` at `path`. */ pragma[nomagic] - predicate satisfiesConstraintType(Term term, Constraint constraint, TypePath path, Type t) { - satisfiesConstraintTypeNonTypeParamInline(term, _, constraint, path, t) + predicate satisfiesConstraint(Term term, Constraint constraint, TypePath path, Type t) { + satisfiesConstraintNonTypeParamInline(term, _, constraint, path, t) or exists(TypePath prefix0, TypePath pathToTypeParamInSub, TypePath suffix | - satisfiesConstraintTypeMention(term, constraint, prefix0, pathToTypeParamInSub) and + satisfiesConstraintAtTypeParameter(term, constraint, prefix0, pathToTypeParamInSub) and getTypeAt(term, pathToTypeParamInSub.appendInverse(suffix)) = t and path = prefix0.append(suffix) ) @@ -1159,25 +1176,34 @@ module Make1 Input1> { t = getTypeAt(term, path) } + pragma[nomagic] + private predicate satisfiesConstraintThrough0( + Term term, Constraint constraint, TypeAbstraction abs, TypePath pathToTypeParamInConstraint, + TypePath pathToTypeParamInSub + ) { + satisfiesConstraintInline(term, constraint, abs, pathToTypeParamInConstraint, + pathToTypeParamInSub, _) + } + /** - * Holds if the type tree at `term` satisfies the constraint `constraint` - * through `abs` with the type `t` at `path`. + * Holds if `term` satisfies the constraint `constraint` through `abs` with + * the type `t` at `path`. */ pragma[nomagic] - predicate satisfiesConstraintTypeThrough( + predicate satisfiesConstraintThrough( Term term, TypeAbstraction abs, Constraint constraint, TypePath path, Type t ) { - satisfiesConstraintTypeNonTypeParamInline(term, abs, constraint, path, t) + satisfiesConstraintNonTypeParamInline(term, abs, constraint, path, t) or exists(TypePath prefix0, TypePath pathToTypeParamInSub, TypePath suffix | - satisfiesConstraintTypeMentionThrough(term, constraint, abs, prefix0, pathToTypeParamInSub) and + satisfiesConstraintThrough0(term, constraint, abs, prefix0, pathToTypeParamInSub) and getTypeAt(term, pathToTypeParamInSub.appendInverse(suffix)) = t and path = prefix0.append(suffix) ) } /** - * Holds if the type tree at `term` does _not_ satisfy the constraint `constraint`. + * Holds if `term` does _not_ satisfy the constraint `constraint`. * * This is an approximation of `not satisfiesConstraintType(term, constraint, _, _)`, * but defined without a negative occurrence of `satisfiesConstraintType`. @@ -1495,7 +1521,7 @@ module Make1 Input1> { TypeMention constraint ) { target = a.getTarget(e) and - typeParameterConstraintHasTypeParameter(target, apos, path, constraint, _, _) + typeParameterHasConstraint(target, apos, _, path, constraint) } private newtype TRelevantAccess = @@ -1556,13 +1582,40 @@ module Make1 Input1> { SatisfiesTypeParameterConstraintInput>; pragma[nomagic] - predicate satisfiesConstraintType( + predicate satisfiesConstraintAtTypeParameter( + Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix, + TypeMention constraint, TypePath pathToTypeParamInConstraint, + TypePath pathToTypeParamInSub + ) { + exists(RelevantAccess ra | + ra = MkRelevantAccess(a, apos, e, prefix) and + SatisfiesTypeParameterConstraint::satisfiesConstraintAtTypeParameter(ra, constraint, + pathToTypeParamInConstraint, pathToTypeParamInSub) and + constraint = ra.getConstraint(target) + ) + } + + pragma[nomagic] + predicate satisfiesConstraint( Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix, TypeMention constraint, TypePath path, Type t ) { exists(RelevantAccess ra | ra = MkRelevantAccess(a, apos, e, prefix) and - SatisfiesTypeParameterConstraint::satisfiesConstraintType(ra, constraint, path, t) and + SatisfiesTypeParameterConstraint::satisfiesConstraint(ra, constraint, path, t) and + constraint = ra.getConstraint(target) + ) + } + + pragma[nomagic] + predicate satisfiesConstraintThrough( + Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix, + TypeAbstraction abs, TypeMention constraint, TypePath path, Type t + ) { + exists(RelevantAccess ra | + ra = MkRelevantAccess(a, apos, e, prefix) and + SatisfiesTypeParameterConstraint::satisfiesConstraintThrough(ra, abs, constraint, path, + t) and constraint = ra.getConstraint(target) ) } @@ -1707,7 +1760,7 @@ module Make1 Input1> { not exists(getTypeArgument(a, target, tp, _)) and exists(TypeMention constraint, AccessPosition apos, TypePath pathToTp, TypePath pathToTp2 | typeParameterConstraintHasTypeParameter(target, apos, pathToTp2, constraint, pathToTp, tp) and - AccessConstraint::satisfiesConstraintType(a, e, target, apos, pathToTp2, constraint, + AccessConstraint::satisfiesConstraint(a, e, target, apos, pathToTp2, constraint, pathToTp.appendInverse(path), t) ) } @@ -1785,6 +1838,82 @@ module Make1 Input1> { not result instanceof TypeParameter ) ) + or + exists( + Declaration target, TypePath prefix, TypeMention constraint, + TypePath pathToTypeParamInConstraint, TypePath pathToTypeParamInSub + | + AccessConstraint::satisfiesConstraintAtTypeParameter(a, e, target, apos, prefix, + constraint, pathToTypeParamInConstraint, pathToTypeParamInSub) + | + exists(TypePath suffix | + /* + * Example: + * + * ```rust + * struct MyThing { ... } + * + * trait MyTrait { ... } + * + * impl MyTrait for MyThing { ... } + * + * fn foo>(x: T) { ... } + * + * let x = MyThing(Default::default()); + * foo(x); + * ``` + * + * At `term` = `foo(x)`, we have + * - `constraint = MyTrait`, + * - `pathToTypeParamInConstraint` = `"B"`, + * - `pathToTypeParamInSub` = `"A"`, + * - `prefix` = `suffix` = `""`, and + * - `result` = `i32`. + * + * That is, it allows us to infer that the type of `x` is `MyThing`. + */ + + result = constraint.getTypeAt(pathToTypeParamInConstraint.appendInverse(suffix)) and + not result instanceof TypeParameter and + path = prefix.append(pathToTypeParamInSub.append(suffix)) + ) + or + exists(TypeParameter tp, TypePath suffix, TypePath mid, TypePath pathToTp | + /* + * Example: + * + * ```rust + * struct MyThing { ... } + * + * trait MyTrait { ... } + * + * impl MyTrait for MyThing { ... } + * + * fn bar>(x: T1, y: T2) {} + * + * let x : i32 = ...; + * let y = MyThing(Default::default()); + * bar(x, y); + * ``` + * + * At `term` = `bar(x, y)`, we have + * - `constraint = MyTrait`, + * - `pathToTypeParamInConstraint` = `"B"`, + * - `pathToTypeParamInSub` = `"A"`, + * - `prefix` = `suffix` = `mid` = `""`, + * - `tp = T1`, + * - `pathToTp` = `"B"`, and + * - `result` = `i32`. + * + * That is, it allows us to infer that the type of `y` is `MyThing`. + */ + + typeMatch(a, e, target, suffix, result, tp) and + typeParameterConstraintHasTypeParameter(target, apos, _, constraint, pathToTp, tp) and + pathToTp = pathToTypeParamInConstraint.appendInverse(mid) and + path = prefix.append(pathToTypeParamInSub.append(mid).append(suffix)) + ) + ) } }