Rust: Handle builtin types in path resolution

This commit is contained in:
Tom Hvitved
2025-11-13 13:01:53 +01:00
parent 39720a17ef
commit 46f5d89674
14 changed files with 2618 additions and 2478 deletions

View File

@@ -4,6 +4,7 @@
private import rust private import rust
private import codeql.rust.controlflow.CfgNodes private import codeql.rust.controlflow.CfgNodes
private import codeql.rust.frameworks.stdlib.Builtins
private import DataFlowImpl private import DataFlowImpl
/** /**
@@ -36,7 +37,11 @@ class TupleFieldContent extends FieldContent, TTupleFieldContent {
/** Holds if this field belongs to a struct. */ /** Holds if this field belongs to a struct. */
predicate isStructField(Struct s, int pos) { field.isStructField(s, pos) } predicate isStructField(Struct s, int pos) { field.isStructField(s, pos) }
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getTupleField() } override FieldExprCfgNode getAnAccess() {
field = result.getFieldExpr().getTupleField() and
// tuples are handled using the special `TupleContent` type
not field = any(TupleType tt).getATupleField()
}
final override string toString() { final override string toString() {
exists(Variant v, int pos, string vname | exists(Variant v, int pos, string vname |

View File

@@ -32,10 +32,16 @@ module Impl {
result.getName().getText() = name result.getName().getText() = name
} }
/** Gets a record field, if any. */
StructField getAStructField() { result = this.getStructField(_) }
/** Gets the `i`th tuple field, if any. */ /** Gets the `i`th tuple field, if any. */
pragma[nomagic] pragma[nomagic]
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) } TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
/** Gets a tuple field, if any. */
TupleField getATupleField() { result = this.getTupleField(_) }
/** Holds if this struct uses tuple fields. */ /** Holds if this struct uses tuple fields. */
pragma[nomagic] pragma[nomagic]
predicate isTuple() { this.getFieldList() instanceof TupleFieldList } predicate isTuple() { this.getFieldList() instanceof TupleFieldList }

View File

@@ -136,3 +136,36 @@ class F32 extends FloatingPointTypeImpl {
class F64 extends FloatingPointTypeImpl { class F64 extends FloatingPointTypeImpl {
F64() { this.getName() = "f64" } F64() { this.getName() = "f64" }
} }
/** The builtin slice type `[T]`. */
class SliceType extends BuiltinType {
SliceType() { this.getName() = "Slice" }
}
/** The builtin array type `[T; N]`. */
class ArrayType extends BuiltinType {
ArrayType() { this.getName() = "Array" }
}
/** The builtin reference type `&T` or `&mut T`. */
class RefType extends BuiltinType {
RefType() { this.getName() = "Ref" }
}
/** The builtin pointer type `*const T` or `*mut T`. */
class PtrType extends BuiltinType {
PtrType() { this.getName() = "Ptr" }
}
/** A builtin tuple type `(T1, T2, ...)`. */
class TupleType extends BuiltinType {
TupleType() { this.getName().matches("Tuple%") }
/** Gets the arity of this tuple type. */
int getArity() {
not this.hasGenericParamList() and
result = 0
or
result = this.getGenericParamList().getNumberOfGenericParams()
}
}

View File

@@ -713,12 +713,34 @@ abstract class ImplOrTraitItemNode extends ItemNode {
predicate hasAssocItem(string name) { name = this.getAnAssocItem().getName() } predicate hasAssocItem(string name) { name = this.getAnAssocItem().getName() }
} }
private TypeItemNode resolveBuiltin(TypeRepr tr) {
tr instanceof SliceTypeRepr and
result instanceof Builtins::SliceType
or
tr instanceof ArrayTypeRepr and
result instanceof Builtins::ArrayType
or
tr instanceof RefTypeRepr and
result instanceof Builtins::RefType
or
tr instanceof PtrTypeRepr and
result instanceof Builtins::PtrType
or
result.(Builtins::TupleType).getArity() = tr.(TupleTypeRepr).getNumberOfFields()
}
final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl { final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() } Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() }
Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() } Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }
TypeItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) } TypeItemNode resolveSelfTyBuiltin() { result = resolveBuiltin(this.(Impl).getSelfTy()) }
TypeItemNode resolveSelfTy() {
result = resolvePath(this.getSelfPath())
or
result = this.resolveSelfTyBuiltin()
}
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) } TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
@@ -893,7 +915,11 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module {
} }
private class ImplItemNodeImpl extends ImplItemNode { private class ImplItemNodeImpl extends ImplItemNode {
TypeItemNode resolveSelfTyCand() { result = resolvePathCand(this.getSelfPath()) } TypeItemNode resolveSelfTyCand() {
result = resolvePathCand(this.getSelfPath())
or
result = this.resolveSelfTyBuiltin()
}
TraitItemNode resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) } TraitItemNode resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) }
} }
@@ -1764,6 +1790,10 @@ private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) {
or or
result = resolveUseTreeListItem(_, _, path, _) and result = resolveUseTreeListItem(_, _, path, _) and
ns = result.getNamespace() ns = result.getNamespace()
or
result = resolveBuiltin(path.getSegment().getTypeRepr()) and
not path.getSegment().hasTraitTypeRepr() and
ns.isType()
} }
pragma[nomagic] pragma[nomagic]
@@ -2141,7 +2171,9 @@ pragma[nomagic]
private predicate builtin(string name, ItemNode i) { private predicate builtin(string name, ItemNode i) {
exists(BuiltinSourceFile builtins | exists(BuiltinSourceFile builtins |
builtins.getFile().getBaseName() = "types.rs" and builtins.getFile().getBaseName() = "types.rs" and
i = builtins.getASuccessor(name) i = builtins.getASuccessor(name) and
not name = ["Slice", "Array", "Ref", "Ptr"] and
not name.matches("Tuple%")
) )
} }

View File

