diff --git a/rust/ql/lib/codeql/rust/internal/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/TypeMention.qll index 6dd69ef49fc5..20389bb4ae37 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeMention.qll @@ -50,24 +50,70 @@ class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr { } } -class PathTypeMention extends TypeMention, Path { - TypeItemNode resolved; +/** 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() + ] +} + +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 } - PathTypeMention() { - resolved = resolvePath(this) + /** + * 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 - resolved = resolvePath(this).(Variant).getEnum() + 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; + + NonAliasPathTypeMention() { + resolved = [resolvePath(this), resolvePath(this).(Variant).getEnum().(TypeItemNode)] and + not exists(resolved.(TypeAlias).getTypeRepr()) } 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] @@ -115,92 +161,75 @@ class PathTypeMention extends TypeMention, Path { // 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*() } - /** - * Holds if this path resolved to a type alias with a rhs. that has the - * resulting type at `typePath`. - */ + /** Gets the type mention in this path for the type parameter `tp`, if any. */ 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) - ) + private TypeMention getTypeMentionForTypeParameter(TypeParameter tp) { + exists(int i | + result = this.getPositionalTypeArgument(pragma[only_bind_into](i)) and + tp = this.resolveRootType().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) + Type resolveRootType() { + result = TStruct(resolved) 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) + 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 - not exists(resolved.(TypeAlias).getTypeRepr()) and - exists(TypeParameter tp, TypeMention arg, TypePath suffix | - result = arg.resolveTypeAt(suffix) and + result = TTypeParamTypeParameter(resolved) + or + result = TAssociatedTypeTypeParameter(resolved) + } + + override Type resolveTypeAt(TypePath typePath) { + typePath.isEmpty() and + result = this.resolveRootType() + or + exists(TypeParameter tp, TypePath suffix | + result = this.getTypeMentionForTypeParameter(tp).resolveTypeAt(suffix) and typePath = TypePath::cons(tp, suffix) - | - exists(int i | - arg = 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 - 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 - arg = alias.getTypeRepr() and - tp = - TAssociatedTypeTypeParameter(resolved - .(TraitItemNode) - .getAssocItem(pragma[only_bind_into](name))) - ) ) } } 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 |
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: