From 620d228ffa41d6af05db73f9467ec2d9dcd49276 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Fri, 18 Jul 2025 15:28:42 +0200 Subject: [PATCH 1/5] Rust: Factor out `getTypeMentionForTypeParameter` --- .../lib/codeql/rust/internal/TypeMention.qll | 75 ++++++++++--------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/TypeMention.qll index 6dd69ef49fc5..e0dfa2666618 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeMention.qll @@ -61,13 +61,14 @@ class PathTypeMention extends TypeMention, Path { TypeItemNode getResolved() { result = resolved } + /** + * Gets a type alias with the name `name` of the trait that this path resolves + * to, if any. + */ pragma[nomagic] private TypeAlias getResolvedTraitAlias(string name) { - exists(TraitItemNode trait | - trait = resolved and - result = trait.getAnAssocItem() and - name = result.getName().getText() - ) + result = resolved.(TraitItemNode).getAnAssocItem() and + name = result.getName().getText() } pragma[nomagic] @@ -140,40 +141,18 @@ class PathTypeMention extends TypeMention, Path { ) } - override Type resolveTypeAt(TypePath typePath) { - result = this.aliasResolveTypeAt(typePath) - or - typePath.isEmpty() and - ( - result = TStruct(resolved) - or - result = TEnum(resolved) - or - exists(TraitItemNode trait | trait = resolved | - // If this is a `Self` path, then it resolves to the implicit `Self` - // type parameter, otherwise it is a trait bound. - if this = trait.getASelfPath() - then result = TSelfTypeParameter(trait) - else result = TTrait(trait) - ) - or - result = TTypeParamTypeParameter(resolved) - or - result = TAssociatedTypeTypeParameter(resolved) - ) - or + /** Gets the type mention in this path for the type parameter `tp`, if any. */ + pragma[nomagic] + private TypeMention getTypeMentionForTypeParameter(TypeParameter tp) { not exists(resolved.(TypeAlias).getTypeRepr()) and - exists(TypeParameter tp, TypeMention arg, TypePath suffix | - result = arg.resolveTypeAt(suffix) and - typePath = TypePath::cons(tp, suffix) - | + ( exists(int i | - arg = this.getPositionalTypeArgument(pragma[only_bind_into](i)) and + result = this.getPositionalTypeArgument(pragma[only_bind_into](i)) and tp = this.resolveType().getTypeParameter(pragma[only_bind_into](i)) ) or exists(TypeAlias alias | - arg = this.getAnAssocTypeArgument(alias) and + result = this.getAnAssocTypeArgument(alias) and tp = TAssociatedTypeTypeParameter(alias) ) or @@ -195,7 +174,7 @@ class PathTypeMention extends TypeMention, Path { param.getTrait() = resolved and name = param.getTypeAlias().getName().getText() and alias = impl.getASuccessor(pragma[only_bind_into](name)) and - arg = alias.getTypeRepr() and + result = alias.getTypeRepr() and tp = TAssociatedTypeTypeParameter(resolved .(TraitItemNode) @@ -203,6 +182,34 @@ class PathTypeMention extends TypeMention, Path { ) ) } + + override Type resolveTypeAt(TypePath typePath) { + result = this.aliasResolveTypeAt(typePath) + or + typePath.isEmpty() and + ( + result = TStruct(resolved) + or + result = TEnum(resolved) + or + exists(TraitItemNode trait | trait = resolved | + // If this is a `Self` path, then it resolves to the implicit `Self` + // type parameter, otherwise it is a trait bound. + if this = trait.getASelfPath() + then result = TSelfTypeParameter(trait) + else result = TTrait(trait) + ) + or + result = TTypeParamTypeParameter(resolved) + or + result = TAssociatedTypeTypeParameter(resolved) + ) + or + exists(TypeParameter tp, TypePath suffix | + result = this.getTypeMentionForTypeParameter(tp).resolveTypeAt(suffix) and + typePath = TypePath::cons(tp, suffix) + ) + } } class PathTypeReprMention extends TypeMention, PathTypeRepr { From 0e8c137a98be068dbc42fbe4acbcc255ab023ecf Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Sat, 19 Jul 2025 11:56:42 +0200 Subject: [PATCH 2/5] Rust: Only include paths as type mentions when they're used as such On databend this changes the number of `PathTypeMention`s from 3,777,464 to 3,330,024. Not a huge difference, but there's also downstream predicates that are reduced as well. --- .../ql/lib/codeql/rust/internal/TypeMention.qll | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/TypeMention.qll index e0dfa2666618..b9f33a68d9d3 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeMention.qll @@ -50,13 +50,24 @@ class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr { } } +/** Holds if `path` is used as a type mention during type inference. */ +predicate relevantPathTypeMention(Path path) { + path = + [ + any(PathTypeRepr r).getPath(), + any(StructExpr s).getPath().getQualifier*(), + any(CallExpr ce).getFunction().(PathExpr).getPath().getQualifier*(), + any(StructPat p).getPath(), + any(TupleStructPat p).getPath() + ] +} + class PathTypeMention extends TypeMention, Path { TypeItemNode resolved; PathTypeMention() { - resolved = resolvePath(this) - or - resolved = resolvePath(this).(Variant).getEnum() + relevantPathTypeMention(this) and + resolved = [resolvePath(this), resolvePath(this).(Variant).getEnum().(TypeItemNode)] } TypeItemNode getResolved() { result = resolved } From 804ffdb682ca197e3939a23abcd3218e4301afa0 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Sat, 19 Jul 2025 13:36:28 +0200 Subject: [PATCH 3/5] Rust: Split `PathTypeMention` into an alias and a non-alias subclass --- .../lib/codeql/rust/internal/TypeMention.qll | 133 ++++++++++-------- 1 file changed, 71 insertions(+), 62 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/TypeMention.qll index b9f33a68d9d3..e19c5fb23d53 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeMention.qll @@ -62,12 +62,46 @@ predicate relevantPathTypeMention(Path path) { ] } -class PathTypeMention extends TypeMention, Path { +abstract class PathTypeMention extends TypeMention, Path { + PathTypeMention() { relevantPathTypeMention(this) } +} + +class AliasPathTypeMention extends PathTypeMention { + TypeAlias resolved; + TypeMention rhs; + + AliasPathTypeMention() { + resolved = resolvePath(this) and + rhs = resolved.getTypeRepr() + } + + TypeItemNode getResolved() { result = resolved } + + /** + * Holds if this path resolved to a type alias with a rhs. that has the + * resulting type at `typePath`. + */ + pragma[nomagic] + override Type resolveTypeAt(TypePath typePath) { + result = rhs.resolveTypeAt(typePath) and + not result = pathGetTypeParameter(resolved, _) + or + exists(TypeParameter tp, TypeMention arg, TypePath prefix, TypePath suffix, int i | + tp = rhs.resolveTypeAt(prefix) and + tp = pathGetTypeParameter(resolved, pragma[only_bind_into](i)) and + arg = this.getSegment().getGenericArgList().getTypeArg(pragma[only_bind_into](i)) and + result = arg.resolveTypeAt(suffix) and + typePath = prefix.append(suffix) + ) + } +} + +class NonAliasPathTypeMention extends PathTypeMention { TypeItemNode resolved; - PathTypeMention() { - relevantPathTypeMention(this) and - resolved = [resolvePath(this), resolvePath(this).(Variant).getEnum().(TypeItemNode)] + NonAliasPathTypeMention() { + resolved = [resolvePath(this), resolvePath(this).(Variant).getEnum().(TypeItemNode)] and + not exists(resolved.(TypeAlias).getTypeRepr()) } TypeItemNode getResolved() { result = resolved } @@ -132,71 +166,46 @@ class PathTypeMention extends TypeMention, Path { this = any(PathTypeRepr ptp).getPath().getQualifier*() } - /** - * Holds if this path resolved to a type alias with a rhs. that has the - * resulting type at `typePath`. - */ - pragma[nomagic] - private Type aliasResolveTypeAt(TypePath typePath) { - exists(TypeAlias alias, TypeMention rhs | alias = resolved and rhs = alias.getTypeRepr() | - result = rhs.resolveTypeAt(typePath) and - not result = pathGetTypeParameter(alias, _) - or - exists(TypeParameter tp, TypeMention arg, TypePath prefix, TypePath suffix, int i | - tp = rhs.resolveTypeAt(prefix) and - tp = pathGetTypeParameter(alias, pragma[only_bind_into](i)) and - arg = this.getSegment().getGenericArgList().getTypeArg(pragma[only_bind_into](i)) and - result = arg.resolveTypeAt(suffix) and - typePath = prefix.append(suffix) - ) - ) - } - /** Gets the type mention in this path for the type parameter `tp`, if any. */ pragma[nomagic] private TypeMention getTypeMentionForTypeParameter(TypeParameter tp) { - not exists(resolved.(TypeAlias).getTypeRepr()) and - ( - exists(int i | - result = this.getPositionalTypeArgument(pragma[only_bind_into](i)) and - tp = this.resolveType().getTypeParameter(pragma[only_bind_into](i)) - ) - or - exists(TypeAlias alias | - result = this.getAnAssocTypeArgument(alias) and - tp = TAssociatedTypeTypeParameter(alias) - ) - or - // If `path` is the trait of an `impl` block then any associated types - // defined in the `impl` block are type arguments to the trait. - // - // For instance, for a trait implementation like this - // ```rust - // impl MyTrait for MyType { - // ^^^^^^^ path - // type AssociatedType = i64 - // ^^^ result - // // ... - // } - // ``` - // the rhs. of the type alias is a type argument to the trait. - exists(ImplItemNode impl, AssociatedTypeTypeParameter param, TypeAlias alias, string name | - this = impl.getTraitPath() and - param.getTrait() = resolved and - name = param.getTypeAlias().getName().getText() and - alias = impl.getASuccessor(pragma[only_bind_into](name)) and - result = alias.getTypeRepr() and - tp = - TAssociatedTypeTypeParameter(resolved - .(TraitItemNode) - .getAssocItem(pragma[only_bind_into](name))) - ) + exists(int i | + result = this.getPositionalTypeArgument(pragma[only_bind_into](i)) and + tp = this.resolveType().getTypeParameter(pragma[only_bind_into](i)) + ) + or + exists(TypeAlias alias | + result = this.getAnAssocTypeArgument(alias) and + tp = TAssociatedTypeTypeParameter(alias) + ) + or + // If `path` is the trait of an `impl` block then any associated types + // defined in the `impl` block are type arguments to the trait. + // + // For instance, for a trait implementation like this + // ```rust + // impl MyTrait for MyType { + // ^^^^^^^ path + // type AssociatedType = i64 + // ^^^ result + // // ... + // } + // ``` + // the rhs. of the type alias is a type argument to the trait. + exists(ImplItemNode impl, AssociatedTypeTypeParameter param, TypeAlias alias, string name | + this = impl.getTraitPath() and + param.getTrait() = resolved and + name = param.getTypeAlias().getName().getText() and + alias = impl.getASuccessor(pragma[only_bind_into](name)) and + result = alias.getTypeRepr() and + tp = + TAssociatedTypeTypeParameter(resolved + .(TraitItemNode) + .getAssocItem(pragma[only_bind_into](name))) ) } override Type resolveTypeAt(TypePath typePath) { - result = this.aliasResolveTypeAt(typePath) - or typePath.isEmpty() and ( result = TStruct(resolved) From 27e52512852f4ce129779459063e109d6ccca6f0 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Sat, 19 Jul 2025 13:57:31 +0200 Subject: [PATCH 4/5] Rust: Add `resolveRootType` predicate instead of using `resolveType` recursively --- .../lib/codeql/rust/internal/TypeMention.qll | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/TypeMention.qll index e19c5fb23d53..20389bb4ae37 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeMention.qll @@ -161,7 +161,7 @@ class NonAliasPathTypeMention extends PathTypeMention { // If a type argument is not given in the path, then we use the default for // the type parameter if one exists for the type. not exists(this.getPositionalTypeArgument0(i)) and - result = this.resolveType().getTypeParameterDefault(i) and + result = this.resolveRootType().getTypeParameterDefault(i) and // Defaults only apply to type mentions in type annotations this = any(PathTypeRepr ptp).getPath().getQualifier*() } @@ -171,7 +171,7 @@ class NonAliasPathTypeMention extends PathTypeMention { private TypeMention getTypeMentionForTypeParameter(TypeParameter tp) { exists(int i | result = this.getPositionalTypeArgument(pragma[only_bind_into](i)) and - tp = this.resolveType().getTypeParameter(pragma[only_bind_into](i)) + tp = this.resolveRootType().getTypeParameter(pragma[only_bind_into](i)) ) or exists(TypeAlias alias | @@ -205,25 +205,27 @@ class NonAliasPathTypeMention extends PathTypeMention { ) } + Type resolveRootType() { + result = TStruct(resolved) + or + result = TEnum(resolved) + or + exists(TraitItemNode trait | trait = resolved | + // If this is a `Self` path, then it resolves to the implicit `Self` + // type parameter, otherwise it is a trait bound. + if this = trait.getASelfPath() + then result = TSelfTypeParameter(trait) + else result = TTrait(trait) + ) + or + result = TTypeParamTypeParameter(resolved) + or + result = TAssociatedTypeTypeParameter(resolved) + } + override Type resolveTypeAt(TypePath typePath) { typePath.isEmpty() and - ( - result = TStruct(resolved) - or - result = TEnum(resolved) - or - exists(TraitItemNode trait | trait = resolved | - // If this is a `Self` path, then it resolves to the implicit `Self` - // type parameter, otherwise it is a trait bound. - if this = trait.getASelfPath() - then result = TSelfTypeParameter(trait) - else result = TTrait(trait) - ) - or - result = TTypeParamTypeParameter(resolved) - or - result = TAssociatedTypeTypeParameter(resolved) - ) + result = this.resolveRootType() or exists(TypeParameter tp, TypePath suffix | result = this.getTypeMentionForTypeParameter(tp).resolveTypeAt(suffix) and From 441cefd0bd41537557e971f1d99ec7118864aba5 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Mon, 21 Jul 2025 08:34:16 +0200 Subject: [PATCH 5/5] Rust: Accept test changes --- .../CONSISTENCY/TypeInferenceConsistency.expected | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 rust/ql/test/query-tests/unusedentities/CONSISTENCY/TypeInferenceConsistency.expected diff --git a/rust/ql/test/query-tests/unusedentities/CONSISTENCY/TypeInferenceConsistency.expected b/rust/ql/test/query-tests/unusedentities/CONSISTENCY/TypeInferenceConsistency.expected deleted file mode 100644 index 56ce1df5c894..000000000000 --- a/rust/ql/test/query-tests/unusedentities/CONSISTENCY/TypeInferenceConsistency.expected +++ /dev/null @@ -1,2 +0,0 @@ -illFormedTypeMention -| main.rs:403:18:403:24 | FuncPtr | pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy