mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #20830 from hvitved/rust/path-resolution-slice-array-builtin
Rust: Model builtin types in path resolution
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +29,11 @@ abstract class FieldContent extends Content {
|
|||||||
class TupleFieldContent extends FieldContent, TTupleFieldContent {
|
class TupleFieldContent extends FieldContent, TTupleFieldContent {
|
||||||
private TupleField field;
|
private TupleField field;
|
||||||
|
|
||||||
TupleFieldContent() { this = TTupleFieldContent(field) }
|
TupleFieldContent() {
|
||||||
|
this = TTupleFieldContent(field) and
|
||||||
|
// tuples are handled using the special `TupleContent` type
|
||||||
|
not field = any(TupleType tt).getATupleField()
|
||||||
|
}
|
||||||
|
|
||||||
/** Holds if this field belongs to an enum variant. */
|
/** Holds if this field belongs to an enum variant. */
|
||||||
predicate isVariantField(Variant v, int pos) { field.isVariantField(v, pos) }
|
predicate isVariantField(Variant v, int pos) { field.isVariantField(v, pos) }
|
||||||
|
|||||||
@@ -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 }
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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,8 @@ 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
|
||||||
|
i.isPublic()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 = "()" }
|
||||||
}
|
}
|
||||||
@@ -226,20 +208,17 @@ class UnionType extends Type, TUnion {
|
|||||||
/**
|
/**
|
||||||
* An array type.
|
* An array type.
|
||||||
*
|
*
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
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 +227,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 +317,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 +336,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 +374,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() }
|
||||||
@@ -461,37 +438,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 +485,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.
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -3131,6 +3074,8 @@ private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInput
|
|||||||
exists(term) and
|
exists(term) and
|
||||||
constraint.(TraitType).getTrait() instanceof FutureTrait
|
constraint.(TraitType).getTrait() instanceof FutureTrait
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate useUniversalConditions() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -3146,7 +3091,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 +3127,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)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3306,6 +3251,8 @@ private module ForIterableSatisfiesConstraintInput implements
|
|||||||
t instanceof IntoIteratorTrait
|
t instanceof IntoIteratorTrait
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate useUniversalConditions() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -3331,7 +3278,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()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3360,6 +3307,8 @@ private module InvokedClosureSatisfiesConstraintInput implements
|
|||||||
exists(term) and
|
exists(term) and
|
||||||
constraint.(TraitType).getTrait() instanceof FnOnceTrait
|
constraint.(TraitType).getTrait() instanceof FnOnceTrait
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate useUniversalConditions() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the type of `ce` when viewed as an implementation of `FnOnce`. */
|
/** Gets the type of `ce` when viewed as an implementation of `FnOnce`. */
|
||||||
@@ -3378,7 +3327,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 +3343,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 +3392,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
|
||||||
|
|||||||
@@ -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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
| 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 bool | |
|
| struct bool | |
|
||||||
| struct char | |
|
| struct char | |
|
||||||
| struct f32 | FloatingPointType, NumericType |
|
| struct f32 | FloatingPointType, NumericType |
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ multipleCallTargets
|
|||||||
| dereference.rs:186:17:186:25 | S.bar(...) |
|
| dereference.rs:186:17:186:25 | S.bar(...) |
|
||||||
| dereference.rs:187:17:187:29 | S.bar(...) |
|
| dereference.rs:187:17:187:29 | S.bar(...) |
|
||||||
| main.rs:590:9:590:18 | ...::m(...) |
|
| main.rs:590:9:590:18 | ...::m(...) |
|
||||||
| main.rs:2553:13:2553:31 | ...::from(...) |
|
| main.rs:2634:13:2634:31 | ...::from(...) |
|
||||||
| main.rs:2554:13:2554:31 | ...::from(...) |
|
| main.rs:2635:13:2635:31 | ...::from(...) |
|
||||||
| main.rs:2555:13:2555:31 | ...::from(...) |
|
| main.rs:2636:13:2636:31 | ...::from(...) |
|
||||||
| main.rs:2561:13:2561:31 | ...::from(...) |
|
| main.rs:2642:13:2642:31 | ...::from(...) |
|
||||||
| main.rs:2562:13:2562:31 | ...::from(...) |
|
| main.rs:2643:13:2643:31 | ...::from(...) |
|
||||||
| main.rs:2563:13:2563:31 | ...::from(...) |
|
| main.rs:2644:13:2644:31 | ...::from(...) |
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ impl<T> S<T> {
|
|||||||
fn explicit_monomorphic_dereference() {
|
fn explicit_monomorphic_dereference() {
|
||||||
// Dereference with method call
|
// Dereference with method call
|
||||||
let a1 = MyIntPointer { value: 34i64 };
|
let a1 = MyIntPointer { value: 34i64 };
|
||||||
let _b1 = a1.deref(); // $ target=MyIntPointer::deref type=_b1:&T.i64
|
let _b1 = a1.deref(); // $ target=MyIntPointer::deref type=_b1:TRef.i64
|
||||||
|
|
||||||
// Dereference with overloaded dereference operator
|
// Dereference with overloaded dereference operator
|
||||||
let a2 = MyIntPointer { value: 34i64 };
|
let a2 = MyIntPointer { value: 34i64 };
|
||||||
@@ -52,7 +52,7 @@ fn explicit_monomorphic_dereference() {
|
|||||||
fn explicit_polymorphic_dereference() {
|
fn explicit_polymorphic_dereference() {
|
||||||
// Explicit dereference with type parameter
|
// Explicit dereference with type parameter
|
||||||
let c1 = MySmartPointer { value: 'a' };
|
let c1 = MySmartPointer { value: 'a' };
|
||||||
let _d1 = c1.deref(); // $ target=MySmartPointer::deref type=_d1:&T.char
|
let _d1 = c1.deref(); // $ target=MySmartPointer::deref type=_d1:TRef.char
|
||||||
|
|
||||||
// Explicit dereference with type parameter
|
// Explicit dereference with type parameter
|
||||||
let c2 = MySmartPointer { value: 'a' };
|
let c2 = MySmartPointer { value: 'a' };
|
||||||
@@ -66,7 +66,7 @@ fn explicit_polymorphic_dereference() {
|
|||||||
fn explicit_ref_dereference() {
|
fn explicit_ref_dereference() {
|
||||||
// Explicit dereference with type parameter
|
// Explicit dereference with type parameter
|
||||||
let e1 = &'a';
|
let e1 = &'a';
|
||||||
let _f1 = e1.deref(); // $ target=deref type=_f1:&T.char
|
let _f1 = e1.deref(); // $ target=deref type=_f1:TRef.char
|
||||||
|
|
||||||
// Explicit dereference with type parameter
|
// Explicit dereference with type parameter
|
||||||
let e2 = &'a';
|
let e2 = &'a';
|
||||||
@@ -80,7 +80,7 @@ fn explicit_ref_dereference() {
|
|||||||
fn explicit_box_dereference() {
|
fn explicit_box_dereference() {
|
||||||
// Explicit dereference with type parameter
|
// Explicit dereference with type parameter
|
||||||
let g1: Box<char> = Box::new('a'); // $ target=new
|
let g1: Box<char> = Box::new('a'); // $ target=new
|
||||||
let _h1 = g1.deref(); // $ target=deref type=_h1:&T.char
|
let _h1 = g1.deref(); // $ target=deref type=_h1:TRef.char
|
||||||
|
|
||||||
// Explicit dereference with type parameter
|
// Explicit dereference with type parameter
|
||||||
let g2: Box<char> = Box::new('a'); // $ target=new
|
let g2: Box<char> = Box::new('a'); // $ target=new
|
||||||
@@ -101,7 +101,7 @@ fn implicit_dereference() {
|
|||||||
let _y = x.is_positive(); // $ MISSING: target=is_positive type=_y:bool
|
let _y = x.is_positive(); // $ MISSING: target=is_positive type=_y:bool
|
||||||
|
|
||||||
let z = MySmartPointer { value: S(0i64) };
|
let z = MySmartPointer { value: S(0i64) };
|
||||||
let z_ = z.foo(); // $ MISSING: target=foo type=z_:&T.i64
|
let z_ = z.foo(); // $ MISSING: target=foo type=z_:TRef.i64
|
||||||
}
|
}
|
||||||
|
|
||||||
mod implicit_deref_coercion_cycle {
|
mod implicit_deref_coercion_cycle {
|
||||||
|
|||||||
@@ -1542,7 +1542,7 @@ mod method_call_type_conversion {
|
|||||||
let x7 = S(&S2);
|
let x7 = S(&S2);
|
||||||
// Non-implicit dereference with nested borrow in order to test that the
|
// Non-implicit dereference with nested borrow in order to test that the
|
||||||
// implicit dereference handling doesn't affect nested borrows.
|
// implicit dereference handling doesn't affect nested borrows.
|
||||||
let t = x7.m1(); // $ target=m1 type=t:& type=t:&T.S2
|
let t = x7.m1(); // $ target=m1 type=t:& type=t:TRef.S2
|
||||||
println!("{:?}", x7);
|
println!("{:?}", x7);
|
||||||
|
|
||||||
let x9: String = "Hello".to_string(); // $ certainType=x9:String target=to_string
|
let x9: String = "Hello".to_string(); // $ certainType=x9:String target=to_string
|
||||||
@@ -1732,10 +1732,91 @@ mod builtins {
|
|||||||
let z = x + y; // $ type=z:i32 target=add
|
let z = x + y; // $ type=z:i32 target=add
|
||||||
let z = x.abs(); // $ target=abs $ type=z:i32
|
let z = x.abs(); // $ target=abs $ type=z:i32
|
||||||
let c = 'c'; // $ certainType=c:char
|
let c = 'c'; // $ certainType=c:char
|
||||||
let hello = "Hello"; // $ certainType=hello:&T.str
|
let hello = "Hello"; // $ certainType=hello:TRef.str
|
||||||
let f = 123.0f64; // $ certainType=f:f64
|
let f = 123.0f64; // $ certainType=f:f64
|
||||||
let t = true; // $ certainType=t:bool
|
let t = true; // $ certainType=t:bool
|
||||||
let f = false; // $ certainType=f:bool
|
let f = false; // $ certainType=f:bool
|
||||||
|
|
||||||
|
trait MyTrait<T> {
|
||||||
|
fn my_method(&self) -> &T;
|
||||||
|
|
||||||
|
fn my_func() -> T;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default, const N: usize> MyTrait<T> for [T; N] {
|
||||||
|
fn my_method(&self) -> &T {
|
||||||
|
self.get(0).unwrap() // $ MISSING: target=get target=unwrap
|
||||||
|
}
|
||||||
|
|
||||||
|
fn my_func() -> T {
|
||||||
|
T::default() // $ target=default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = [1, 2, 3].my_method(); // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <[_; 3]>::my_method(&[1, 2, 3]); // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <[i32; 3]>::my_func(); // $ target=my_func type=x:i32
|
||||||
|
|
||||||
|
impl<T: Default> MyTrait<T> for [T] {
|
||||||
|
fn my_method(&self) -> &T {
|
||||||
|
self.get(0).unwrap() // $ target=get target=unwrap
|
||||||
|
}
|
||||||
|
|
||||||
|
fn my_func() -> T {
|
||||||
|
T::default() // $ target=default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let s: &[i32] = &[1, 2, 3];
|
||||||
|
let x = s.my_method(); // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <[_]>::my_method(s); // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <[i32]>::my_func(); // $ target=my_func type=x:i32
|
||||||
|
|
||||||
|
impl<T: Default> MyTrait<T> for (T, i32) {
|
||||||
|
fn my_method(&self) -> &T {
|
||||||
|
&self.0 // $ fieldof=Tuple2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn my_func() -> T {
|
||||||
|
T::default() // $ target=default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let p = (42, 7);
|
||||||
|
let x = p.my_method(); // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <(_, _)>::my_method(&p); // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <(i32, i32)>::my_func(); // $ target=my_func type=x:i32
|
||||||
|
|
||||||
|
impl<T: Default> MyTrait<T> for &T {
|
||||||
|
fn my_method(&self) -> &T {
|
||||||
|
*self // $ target=deref
|
||||||
|
}
|
||||||
|
|
||||||
|
fn my_func() -> T {
|
||||||
|
T::default() // $ target=default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = &42;
|
||||||
|
let x = r.my_method(); // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <&_>::my_method(&r); // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <&i32>::my_func(); // $ target=my_func type=x:i32
|
||||||
|
|
||||||
|
impl<T: Default> MyTrait<T> for *mut T {
|
||||||
|
fn my_method(&self) -> &T {
|
||||||
|
unsafe { &**self } // $ target=deref target=deref
|
||||||
|
}
|
||||||
|
|
||||||
|
fn my_func() -> T {
|
||||||
|
T::default() // $ target=default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut v = 42;
|
||||||
|
let p: *mut i32 = &mut v;
|
||||||
|
let x = unsafe { p.my_method() }; // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = unsafe { <*mut _>::my_method(&p) }; // $ target=my_method type=x:TRef.i32
|
||||||
|
let x = <*mut i32>::my_func(); // $ target=my_func type=x:i32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2263,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2531,24 +2612,24 @@ mod loops {
|
|||||||
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 MISSING: type=i:i32
|
||||||
for i in [1, 2, 3].into_iter() {} // $ target=into_iter type=i:i32
|
for i in [1, 2, 3].into_iter() {} // $ target=into_iter type=i:i32
|
||||||
|
|
||||||
let vals1 = [1u8, 2, 3]; // $ type=vals1:[T;...].u8
|
let vals1 = [1u8, 2, 3]; // $ type=vals1:TArray.u8
|
||||||
for u in vals1 {} // $ type=u:u8
|
for u in vals1 {} // $ type=u:u8
|
||||||
|
|
||||||
let vals2 = [1u16; 3]; // $ type=vals2:[T;...].u16
|
let vals2 = [1u16; 3]; // $ type=vals2:TArray.u16
|
||||||
for u in vals2 {} // $ type=u:u16
|
for u in vals2 {} // $ type=u:u16
|
||||||
|
|
||||||
let vals3: [u32; 3] = [1, 2, 3]; // $ certainType=vals3:[T;...].u32
|
let vals3: [u32; 3] = [1, 2, 3]; // $ certainType=vals3:TArray.u32
|
||||||
for u in vals3 {} // $ type=u:u32
|
for u in vals3 {} // $ type=u:u32
|
||||||
|
|
||||||
let vals4: [u64; 3] = [1; 3]; // $ certainType=vals4:[T;...].u64
|
let vals4: [u64; 3] = [1; 3]; // $ certainType=vals4:TArray.u64
|
||||||
for u in vals4 {} // $ type=u:u64
|
for u in vals4 {} // $ type=u:u64
|
||||||
|
|
||||||
let mut strings1 = ["foo", "bar", "baz"]; // $ type=strings1:[T;...].&T.str
|
let mut strings1 = ["foo", "bar", "baz"]; // $ type=strings1:TArray.TRef.str
|
||||||
for s in &strings1 {} // $ type=s:&T.&T.str
|
for s in &strings1 {} // $ type=s:TRef.TRef.str
|
||||||
for s in &mut strings1 {} // $ type=s:&T.&T.str
|
for s in &mut strings1 {} // $ type=s:TRef.TRef.str
|
||||||
for s in strings1 {} // $ type=s:&T.str
|
for s in strings1 {} // $ type=s:TRef.str
|
||||||
|
|
||||||
let strings2 = // $ type=strings2:[T;...].String
|
let strings2 = // $ type=strings2:TArray.String
|
||||||
[
|
[
|
||||||
String::from("foo"), // $ target=from
|
String::from("foo"), // $ target=from
|
||||||
String::from("bar"), // $ target=from
|
String::from("bar"), // $ target=from
|
||||||
@@ -2556,15 +2637,15 @@ mod loops {
|
|||||||
];
|
];
|
||||||
for s in strings2 {} // $ type=s:String
|
for s in strings2 {} // $ type=s:String
|
||||||
|
|
||||||
let strings3 = // $ type=strings3:&T.[T;...].String
|
let strings3 = // $ type=strings3:TRef.TArray.String
|
||||||
&[
|
&[
|
||||||
String::from("foo"), // $ target=from
|
String::from("foo"), // $ target=from
|
||||||
String::from("bar"), // $ target=from
|
String::from("bar"), // $ target=from
|
||||||
String::from("baz"), // $ target=from
|
String::from("baz"), // $ target=from
|
||||||
];
|
];
|
||||||
for s in strings3 {} // $ type=s:&T.String
|
for s in strings3 {} // $ type=s:TRef.String
|
||||||
|
|
||||||
let callables = [MyCallable::new(), MyCallable::new(), MyCallable::new()]; // $ target=new $ type=callables:[T;...].MyCallable
|
let callables = [MyCallable::new(), MyCallable::new(), MyCallable::new()]; // $ target=new $ type=callables:TArray.MyCallable
|
||||||
for c // $ type=c:MyCallable
|
for c // $ type=c:MyCallable
|
||||||
in callables
|
in callables
|
||||||
{
|
{
|
||||||
@@ -2578,7 +2659,7 @@ mod loops {
|
|||||||
let range = 0..10; // $ certainType=range:Range type=range:Idx.i32
|
let range = 0..10; // $ certainType=range:Range type=range:Idx.i32
|
||||||
for i in range {} // $ type=i:i32
|
for i in range {} // $ type=i:i32
|
||||||
let range_full = ..; // $ certainType=range_full:RangeFull
|
let range_full = ..; // $ certainType=range_full:RangeFull
|
||||||
for i in &[1i64, 2i64, 3i64][range_full] {} // $ target=index MISSING: type=i:&T.i64
|
for i in &[1i64, 2i64, 3i64][range_full] {} // $ target=index MISSING: type=i:TRef.i64
|
||||||
|
|
||||||
let range1 = // $ certainType=range1:Range type=range1:Idx.u16
|
let range1 = // $ certainType=range1:Range type=range1:Idx.u16
|
||||||
std::ops::Range {
|
std::ops::Range {
|
||||||
@@ -2589,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
|
||||||
@@ -2601,27 +2682,27 @@ mod loops {
|
|||||||
let vals5 = Vec::from([1u32, 2, 3]); // $ certainType=vals5:Vec target=from type=vals5:T.u32
|
let vals5 = Vec::from([1u32, 2, 3]); // $ certainType=vals5:Vec target=from type=vals5:T.u32
|
||||||
for u in vals5 {} // $ type=u:u32
|
for u in vals5 {} // $ type=u:u32
|
||||||
|
|
||||||
let vals6: Vec<&u64> = [1u64, 2, 3].iter().collect(); // $ certainType=vals6:Vec certainType=vals6:T.&T.u64
|
let vals6: Vec<&u64> = [1u64, 2, 3].iter().collect(); // $ certainType=vals6:Vec certainType=vals6:T.TRef.u64
|
||||||
for u in vals6 {} // $ type=u:&T.u64
|
for u in vals6 {} // $ type=u:TRef.u64
|
||||||
|
|
||||||
let mut vals7 = Vec::new(); // $ target=new certainType=vals7:Vec type=vals7:T.u8
|
let mut vals7 = Vec::new(); // $ target=new certainType=vals7:Vec type=vals7:T.u8
|
||||||
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
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut map1 = std::collections::HashMap::new(); // $ target=new type=map1:K.i32 type=map1:V.Box $ MISSING: type=map1:Hashmap type1=map1:V.T.&T.str
|
let mut map1 = std::collections::HashMap::new(); // $ target=new type=map1:K.i32 type=map1:V.Box $ MISSING: type=map1:Hashmap type1=map1:V.T.TRef.str
|
||||||
map1.insert(1, Box::new("one")); // $ target=insert target=new
|
map1.insert(1, Box::new("one")); // $ target=insert target=new
|
||||||
map1.insert(2, Box::new("two")); // $ target=insert target=new
|
map1.insert(2, Box::new("two")); // $ target=insert target=new
|
||||||
for key in map1.keys() {} // $ target=keys type=key:&T.i32
|
for key in map1.keys() {} // $ target=keys type=key:TRef.i32
|
||||||
for value in map1.values() {} // $ target=values type=value:&T.Box type=value:&T.T.&T.str
|
for value in map1.values() {} // $ target=values type=value:TRef.Box type=value:TRef.T.TRef.str
|
||||||
for (key, value) in map1.iter() {} // $ target=iter type=key:&T.i32 type=value:&T.Box type=value:&T.T.&T.str
|
for (key, value) in map1.iter() {} // $ target=iter type=key:TRef.i32 type=value:TRef.Box type=value:TRef.T.TRef.str
|
||||||
for (key, value) in &map1 {} // $ type=key:&T.i32 type=value:&T.Box type=value:&T.T.&T.str
|
for (key, value) in &map1 {} // $ type=key:TRef.i32 type=value:TRef.Box type=value:TRef.T.TRef.str
|
||||||
|
|
||||||
// while loops
|
// while loops
|
||||||
|
|
||||||
@@ -2709,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
|
||||||
@@ -2723,19 +2804,19 @@ mod tuples {
|
|||||||
// `a` and `b` to be inferred.
|
// `a` and `b` to be inferred.
|
||||||
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:T0.i64 type=pair:T1.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:T0.i32 type=pair:T1.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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,18 +37,18 @@ pub fn f() -> Option<()> {
|
|||||||
|
|
||||||
let value3 = 42;
|
let value3 = 42;
|
||||||
if let ref mesg = value3 {
|
if let ref mesg = value3 {
|
||||||
let mesg = mesg; // $ type=mesg:&T.i32
|
let mesg = mesg; // $ type=mesg:TRef.i32
|
||||||
println!("{mesg}");
|
println!("{mesg}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let value4 = Some(42);
|
let value4 = Some(42);
|
||||||
if let Some(ref mesg) = value4 {
|
if let Some(ref mesg) = value4 {
|
||||||
let mesg = mesg; // $ type=mesg:&T.i32
|
let mesg = mesg; // $ type=mesg:TRef.i32
|
||||||
println!("{mesg}");
|
println!("{mesg}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let ref value5 = 42;
|
let ref value5 = 42;
|
||||||
let x = value5; // $ type=x:&T.i32
|
let x = value5; // $ type=x:TRef.i32
|
||||||
|
|
||||||
let my_record_struct = MyRecordStruct {
|
let my_record_struct = MyRecordStruct {
|
||||||
value1: 42,
|
value1: 42,
|
||||||
@@ -102,7 +102,7 @@ pub fn f() -> Option<()> {
|
|||||||
) => {
|
) => {
|
||||||
let a = value1; // $ type=a:bool
|
let a = value1; // $ type=a:bool
|
||||||
let b = x; // $ type=b:i32
|
let b = x; // $ type=b:i32
|
||||||
let c = y; // $ type=c:&T.str
|
let c = y; // $ type=c:TRef.str
|
||||||
();
|
();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
@@ -197,7 +197,7 @@ pub fn literal_patterns() {
|
|||||||
let string_val = "hello";
|
let string_val = "hello";
|
||||||
match string_val {
|
match string_val {
|
||||||
"hello" => {
|
"hello" => {
|
||||||
let hello_match = string_val; // $ certainType=hello_match:&T.str
|
let hello_match = string_val; // $ certainType=hello_match:TRef.str
|
||||||
println!("String literal: {}", hello_match);
|
println!("String literal: {}", hello_match);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -230,7 +230,7 @@ pub fn identifier_patterns() {
|
|||||||
// IdentPat with ref
|
// IdentPat with ref
|
||||||
match &value {
|
match &value {
|
||||||
ref x => {
|
ref x => {
|
||||||
let ref_bound = x; // $ type=ref_bound:&T.&T.i32
|
let ref_bound = x; // $ type=ref_bound:TRef.TRef.i32
|
||||||
println!("Reference identifier: {:?}", ref_bound);
|
println!("Reference identifier: {:?}", ref_bound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,7 +269,7 @@ pub fn identifier_patterns() {
|
|||||||
let mut ref_mut_val = 5i32;
|
let mut ref_mut_val = 5i32;
|
||||||
match &mut ref_mut_val {
|
match &mut ref_mut_val {
|
||||||
ref mut x => {
|
ref mut x => {
|
||||||
let ref_mut_bound = x; // $ type=ref_mut_bound:&T.&T.i32
|
let ref_mut_bound = x; // $ type=ref_mut_bound:TRef.TRef.i32
|
||||||
**ref_mut_bound += 1; // $ target=deref target=add_assign
|
**ref_mut_bound += 1; // $ target=deref target=add_assign
|
||||||
println!("Ref mut pattern");
|
println!("Ref mut pattern");
|
||||||
}
|
}
|
||||||
@@ -341,14 +341,14 @@ pub fn reference_patterns() {
|
|||||||
|
|
||||||
match &mut mutable_value {
|
match &mut mutable_value {
|
||||||
&mut ref x => {
|
&mut ref x => {
|
||||||
let mut_ref_bound = x; // $ type=mut_ref_bound:&T.i32
|
let mut_ref_bound = x; // $ type=mut_ref_bound:TRef.i32
|
||||||
println!("Mutable ref pattern: {}", mut_ref_bound);
|
println!("Mutable ref pattern: {}", mut_ref_bound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match &value {
|
match &value {
|
||||||
ref x => {
|
ref x => {
|
||||||
let ref_pattern = x; // $ type=ref_pattern:&T.&T.i32
|
let ref_pattern = x; // $ type=ref_pattern:TRef.TRef.i32
|
||||||
println!("Reference pattern: {}", ref_pattern);
|
println!("Reference pattern: {}", ref_pattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -525,7 +525,7 @@ pub fn slice_patterns() {
|
|||||||
// SlicePat - Slice patterns
|
// SlicePat - Slice patterns
|
||||||
match slice {
|
match slice {
|
||||||
[] => {
|
[] => {
|
||||||
let empty_slice = slice; // $ certainType=empty_slice:&T.[T].i32
|
let empty_slice = slice; // $ certainType=empty_slice:TRef.TSlice.i32
|
||||||
println!("Empty slice: {:?}", empty_slice);
|
println!("Empty slice: {:?}", empty_slice);
|
||||||
}
|
}
|
||||||
[x] => {
|
[x] => {
|
||||||
@@ -540,7 +540,7 @@ pub fn slice_patterns() {
|
|||||||
[first, middle @ .., last] => {
|
[first, middle @ .., last] => {
|
||||||
let slice_start = *first; // $ MISSING: type=slice_start:i32
|
let slice_start = *first; // $ MISSING: type=slice_start:i32
|
||||||
let slice_end = *last; // $ MISSING: type=slice_end:i32
|
let slice_end = *last; // $ MISSING: type=slice_end:i32
|
||||||
let slice_middle = middle; // $ MISSING: type=slice_middle:&T.[T].i32
|
let slice_middle = middle; // $ MISSING: type=slice_middle:TRef.TSlice.i32
|
||||||
println!(
|
println!(
|
||||||
"First: {}, last: {}, middle len: {}",
|
"First: {}, last: {}, middle len: {}",
|
||||||
slice_start,
|
slice_start,
|
||||||
@@ -717,7 +717,7 @@ pub fn complex_nested_patterns() {
|
|||||||
}
|
}
|
||||||
// Catch-all with identifier pattern
|
// Catch-all with identifier pattern
|
||||||
other => {
|
other => {
|
||||||
let other_complex = other; // $ type=other_complex:0(2).Point type=other_complex:1(2).MyOption
|
let other_complex = other; // $ type=other_complex:T0.Point type=other_complex:T1.MyOption
|
||||||
println!("Other complex data: {:?}", other_complex);
|
println!("Other complex data: {:?}", other_complex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -750,7 +750,7 @@ pub fn patterns_in_let_statements() {
|
|||||||
// Let with reference pattern
|
// Let with reference pattern
|
||||||
let value = 42i32;
|
let value = 42i32;
|
||||||
let ref ref_val = value;
|
let ref ref_val = value;
|
||||||
let let_ref = ref_val; // $ certainType=let_ref:&T.i32
|
let let_ref = ref_val; // $ certainType=let_ref:TRef.i32
|
||||||
|
|
||||||
// Let with mutable pattern
|
// Let with mutable pattern
|
||||||
let mut mut_val = 10i32;
|
let mut mut_val = 10i32;
|
||||||
@@ -779,13 +779,13 @@ pub fn patterns_in_function_parameters() {
|
|||||||
|
|
||||||
// Call the functions to use them
|
// Call the functions to use them
|
||||||
let point = Point { x: 5, y: 10 };
|
let point = Point { x: 5, y: 10 };
|
||||||
let extracted = extract_point(point); // $ target=extract_point certainType=extracted:0(2).i32 certainType=extracted:1(2).i32
|
let extracted = extract_point(point); // $ target=extract_point certainType=extracted:T0.i32 certainType=extracted:T1.i32
|
||||||
|
|
||||||
let color = Color(200, 100, 50);
|
let color = Color(200, 100, 50);
|
||||||
let red = extract_color(color); // $ target=extract_color certainType=red:u8
|
let red = extract_color(color); // $ target=extract_color certainType=red:u8
|
||||||
|
|
||||||
let tuple = (42i32, 3.14f64, true);
|
let tuple = (42i32, 3.14f64, true);
|
||||||
let tuple_extracted = extract_tuple(tuple); // $ target=extract_tuple certainType=tuple_extracted:0(2).i32 certainType=tuple_extracted:1(2).bool
|
let tuple_extracted = extract_tuple(tuple); // $ target=extract_tuple certainType=tuple_extracted:T0.i32 certainType=tuple_extracted:T1.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -23,3 +23,48 @@ pub struct isize;
|
|||||||
// floating-point types
|
// floating-point types
|
||||||
pub struct f32;
|
pub struct f32;
|
||||||
pub struct f64;
|
pub struct f64;
|
||||||
|
|
||||||
|
struct Slice<TSlice>;
|
||||||
|
struct Array<TArray, const N: usize>;
|
||||||
|
struct Ref<TRef>; // todo: add mut variant
|
||||||
|
struct Ptr<TPtr>; // todo: add mut variant
|
||||||
|
|
||||||
|
// tuples
|
||||||
|
struct Tuple0;
|
||||||
|
struct Tuple1<T0>(T0);
|
||||||
|
struct Tuple2<T0, T1>(T0, T1);
|
||||||
|
struct Tuple3<T0, T1, T2>(T0, T1, T2);
|
||||||
|
struct Tuple4<T0, T1, T2, T3>(T0, T1, T2, T3);
|
||||||
|
struct Tuple5<T0, T1, T2, T3, T4>(T0, T1, T2, T3, T4);
|
||||||
|
struct Tuple6<T0, T1, T2, T3, T4, T5>(T0, T1, T2, T3, T4, T5);
|
||||||
|
struct Tuple7<T0, T1, T2, T3, T4, T5, T6>(T0, T1, T2, T3, T4, T5, T6);
|
||||||
|
struct Tuple8<T0, T1, T2, T3, T4, T5, T6, T7>(T0, T1, T2, T3, T4, T5, T6, T7);
|
||||||
|
struct Tuple9<T0, T1, T2, T3, T4, T5, T6, T7, T8>(T0, T1, T2, T3, T4, T5, T6, T7, T8);
|
||||||
|
struct Tuple10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
|
||||||
|
struct Tuple11<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(
|
||||||
|
T0,
|
||||||
|
T1,
|
||||||
|
T2,
|
||||||
|
T3,
|
||||||
|
T4,
|
||||||
|
T5,
|
||||||
|
T6,
|
||||||
|
T7,
|
||||||
|
T8,
|
||||||
|
T9,
|
||||||
|
T10,
|
||||||
|
);
|
||||||
|
struct Tuple12<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(
|
||||||
|
T0,
|
||||||
|
T1,
|
||||||
|
T2,
|
||||||
|
T3,
|
||||||
|
T4,
|
||||||
|
T5,
|
||||||
|
T6,
|
||||||
|
T7,
|
||||||
|
T8,
|
||||||
|
T9,
|
||||||
|
T10,
|
||||||
|
T11,
|
||||||
|
);
|
||||||
|
|||||||
@@ -992,7 +992,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
|||||||
TypeMention constraintMention
|
TypeMention constraintMention
|
||||||
) {
|
) {
|
||||||
exists(Type type | hasTypeConstraint(tt, type, constraint) |
|
exists(Type type | hasTypeConstraint(tt, type, constraint) |
|
||||||
useUniversalConditions() and
|
useUniversalConditions() and // todo: remove, and instead check constraints
|
||||||
not exists(countConstraintImplementations(type, constraint)) and
|
not exists(countConstraintImplementations(type, constraint)) and
|
||||||
conditionSatisfiesConstraintTypeAt(abs, condition, constraintMention, _, _) and
|
conditionSatisfiesConstraintTypeAt(abs, condition, constraintMention, _, _) and
|
||||||
resolveTypeMentionRoot(condition) = abs.getATypeParameter() and
|
resolveTypeMentionRoot(condition) = abs.getATypeParameter() and
|
||||||
|
|||||||
Reference in New Issue
Block a user