@@ -7,6 +7,7 @@ private import codeql.rust.internal.CachedStages
private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.frameworks.stdlib.Stdlib private import codeql.rust.frameworks.stdlib.Stdlib
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
/** /**
* Holds if a dyn trait type should have a type parameter associated with `n`. A * Holds if a dyn trait type should have a type parameter associated with `n`. A
@@ -31,39 +32,21 @@ private predicate dynTraitTypeParameter(Trait trait, AstNode n) {
cached cached
newtype TType = newtype TType =
TTuple(int arity) { TStruct(Struct s) { Stages::TypeInferenceStage::ref() } or
arity =
[
any(TupleTypeRepr t).getNumberOfFields(),
any(TupleExpr e).getNumberOfFields(),
any(TuplePat p).getNumberOfFields()
] and
Stages::TypeInferenceStage::ref()
} or
TStruct(Struct s) or
TEnum(Enum e) or TEnum(Enum e) or
TTrait(Trait t) or TTrait(Trait t) or
TUnion(Union u) or TUnion(Union u) or
TArrayType() or // todo: add size?
TRefType() or // todo: add mut?
TImplTraitType(ImplTraitTypeRepr impl) or TImplTraitType(ImplTraitTypeRepr impl) or
TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or
TSliceType() or
TNeverType() or TNeverType() or
TPtrType() or
TUnknownType() or TUnknownType() or
TTupleTypeParameter(int arity, int i) { exists(TTuple(arity)) and i in [0 .. arity - 1] } or
TTypeParamTypeParameter(TypeParam t) or TTypeParamTypeParameter(TypeParam t) or
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
TArrayTypeParameter() or
TDynTraitTypeParameter(AstNode n) { dynTraitTypeParameter(_, n) } or TDynTraitTypeParameter(AstNode n) { dynTraitTypeParameter(_, n) } or
TImplTraitTypeParameter(ImplTraitTypeRepr implTrait, TypeParam tp) { TImplTraitTypeParameter(ImplTraitTypeRepr implTrait, TypeParam tp) {
implTraitTypeParam(implTrait, _, tp) implTraitTypeParam(implTrait, _, tp)
} or } or
TRefTypeParameter() or TSelfTypeParameter(Trait t)
TSelfTypeParameter(Trait t) or
TSliceTypeParameter() or
TPtrTypeParameter()
private predicate implTraitTypeParam(ImplTraitTypeRepr implTrait, int i, TypeParam tp) { private predicate implTraitTypeParam(ImplTraitTypeRepr implTrait, int i, TypeParam tp) {
implTrait.isInReturnPos() and implTrait.isInReturnPos() and
@@ -106,26 +89,25 @@ abstract class Type extends TType {
} }
/** A tuple type `(T, ...)`. */ /** A tuple type `(T, ...)`. */
class TupleType extends Type, TTuple { class TupleType extends StructType {
private int arity; private int arity;
TupleType() { this = TTuple(arity) } TupleType() { arity = this.getStruct().(Builtins::TupleType).getArity() }
override TypeParameter getPositionalTypeParameter(int i) {
result = TTupleTypeParameter(arity, i)
}
/** Gets the arity of this tuple type. */ /** Gets the arity of this tuple type. */
int getArity() { result = arity } int getArity() { result = arity }
override string toString() { result = "(T_" + arity + ")" } override string toString() { result = "(T_" + arity + ")" }
}
override Location getLocation() { result instanceof EmptyLocation } pragma[nomagic]
TypeParamTypeParameter getTupleTypeParameter(int arity, int i) {
result = any(TupleType t | t.getArity() = arity).getPositionalTypeParameter(i)
} }
/** The unit type `()`. */ /** The unit type `()`. */
class UnitType extends TupleType { class UnitType extends TupleType {
UnitType() { this = TTuple(0) } UnitType() { this.getArity() = 0 }
override string toString() { result = "()" } override string toString() { result = "()" }
} }
@@ -229,17 +211,15 @@ class UnionType extends Type, TUnion {
* Array types like `[i64; 5]` are modeled as normal generic types * Array types like `[i64; 5]` are modeled as normal generic types
* with a single type argument. * with a single type argument.
*/ */
class ArrayType extends Type, TArrayType { class ArrayType extends StructType {
ArrayType() { this = TArrayType() } ArrayType() { this.getStruct() instanceof Builtins::ArrayType }
override TypeParameter getPositionalTypeParameter(int i) { override string toString() { result = "[;]" }
result = TArrayTypeParameter() and }
i = 0
}
override string toString() { result = "[]" } pragma[nomagic]
TypeParamTypeParameter getArrayTypeParameter() {
override Location getLocation() { result instanceof EmptyLocation } result = any(ArrayType t).getPositionalTypeParameter(0)
} }
/** /**
@@ -248,17 +228,15 @@ class ArrayType extends Type, TArrayType {
* Reference types like `& i64` are modeled as normal generic types * Reference types like `& i64` are modeled as normal generic types
* with a single type argument. * with a single type argument.
*/ */
class RefType extends Type, TRefType { class RefType extends StructType {
RefType() { this = TRefType() } RefType() { this.getStruct() instanceof Builtins::RefType }
override TypeParameter getPositionalTypeParameter(int i) {
result = TRefTypeParameter() and
i = 0
}
override string toString() { result = "&" } override string toString() { result = "&" }
}
override Location getLocation() { result instanceof EmptyLocation } pragma[nomagic]
TypeParamTypeParameter getRefTypeParameter() {
result = any(RefType t).getPositionalTypeParameter(0)
} }
/** /**
@@ -340,17 +318,15 @@ class ImplTraitReturnType extends ImplTraitType {
* Slice types like `[i64]` are modeled as normal generic types * Slice types like `[i64]` are modeled as normal generic types
* with a single type argument. * with a single type argument.
*/ */
class SliceType extends Type, TSliceType { class SliceType extends StructType {
SliceType() { this = TSliceType() } SliceType() { this.getStruct() instanceof Builtins::SliceType }
override TypeParameter getPositionalTypeParameter(int i) {
result = TSliceTypeParameter() and
i = 0
}
override string toString() { result = "[]" } override string toString() { result = "[]" }
}
override Location getLocation() { result instanceof EmptyLocation } pragma[nomagic]
TypeParamTypeParameter getSliceTypeParameter() {
result = any(SliceType t).getPositionalTypeParameter(0)
} }
class NeverType extends Type, TNeverType { class NeverType extends Type, TNeverType {
@@ -361,11 +337,8 @@ class NeverType extends Type, TNeverType {
override Location getLocation() { result instanceof EmptyLocation } override Location getLocation() { result instanceof EmptyLocation }
} }
class PtrType extends Type, TPtrType { class PtrType extends StructType {
override TypeParameter getPositionalTypeParameter(int i) { PtrType() { this.getStruct() instanceof Builtins::PtrType }
i = 0 and
result = TPtrTypeParameter()
}
override string toString() { result = "*" } override string toString() { result = "*" }
@@ -402,6 +375,11 @@ class UnknownType extends Type, TUnknownType {
override Location getLocation() { result instanceof EmptyLocation } override Location getLocation() { result instanceof EmptyLocation }
} }
pragma[nomagic]
TypeParamTypeParameter getPtrTypeParameter() {
result = any(PtrType t).getPositionalTypeParameter(0)
}
/** A type parameter. */ /** A type parameter. */
abstract class TypeParameter extends Type { abstract class TypeParameter extends Type {
override TypeParameter getPositionalTypeParameter(int i) { none() } override TypeParameter getPositionalTypeParameter(int i) { none() }
@@ -423,7 +401,32 @@ class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter {
TypeParam getTypeParam() { result = typeParam } TypeParam getTypeParam() { result = typeParam }
override string toString() { result = typeParam.toString() } override string toString() {
this = any(SliceType st).getATypeParameter() and
result = "[T]"
or
this = any(ArrayType at).getATypeParameter() and
result = "[T;...]"
or
this = any(RefType rt).getATypeParameter() and
result = "&T"
or
this = any(PtrType pt).getATypeParameter() and
result = "*T"
or
exists(TupleType tt, int arity, int i |
this = tt.getPositionalTypeParameter(i) and
arity = tt.getArity() and
result = i + "(" + arity + ")"
)
or
not this = any(SliceType st).getATypeParameter() and
not this = any(ArrayType at).getATypeParameter() and
not this = any(RefType rt).getATypeParameter() and
not this = any(PtrType pt).getATypeParameter() and
not this = any(TupleType tt).getATypeParameter() and
result = typeParam.toString()
}
override Location getLocation() { result = typeParam.getLocation() } override Location getLocation() { result = typeParam.getLocation() }
} }
@@ -461,37 +464,6 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara
override Location getLocation() { result = typeAlias.getLocation() } override Location getLocation() { result = typeAlias.getLocation() }
} }
/**
* A tuple type parameter. For instance the `T` in `(T, U)`.
*
* Since tuples are structural their type parameters can be represented as their
* positional index. The type inference library requires that type parameters
* belong to a single type, so we also include the arity of the tuple type.
*/
class TupleTypeParameter extends TypeParameter, TTupleTypeParameter {
private int arity;
private int index;
TupleTypeParameter() { this = TTupleTypeParameter(arity, index) }
override string toString() { result = index.toString() + "(" + arity + ")" }
override Location getLocation() { result instanceof EmptyLocation }
/** Gets the index of this tuple type parameter. */
int getIndex() { result = index }
/** Gets the tuple type that corresponds to this tuple type parameter. */
TupleType getTupleType() { result = TTuple(arity) }
}
/** An implicit array type parameter. */
class ArrayTypeParameter extends TypeParameter, TArrayTypeParameter {
override string toString() { result = "[T;...]" }
override Location getLocation() { result instanceof EmptyLocation }
}
class DynTraitTypeParameter extends TypeParameter, TDynTraitTypeParameter { class DynTraitTypeParameter extends TypeParameter, TDynTraitTypeParameter {
private AstNode n; private AstNode n;
@@ -539,26 +511,6 @@ class ImplTraitTypeParameter extends TypeParameter, TImplTraitTypeParameter {
override Location getLocation() { result = typeParam.getLocation() } override Location getLocation() { result = typeParam.getLocation() }
} }
/** An implicit reference type parameter. */
class RefTypeParameter extends TypeParameter, TRefTypeParameter {
override string toString() { result = "&T" }
override Location getLocation() { result instanceof EmptyLocation }
}
/** An implicit slice type parameter. */
class SliceTypeParameter extends TypeParameter, TSliceTypeParameter {
override string toString() { result = "[T]" }
override Location getLocation() { result instanceof EmptyLocation }
}
class PtrTypeParameter extends TypeParameter, TPtrTypeParameter {
override string toString() { result = "*T" }
override Location getLocation() { result instanceof EmptyLocation }
}
/** /**
* The implicit `Self` type parameter of a trait, that refers to the * The implicit `Self` type parameter of a trait, that refers to the
* implementing type of the trait. * implementing type of the trait.

View File

@@ -87,26 +87,6 @@ private module Input1 implements InputSig1<Location> {
int getTypeParameterId(TypeParameter tp) { int getTypeParameterId(TypeParameter tp) {
tp = tp =
rank[result](TypeParameter tp0, int kind, int id1, int id2 | rank[result](TypeParameter tp0, int kind, int id1, int id2 |
tp0 instanceof ArrayTypeParameter and
kind = 0 and
id1 = 0 and
id2 = 0
or
tp0 instanceof RefTypeParameter and
kind = 0 and
id1 = 0 and
id2 = 1
or
tp0 instanceof SliceTypeParameter and
kind = 0 and
id1 = 0 and
id2 = 2
or
tp0 instanceof PtrTypeParameter and
kind = 0 and
id1 = 0 and
id2 = 3
or
kind = 1 and kind = 1 and
id1 = 0 and id1 = 0 and
id2 = id2 =
@@ -127,10 +107,6 @@ private module Input1 implements InputSig1<Location> {
node = tp0.(SelfTypeParameter).getTrait() or node = tp0.(SelfTypeParameter).getTrait() or
node = tp0.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr() node = tp0.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr()
) )
or
kind = 4 and
id1 = tp0.(TupleTypeParameter).getTupleType().getArity() and
id2 = tp0.(TupleTypeParameter).getIndex()
| |
tp0 order by kind, id1, id2 tp0 order by kind, id1, id2
) )
@@ -421,7 +397,9 @@ module CertainTypeInference {
any(IdentPat ip | any(IdentPat ip |
n2 = ip.getName() and n2 = ip.getName() and
prefix1.isEmpty() and prefix1.isEmpty() and
if ip.isRef() then prefix2 = TypePath::singleton(TRefTypeParameter()) else prefix2.isEmpty() if ip.isRef()
then prefix2 = TypePath::singleton(getRefTypeParameter())
else prefix2.isEmpty()
) )
} }
@@ -631,11 +609,11 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
n1 = n2.(RefPat).getPat() n1 = n2.(RefPat).getPat()
) and ) and
prefix1.isEmpty() and prefix1.isEmpty() and
prefix2 = TypePath::singleton(TRefTypeParameter()) prefix2 = TypePath::singleton(getRefTypeParameter())
or or
exists(int i, int arity | exists(int i, int arity |
prefix1.isEmpty() and prefix1.isEmpty() and
prefix2 = TypePath::singleton(TTupleTypeParameter(arity, i)) prefix2 = TypePath::singleton(getTupleTypeParameter(arity, i))
| |
arity = n2.(TupleExpr).getNumberOfFields() and arity = n2.(TupleExpr).getNumberOfFields() and
n1 = n2.(TupleExpr).getField(i) n1 = n2.(TupleExpr).getField(i)
@@ -663,12 +641,12 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
ale.getAnExpr() = n2 and ale.getAnExpr() = n2 and
ale.getNumberOfExprs() = 1 ale.getNumberOfExprs() = 1
) and ) and
prefix1 = TypePath::singleton(TArrayTypeParameter()) and prefix1 = TypePath::singleton(getArrayTypeParameter()) and
prefix2.isEmpty() prefix2.isEmpty()
or or
// an array repeat expression (`[1; 3]`) has the type of the repeat operand // an array repeat expression (`[1; 3]`) has the type of the repeat operand
n1.(ArrayRepeatExpr).getRepeatOperand() = n2 and n1.(ArrayRepeatExpr).getRepeatOperand() = n2 and
prefix1 = TypePath::singleton(TArrayTypeParameter()) and prefix1 = TypePath::singleton(getArrayTypeParameter()) and
prefix2.isEmpty() prefix2.isEmpty()
or or
exists(Struct s | exists(Struct s |
@@ -717,7 +695,7 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) {
child = ale.getAnExpr() and child = ale.getAnExpr() and
ale.getNumberOfExprs() > 1 ale.getNumberOfExprs() > 1
) and ) and
prefix = TypePath::singleton(TArrayTypeParameter()) prefix = TypePath::singleton(getArrayTypeParameter())
or or
bodyReturns(parent, child) and bodyReturns(parent, child) and
strictcount(Expr e | bodyReturns(parent, e)) > 1 and strictcount(Expr e | bodyReturns(parent, e)) > 1 and
@@ -956,9 +934,9 @@ private predicate inferStructExprType =
ContextTyping::CheckContextTyping<inferStructExprType0/3>::check/2; ContextTyping::CheckContextTyping<inferStructExprType0/3>::check/2;
pragma[nomagic] pragma[nomagic]
private Type inferTupleRootType(AstNode n) { private TupleType inferTupleRootType(AstNode n) {
// `typeEquality` handles the non-root cases // `typeEquality` handles the non-root cases
result = TTuple([n.(TupleExpr).getNumberOfFields(), n.(TuplePat).getTupleArity()]) result.getArity() = [n.(TupleExpr).getNumberOfFields(), n.(TuplePat).getTupleArity()]
} }
pragma[nomagic] pragma[nomagic]
@@ -1191,7 +1169,7 @@ private module MethodResolution {
* *
* `strippedTypePath` points to the type `strippedType` inside `selfType`, * `strippedTypePath` points to the type `strippedType` inside `selfType`,
* which is the (possibly complex-stripped) root type of `selfType`. For example, * which is the (possibly complex-stripped) root type of `selfType`. For example,
* if `m` has a `&self` parameter, then `strippedTypePath` is `TRefTypeParameter()` * if `m` has a `&self` parameter, then `strippedTypePath` is `getRefTypeParameter()`
* and `strippedType` is the type inside the reference. * and `strippedType` is the type inside the reference.
*/ */
pragma[nomagic] pragma[nomagic]
@@ -1401,7 +1379,7 @@ private module MethodResolution {
this.hasNoCompatibleTargetBorrow(derefChain0) and this.hasNoCompatibleTargetBorrow(derefChain0) and
t0 = this.getACandidateReceiverTypeAtNoBorrow(derefChain0, path0) t0 = this.getACandidateReceiverTypeAtNoBorrow(derefChain0, path0)
| |
path0.isCons(TRefTypeParameter(), path) and path0.isCons(getRefTypeParameter(), path) and
result = t0 and result = t0 and
derefChain = derefChain0 + ".ref" derefChain = derefChain0 + ".ref"
or or
@@ -1583,11 +1561,11 @@ private module MethodResolution {
borrow = true and borrow = true and
( (
path.isEmpty() and path.isEmpty() and
result = TRefType() result instanceof RefType
or or
exists(TypePath suffix | exists(TypePath suffix |
result = this.getACandidateReceiverTypeAtNoBorrow(derefChain, suffix) and result = this.getACandidateReceiverTypeAtNoBorrow(derefChain, suffix) and
path = TypePath::cons(TRefTypeParameter(), suffix) path = TypePath::cons(getRefTypeParameter(), suffix)
) )
) )
} }
@@ -1706,12 +1684,12 @@ private module MethodResolution {
override Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) { override Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) {
if this.(Call).implicitBorrowAt(pos, true) if this.(Call).implicitBorrowAt(pos, true)
then then
result = TRefType() and result instanceof RefType and
path.isEmpty() path.isEmpty()
or or
exists(TypePath path0 | exists(TypePath path0 |
result = inferType(this.getArgument(pos), path0) and result = inferType(this.getArgument(pos), path0) and
path = TypePath::cons(TRefTypeParameter(), path0) path = TypePath::cons(getRefTypeParameter(), path0)
) )
else result = inferType(this.getArgument(pos), path) else result = inferType(this.getArgument(pos), path)
} }
@@ -1854,7 +1832,7 @@ private module MethodResolution {
| |
mcc.hasNoBorrow() mcc.hasNoBorrow()
or or
blanketPath.getHead() = TRefTypeParameter() blanketPath.getHead() = getRefTypeParameter()
) )
} }
} }
@@ -2133,11 +2111,11 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
this instanceof IndexExpr this instanceof IndexExpr
then then
path.isEmpty() and path.isEmpty() and
result = TRefType() result instanceof RefType
or or
exists(TypePath suffix | exists(TypePath suffix |
result = inferType(this.getNodeAt(apos), suffix) and result = inferType(this.getNodeAt(apos), suffix) and
path = TypePath::cons(TRefTypeParameter(), suffix) path = TypePath::cons(getRefTypeParameter(), suffix)
) )
else ( else (
not apos.isSelf() and not apos.isSelf() and
@@ -2195,7 +2173,7 @@ private Type inferMethodCallType0(
// the implicit deref // the implicit deref
apos.isReturn() and apos.isReturn() and
a instanceof IndexExpr a instanceof IndexExpr
then path0.isCons(TRefTypeParameter(), path) then path0.isCons(getRefTypeParameter(), path)
else path = path0 else path = path0
) )
} }
@@ -2219,12 +2197,12 @@ private Type inferMethodCallType1(AstNode n, boolean isReturn, TypePath path) {
// adjust for implicit deref // adjust for implicit deref
apos.isSelf() and apos.isSelf() and
derefChainBorrow = ".ref;" and derefChainBorrow = ".ref;" and
path = TypePath::cons(TRefTypeParameter(), path0) path = TypePath::cons(getRefTypeParameter(), path0)
or or
// adjust for implicit borrow // adjust for implicit borrow
apos.isSelf() and apos.isSelf() and
derefChainBorrow = ";borrow" and derefChainBorrow = ";borrow" and
path0.isCons(TRefTypeParameter(), path) path0.isCons(getRefTypeParameter(), path)
) )
} }
@@ -2751,7 +2729,7 @@ private module OperationMatchingInput implements MatchingInputSig {
private Type getParameterType(DeclarationPosition dpos, TypePath path) { private Type getParameterType(DeclarationPosition dpos, TypePath path) {
exists(TypePath path0 | exists(TypePath path0 |
result = super.getParameterType(dpos, path0) and result = super.getParameterType(dpos, path0) and
if this.borrowsAt(dpos) then path0.isCons(TRefTypeParameter(), path) else path0 = path if this.borrowsAt(dpos) then path0.isCons(getRefTypeParameter(), path) else path0 = path
) )
} }
@@ -2762,7 +2740,7 @@ private module OperationMatchingInput implements MatchingInputSig {
private Type getReturnType(TypePath path) { private Type getReturnType(TypePath path) {
exists(TypePath path0 | exists(TypePath path0 |
result = super.getReturnType(path0) and result = super.getReturnType(path0) and
if this.derefsReturn() then path0.isCons(TRefTypeParameter(), path) else path0 = path if this.derefsReturn() then path0.isCons(getRefTypeParameter(), path) else path0 = path
) )
} }
@@ -2819,14 +2797,6 @@ private Type getTupleFieldExprLookupType(FieldExpr fe, int pos) {
) )
} }
pragma[nomagic]
private TupleTypeParameter resolveTupleTypeFieldExpr(FieldExpr fe) {
exists(int arity, int i |
TTuple(arity) = getTupleFieldExprLookupType(fe, i) and
result = TTupleTypeParameter(arity, i)
)
}
/** /**
* A matching configuration for resolving types of field expressions like `x.field`. * A matching configuration for resolving types of field expressions like `x.field`.
*/ */
@@ -2851,8 +2821,7 @@ private module FieldExprMatchingInput implements MatchingInputSig {
private newtype TDeclaration = private newtype TDeclaration =
TStructFieldDecl(StructField sf) or TStructFieldDecl(StructField sf) or
TTupleFieldDecl(TupleField tf) or TTupleFieldDecl(TupleField tf)
TTupleTypeParameterDecl(TupleTypeParameter ttp)
abstract class Declaration extends TDeclaration { abstract class Declaration extends TDeclaration {
TypeParameter getTypeParameter(TypeParameterPosition ppos) { none() } TypeParameter getTypeParameter(TypeParameterPosition ppos) { none() }
@@ -2909,31 +2878,6 @@ private module FieldExprMatchingInput implements MatchingInputSig {
override TypeRepr getTypeRepr() { result = tf.getTypeRepr() } override TypeRepr getTypeRepr() { result = tf.getTypeRepr() }
} }
private class TupleTypeParameterDecl extends Declaration, TTupleTypeParameterDecl {
private TupleTypeParameter ttp;
TupleTypeParameterDecl() { this = TTupleTypeParameterDecl(ttp) }
override Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
dpos.isSelf() and
(
result = ttp.getTupleType() and
path.isEmpty()
or
result = ttp and
path = TypePath::singleton(ttp)
)
or
dpos.isField() and
result = ttp and
path.isEmpty()
}
override string toString() { result = ttp.toString() }
override Location getLocation() { result = ttp.getLocation() }
}
class AccessPosition = DeclarationPosition; class AccessPosition = DeclarationPosition;
class Access extends FieldExpr { class Access extends FieldExpr {
@@ -2952,10 +2896,10 @@ private module FieldExprMatchingInput implements MatchingInputSig {
if apos.isSelf() if apos.isSelf()
then then
// adjust for implicit deref // adjust for implicit deref
path0.isCons(TRefTypeParameter(), path) path0.isCons(getRefTypeParameter(), path)
or or
not path0.isCons(TRefTypeParameter(), _) and not path0.isCons(getRefTypeParameter(), _) and
not (result = TRefType() and path0.isEmpty()) and not (result instanceof RefType and path0.isEmpty()) and
path = path0 path = path0
else path = path0 else path = path0
) )
@@ -2966,8 +2910,7 @@ private module FieldExprMatchingInput implements MatchingInputSig {
result = result =
[ [
TStructFieldDecl(resolveStructFieldExpr(this)).(TDeclaration), TStructFieldDecl(resolveStructFieldExpr(this)).(TDeclaration),
TTupleFieldDecl(resolveTupleFieldExpr(this)), TTupleFieldDecl(resolveTupleFieldExpr(this))
TTupleTypeParameterDecl(resolveTupleTypeFieldExpr(this))
] ]
} }
} }
@@ -2994,12 +2937,12 @@ private Type inferFieldExprType(AstNode n, TypePath path) {
if apos.isSelf() if apos.isSelf()
then then
exists(Type receiverType | receiverType = inferType(n) | exists(Type receiverType | receiverType = inferType(n) |
if receiverType = TRefType() if receiverType instanceof RefType
then then
// adjust for implicit deref // adjust for implicit deref
not path0.isCons(TRefTypeParameter(), _) and not path0.isCons(getRefTypeParameter(), _) and
not (path0.isEmpty() and result = TRefType()) and not (path0.isEmpty() and result instanceof RefType) and
path = TypePath::cons(TRefTypeParameter(), path0) path = TypePath::cons(getRefTypeParameter(), path0)
else path = path0 else path = path0
) )
else path = path0 else path = path0
@@ -3016,7 +2959,7 @@ private Type inferRefNodeType(AstNode ref) {
or or
ref instanceof RefPat ref instanceof RefPat
) and ) and
result = TRefType() result instanceof RefType
} }
pragma[nomagic] pragma[nomagic]
@@ -3070,9 +3013,9 @@ private Type inferLiteralType(LiteralExpr le, TypePath path, boolean certain) {
or or
le instanceof StringLiteralExpr and le instanceof StringLiteralExpr and
( (
path.isEmpty() and result = TRefType() path.isEmpty() and result instanceof RefType
or or
path = TypePath::singleton(TRefTypeParameter()) and path = TypePath::singleton(getRefTypeParameter()) and
result = getStrStruct() result = getStrStruct()
) and ) and
certain = true certain = true
@@ -3146,7 +3089,7 @@ private Type inferAwaitExprType(AstNode n, TypePath path) {
* Gets the root type of the array expression `ae`. * Gets the root type of the array expression `ae`.
*/ */
pragma[nomagic] pragma[nomagic]
private Type inferArrayExprType(ArrayExpr ae) { exists(ae) and result = TArrayType() } private Type inferArrayExprType(ArrayExpr ae) { exists(ae) and result instanceof ArrayType }
/** /**
* Gets the root type of the range expression `re`. * Gets the root type of the range expression `re`.
@@ -3182,11 +3125,11 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
// todo: remove? // todo: remove?
exprPath.isCons(TTypeParamTypeParameter(any(Vec v).getElementTypeParam()), path) exprPath.isCons(TTypeParamTypeParameter(any(Vec v).getElementTypeParam()), path)
or or
exprPath.isCons(any(ArrayTypeParameter tp), path) exprPath.isCons(getArrayTypeParameter(), path)
or or
exists(TypePath path0 | exists(TypePath path0 |
exprPath.isCons(any(RefTypeParameter tp), path0) and exprPath.isCons(getRefTypeParameter(), path0) and
path0.isCons(any(SliceTypeParameter tp), path) path0.isCons(getSliceTypeParameter(), path)
) )
) )
} }
@@ -3331,7 +3274,7 @@ private Type inferForLoopExprType(AstNode n, TypePath path) {
or or
// TODO: Remove once we can handle the `impl<I: Iterator> IntoIterator for I` implementation // TODO: Remove once we can handle the `impl<I: Iterator> IntoIterator for I` implementation
tp = getIteratorItemTypeParameter() and tp = getIteratorItemTypeParameter() and
inferType(fe.getIterable()) != TArrayType() inferType(fe.getIterable()) != getArrayTypeParameter()
) )
} }
@@ -3378,7 +3321,7 @@ pragma[nomagic]
private TypePath closureParameterPath(int arity, int index) { private TypePath closureParameterPath(int arity, int index) {
result = result =
TypePath::cons(TDynTraitTypeParameter(any(FnOnceTrait t).getTypeParam()), TypePath::cons(TDynTraitTypeParameter(any(FnOnceTrait t).getTypeParam()),
TypePath::singleton(TTupleTypeParameter(arity, index))) TypePath::singleton(getTupleTypeParameter(arity, index)))
} }
/** Gets the path to the return type of the `FnOnce` trait. */ /** Gets the path to the return type of the `FnOnce` trait. */
@@ -3394,7 +3337,7 @@ pragma[nomagic]
private TypePath fnParameterPath(int arity, int index) { private TypePath fnParameterPath(int arity, int index) {
result = result =
TypePath::cons(TTypeParamTypeParameter(any(FnOnceTrait t).getTypeParam()), TypePath::cons(TTypeParamTypeParameter(any(FnOnceTrait t).getTypeParam()),
TypePath::singleton(TTupleTypeParameter(arity, index))) TypePath::singleton(getTupleTypeParameter(arity, index)))
} }
pragma[nomagic] pragma[nomagic]
@@ -3443,7 +3386,7 @@ private Type inferClosureExprType(AstNode n, TypePath path) {
or or
n = ce and n = ce and
path = TypePath::singleton(TDynTraitTypeParameter(any(FnOnceTrait t).getTypeParam())) and path = TypePath::singleton(TDynTraitTypeParameter(any(FnOnceTrait t).getTypeParam())) and
result = TTuple(ce.getNumberOfParams()) result.(TupleType).getArity() = ce.getNumberOfParams()
or or
// Propagate return type annotation to body // Propagate return type annotation to body
n = ce.getClosureBody() and n = ce.getClosureBody() and

View File

@@ -20,11 +20,11 @@ abstract class TypeMention extends AstNode {
class TupleTypeReprMention extends TypeMention instanceof TupleTypeRepr { class TupleTypeReprMention extends TypeMention instanceof TupleTypeRepr {
override Type resolveTypeAt(TypePath path) { override Type resolveTypeAt(TypePath path) {
path.isEmpty() and path.isEmpty() and
result = TTuple(super.getNumberOfFields()) result.(TupleType).getArity() = super.getNumberOfFields()
or or
exists(TypePath suffix, int i | exists(TypePath suffix, int i |
result = super.getField(i).(TypeMention).resolveTypeAt(suffix) and result = super.getField(i).(TypeMention).resolveTypeAt(suffix) and
path = TypePath::cons(TTupleTypeParameter(super.getNumberOfFields(), i), suffix) path = TypePath::cons(getTupleTypeParameter(super.getNumberOfFields(), i), suffix)
) )
} }
} }
@@ -32,11 +32,11 @@ class TupleTypeReprMention extends TypeMention instanceof TupleTypeRepr {
class ParenthesizedArgListMention extends TypeMention instanceof ParenthesizedArgList { class ParenthesizedArgListMention extends TypeMention instanceof ParenthesizedArgList {
override Type resolveTypeAt(TypePath path) { override Type resolveTypeAt(TypePath path) {
path.isEmpty() and path.isEmpty() and
result = TTuple(super.getNumberOfTypeArgs()) result.(TupleType).getArity() = super.getNumberOfTypeArgs()
or or
exists(TypePath suffix, int index | exists(TypePath suffix, int index |
result = super.getTypeArg(index).getTypeRepr().(TypeMention).resolveTypeAt(suffix) and result = super.getTypeArg(index).getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
path = TypePath::cons(TTupleTypeParameter(super.getNumberOfTypeArgs(), index), suffix) path = TypePath::cons(getTupleTypeParameter(super.getNumberOfTypeArgs(), index), suffix)
) )
} }
} }
@@ -44,11 +44,11 @@ class ParenthesizedArgListMention extends TypeMention instanceof ParenthesizedAr
class ArrayTypeReprMention extends TypeMention instanceof ArrayTypeRepr { class ArrayTypeReprMention extends TypeMention instanceof ArrayTypeRepr {
override Type resolveTypeAt(TypePath path) { override Type resolveTypeAt(TypePath path) {
path.isEmpty() and path.isEmpty() and
result = TArrayType() result instanceof ArrayType
or or
exists(TypePath suffix | exists(TypePath suffix |
result = super.getElementTypeRepr().(TypeMention).resolveTypeAt(suffix) and result = super.getElementTypeRepr().(TypeMention).resolveTypeAt(suffix) and
path = TypePath::cons(TArrayTypeParameter(), suffix) path = TypePath::cons(getArrayTypeParameter(), suffix)
) )
} }
} }
@@ -56,11 +56,11 @@ class ArrayTypeReprMention extends TypeMention instanceof ArrayTypeRepr {
class RefTypeReprMention extends TypeMention instanceof RefTypeRepr { class RefTypeReprMention extends TypeMention instanceof RefTypeRepr {
override Type resolveTypeAt(TypePath path) { override Type resolveTypeAt(TypePath path) {
path.isEmpty() and path.isEmpty() and
result = TRefType() result instanceof RefType
or or
exists(TypePath suffix | exists(TypePath suffix |
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
path = TypePath::cons(TRefTypeParameter(), suffix) path = TypePath::cons(getRefTypeParameter(), suffix)
) )
} }
} }
@@ -68,11 +68,11 @@ class RefTypeReprMention extends TypeMention instanceof RefTypeRepr {
class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr { class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr {
override Type resolveTypeAt(TypePath path) { override Type resolveTypeAt(TypePath path) {
path.isEmpty() and path.isEmpty() and
result = TSliceType() result instanceof SliceType
or or
exists(TypePath suffix | exists(TypePath suffix |
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
path = TypePath::cons(TSliceTypeParameter(), suffix) path = TypePath::cons(getSliceTypeParameter(), suffix)
) )
} }
} }
@@ -291,6 +291,9 @@ class NonAliasPathTypeMention extends PathTypeMention {
result = this.getSelfTraitBoundArg().resolveTypeAt(suffix) and result = this.getSelfTraitBoundArg().resolveTypeAt(suffix) and
typePath = TypePath::cons(TSelfTypeParameter(resolved), suffix) typePath = TypePath::cons(TSelfTypeParameter(resolved), suffix)
) )
or
not this.getSegment().hasTraitTypeRepr() and
result = this.getSegment().getTypeRepr().(TypeMention).resolveTypeAt(typePath)
} }
} }
@@ -426,11 +429,11 @@ class ShorthandSelfParameterMention extends TypeMention instanceof SelfParam {
then then
// `fn f(&self, ...)` // `fn f(&self, ...)`
typePath.isEmpty() and typePath.isEmpty() and
result = TRefType() result instanceof RefType
or or
exists(TypePath suffix | exists(TypePath suffix |
result = this.resolveSelfType(suffix) and result = this.resolveSelfType(suffix) and
typePath = TypePath::cons(TRefTypeParameter(), suffix) typePath = TypePath::cons(getRefTypeParameter(), suffix)
) )
else else
// `fn f(self, ...)` // `fn f(self, ...)`
@@ -541,11 +544,11 @@ class NeverTypeReprMention extends TypeMention, NeverTypeRepr {
class PtrTypeReprMention extends TypeMention instanceof PtrTypeRepr { class PtrTypeReprMention extends TypeMention instanceof PtrTypeRepr {
override Type resolveTypeAt(TypePath path) { override Type resolveTypeAt(TypePath path) {
path.isEmpty() and path.isEmpty() and
result = TPtrType() result instanceof PtrType
or or
exists(TypePath suffix | exists(TypePath suffix |
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
path = TypePath::cons(TPtrTypeParameter(), suffix) path = TypePath::cons(getPtrTypeParameter(), suffix)
) )
} }
} }

View File

@@ -7,7 +7,7 @@ import rust
private import codeql.rust.dataflow.DataFlow private import codeql.rust.dataflow.DataFlow
private import codeql.rust.internal.TypeInference as TypeInference private import codeql.rust.internal.TypeInference as TypeInference
private import codeql.rust.internal.Type private import codeql.rust.internal.Type
private import codeql.rust.frameworks.stdlib.Builtins private import codeql.rust.frameworks.stdlib.Builtins as Builtins
/** /**
* A node whose type is a numeric or boolean type, which may be an appropriate * A node whose type is a numeric or boolean type, which may be an appropriate
@@ -19,8 +19,8 @@ class NumericTypeBarrier extends DataFlow::Node {
t = TypeInference::inferType(this.asExpr().getExpr()) and t = TypeInference::inferType(this.asExpr().getExpr()) and
s = t.getStruct() s = t.getStruct()
| |
s instanceof NumericType or s instanceof Builtins::NumericType or
s instanceof Bool s instanceof Builtins::Bool
) )
} }
} }
@@ -35,8 +35,8 @@ class IntegralOrBooleanTypeBarrier extends DataFlow::Node {
t = TypeInference::inferType(this.asExpr().getExpr()) and t = TypeInference::inferType(this.asExpr().getExpr()) and
s = t.getStruct() s = t.getStruct()
| |
s instanceof IntegralType or s instanceof Builtins::IntegralType or
s instanceof Bool s instanceof Builtins::Bool
) )
} }
} }

View File

@@ -1,3 +1,24 @@
| struct Array | |
| struct Ptr | |
| struct Ref | |
| struct Slice | |
| struct Tuple0 | |
| struct Tuple1 | |
| struct Tuple2 | |
| struct Tuple3 | |
| struct Tuple4 | |
| struct Tuple5 | |
| struct Tuple6 | |
| struct Tuple7 | |
| struct Tuple8 | |
| struct Tuple9 | |
| struct Tuple10 | |
| struct Tuple11 | |
| struct Tuple12 | |
| struct Tuple13 | |
| struct Tuple14 | |
| struct Tuple15 | |
| struct Tuple16 | |
| struct bool | | | struct bool | |
| struct char | | | struct char | |
| struct f32 | FloatingPointType, NumericType | | struct f32 | FloatingPointType, NumericType |

View File

@@ -1,6 +1,5 @@
import rust import rust
import codeql.rust.frameworks.stdlib.Builtins import codeql.rust.frameworks.stdlib.Builtins
import codeql.rust.internal.Type
string describe(BuiltinType t) { string describe(BuiltinType t) {
t instanceof NumericType and result = "NumericType" t instanceof NumericType and result = "NumericType"

View File

@@ -1755,7 +1755,7 @@ mod builtins {
let x = [1, 2, 3].my_method(); // $ target=my_method type=x:&T.i32 let x = [1, 2, 3].my_method(); // $ target=my_method type=x:&T.i32
let x = <[_; 3]>::my_method(&[1, 2, 3]); // $ target=my_method type=x:&T.i32 let x = <[_; 3]>::my_method(&[1, 2, 3]); // $ target=my_method type=x:&T.i32
let x = <[i32; 3]>::my_func(); // $ MISSING: target=my_func type=x:i32 let x = <[i32; 3]>::my_func(); // $ target=my_func type=x:i32
impl<T: Default> MyTrait<T> for [T] { impl<T: Default> MyTrait<T> for [T] {
fn my_method(&self) -> &T { fn my_method(&self) -> &T {
@@ -1770,11 +1770,11 @@ mod builtins {
let s: &[i32] = &[1, 2, 3]; let s: &[i32] = &[1, 2, 3];
let x = s.my_method(); // $ target=my_method type=x:&T.i32 let x = s.my_method(); // $ target=my_method type=x:&T.i32
let x = <[_]>::my_method(s); // $ target=my_method type=x:&T.i32 let x = <[_]>::my_method(s); // $ target=my_method type=x:&T.i32
let x = <[i32]>::my_func(); // $ MISSING: target=my_func type=x:i32 let x = <[i32]>::my_func(); // $ target=my_func type=x:i32
impl<T: Default> MyTrait<T> for (T, i32) { impl<T: Default> MyTrait<T> for (T, i32) {
fn my_method(&self) -> &T { fn my_method(&self) -> &T {
&self.0 &self.0 // $ fieldof=Tuple2
} }
fn my_func() -> T { fn my_func() -> T {
@@ -1785,7 +1785,7 @@ mod builtins {
let p = (42, 7); let p = (42, 7);
let x = p.my_method(); // $ target=my_method type=x:&T.i32 let x = p.my_method(); // $ target=my_method type=x:&T.i32
let x = <(_, _)>::my_method(&p); // $ target=my_method type=x:&T.i32 let x = <(_, _)>::my_method(&p); // $ target=my_method type=x:&T.i32
let x = <(i32, i32)>::my_func(); // $ MISSING: target=my_func type=x:i32 let x = <(i32, i32)>::my_func(); // $ target=my_func type=x:i32
impl<T: Default> MyTrait<T> for &T { impl<T: Default> MyTrait<T> for &T {
fn my_method(&self) -> &T { fn my_method(&self) -> &T {
@@ -1800,7 +1800,7 @@ mod builtins {
let r = &42; let r = &42;
let x = r.my_method(); // $ target=my_method type=x:&T.i32 let x = r.my_method(); // $ target=my_method type=x:&T.i32
let x = <&_>::my_method(&r); // $ target=my_method type=x:&T.i32 let x = <&_>::my_method(&r); // $ target=my_method type=x:&T.i32
let x = <&i32>::my_func(); // $ MISSING: target=my_func type=x:i32 let x = <&i32>::my_func(); // $ target=my_func type=x:i32
impl<T: Default> MyTrait<T> for *mut T { impl<T: Default> MyTrait<T> for *mut T {
fn my_method(&self) -> &T { fn my_method(&self) -> &T {
@@ -1816,7 +1816,7 @@ mod builtins {
let p: *mut i32 = &mut v; let p: *mut i32 = &mut v;
let x = unsafe { p.my_method() }; // $ target=my_method type=x:&T.i32 let x = unsafe { p.my_method() }; // $ target=my_method type=x:&T.i32
let x = unsafe { <*mut _>::my_method(&p) }; // $ target=my_method type=x:&T.i32 let x = unsafe { <*mut _>::my_method(&p) }; // $ target=my_method type=x:&T.i32
let x = <*mut i32>::my_func(); // $ MISSING: target=my_func type=x:i32 let x = <*mut i32>::my_func(); // $ target=my_func type=x:i32
} }
} }
@@ -2344,7 +2344,7 @@ mod impl_trait {
// For this function the `impl` type does not appear in the root of the return type // For this function the `impl` type does not appear in the root of the return type
let f = get_a_my_trait3(S1).unwrap().get_a(); // $ target=get_a_my_trait3 target=unwrap target=MyTrait::get_a type=f:S1 let f = get_a_my_trait3(S1).unwrap().get_a(); // $ target=get_a_my_trait3 target=unwrap target=MyTrait::get_a type=f:S1
let g = get_a_my_trait4(S1).0.get_a(); // $ target=get_a_my_trait4 target=MyTrait::get_a type=g:S1 let g = get_a_my_trait4(S1).0.get_a(); // $ target=get_a_my_trait4 target=MyTrait::get_a type=g:S1 fieldof=Tuple2
} }
} }
@@ -2670,7 +2670,7 @@ mod loops {
// for loops with containers // for loops with containers
let vals3 = vec![1, 2, 3]; // $ MISSING: type=vals3:Vec type=vals3:T.i32 let vals3 = vec![1, 2, 3]; // $ type=vals3:Vec $ MISSING: type=vals3:T.i32
for i in vals3 {} // $ MISSING: type=i:i32 for i in vals3 {} // $ MISSING: type=i:i32
let vals4a: Vec<u16> = [1u16, 2, 3].to_vec(); // $ certainType=vals4a:Vec certainType=vals4a:T.u16 let vals4a: Vec<u16> = [1u16, 2, 3].to_vec(); // $ certainType=vals4a:Vec certainType=vals4a:T.u16
@@ -2689,7 +2689,7 @@ mod loops {
vals7.push(1u8); // $ target=push vals7.push(1u8); // $ target=push
for u in vals7 {} // $ type=u:u8 for u in vals7 {} // $ type=u:u8
let matrix1 = vec![vec![1, 2], vec![3, 4]]; // $ MISSING: type=matrix1:Vec type=matrix1:T.Vec type=matrix1:T.T.i32 let matrix1 = vec![vec![1, 2], vec![3, 4]]; // $ type=matrix1:Vec $ MISSING: type=matrix1:T.Vec type=matrix1:T.T.i32
#[rustfmt::skip] #[rustfmt::skip]
let _ = for row in matrix1 { // $ MISSING: type=row:Vec type=row:T.i32 let _ = for row in matrix1 { // $ MISSING: type=row:Vec type=row:T.i32
for cell in row { // $ MISSING: type=cell:i32 for cell in row { // $ MISSING: type=cell:i32
@@ -2790,8 +2790,8 @@ mod tuples {
let (mut e, f) = S1::get_pair(); // $ target=get_pair type=e:S1 type=f:S1 let (mut e, f) = S1::get_pair(); // $ target=get_pair type=e:S1 type=f:S1
let (mut g, mut h) = S1::get_pair(); // $ target=get_pair type=g:S1 type=h:S1 let (mut g, mut h) = S1::get_pair(); // $ target=get_pair type=g:S1 type=h:S1
a.0.foo(); // $ target=foo a.0.foo(); // $ target=foo fieldof=Tuple2
b.1.foo(); // $ target=foo b.1.foo(); // $ target=foo fieldof=Tuple2
c.foo(); // $ target=foo c.foo(); // $ target=foo
d.foo(); // $ target=foo d.foo(); // $ target=foo
e.foo(); // $ target=foo e.foo(); // $ target=foo
@@ -2805,18 +2805,18 @@ mod tuples {
let a = Default::default(); // $ target=default type=a:i64 let a = Default::default(); // $ target=default type=a:i64
let b = Default::default(); // $ target=default type=b:bool let b = Default::default(); // $ target=default type=b:bool
let pair = (a, b); // $ type=pair:0(2).i64 type=pair:1(2).bool let pair = (a, b); // $ type=pair:0(2).i64 type=pair:1(2).bool
let i: i64 = pair.0; let i: i64 = pair.0; // $ fieldof=Tuple2
let j: bool = pair.1; let j: bool = pair.1; // $ fieldof=Tuple2
let pair = [1, 1].into(); // $ type=pair:(T_2) type=pair:0(2).i32 type=pair:1(2).i32 MISSING: target=into let pair = [1, 1].into(); // $ type=pair:(T_2) type=pair:0(2).i32 type=pair:1(2).i32 MISSING: target=into
match pair { match pair {
(0, 0) => print!("unexpected"), (0, 0) => print!("unexpected"),
_ => print!("expected"), _ => print!("expected"),
} }
let x = pair.0; // $ type=x:i32 let x = pair.0; // $ type=x:i32 fieldof=Tuple2
let y = &S1::get_pair(); // $ target=get_pair let y = &S1::get_pair(); // $ target=get_pair
y.0.foo(); // $ target=foo y.0.foo(); // $ target=foo fieldof=Tuple2
} }
} }

View File

@@ -60,9 +60,10 @@ module TypeTest implements TestSig {
exists(AstNode n, TypePath path, Type t | exists(AstNode n, TypePath path, Type t |
t = TypeInference::inferType(n, path) and t = TypeInference::inferType(n, path) and
( (
if t = TypeInference::CertainTypeInference::inferCertainType(n, path) tag = "type"
then tag = "certainType" or
else tag = "type" t = TypeInference::CertainTypeInference::inferCertainType(n, path) and
tag = "certainType"
) and ) and
location = n.getLocation() and location = n.getLocation() and
( (

View File

@@ -23,3 +23,125 @@ pub struct isize;
// floating-point types // floating-point types
pub struct f32; pub struct f32;
pub struct f64; pub struct f64;
pub struct Slice<T>;
pub struct Array<T, const N: usize>;
pub struct Ref<T>; // todo: add mut variant
pub struct Ptr<T>; // todo: add mut variant
// tuples
pub struct Tuple0;
pub struct Tuple1<T>(T);
pub struct Tuple2<T1, T2>(T1, T2);
pub struct Tuple3<T1, T2, T3>(T1, T2, T3);
pub struct Tuple4<T1, T2, T3, T4>(T1, T2, T3, T4);
pub struct Tuple5<T1, T2, T3, T4, T5>(T1, T2, T3, T4, T5);
pub struct Tuple6<T1, T2, T3, T4, T5, T6>(T1, T2, T3, T4, T5, T6);
pub struct Tuple7<T1, T2, T3, T4, T5, T6, T7>(T1, T2, T3, T4, T5, T6, T7);
pub struct Tuple8<T1, T2, T3, T4, T5, T6, T7, T8>(T1, T2, T3, T4, T5, T6, T7, T8);
pub struct Tuple9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1, T2, T3, T4, T5, T6, T7, T8, T9);
pub struct Tuple10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
T10,
);
pub struct Tuple11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
T10,
T11,
);
pub struct Tuple12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
T10,
T11,
T12,
);
pub struct Tuple13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
T10,
T11,
T12,
T13,
);
pub struct Tuple14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
T10,
T11,
T12,
T13,
T14,
);
pub struct Tuple15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
T10,
T11,
T12,
T13,
T14,
T15,
);
pub struct Tuple16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
T10,
T11,
T12,
T13,
T14,
T15,
T16,
);