Rust: Implement basic type inference in QL

This commit is contained in:
Tom Hvitved
2025-03-07 08:38:28 +01:00
parent 3a58611271
commit 62d4e6fe3f
24 changed files with 3196 additions and 34 deletions

View File

@@ -286,7 +286,6 @@ lib/codeql/rust/elements/internal/GenericArgImpl.qll 6b1b804c357425c223f926e560a
lib/codeql/rust/elements/internal/GenericArgListConstructor.qll 46859bb3eb09d77987a18642d65ba2e13471a4dc9c0a83a192fddc82e37c335c 2c7d54c876269a88d3461b05745e73b06532b1616cae9b614ac94b28735d8fc4
lib/codeql/rust/elements/internal/GenericParamImpl.qll f435f80d7f275803c1311d362467f4a367deb5a2c0245b17a9e12468a2c3ce2f 8e8fcc29f510efa03ce194ad3a1e2ae3fbd7f8e04ab5a4a2d1db03e95f388446
lib/codeql/rust/elements/internal/GenericParamListConstructor.qll 7221146d1724e0add3a8e70e0e46670142589eb7143425e1871ac4358a8c8bdb 2fbb7576444d6b2da6164245e2660d592d276ae2c1ca9f2bda5656b1c5c0a73a
lib/codeql/rust/elements/internal/GenericParamListImpl.qll 524aa0949df6d4d2cb9bee6226650f63a6f181d7644933fa265673b281074885 27b0210e5eaa2040bc8a093e35e1394befb6994b25369544738d0447ef269a9c
lib/codeql/rust/elements/internal/IdentPatConstructor.qll 09792f5a070996b65f095dc6b1b9e0fb096a56648eed26c0643c59f82377cab0 0bb1a9fcdc62b5197aef3dd6e0ea4d679dde10d5be54b57b5209727ba66e078b
lib/codeql/rust/elements/internal/IfExprConstructor.qll 03088b54c8fa623f93a5b5a7eb896f680e8b0e9025488157a02c48aaebc6ad56 906f916c3690d0721a31dd31b302dcdcec4233bb507683007d82cf10793a648f
lib/codeql/rust/elements/internal/ImplConstructor.qll 24edccca59f70d812d1458b412a45310ddc096d095332f6e3258903c54c1bb44 7eb673b3ab33a0873ee5ce189105425066b376821cce0fc9eb8ace22995f0bc7

1
rust/ql/.gitattributes generated vendored
View File

@@ -288,7 +288,6 @@
/lib/codeql/rust/elements/internal/GenericArgListConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/GenericParamImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/GenericParamListConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/GenericParamListImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/IdentPatConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/IfExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ImplConstructor.qll linguist-generated

View File

@@ -239,9 +239,8 @@ final class RecordExprCfgNode extends Nodes::RecordExprCfgNode {
pragma[nomagic]
ExprCfgNode getFieldExpr(string field) {
exists(RecordExprField ref |
ref = node.getRecordExprFieldList().getAField() and
any(ChildMapping mapping).hasCfgChild(node, ref.getExpr(), this, result) and
field = ref.getFieldName()
ref = node.getFieldExpr(field) and
any(ChildMapping mapping).hasCfgChild(node, ref.getExpr(), this, result)
)
}
}

View File

@@ -15,6 +15,14 @@ module Impl {
private import rust
private import PathResolution as PathResolution
pragma[nomagic]
Path getFunctionPath(CallExpr ce) { result = ce.getFunction().(PathExpr).getPath() }
pragma[nomagic]
PathResolution::ItemNode getResolvedFunction(CallExpr ce) {
result = PathResolution::resolvePath(getFunctionPath(ce))
}
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A function call expression. For example:
@@ -28,9 +36,15 @@ module Impl {
class CallExpr extends Generated::CallExpr {
override string toString() { result = this.getFunction().toAbbreviatedString() + "(...)" }
/** Gets the struct that this call resolves to, if any. */
Struct getStruct() { result = getResolvedFunction(this) }
/** Gets the variant that this call resolves to, if any. */
Variant getVariant() { result = getResolvedFunction(this) }
pragma[nomagic]
private PathResolution::ItemNode getResolvedFunction(int pos) {
result = PathResolution::resolvePath(this.getFunction().(PathExpr).getPath()) and
private PathResolution::ItemNode getResolvedFunctionAndPos(int pos) {
result = getResolvedFunction(this) and
exists(this.getArgList().getArg(pos))
}
@@ -42,7 +56,7 @@ module Impl {
*/
pragma[nomagic]
TupleField getTupleField(int pos) {
exists(PathResolution::ItemNode i | i = this.getResolvedFunction(pos) |
exists(PathResolution::ItemNode i | i = this.getResolvedFunctionAndPos(pos) |
result.isStructField(i, pos) or
result.isVariantField(i, pos)
)

View File

@@ -11,6 +11,9 @@ private import codeql.rust.elements.internal.generated.FieldExpr
* be referenced directly.
*/
module Impl {
private import rust
private import TypeInference as TypeInference
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A field access expression. For example:
@@ -19,6 +22,12 @@ module Impl {
* ```
*/
class FieldExpr extends Generated::FieldExpr {
/** Gets the record field that this access references, if any. */
RecordField getRecordField() { result = TypeInference::resolveRecordFieldExpr(this) }
/** Gets the tuple field that this access references, if any. */
TupleField getTupleField() { result = TypeInference::resolveTupleFieldExpr(this) }
override string toString() {
exists(string abbr, string name |
abbr = this.getExpr().toAbbreviatedString() and

View File

@@ -11,6 +11,8 @@ private import codeql.rust.elements.internal.generated.GenericArgList
* be referenced directly.
*/
module Impl {
private import rust
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* The base class for generic arguments.
@@ -22,5 +24,18 @@ module Impl {
override string toString() { result = this.toAbbreviatedString() }
override string toAbbreviatedString() { result = "<...>" }
/** Gets the `i`th type argument of this list. */
TypeRepr getTypeArgument(int i) {
result =
rank[i + 1](TypeRepr res, int j |
res = this.getGenericArg(j).(TypeArg).getTypeRepr()
|
res order by j
)
}
/** Gets a type argument of this list. */
TypeRepr getATypeArgument() { result = this.getTypeArgument(_) }
}
}

View File

@@ -1,4 +1,3 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `GenericParamList`.
*
@@ -12,11 +11,26 @@ private import codeql.rust.elements.internal.generated.GenericParamList
* be referenced directly.
*/
module Impl {
private import rust
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A GenericParamList. For example:
* ```rust
* todo!()
* ```
*/
class GenericParamList extends Generated::GenericParamList { }
class GenericParamList extends Generated::GenericParamList {
override string toString() { result = this.toAbbreviatedString() }
override string toAbbreviatedString() { result = "<...>" }
/** Gets the `i`th type parameter of this list. */
TypeParam getTypeParam(int i) {
result = rank[i + 1](TypeParam res, int j | res = this.getGenericParam(j) | res order by j)
}
/** Gets a type parameter of this list. */
TypeParam getATypeParam() { result = this.getTypeParam(_) }
}
}

View File

@@ -83,6 +83,9 @@ abstract class ItemNode extends AstNode {
/** Gets the visibility of this item, if any. */
abstract Visibility getVisibility();
/** Gets the `i`th type parameter of this item, if any. */
abstract TypeParam getTypeParam(int i);
/** Holds if this item is declared as `pub`. */
bindingset[this]
pragma[inline_late]
@@ -207,6 +210,8 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
}
override Visibility getVisibility() { none() }
override TypeParam getTypeParam(int i) { none() }
}
/** An item that can occur in a trait or an `impl` block. */
@@ -223,6 +228,8 @@ private class ConstItemNode extends AssocItemNode instanceof Const {
override Namespace getNamespace() { result.isValue() }
override Visibility getVisibility() { result = Const.super.getVisibility() }
override TypeParam getTypeParam(int i) { none() }
}
private class EnumItemNode extends ItemNode instanceof Enum {
@@ -231,6 +238,8 @@ private class EnumItemNode extends ItemNode instanceof Enum {
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { result = Enum.super.getVisibility() }
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
}
private class VariantItemNode extends ItemNode instanceof Variant {
@@ -240,6 +249,10 @@ private class VariantItemNode extends ItemNode instanceof Variant {
if super.getFieldList() instanceof RecordFieldList then result.isType() else result.isValue()
}
override TypeParam getTypeParam(int i) {
result = super.getEnum().getGenericParamList().getTypeParam(i)
}
override Visibility getVisibility() { result = Variant.super.getVisibility() }
}
@@ -250,10 +263,12 @@ class FunctionItemNode extends AssocItemNode instanceof Function {
override Namespace getNamespace() { result.isValue() }
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
override Visibility getVisibility() { result = Function.super.getVisibility() }
}
abstract private class ImplOrTraitItemNode extends ItemNode {
abstract class ImplOrTraitItemNode extends ItemNode {
/** Gets an item that may refer to this node using `Self`. */
pragma[nomagic]
ItemNode getAnItemInSelfScope() {
@@ -265,6 +280,19 @@ abstract private class ImplOrTraitItemNode extends ItemNode {
not mid instanceof ImplOrTraitItemNode
)
}
/** Gets a `Self` path that refers to this item. */
Path getASelfPath() {
isUnqualifiedSelfPath(result) and
this = unqualifiedPathLookup(result)
}
/** Gets an associated item belonging to this trait or `impl` block. */
abstract AssocItemNode getAnAssocItem();
/** Holds if this trait or `impl` block declares an associated item named `name`. */
pragma[nomagic]
predicate hasAssocItem(string name) { name = this.getAnAssocItem().getName() }
}
class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
@@ -276,18 +304,73 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
/** Holds if this `impl` block declares an associated item named `name`. */
pragma[nomagic]
predicate hasAssocItem(string name) {
name = super.getAssocItemList().getAnAssocItem().(AssocItemNode).getName()
private TypeRepr getASelfTyArg() {
result =
this.getSelfPath().getPart().getGenericArgList().getAGenericArg().(TypeArg).getTypeRepr()
}
pragma[nomagic]
private TypeParamItemNode getASelfTyTypeParamArg(TypeRepr arg) {
arg = this.getASelfTyArg() and
result = resolvePath(arg.(PathTypeRepr).getPath())
}
/**
* Holds if this `impl` block is constrained. Examples:
*
* ```rust
* impl Foo { ... } // unconstrained
*
* impl<T> Foo<T> { ... } // unconstrained
*
* impl Foo<i64> { ... } // constrained
*
* impl<T> Foo<Foo<T>> { ... } // constrained
*
* impl<T: Trait> Foo<T> { ... } // constrained
*
* impl<T> Foo<T> where T: Trait { ... } // constrained
* ```
*/
pragma[nomagic]
predicate isConstrained() {
exists(TypeRepr arg | arg = this.getASelfTyArg() |
not exists(this.getASelfTyTypeParamArg(arg))
or
this.getASelfTyTypeParamArg(arg).isConstrained()
)
}
/**
* Holds if this `impl` block is unconstrained. Examples:
*
* ```rust
* impl Foo { ... } // unconstrained
*
* impl<T> Foo<T> { ... } // unconstrained
*
* impl Foo<i64> { ... } // constrained
*
* impl<T> Foo<Foo<T>> { ... } // constrained
*
* impl<T: Trait> Foo<T> { ... } // constrained
*
* impl<T> Foo<T> where T: Trait { ... } // constrained
* ```
*/
predicate isUnconstrained() { not this.isConstrained() }
override AssocItemNode getAnAssocItem() { result = super.getAssocItemList().getAnAssocItem() }
override string getName() { result = "(impl)" }
override Namespace getNamespace() {
result.isType() // can be referenced with `Self`
}
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
override Visibility getVisibility() { result = Impl.super.getVisibility() }
}
@@ -298,6 +381,8 @@ private class MacroCallItemNode extends AssocItemNode instanceof MacroCall {
override Namespace getNamespace() { none() }
override TypeParam getTypeParam(int i) { none() }
override Visibility getVisibility() { none() }
}
@@ -307,6 +392,8 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module {
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { result = Module.super.getVisibility() }
override TypeParam getTypeParam(int i) { none() }
}
private class StructItemNode extends ItemNode instanceof Struct {
@@ -320,6 +407,8 @@ private class StructItemNode extends ItemNode instanceof Struct {
}
override Visibility getVisibility() { result = Struct.super.getVisibility() }
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
}
class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
@@ -330,17 +419,15 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
/** Holds if this trait declares an associated item named `name`. */
pragma[nomagic]
predicate hasAssocItem(string name) {
name = super.getAssocItemList().getAnAssocItem().(AssocItemNode).getName()
}
override AssocItemNode getAnAssocItem() { result = super.getAssocItemList().getAnAssocItem() }
override string getName() { result = Trait.super.getName().getText() }
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { result = Trait.super.getVisibility() }
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
}
class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
@@ -351,6 +438,8 @@ class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { result = TypeAlias.super.getVisibility() }
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
}
private class UnionItemNode extends ItemNode instanceof Union {
@@ -359,6 +448,8 @@ private class UnionItemNode extends ItemNode instanceof Union {
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { result = Union.super.getVisibility() }
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
}
private class UseItemNode extends ItemNode instanceof Use {
@@ -367,6 +458,8 @@ private class UseItemNode extends ItemNode instanceof Use {
override Namespace getNamespace() { none() }
override Visibility getVisibility() { none() }
override TypeParam getTypeParam(int i) { none() }
}
private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
@@ -375,6 +468,8 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
override Namespace getNamespace() { none() }
override Visibility getVisibility() { none() }
override TypeParam getTypeParam(int i) { none() }
}
private class TypeParamItemNode extends ItemNode instanceof TypeParam {
@@ -385,12 +480,50 @@ private class TypeParamItemNode extends ItemNode instanceof TypeParam {
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
/**
* Holds if this type parameter is constrained. Examples:
*
* ```rust
* impl<T> Foo<T> { ... } // unconstrained
*
* impl<T: Trait> Foo<T> { ... } // constrained
*
* impl<T> Foo<T> where T: Trait { ... } // constrained
* ```
*/
pragma[nomagic]
predicate isConstrained() {
exists(this.getABoundPath())
or
exists(ItemNode declaringItem, WherePred wp |
this = resolvePath(wp.getTypeRepr().(PathTypeRepr).getPath()) and
wp = declaringItem.getADescendant() and
this = declaringItem.getADescendant()
)
}
/**
* Holds if this type parameter is unconstrained. Examples:
*
* ```rust
* impl<T> Foo<T> { ... } // unconstrained
*
* impl<T: Trait> Foo<T> { ... } // constrained
*
* impl<T> Foo<T> where T: Trait { ... } // constrained
* ```
*/
pragma[nomagic]
predicate isUnconstrained() { not this.isConstrained() }
override string getName() { result = TypeParam.super.getName().getText() }
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { none() }
override TypeParam getTypeParam(int i) { none() }
override Location getLocation() { result = TypeParam.super.getName().getLocation() }
}
@@ -547,14 +680,23 @@ private ItemNode getASuccessor(ItemNode pred, string name, Namespace ns) {
}
pragma[nomagic]
private ItemNode resolvePath0(RelevantPath path) {
exists(ItemNode encl, Namespace ns, string name, ItemNode res |
private ItemNode unqualifiedPathLookup(RelevantPath path) {
exists(ItemNode encl, Namespace ns, string name |
unqualifiedPathLookup(path, name, ns, encl) and
res = getASuccessor(encl, name, ns)
|
result = getASuccessor(encl, name, ns)
)
}
pragma[nomagic]
private predicate isUnqualifiedSelfPath(RelevantPath path) { path.isUnqualified("Self") }
pragma[nomagic]
private ItemNode resolvePath0(RelevantPath path) {
exists(ItemNode res |
res = unqualifiedPathLookup(path) and
if
not any(RelevantPath parent).getQualifier() = path and
name = "Self" and
isUnqualifiedSelfPath(path) and
res instanceof ImplItemNode
then result = res.(ImplItemNode).resolveSelfTy()
else result = res

View File

@@ -27,13 +27,23 @@ module Impl {
class RecordExpr extends Generated::RecordExpr {
override string toString() { result = this.getPath().toString() + " {...}" }
/** Gets the record expression for the field `name`. */
pragma[nomagic]
RecordExprField getFieldExpr(string name) {
result = this.getRecordExprFieldList().getAField() and
name = result.getFieldName()
}
pragma[nomagic]
private PathResolution::ItemNode getResolvedPath(string name) {
result = PathResolution::resolvePath(this.getPath()) and
exists(this.getFieldExpr(name))
}
/** Gets the record field that matches the `name` field of this record expression. */
pragma[nomagic]
RecordField getRecordField(string name) {
exists(PathResolution::ItemNode i |
i = PathResolution::resolvePath(this.getPath()) and
name = this.getRecordExprFieldList().getAField().getFieldName()
|
exists(PathResolution::ItemNode i | i = this.getResolvedPath(name) |
result.isStructField(i, name) or
result.isVariantField(i, name)
)

View File

@@ -27,13 +27,16 @@ module Impl {
class RecordPat extends Generated::RecordPat {
override string toString() { result = this.getPath().toAbbreviatedString() + " {...}" }
pragma[nomagic]
private PathResolution::ItemNode getResolvedPath(string name) {
result = PathResolution::resolvePath(this.getPath()) and
name = this.getRecordPatFieldList().getAField().getFieldName()
}
/** Gets the record field that matches the `name` pattern of this pattern. */
pragma[nomagic]
RecordField getRecordField(string name) {
exists(PathResolution::ItemNode i |
i = PathResolution::resolvePath(this.getPath()) and
name = this.getRecordPatFieldList().getAField().getFieldName()
|
exists(PathResolution::ItemNode i | i = this.getResolvedPath(name) |
result.isStructField(i, name) or
result.isVariantField(i, name)
)

View File

@@ -32,5 +32,17 @@ module Impl {
/** Gets the `i`th tuple field, if any. */
pragma[nomagic]
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
/** Holds if this struct uses tuple fields. */
pragma[nomagic]
predicate isTuple() { this.getFieldList() instanceof TupleFieldList }
/**
* Holds if this struct uses record fields.
*
* Empty structs are considered to use record fields.
*/
pragma[nomagic]
predicate isRecord() { not this.isTuple() }
}
}

View File

@@ -0,0 +1,329 @@
/** Provides classes representing types without type arguments. */
private import rust
private import PathResolution
private import TypeInference
private import TypeMention
private import codeql.rust.internal.CachedStages
cached
newtype TType =
TStruct(Struct s) { Stages::TypeInference::ref() } or
TEnum(Enum e) or
TTrait(Trait t) or
TImpl(Impl i) or
TArrayType() or // todo: add size?
TRefType() or // todo: add mut?
TTypeParamTypeParameter(TypeParam t) or
TRefTypeParameter() or
TSelfTypeParameter()
/** A type without type arguments. */
abstract class Type extends TType {
/** Gets the method `name` belonging to this type, if any. */
pragma[nomagic]
abstract Function getMethod(string name);
/** Gets the record field `name` belonging to this type, if any. */
pragma[nomagic]
abstract RecordField getRecordField(string name);
/** Gets the `i`th tuple field belonging to this type, if any. */
pragma[nomagic]
abstract TupleField getTupleField(int i);
/** Gets the `i`th type parameter of this type, if any. */
abstract TypeParameter getTypeParameter(int i);
/** Gets a type parameter of this type. */
final TypeParameter getATypeParameter() { result = this.getTypeParameter(_) }
/**
* Gets an AST node that mentions a base type of this type, if any.
*
* Although Rust doesn't have traditional OOP-style inheritance, we model trait
* bounds and `impl` blocks as base types. Example:
*
* ```rust
* trait T1 {}
*
* trait T2 {}
*
* trait T3 : T1, T2 {}
* // ^^ `this`
* // ^^ `result`
* // ^^ `result`
* ```
*/
abstract TypeMention getABaseTypeMention();
/** Gets a textual representation of this type. */
abstract string toString();
/** Gets the location of this type. */
abstract Location getLocation();
}
abstract private class StructOrEnumType extends Type {
abstract ItemNode asItemNode();
final override Function getMethod(string name) {
result = this.asItemNode().getASuccessor(name) and
exists(ImplOrTraitItemNode impl | result = impl.getAnAssocItem() |
impl instanceof Trait
or
impl.(ImplItemNode).isUnconstrained()
)
}
final override ImplMention getABaseTypeMention() {
this.asItemNode() = result.resolveSelfTy() and
result.isUnconstrained()
}
}
/** A struct type. */
class StructType extends StructOrEnumType, TStruct {
private Struct struct;
StructType() { this = TStruct(struct) }
override ItemNode asItemNode() { result = struct }
override RecordField getRecordField(string name) { result = struct.getRecordField(name) }
override TupleField getTupleField(int i) { result = struct.getTupleField(i) }
override TypeParameter getTypeParameter(int i) {
result = TTypeParamTypeParameter(struct.getGenericParamList().getTypeParam(i))
}
override string toString() { result = struct.toString() }
override Location getLocation() { result = struct.getLocation() }
}
/** An enum type. */
class EnumType extends StructOrEnumType, TEnum {
private Enum enum;
EnumType() { this = TEnum(enum) }
override ItemNode asItemNode() { result = enum }
override RecordField getRecordField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getTypeParameter(int i) {
result = TTypeParamTypeParameter(enum.getGenericParamList().getTypeParam(i))
}
override string toString() { result = enum.toString() }
override Location getLocation() { result = enum.getLocation() }
}
/** A trait type. */
class TraitType extends Type, TTrait {
private Trait trait;
TraitType() { this = TTrait(trait) }
override Function getMethod(string name) { result = trait.(ItemNode).getASuccessor(name) }
override RecordField getRecordField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getTypeParameter(int i) {
result = TTypeParamTypeParameter(trait.getGenericParamList().getTypeParam(i))
or
result = TSelfTypeParameter() and
i = -1
}
pragma[nomagic]
private TypeReprMention getABoundMention() {
result = trait.getTypeBoundList().getABound().getTypeRepr()
}
override TypeMention getABaseTypeMention() { result = this.getABoundMention() }
override string toString() { result = trait.toString() }
override Location getLocation() { result = trait.getLocation() }
}
/**
* An `impl` block type.
*
* Although `impl` blocks are not really types, we treat them as such in order
* to be able to match type parameters from structs (or enums) with type
* parameters from `impl` blocks. For example, in
*
* ```rust
* struct S<T1>(T1);
*
* impl<T2> S<T2> {
* fn id(self) -> S<T2> { self }
* }
*
* let x : S(i64) = S(42);
* x.id();
* ```
*
* we pretend that the `impl` block is a base type mention of the struct `S`,
* with type argument `T1`. This means that from knowing that `x` has type
* `S(i64)`, we can first match `i64` with `T1`, and then by matching `T1` with
* `T2`, we can match `i64` with `T2`.
*
* `impl` blocks can also have base type mentions, namely the trait that they
* implement (if any). Example:
*
* ```rust
* struct S<T1>(T1);
*
* trait Trait<T2> {
* fn f(self) -> T2;
*
* fn g(self) -> T2 { self.f() }
* }
*
* impl<T3> Trait<T3> for S<T3> { // `Trait<T3>` is a base type mention of this `impl` block
* fn f(self) -> T3 {
* match self {
* S(x) => x
* }
* }
* }
*
* let x : S(i64) = S(42);
* x.g();
* ```
*
* In this case we can match `i64` with `T1`, `T1` with `T3`, and `T3` with `T2`,
* allowing us match `i64` with `T2`, and hence infer that the return type of `g`
* is `i64`.
*/
class ImplType extends Type, TImpl {
private Impl impl;
ImplType() { this = TImpl(impl) }
override Function getMethod(string name) { result = impl.(ItemNode).getASuccessor(name) }
override RecordField getRecordField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getTypeParameter(int i) {
result = TTypeParamTypeParameter(impl.getGenericParamList().getTypeParam(i))
or
result = TSelfTypeParameter() and
i = -1
}
override TypeMention getABaseTypeMention() { result = impl.getTrait() }
override string toString() { result = impl.toString() }
override Location getLocation() { result = impl.getLocation() }
}
/**
* An array type.
*
* Array types like `[i64; 5]` are modeled as normal generic types
* with a single type argument.
*/
class ArrayType extends Type, TArrayType {
ArrayType() { this = TArrayType() }
override Function getMethod(string name) { none() }
override RecordField getRecordField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getTypeParameter(int i) {
none() // todo
}
override TypeMention getABaseTypeMention() { none() }
override string toString() { result = "[]" }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* A reference type.
*
* Reference types like `& i64` are modeled as normal generic types
* with a single type argument.
*/
class RefType extends Type, TRefType {
RefType() { this = TRefType() }
override Function getMethod(string name) { none() }
override RecordField getRecordField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getTypeParameter(int i) {
result = TRefTypeParameter() and
i = 0
}
override TypeMention getABaseTypeMention() { none() }
override string toString() { result = "&" }
override Location getLocation() { result instanceof EmptyLocation }
}
/** A type parameter. */
abstract class TypeParameter extends Type {
override TypeMention getABaseTypeMention() { none() }
override RecordField getRecordField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getTypeParameter(int i) { none() }
}
/** A type parameter from source code. */
class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter {
private TypeParam typeParam;
TypeParamTypeParameter() { this = TTypeParamTypeParameter(typeParam) }
TypeParam getTypeParam() { result = typeParam }
override Function getMethod(string name) { result = typeParam.(ItemNode).getASuccessor(name) }
override string toString() { result = typeParam.toString() }
override Location getLocation() { result = typeParam.getLocation() }
}
/** An implicit reference type parameter. */
class RefTypeParameter extends TypeParameter, TRefTypeParameter {
override Function getMethod(string name) { none() }
override string toString() { result = "&T" }
override Location getLocation() { result instanceof EmptyLocation }
}
/** An implicit `Self` type parameter. */
class SelfTypeParameter extends TypeParameter, TSelfTypeParameter {
override Function getMethod(string name) { none() }
override string toString() { result = "(Self)" }
override Location getLocation() { result instanceof EmptyLocation }
}

View File

@@ -0,0 +1,999 @@
/** Provides functionality for inferring types. */
private import rust
private import PathResolution
private import Type
private import Type as T
private import TypeMention
private import codeql.typeinference.internal.TypeInference
class Type = T::Type;
private module Input1 implements InputSig1<Location> {
private import Type as T
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
class Type = T::Type;
class TypeParameter = T::TypeParameter;
private newtype TTypeArgumentPosition =
// method type parameters are matched by position instead of by type
// parameter entity, to avoid extra recursion through method call resolution
TMethodTypeArgumentPosition(int pos) {
exists(any(MethodCallExpr mce).getGenericArgList().getTypeArgument(pos))
} or
TTypeParamTypeArgumentPosition(TypeParam tp)
class TypeArgumentPosition extends TTypeArgumentPosition {
int asMethodTypeArgumentPosition() { this = TMethodTypeArgumentPosition(result) }
TypeParam asTypeParam() { this = TTypeParamTypeArgumentPosition(result) }
string toString() {
result = this.asMethodTypeArgumentPosition().toString()
or
result = this.asTypeParam().toString()
}
}
class TypeParameterPosition = TypeParam;
bindingset[apos]
bindingset[ppos]
predicate typeArgumentParameterPositionMatch(TypeArgumentPosition apos, TypeParameterPosition ppos) {
apos.asTypeParam() = ppos
or
apos.asMethodTypeArgumentPosition() = ppos.getPosition()
}
private predicate id(Raw::TypeParam x, Raw::TypeParam y) { x = y }
private predicate idOfRaw(Raw::TypeParam x, int y) = equivalenceRelation(id/2)(x, y)
private int idOf(TypeParam node) { idOfRaw(Synth::convertAstNodeToRaw(node), result) }
int getTypeParameterId(TypeParameter tp) {
tp =
rank[result](TypeParameter tp0, int kind, int id |
tp0 instanceof RefTypeParameter and
kind = 0 and
id = 0
or
tp0 instanceof SelfTypeParameter and
kind = 0 and
id = 1
or
id = idOf(tp0.(TypeParamTypeParameter).getTypeParam()) and
kind = 1
|
tp0 order by kind, id
)
}
}
private import Input1
private module M1 = Make1<Location, Input1>;
private import M1
class TypePath = M1::TypePath;
module TypePath = M1::TypePath;
private module Input2 implements InputSig2 {
private import TypeMention as TM
class TypeMention = TM::TypeMention;
TypeMention getABaseTypeMention(Type t) { result = t.getABaseTypeMention() }
}
private module M2 = Make2<Input2>;
private import M2
module Consistency = M2::Consistency;
/** Gets the type annotation that applies to `n`, if any. */
private TypeMention getTypeAnnotation(AstNode n) {
exists(LetStmt let |
n = let.getPat() and
result = let.getTypeRepr()
)
or
result = n.(SelfParam).getTypeRepr()
or
exists(Param p |
n = p.getPat() and
result = p.getTypeRepr()
)
or
exists(Function f |
result = f.getRetType().getTypeRepr() and
n = f.getBody()
)
}
/** Gets the type of `n`, which has an explicit type annotation. */
pragma[nomagic]
private Type resolveAnnotatedType(AstNode n, TypePath path) {
result = getTypeAnnotation(n).resolveTypeAt(path)
}
/**
* Holds if the type of `n1` at `path1` is the same as the type of `n2` at `path2`.
*/
bindingset[path1]
bindingset[path2]
private predicate typeSymmetry(AstNode n1, TypePath path1, AstNode n2, TypePath path2) {
exists(Variable v |
path1 = path2 and
n1 = v.getAnAccess()
|
n2 = v.getPat()
or
n2 = v.getParameter().(SelfParam)
)
or
exists(LetStmt let |
let.getPat() = n1 and
let.getInitializer() = n2 and
path1 = path2
)
or
n2 =
any(PrefixExpr pe |
pe.getOperatorName() = "*" and
pe.getExpr() = n1 and
path1 = TypePath::cons(TRefTypeParameter(), path2)
)
or
n1 = n2.(ParenExpr).getExpr() and
path1 = path2
or
n1 = n2.(BlockExpr).getStmtList().getTailExpr() and
path1 = path2
}
pragma[nomagic]
private Type resolveTypeSymmetry(AstNode n, TypePath path) {
exists(AstNode n2, TypePath path2 | result = resolveType(n2, path2) |
typeSymmetry(n, path, n2, path2)
or
typeSymmetry(n2, path2, n, path)
)
}
/**
* Gets the type of the implicitly typed `self` parameter, taking into account
* whether the parameter is passed by value or by reference.
*/
bindingset[self, suffix, t]
pragma[inline_late]
private Type getRefAdjustImplicitSelfType(SelfParam self, TypePath suffix, Type t, TypePath path) {
not self.hasTypeRepr() and
(
if self.isRef()
then
// `fn f(&self, ...)`
path.isEmpty() and
result = TRefType()
or
path = TypePath::cons(TRefTypeParameter(), suffix) and
result = t
else (
// `fn f(self, ...)`
path = suffix and
result = t
)
)
}
pragma[nomagic]
private Type resolveImplSelfType(Impl i, TypePath path) {
result = i.getSelfTy().(TypeReprMention).resolveTypeAt(path)
}
pragma[nomagic]
private Type resolveTraitSelfType(Trait t, TypePath path) {
result = TTrait(t) and
path.isEmpty()
or
result = TTypeParamTypeParameter(t.getGenericParamList().getATypeParam()) and
path = TypePath::singleton(result)
}
/** Gets the type at `path` of the implicitly typed `self` parameter. */
pragma[nomagic]
private Type resolveImplicitSelfType(SelfParam self, TypePath path) {
exists(ImplOrTraitItemNode i, Function f, TypePath suffix, Type t |
f = i.getAnAssocItem() and
self = f.getParamList().getSelfParam() and
result = getRefAdjustImplicitSelfType(self, suffix, t, path)
|
t = resolveImplSelfType(i, suffix)
or
t = resolveTraitSelfType(i, suffix)
)
}
private TypeMention getExplicitTypeArgMention(Path path, TypeParam tp) {
exists(int i |
result = path.getPart().getGenericArgList().getTypeArgument(pragma[only_bind_into](i)) and
tp = resolvePath(path).getTypeParam(pragma[only_bind_into](i))
)
or
result = getExplicitTypeArgMention(path.getQualifier(), tp)
}
/**
* A matching configuration for resolving types of record expressions
* like `Foo { bar = baz }`.
*/
private module RecordExprMatchingInput implements MatchingInputSig {
private newtype TPos =
TFieldPos(string name) { exists(any(Declaration decl).getField(name)) } or
TRecordPos()
class DeclarationPosition extends TPos {
string asFieldPos() { this = TFieldPos(result) }
predicate isRecordPos() { this = TRecordPos() }
string toString() {
result = this.asFieldPos()
or
this.isRecordPos() and
result = "(record)"
}
}
abstract class Declaration extends AstNode {
abstract TypeParam getATypeParam();
final TypeParameter getTypeParameter(TypeParameterPosition ppos) {
result.(TypeParamTypeParameter).getTypeParam() = ppos and
ppos = this.getATypeParam()
}
abstract RecordField getField(string name);
Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
// type of a field
exists(TypeReprMention tp |
tp = this.getField(dpos.asFieldPos()).getTypeRepr() and
result = tp.resolveTypeAt(path)
)
or
// type parameter of the record itself
dpos.isRecordPos() and
result = this.getTypeParameter(_) and
path = TypePath::singleton(result)
}
}
private class RecordStructDecl extends Declaration, Struct {
RecordStructDecl() { this.isRecord() }
override TypeParam getATypeParam() { result = this.getGenericParamList().getATypeParam() }
override RecordField getField(string name) { result = this.getRecordField(name) }
override Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
result = super.getDeclaredType(dpos, path)
or
// type of the struct itself
dpos.isRecordPos() and
path.isEmpty() and
result = TStruct(this)
}
}
private class RecordVariantDecl extends Declaration, Variant {
RecordVariantDecl() { this.isRecord() }
Enum getEnum() { result.getVariantList().getAVariant() = this }
override TypeParam getATypeParam() {
result = this.getEnum().getGenericParamList().getATypeParam()
}
override RecordField getField(string name) { result = this.getRecordField(name) }
override Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
result = super.getDeclaredType(dpos, path)
or
// type of the enum itself
dpos.isRecordPos() and
path.isEmpty() and
result = TEnum(this.getEnum())
}
}
class AccessPosition = DeclarationPosition;
class Access extends RecordExpr {
Type getExplicitTypeArgument(TypeArgumentPosition apos, TypePath path) {
result = getExplicitTypeArgMention(this.getPath(), apos.asTypeParam()).resolveTypeAt(path)
}
AstNode getNodeAt(AccessPosition apos) {
result = this.getFieldExpr(apos.asFieldPos()).getExpr()
or
result = this and
apos.isRecordPos()
}
Type getResolvedType(AccessPosition apos, TypePath path) {
result = resolveType(this.getNodeAt(apos), path)
}
Declaration getTarget() { result = resolvePath(this.getPath()) }
}
predicate accessDeclarationPositionMatch(AccessPosition apos, DeclarationPosition dpos) {
apos = dpos
}
}
private module RecordExprMatching = Matching<RecordExprMatchingInput>;
/**
* Gets the type of `n` at `path`, where `n` is either a record expression or
* a field expression of a record expression.
*/
pragma[nomagic]
private Type resolveRecordExprType(AstNode n, TypePath path) {
exists(RecordExprMatchingInput::Access a, RecordExprMatchingInput::AccessPosition apos |
n = a.getNodeAt(apos) and
result = RecordExprMatching::resolveAccessType(a, apos, path)
)
}
pragma[nomagic]
private Type resolvePathExprType(PathExpr pe, TypePath path) {
// nullary struct/variant constructors
not exists(CallExpr ce | pe = ce.getFunction()) and
path.isEmpty() and
exists(ItemNode i | i = resolvePath(pe.getPath()) |
result = TEnum(i.(Variant).getEnum())
or
result = TStruct(i)
)
}
/**
* A matching configuration for resolving types of call expressions
* like `foo::bar(baz)` and `foo.bar(baz)`.
*/
private module CallExprBaseMatchingInput implements MatchingInputSig {
private predicate paramPos(ParamList pl, Param p, int pos, boolean inMethod) {
p = pl.getParam(pos) and
if pl.hasSelfParam() then inMethod = true else inMethod = false
}
private newtype TDeclarationPosition =
TSelfDeclarationPosition() or
TPositionalDeclarationPosition(int pos, boolean inMethod) { paramPos(_, _, pos, inMethod) } or
TReturnDeclarationPosition()
class DeclarationPosition extends TDeclarationPosition {
predicate isSelf() { this = TSelfDeclarationPosition() }
int asPosition(boolean inMethod) { this = TPositionalDeclarationPosition(result, inMethod) }
predicate isReturn() { this = TReturnDeclarationPosition() }
string toString() {
this.isSelf() and
result = "self"
or
result = this.asPosition(_).toString()
or
this.isReturn() and
result = "(return)"
}
}
abstract class Declaration extends AstNode {
abstract TypeParam getATypeParam();
final TypeParameter getTypeParameter(TypeParameterPosition ppos) {
result.(TypeParamTypeParameter).getTypeParam() = ppos and
ppos = this.getATypeParam()
}
pragma[nomagic]
abstract Type getParameterType(DeclarationPosition dpos, TypePath path);
abstract Type getReturnType(TypePath path);
final Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
result = this.getParameterType(dpos, path)
or
dpos.isReturn() and
result = this.getReturnType(path)
}
}
private class TupleStructDecl extends Declaration, Struct {
TupleStructDecl() { this.isTuple() }
override TypeParam getATypeParam() { result = this.getGenericParamList().getATypeParam() }
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
exists(int pos |
result = this.getTupleField(pos).getTypeRepr().(TypeReprMention).resolveTypeAt(path) and
dpos = TPositionalDeclarationPosition(pos, false)
)
}
override Type getReturnType(TypePath path) {
result = TStruct(this) and
path.isEmpty()
or
result = TTypeParamTypeParameter(this.getGenericParamList().getATypeParam()) and
path = TypePath::singleton(result)
}
}
private class TupleVariantDecl extends Declaration, Variant {
TupleVariantDecl() { this.isTuple() }
override TypeParam getATypeParam() {
result = this.getEnum().getGenericParamList().getATypeParam()
}
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
exists(int p |
result = this.getTupleField(p).getTypeRepr().(TypeReprMention).resolveTypeAt(path) and
dpos = TPositionalDeclarationPosition(p, false)
)
}
override Type getReturnType(TypePath path) {
exists(Enum enum | enum = this.getEnum() |
result = TEnum(enum) and
path.isEmpty()
or
result = TTypeParamTypeParameter(enum.getGenericParamList().getATypeParam()) and
path = TypePath::singleton(result)
)
}
}
pragma[nomagic]
private Type resolveAnnotatedTypeInclSelf(AstNode n, TypePath path) {
result = getTypeAnnotation(n).resolveTypeAtInclSelf(path)
}
private class FunctionDecl extends Declaration, Function {
override TypeParam getATypeParam() { result = this.getGenericParamList().getATypeParam() }
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
exists(Param p, int i, boolean inMethod |
paramPos(this.getParamList(), p, i, inMethod) and
dpos = TPositionalDeclarationPosition(i, inMethod) and
result = resolveAnnotatedTypeInclSelf(p.getPat(), path)
)
or
exists(SelfParam self |
self = pragma[only_bind_into](this.getParamList().getSelfParam()) and
dpos.isSelf()
|
// `self` parameter with type annotation
result = resolveAnnotatedTypeInclSelf(self, path)
or
// `self` parameter without type annotation
result = resolveImplicitSelfType(self, path)
or
// `self` parameter without type annotation should also have the special `Self` type
result = getRefAdjustImplicitSelfType(self, TypePath::nil(), TSelfTypeParameter(), path)
)
}
override Type getReturnType(TypePath path) {
result = this.getRetType().getTypeRepr().(TypeReprMention).resolveTypeAtInclSelf(path)
}
}
private predicate argPos(CallExprBase call, Expr e, int pos, boolean isMethodCall) {
exists(ArgList al |
e = al.getArg(pos) and
call.getArgList() = al and
if call instanceof MethodCallExpr then isMethodCall = true else isMethodCall = false
)
}
private newtype TAccessPosition =
TSelfAccessPosition() or
TPositionalAccessPosition(int pos, boolean isMethodCall) { argPos(_, _, pos, isMethodCall) } or
TReturnAccessPosition()
class AccessPosition extends TAccessPosition {
predicate isSelf() { this = TSelfAccessPosition() }
int asPosition(boolean isMethodCall) { this = TPositionalAccessPosition(result, isMethodCall) }
predicate isReturn() { this = TReturnAccessPosition() }
string toString() {
this.isSelf() and
result = "self"
or
result = this.asPosition(_).toString()
or
this.isReturn() and
result = "(return)"
}
}
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
class Access extends CallExprBase {
private TypeReprMention getMethodTypeArg(int i) {
result = this.(MethodCallExpr).getGenericArgList().getTypeArgument(i)
}
Type getExplicitTypeArgument(TypeArgumentPosition apos, TypePath path) {
exists(TypeMention arg | result = arg.resolveTypeAt(path) |
arg = getExplicitTypeArgMention(CallExprImpl::getFunctionPath(this), apos.asTypeParam())
or
arg = this.getMethodTypeArg(apos.asMethodTypeArgumentPosition())
)
}
AstNode getNodeAt(AccessPosition apos) {
exists(int p, boolean isMethodCall |
argPos(this, result, p, isMethodCall) and
apos = TPositionalAccessPosition(p, isMethodCall)
)
or
result = this.(MethodCallExpr).getReceiver() and
apos = TSelfAccessPosition()
or
result = this and
apos = TReturnAccessPosition()
}
Type getResolvedType(AccessPosition apos, TypePath path) {
result = resolveType(this.getNodeAt(apos), path)
}
Declaration getTarget() {
result =
[
CallExprImpl::getResolvedFunction(this).(AstNode),
this.(CallExpr).getStruct(),
this.(CallExpr).getVariant(),
// mutual recursion; resolving method calls requires resolving types and vice versa
resolveMethodCallExpr(this)
]
}
}
predicate accessDeclarationPositionMatch(AccessPosition apos, DeclarationPosition dpos) {
apos.isSelf() and
dpos.isSelf()
or
exists(int pos, boolean isMethodCall | pos = apos.asPosition(isMethodCall) |
pos = 0 and
isMethodCall = false and
dpos.isSelf()
or
isMethodCall = false and
pos = dpos.asPosition(true) + 1
or
pos = dpos.asPosition(isMethodCall)
)
or
apos.isReturn() and
dpos.isReturn()
}
bindingset[apos, target, path, t]
pragma[inline_late]
predicate adjustAccessType(
AccessPosition apos, Declaration target, TypePath path, Type t, TypePath pathAdj, Type tAdj
) {
if apos.isSelf()
then
exists(Type selfParamType |
selfParamType = target.getParameterType(TSelfDeclarationPosition(), TypePath::nil())
|
if selfParamType = TRefType()
then
if t != TRefType() and path.isEmpty()
then
// adjust for implicit borrow
pathAdj.isEmpty() and
tAdj = TRefType()
or
// adjust for implicit borrow
pathAdj = TypePath::singleton(TRefTypeParameter()) and
tAdj = t
else
if path.startsWith(TRefTypeParameter(), _)
then
pathAdj = path and
tAdj = t
else (
// adjust for implicit borrow
not (t = TRefType() and path.isEmpty()) and
pathAdj = TypePath::cons(TRefTypeParameter(), path) and
tAdj = t
)
else (
// adjust for implicit deref
path.startsWith(TRefTypeParameter(), pathAdj) and
tAdj = t
or
not path.startsWith(TRefTypeParameter(), _) and
not (t = TRefType() and path.isEmpty()) and
pathAdj = path and
tAdj = t
)
)
else (
pathAdj = path and
tAdj = t
)
}
pragma[nomagic]
additional Type resolveReceiverType(AstNode n) {
exists(Access a, AccessPosition apos |
result = resolveType(n) and
n = a.getNodeAt(apos) and
apos.isSelf()
)
}
}
private module CallExprBaseMatching = Matching<CallExprBaseMatchingInput>;
/**
* Gets the type of `n` at `path`, where `n` is either a call or an
* argument/receiver of a call.
*/
pragma[nomagic]
private Type resolveCallExprBaseType(AstNode n, TypePath path) {
exists(
CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos,
TypePath path0
|
n = a.getNodeAt(apos) and
result = CallExprBaseMatching::resolveAccessType(a, apos, path0)
|
if apos.isSelf()
then
exists(Type receiverType | receiverType = CallExprBaseMatchingInput::resolveReceiverType(n) |
if receiverType = TRefType()
then
path = path0 and
path0.startsWith(TRefTypeParameter(), _)
or
// adjust for implicit deref
not path0.startsWith(TRefTypeParameter(), _) and
not (path0.isEmpty() and result = TRefType()) and
path = TypePath::cons(TRefTypeParameter(), path0)
else (
not path0.startsWith(TRefTypeParameter(), _) and
not (path0.isEmpty() and result = TRefType()) and
path = path0
or
// adjust for implicit borrow
path0.startsWith(TRefTypeParameter(), path)
)
)
else path = path0
)
}
/**
* A matching configuration for resolving types of field expressions
* like `x.field`.
*/
private module FieldExprMatchingInput implements MatchingInputSig {
private newtype TDeclarationPosition =
TSelfDeclarationPosition() or
TFieldPos()
class DeclarationPosition extends TDeclarationPosition {
predicate isSelf() { this = TSelfDeclarationPosition() }
predicate isField() { this = TFieldPos() }
string toString() {
this.isSelf() and
result = "self"
or
this.isField() and
result = "(field)"
}
}
abstract class Declaration extends AstNode {
TypeParameter getTypeParameter(TypeParameterPosition ppos) { none() }
abstract TypeRepr getTypeRepr();
Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
dpos.isSelf() and
// no case for variants as those can only be destructured using pattern matching
exists(Struct s | s.getRecordField(_) = this or s.getTupleField(_) = this |
result = TStruct(s) and
path.isEmpty()
or
result = TTypeParamTypeParameter(s.getGenericParamList().getATypeParam()) and
path = TypePath::singleton(result)
)
or
dpos.isField() and
result = this.getTypeRepr().(TypeReprMention).resolveTypeAt(path)
}
}
private class RecordFieldDecl extends Declaration instanceof RecordField {
override TypeRepr getTypeRepr() { result = RecordField.super.getTypeRepr() }
}
private class TupleFieldDecl extends Declaration instanceof TupleField {
override TypeRepr getTypeRepr() { result = TupleField.super.getTypeRepr() }
}
class AccessPosition = DeclarationPosition;
class Access extends FieldExpr {
Type getExplicitTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
AstNode getNodeAt(AccessPosition apos) {
result = this.getExpr() and
apos.isSelf()
or
result = this and
apos.isField()
}
Type getResolvedType(AccessPosition apos, TypePath path) {
result = resolveType(this.getNodeAt(apos), path)
}
Declaration getTarget() {
// mutual recursion; resolving fields requires resolving types and vice versa
result = [resolveRecordFieldExpr(this).(AstNode), resolveTupleFieldExpr(this)]
}
}
predicate accessDeclarationPositionMatch(AccessPosition apos, DeclarationPosition dpos) {
apos = dpos
}
bindingset[apos, target, path, t]
pragma[inline_late]
predicate adjustAccessType(
AccessPosition apos, Declaration target, TypePath path, Type t, TypePath pathAdj, Type tAdj
) {
exists(target) and
if apos.isSelf()
then
// adjust for implicit deref
path.startsWith(TRefTypeParameter(), pathAdj) and
tAdj = t
or
not path.startsWith(TRefTypeParameter(), _) and
not (t = TRefType() and path.isEmpty()) and
pathAdj = path and
tAdj = t
else (
pathAdj = path and
tAdj = t
)
}
pragma[nomagic]
additional Type resolveReceiverType(AstNode n) {
exists(Access a, AccessPosition apos |
result = resolveType(n) and
n = a.getNodeAt(apos) and
apos.isSelf()
)
}
}
private module FieldExprMatching = Matching<FieldExprMatchingInput>;
/**
* Gets the type of `n` at `path`, where `n` is either a field expression or
* the receiver of field expression call.
*/
pragma[nomagic]
private Type resolveFieldExprType(AstNode n, TypePath path) {
exists(
FieldExprMatchingInput::Access a, FieldExprMatchingInput::AccessPosition apos, TypePath path0
|
n = a.getNodeAt(apos) and
result = FieldExprMatching::resolveAccessType(a, apos, path0)
|
if apos.isSelf()
then
exists(Type receiverType | receiverType = FieldExprMatchingInput::resolveReceiverType(n) |
if receiverType = TRefType()
then
// adjust for implicit deref
not path0.startsWith(TRefTypeParameter(), _) and
not (path0.isEmpty() and result = TRefType()) and
path = TypePath::cons(TRefTypeParameter(), path0)
else path = path0
)
else path = path0
)
}
/**
* Gets the type of `n` at `path`, where `n` is either a reference expression
* `& x` or an expression `x` inside a reference expression `& x`.
*/
pragma[nomagic]
private Type resolveRefExprType(Expr e, TypePath path) {
exists(RefExpr re |
e = re and
path.isEmpty() and
result = TRefType()
or
e = re and
exists(TypePath exprPath | result = resolveType(re.getExpr(), exprPath) |
if exprPath.startsWith(TRefTypeParameter(), _)
then
// `&x` simply means `x` when `x` already has reference type
path = exprPath
else (
path = TypePath::cons(TRefTypeParameter(), exprPath) and
not (exprPath.isEmpty() and result = TRefType())
)
)
or
e = re.getExpr() and
exists(TypePath exprPath, TypePath refPath, Type exprType |
result = resolveType(re, exprPath) and
exprPath = TypePath::cons(TRefTypeParameter(), refPath) and
exprType = resolveType(e)
|
if exprType = TRefType()
then
// `&x` simply means `x` when `x` already has reference type
path = exprPath
else path = refPath
)
)
}
cached
private module Cached {
private import codeql.rust.internal.CachedStages
pragma[inline]
private Type getLookupType(AstNode n) {
exists(Type t |
t = resolveType(n) and
if t = TRefType()
then
// for reference types, lookup members in the type being referenced
result = resolveType(n, TypePath::singleton(TRefTypeParameter()))
else result = t
)
}
pragma[nomagic]
private Type getMethodCallExprLookupType(MethodCallExpr mce, string name) {
result = getLookupType(mce.getReceiver()) and
name = mce.getNameRef().getText()
}
/**
* Gets a method that the method call `mce` resolves to, if any.
*/
cached
Function resolveMethodCallExpr(MethodCallExpr mce) {
exists(string name | result = getMethodCallExprLookupType(mce, name).getMethod(name))
}
pragma[nomagic]
private Type getFieldExprLookupType(FieldExpr fe, string name) {
result = getLookupType(fe.getExpr()) and
name = fe.getNameRef().getText()
}
/**
* Gets the record field that the field expression `fe` resolves to, if any.
*/
cached
RecordField resolveRecordFieldExpr(FieldExpr fe) {
exists(string name | result = getFieldExprLookupType(fe, name).getRecordField(name))
}
pragma[nomagic]
private Type getTupleFieldExprLookupType(FieldExpr fe, int pos) {
exists(string name |
result = getFieldExprLookupType(fe, name) and
pos = name.toInt()
)
}
/**
* Gets the tuple field that the field expression `fe` resolves to, if any.
*/
cached
TupleField resolveTupleFieldExpr(FieldExpr fe) {
exists(int i | result = getTupleFieldExprLookupType(fe, i).getTupleField(i))
}
/**
* Gets a type at `path` that `n` resolves to, if any.
*
* The type inference implementation works by computing all possible types, so
* the result is not necessarily unique. For example, in
*
* ```rust
* trait MyTrait {
* fn foo(&self) -> &Self;
*
* fn bar(&self) -> &Self {
* self.foo()
* }
* }
*
* struct MyStruct;
*
* impl MyTrait for MyStruct {
* fn foo(&self) -> &MyStruct {
* self
* }
* }
*
* fn baz() {
* let x = MyStruct;
* x.bar();
* }
* ```
*
* the type inference engine will roughly make the following deductions:
*
* 1. `MyStruct` has type `MyStruct`.
* 2. `x` has type `MyStruct` (via 1.).
* 3. The return type of `bar` is `&Self`.
* 3. `x.bar()` has type `&MyStruct` (via 2 and 3, by matching the implicit `Self`
* type parameter with `MyStruct`.).
* 4. The return type of `bar` is `&MyTrait`.
* 5. `x.bar()` has type `&MyTrait` (via 2 and 4).
*/
cached
Type resolveType(AstNode n, TypePath path) {
Stages::TypeInference::backref() and
result = resolveAnnotatedType(n, path)
or
result = resolveTypeSymmetry(n, path)
or
result = resolveImplicitSelfType(n, path)
or
result = resolveRecordExprType(n, path)
or
result = resolvePathExprType(n, path)
or
result = resolveCallExprBaseType(n, path)
or
result = resolveFieldExprType(n, path)
or
result = resolveRefExprType(n, path)
}
}
import Cached
/**
* Gets a type that `n` resolves to, if any.
*/
Type resolveType(AstNode n) { result = resolveType(n, TypePath::nil()) }

View File

@@ -0,0 +1,173 @@
/** Provides classes for representing type mentions, used in type inference. */
private import rust
private import Type
private import PathResolution
private import TypeInference
/** An AST node that may mention a type. */
abstract class TypeMention extends AstNode {
/** Gets the `i`th type argument mention, if any. */
abstract TypeMention getTypeArgument(int i);
/** Gets the type that this node resolves to, if any. */
abstract Type resolveType();
/** Gets the sub mention at `path`. */
pragma[nomagic]
private TypeMention getMentionAt(TypePath path) {
path.isEmpty() and
result = this
or
exists(int i, TypeParameter tp, TypeMention arg, TypePath suffix |
arg = this.getTypeArgument(pragma[only_bind_into](i)) and
result = arg.getMentionAt(suffix) and
path = TypePath::cons(tp, suffix) and
tp = this.resolveType().getTypeParameter(pragma[only_bind_into](i))
)
}
/** Gets the type that the sub mention at `path` resolves to, if any. */
Type resolveTypeAt(TypePath path) { result = this.getMentionAt(path).resolveType() }
/**
* Like `resolveTypeAt`, but also resolves `Self` mentions to the implicit
* `Self` type parameter.
*
* This is only needed when resolving types for calls to methods; inside the
* methods themselves, `Self` only resolves to the relevant trait or type
* being implemented.
*/
final Type resolveTypeAtInclSelf(TypePath path) {
result = this.resolveTypeAt(path)
or
exists(TypeMention tm, ImplOrTraitItemNode node |
tm = this.getMentionAt(path) and
result = TSelfTypeParameter()
|
tm = node.getASelfPath()
or
tm.(PathTypeRepr).getPath() = node.getASelfPath()
)
}
}
class TypeReprMention extends TypeMention, TypeRepr {
TypeReprMention() { not this instanceof InferTypeRepr }
override TypeReprMention getTypeArgument(int i) {
result = this.(ArrayTypeRepr).getElementTypeRepr() and
i = 0
or
result = this.(RefTypeRepr).getTypeRepr() and
i = 0
or
result = this.(PathTypeRepr).getPath().(PathMention).getTypeArgument(i)
}
override Type resolveType() {
this instanceof ArrayTypeRepr and
result = TArrayType()
or
this instanceof RefTypeRepr and
result = TRefType()
or
result = this.(PathTypeRepr).getPath().(PathMention).resolveType()
}
}
class PathMention extends TypeMention, Path {
override TypeMention getTypeArgument(int i) {
result = this.getPart().getGenericArgList().getTypeArgument(i)
or
// `Self` paths inside traits and `impl` blocks have implicit type arguments
// that are the type parameters of the trait or impl. For example, in
//
// ```rust
// impl Foo<T> {
// fn m(self) -> Self {
// self
// }
// }
// ```
//
// the `Self` return type is shorthand for `Foo<T>`.
exists(ImplOrTraitItemNode node | this = node.getASelfPath() |
result = node.(ImplItemNode).getSelfPath().getPart().getGenericArgList().getTypeArgument(i)
or
result = node.(Trait).getGenericParamList().getTypeParam(i)
)
}
override Type resolveType() {
exists(ItemNode i | i = resolvePath(this) |
result = TStruct(i)
or
result = TEnum(i)
or
result = TTrait(i)
or
result = TTypeParamTypeParameter(i)
or
result = i.(TypeAlias).getTypeRepr().(TypeReprMention).resolveType()
)
}
}
// Used to represent implicit `Self` type arguments in traits and `impl` blocks,
// see `PathMention` for details.
class TypeParamMention extends TypeMention, TypeParam {
override TypeReprMention getTypeArgument(int i) { none() }
override Type resolveType() { result = TTypeParamTypeParameter(this) }
}
/**
* Holds if the `i`th type argument of `selfPath`, belonging to `impl`, resolves
* to type parameter `tp`.
*
* Example:
*
* ```rust
* impl<T> Foo<T> for Bar<T> { ... }
* // ^^^^^^ selfPath
* // ^ tp
* ```
*/
pragma[nomagic]
private predicate isImplSelfTypeParam(
ImplItemNode impl, PathMention selfPath, int i, TypeParameter tp
) {
exists(PathMention path |
selfPath = impl.getSelfPath() and
path = selfPath.getPart().getGenericArgList().getTypeArgument(i).(PathTypeRepr).getPath() and
tp = path.resolveType()
)
}
class ImplMention extends TypeMention, ImplItemNode {
override TypeReprMention getTypeArgument(int i) { none() }
override Type resolveType() { result = TImpl(this) }
override Type resolveTypeAt(TypePath path) {
result = TImpl(this) and
path.isEmpty()
or
// For example, in
//
// ```rust
// struct S<T1>(T1);
//
// impl<T2> S<T2> { ... }
// ```
//
// We get that the type path "0" resolves to `T1` for the `impl` block,
// which is considered a base type mention of `S`.
exists(PathMention selfPath, TypeParameter tp, int i |
isImplSelfTypeParam(this, selfPath, pragma[only_bind_into](i), tp) and
result = selfPath.resolveType().getTypeParameter(pragma[only_bind_into](i)) and
path = TypePath::singleton(tp)
)
}
}

View File

@@ -11,6 +11,8 @@ private import codeql.rust.elements.internal.generated.TypeParam
* be referenced directly.
*/
module Impl {
private import rust
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A TypeParam. For example:
@@ -19,6 +21,9 @@ module Impl {
* ```
*/
class TypeParam extends Generated::TypeParam {
/** Gets the position of this type parameter. */
int getPosition() { this = any(GenericParamList l).getTypeParam(result) }
override string toAbbreviatedString() { result = this.getName().getText() }
override string toString() { result = this.getName().getText() }

View File

@@ -32,5 +32,20 @@ module Impl {
/** Gets the `i`th tuple field, if any. */
pragma[nomagic]
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
/** Holds if this variant uses tuple fields. */
pragma[nomagic]
predicate isTuple() { this.getFieldList() instanceof TupleFieldList }
/**
* Holds if this variant uses record fields.
*
* Empty variants are considered to use record fields.
*/
pragma[nomagic]
predicate isRecord() { not this.isTuple() }
/** Gets the enum that this variant belongs to. */
Enum getEnum() { this = result.getVariantList().getAVariant() }
}
}

View File

@@ -95,6 +95,36 @@ module Stages {
}
}
/**
* The type inference stage.
*/
cached
module TypeInference {
private import codeql.rust.elements.internal.Type
private import codeql.rust.elements.internal.TypeInference
/**
* Always holds.
* Ensures that a predicate is evaluated as part of the CFG stage.
*/
cached
predicate ref() { 1 = 1 }
/**
* DO NOT USE!
*
* Contains references to each predicate that use the above `ref` predicate.
*/
cached
predicate backref() {
1 = 1
or
exists(Type t)
or
exists(resolveType(_))
}
}
/**
* The data flow stage.
*/

View File

@@ -12,6 +12,7 @@ dependencies:
codeql/mad: ${workspace}
codeql/ssa: ${workspace}
codeql/tutorial: ${workspace}
codeql/typeinference: ${workspace}
codeql/util: ${workspace}
dataExtensions:
- /**/*.model.yml

View File

@@ -1 +1 @@
| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:14:10:30 | GenericParamList |
| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:14:10:30 | <...> |

View File

@@ -4,7 +4,7 @@
| utf8_identifiers.rs:1:1:4:6 | fn foo |
| utf8_identifiers.rs:1:1:12:2 | SourceFile |
| utf8_identifiers.rs:1:4:1:6 | foo |
| utf8_identifiers.rs:1:7:4:1 | GenericParamList |
| utf8_identifiers.rs:1:7:4:1 | <...> |
| utf8_identifiers.rs:2:5:2:6 | ''\u03b2 |
| utf8_identifiers.rs:2:5:2:6 | LifetimeParam |
| utf8_identifiers.rs:3:5:3:5 | \u03b3 |

View File

@@ -0,0 +1,5 @@
multiplePathResolutions
| main.rs:385:34:385:34 | S | main.rs:384:19:384:19 | S |
| main.rs:385:34:385:34 | S | main.rs:411:5:412:13 | struct S |
| main.rs:387:39:387:39 | S | main.rs:384:19:384:19 | S |
| main.rs:387:39:387:39 | S | main.rs:411:5:412:13 | struct S |

View File

@@ -0,0 +1,574 @@
mod m1 {
pub struct Foo {}
impl Foo {
pub fn m1(self) -> Self {
self
}
pub fn m2(self) -> Foo {
self
}
}
pub fn f() -> Foo {
println!("main.rs::m1::f");
let x = Foo {};
let y: _ = Foo {};
x
}
pub fn g(x: Foo, y: Foo) -> Foo {
println!("main.rs::m1::g");
x.m1();
y.m2()
}
}
mod m2 {
#[derive(Debug)]
struct MyThing<A> {
a: A,
}
#[derive(Debug)]
struct S1;
#[derive(Debug)]
struct S2;
impl MyThing<S1> {
fn m1(self) -> S1 {
self.a
}
}
impl MyThing<S2> {
fn m1(self) -> Self {
Self { a: self.a }
}
}
impl<T> MyThing<T> {
fn m2(self) -> T {
self.a
}
}
pub fn f() {
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", x.m1()); // missing call target
println!("{:?}", y.m1().a); // missing call target
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", x.m2());
println!("{:?}", y.m2());
}
}
mod m3 {
#[derive(Debug)]
struct MyThing<A> {
a: A,
}
#[derive(Debug)]
struct S1;
#[derive(Debug)]
struct S2;
trait MyTrait<A> {
fn m1(self) -> A;
fn m2(self) -> Self
where
Self: Sized,
{
self
}
}
fn call_trait_m1<T1, T2: MyTrait<T1>>(x: T2) -> T1 {
x.m1()
}
impl MyTrait<S1> for MyThing<S1> {
fn m1(self) -> S1 {
self.a
}
}
impl MyTrait<Self> for MyThing<S2> {
fn m1(self) -> Self {
Self { a: self.a }
}
}
pub fn f() {
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", x.m1()); // missing call target
println!("{:?}", y.m1().a); // missing call target
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", call_trait_m1(x)); // missing
println!("{:?}", call_trait_m1(y).a); // missing
}
}
mod m4 {
#[derive(Debug)]
struct MyThing<A> {
a: A,
}
#[derive(Debug)]
struct S1;
#[derive(Debug)]
struct S2;
trait MyTrait<A> {
fn m1(self) -> A;
fn m2(self) -> A
where
Self: Sized,
{
self.m1()
}
}
fn call_trait_m1<T1, T2: MyTrait<T1>>(x: T2) -> T1 {
x.m1()
}
impl<T> MyTrait<T> for MyThing<T> {
fn m1(self) -> T {
self.a
}
}
pub fn f() {
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", x.m1());
println!("{:?}", y.m1());
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", x.m2());
println!("{:?}", y.m2());
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", call_trait_m1(x)); // missing
println!("{:?}", call_trait_m1(y)); // missing
}
}
mod m5 {
trait MyTrait {
type AssociatedType;
fn m1(self) -> Self::AssociatedType;
fn m2(self) -> Self::AssociatedType
where
Self::AssociatedType: Default,
Self: Sized,
{
Self::AssociatedType::default()
}
}
#[derive(Debug, Default)]
struct S;
impl MyTrait for S {
type AssociatedType = S;
fn m1(self) -> Self::AssociatedType {
S
}
}
pub fn f() {
let x = S;
println!("{:?}", x.m1());
let x = S;
println!("{:?}", x.m2()); // missing
}
}
mod m6 {
#[derive(Debug)]
enum MyEnum<A> {
C1(A),
C2 { a: A },
}
#[derive(Debug)]
struct S1;
#[derive(Debug)]
struct S2;
impl<T> MyEnum<T> {
fn m1(self) -> T {
match self {
MyEnum::C1(a) => a, // missing
MyEnum::C2 { a } => a, // missing
}
}
}
pub fn f() {
let x = MyEnum::C1(S1);
let y = MyEnum::C2 { a: S2 };
println!("{:?}", x.m1());
println!("{:?}", y.m1());
}
}
mod m7 {
#[derive(Debug)]
struct MyThing<A> {
a: A,
}
#[derive(Debug)]
struct MyThing2<A> {
a: A,
}
#[derive(Debug)]
struct S1;
#[derive(Debug)]
struct S2;
trait MyTrait1<A> {
fn m1(self) -> A;
}
trait MyTrait2<A>: MyTrait1<A> {
fn m2(self) -> A
where
Self: Sized,
{
if 1 + 1 > 2 {
self.m1()
} else {
Self::m1(self)
}
}
}
trait MyTrait3<A>: MyTrait2<MyThing<A>> {
fn m3(self) -> A
where
Self: Sized,
{
if 1 + 1 > 2 {
self.m2().a
} else {
Self::m2(self).a
}
}
}
impl<T> MyTrait1<T> for MyThing<T> {
fn m1(self) -> T {
self.a
}
}
impl<T> MyTrait2<T> for MyThing<T> {}
impl<T> MyTrait1<MyThing<T>> for MyThing2<T> {
fn m1(self) -> MyThing<T> {
MyThing { a: self.a }
}
}
impl<T> MyTrait2<MyThing<T>> for MyThing2<T> {}
impl<T> MyTrait3<T> for MyThing2<T> {}
pub fn f() {
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", x.m1());
println!("{:?}", y.m1());
let x = MyThing { a: S1 };
let y = MyThing { a: S2 };
println!("{:?}", x.m2());
println!("{:?}", y.m2());
let x = MyThing2 { a: S1 };
let y = MyThing2 { a: S2 };
println!("{:?}", x.m3());
println!("{:?}", y.m3());
}
}
mod m8 {
use std::convert::From;
use std::fmt::Debug;
#[derive(Debug)]
struct S1;
#[derive(Debug)]
struct S2;
trait Trait: Debug {}
impl Trait for S1 {}
fn id<T: ?Sized>(x: &T) -> &T {
x
}
impl Into<S2> for S1 {
fn into(self) -> S2 {
S2
}
}
fn into<T1, T2>(x: T1) -> T2
where
T1: Into<T2>,
{
x.into()
}
pub fn f() {
let x = S1;
println!("{:?}", id(&x));
let x = S1;
println!("{:?}", id::<S1>(&x));
let x = S1;
println!("{:?}", id::<dyn Trait>(&x)); // incorrectly has type `S1` instead of `Trait`
let x = S1;
into::<S1, S2>(x);
let x = S1;
let y: S2 = into(x);
}
}
mod m9 {
#[derive(Debug)]
enum MyOption<T> {
MyNone(),
MySome(T),
}
trait MyTrait<S> {
fn set(&mut self, value: S);
fn call_set(&mut self, value: S) {
self.set(value);
}
}
impl<T> MyTrait<T> for MyOption<T> {
fn set(&mut self, value: T) {}
}
impl<T> MyOption<T> {
fn new() -> Self {
MyOption::MyNone()
}
}
impl<T> MyOption<MyOption<T>> {
fn flatten(self) -> MyOption<T> {
match self {
MyOption::MyNone() => MyOption::MyNone(), // missing inner type `Option<T>`
MyOption::MySome(x) => x, // missing
}
}
}
#[derive(Debug)]
struct S;
pub fn f() {
let x1 = MyOption::<S>::new(); // `::new` missing type `S`
println!("{:?}", x1);
let mut x2 = MyOption::new();
x2.set(S);
println!("{:?}", x2);
let mut x3 = MyOption::new(); // missing type `S` from `MyOption<S>` (but can resolve `MyTrait<S>`)
x3.call_set(S);
println!("{:?}", x3);
let mut x4 = MyOption::new();
MyOption::set(&mut x4, S);
println!("{:?}", x4);
let x5 = MyOption::MySome(MyOption::<S>::MyNone());
println!("{:?}", x5.flatten()); // missing call target
let x6 = MyOption::MySome(MyOption::<S>::MyNone());
println!("{:?}", MyOption::<MyOption<S>>::flatten(x6));
}
}
mod m10 {
#[derive(Debug, Copy, Clone)]
struct S<T>(T);
#[derive(Debug, Copy, Clone)]
struct S2;
impl<T> S<T> {
fn m1(self) -> T {
self.0
}
fn m2(&self) -> &T {
&self.0
}
fn m3(self: &S<T>) -> &T {
&self.0
}
}
pub fn f() {
let x1 = S(S2);
println!("{:?}", x1.m1());
let x2 = S(S2);
// implicit borrow
println!("{:?}", x2.m2());
println!("{:?}", x2.m3());
let x3 = S(S2);
// explicit borrow
println!("{:?}", S::<S2>::m2(&x3));
println!("{:?}", S::<S2>::m3(&x3));
let x4 = &S(S2);
// explicit borrow
println!("{:?}", x4.m2());
println!("{:?}", x4.m3());
let x5 = &S(S2);
// implicit dereference
println!("{:?}", x5.m1());
println!("{:?}", x5.0);
let x6 = &S(S2);
// explicit dereference
println!("{:?}", (*x6).m1());
}
}
mod m11 {
trait MyTrait {
fn foo(&self) -> &Self;
fn bar(&self) -> &Self {
self.foo()
}
}
struct MyStruct;
impl MyTrait for MyStruct {
fn foo(&self) -> &MyStruct {
self
}
}
pub fn f() {
let x = MyStruct;
x.bar();
}
}
mod m12 {
struct S;
struct MyStruct<T>(T);
impl<T> MyStruct<T> {
fn foo(&self) -> &Self {
self
}
}
pub fn f() {
let x = MyStruct(S);
x.foo();
}
}
mod m13 {
struct S;
impl S {
fn f1(&self) -> &Self {
&&&self
}
fn f2(self: &Self) -> &Self {
&&&self
}
fn f3(x: &Self) -> &Self {
x
}
fn f4(x: &Self) -> &Self {
&&&x
}
}
pub fn f() {
let x = S;
x.f1();
x.f2();
S::f3(&x);
}
}
fn main() {
m1::f();
m1::g(m1::Foo {}, m1::Foo {});
m2::f();
m3::f();
m4::f();
m5::f();
m6::f();
m7::f();
m8::f();
m9::f();
m10::f();
m11::f();
m12::f();
m13::f();
}

View File

@@ -0,0 +1,797 @@
resolveType
| main.rs:5:19:5:22 | SelfParam | | main.rs:2:5:2:21 | struct Foo |
| main.rs:5:33:7:9 | { ... } | | main.rs:2:5:2:21 | struct Foo |
| main.rs:6:13:6:16 | self | | main.rs:2:5:2:21 | struct Foo |
| main.rs:9:19:9:22 | SelfParam | | main.rs:2:5:2:21 | struct Foo |
| main.rs:9:32:11:9 | { ... } | | main.rs:2:5:2:21 | struct Foo |
| main.rs:10:13:10:16 | self | | main.rs:2:5:2:21 | struct Foo |
| main.rs:14:23:19:5 | { ... } | | main.rs:2:5:2:21 | struct Foo |
| main.rs:16:13:16:13 | x | | main.rs:2:5:2:21 | struct Foo |
| main.rs:16:17:16:22 | Foo {...} | | main.rs:2:5:2:21 | struct Foo |
| main.rs:17:13:17:13 | y | | main.rs:2:5:2:21 | struct Foo |
| main.rs:17:20:17:25 | Foo {...} | | main.rs:2:5:2:21 | struct Foo |
| main.rs:18:9:18:9 | x | | main.rs:2:5:2:21 | struct Foo |
| main.rs:21:14:21:14 | x | | main.rs:2:5:2:21 | struct Foo |
| main.rs:21:22:21:22 | y | | main.rs:2:5:2:21 | struct Foo |
| main.rs:21:37:25:5 | { ... } | | main.rs:2:5:2:21 | struct Foo |
| main.rs:23:9:23:9 | x | | main.rs:2:5:2:21 | struct Foo |
| main.rs:23:9:23:14 | x.m1(...) | | main.rs:2:5:2:21 | struct Foo |
| main.rs:24:9:24:9 | y | | main.rs:2:5:2:21 | struct Foo |
| main.rs:24:9:24:14 | y.m2(...) | | main.rs:2:5:2:21 | struct Foo |
| main.rs:40:15:40:18 | SelfParam | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:40:15:40:18 | SelfParam | A | main.rs:34:5:35:14 | struct S1 |
| main.rs:40:27:42:9 | { ... } | | main.rs:34:5:35:14 | struct S1 |
| main.rs:41:13:41:16 | self | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:41:13:41:16 | self | A | main.rs:34:5:35:14 | struct S1 |
| main.rs:41:13:41:18 | self.a | | main.rs:34:5:35:14 | struct S1 |
| main.rs:46:15:46:18 | SelfParam | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:46:15:46:18 | SelfParam | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:46:29:48:9 | { ... } | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:46:29:48:9 | { ... } | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:47:13:47:30 | Self {...} | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:47:13:47:30 | Self {...} | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:47:23:47:26 | self | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:47:23:47:26 | self | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:47:23:47:28 | self.a | | main.rs:36:5:37:14 | struct S2 |
| main.rs:52:15:52:18 | SelfParam | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:52:15:52:18 | SelfParam | A | main.rs:51:10:51:10 | T |
| main.rs:52:26:54:9 | { ... } | | main.rs:51:10:51:10 | T |
| main.rs:53:13:53:16 | self | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:53:13:53:16 | self | A | main.rs:51:10:51:10 | T |
| main.rs:53:13:53:18 | self.a | | main.rs:51:10:51:10 | T |
| main.rs:58:13:58:13 | x | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:58:13:58:13 | x | A | main.rs:34:5:35:14 | struct S1 |
| main.rs:58:17:58:33 | MyThing {...} | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:58:17:58:33 | MyThing {...} | A | main.rs:34:5:35:14 | struct S1 |
| main.rs:58:30:58:31 | S1 | | main.rs:34:5:35:14 | struct S1 |
| main.rs:59:13:59:13 | y | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:59:13:59:13 | y | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:59:17:59:33 | MyThing {...} | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:59:17:59:33 | MyThing {...} | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:59:30:59:31 | S2 | | main.rs:36:5:37:14 | struct S2 |
| main.rs:61:26:61:26 | x | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:61:26:61:26 | x | A | main.rs:34:5:35:14 | struct S1 |
| main.rs:62:26:62:26 | y | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:62:26:62:26 | y | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:64:13:64:13 | x | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:64:13:64:13 | x | A | main.rs:34:5:35:14 | struct S1 |
| main.rs:64:17:64:33 | MyThing {...} | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:64:17:64:33 | MyThing {...} | A | main.rs:34:5:35:14 | struct S1 |
| main.rs:64:30:64:31 | S1 | | main.rs:34:5:35:14 | struct S1 |
| main.rs:65:13:65:13 | y | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:65:13:65:13 | y | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:65:17:65:33 | MyThing {...} | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:65:17:65:33 | MyThing {...} | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:65:30:65:31 | S2 | | main.rs:36:5:37:14 | struct S2 |
| main.rs:67:26:67:26 | x | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:67:26:67:26 | x | A | main.rs:34:5:35:14 | struct S1 |
| main.rs:67:26:67:31 | x.m2(...) | | main.rs:34:5:35:14 | struct S1 |
| main.rs:68:26:68:26 | y | | main.rs:29:5:32:5 | struct MyThing |
| main.rs:68:26:68:26 | y | A | main.rs:36:5:37:14 | struct S2 |
| main.rs:68:26:68:31 | y.m2(...) | | main.rs:36:5:37:14 | struct S2 |
| main.rs:84:15:84:18 | SelfParam | | main.rs:83:5:92:5 | trait MyTrait |
| main.rs:84:15:84:18 | SelfParam | A | main.rs:83:19:83:19 | A |
| main.rs:86:15:86:18 | SelfParam | | main.rs:83:5:92:5 | trait MyTrait |
| main.rs:86:15:86:18 | SelfParam | A | main.rs:83:19:83:19 | A |
| main.rs:89:9:91:9 | { ... } | | main.rs:83:5:92:5 | trait MyTrait |
| main.rs:89:9:91:9 | { ... } | A | main.rs:83:19:83:19 | A |
| main.rs:90:13:90:16 | self | | main.rs:83:5:92:5 | trait MyTrait |
| main.rs:90:13:90:16 | self | A | main.rs:83:19:83:19 | A |
| main.rs:94:43:94:43 | x | | main.rs:83:5:92:5 | trait MyTrait |
| main.rs:94:43:94:43 | x | | main.rs:94:26:94:40 | T2 |
| main.rs:94:43:94:43 | x | A | main.rs:94:22:94:23 | T1 |
| main.rs:94:56:96:5 | { ... } | | main.rs:94:22:94:23 | T1 |
| main.rs:95:9:95:9 | x | | main.rs:83:5:92:5 | trait MyTrait |
| main.rs:95:9:95:9 | x | | main.rs:94:26:94:40 | T2 |
| main.rs:95:9:95:9 | x | A | main.rs:94:22:94:23 | T1 |
| main.rs:95:9:95:14 | x.m1(...) | | main.rs:94:22:94:23 | T1 |
| main.rs:99:15:99:18 | SelfParam | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:99:15:99:18 | SelfParam | A | main.rs:78:5:79:14 | struct S1 |
| main.rs:99:27:101:9 | { ... } | | main.rs:78:5:79:14 | struct S1 |
| main.rs:100:13:100:16 | self | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:100:13:100:16 | self | A | main.rs:78:5:79:14 | struct S1 |
| main.rs:100:13:100:18 | self.a | | main.rs:78:5:79:14 | struct S1 |
| main.rs:105:15:105:18 | SelfParam | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:105:15:105:18 | SelfParam | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:105:29:107:9 | { ... } | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:105:29:107:9 | { ... } | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:106:13:106:30 | Self {...} | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:106:13:106:30 | Self {...} | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:106:23:106:26 | self | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:106:23:106:26 | self | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:106:23:106:28 | self.a | | main.rs:80:5:81:14 | struct S2 |
| main.rs:111:13:111:13 | x | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:111:13:111:13 | x | A | main.rs:78:5:79:14 | struct S1 |
| main.rs:111:17:111:33 | MyThing {...} | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:111:17:111:33 | MyThing {...} | A | main.rs:78:5:79:14 | struct S1 |
| main.rs:111:30:111:31 | S1 | | main.rs:78:5:79:14 | struct S1 |
| main.rs:112:13:112:13 | y | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:112:13:112:13 | y | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:112:17:112:33 | MyThing {...} | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:112:17:112:33 | MyThing {...} | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:112:30:112:31 | S2 | | main.rs:80:5:81:14 | struct S2 |
| main.rs:114:26:114:26 | x | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:114:26:114:26 | x | A | main.rs:78:5:79:14 | struct S1 |
| main.rs:115:26:115:26 | y | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:115:26:115:26 | y | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:117:13:117:13 | x | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:117:13:117:13 | x | A | main.rs:78:5:79:14 | struct S1 |
| main.rs:117:17:117:33 | MyThing {...} | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:117:17:117:33 | MyThing {...} | A | main.rs:78:5:79:14 | struct S1 |
| main.rs:117:30:117:31 | S1 | | main.rs:78:5:79:14 | struct S1 |
| main.rs:118:13:118:13 | y | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:118:13:118:13 | y | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:118:17:118:33 | MyThing {...} | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:118:17:118:33 | MyThing {...} | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:118:30:118:31 | S2 | | main.rs:80:5:81:14 | struct S2 |
| main.rs:120:40:120:40 | x | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:120:40:120:40 | x | A | main.rs:78:5:79:14 | struct S1 |
| main.rs:121:40:121:40 | y | | main.rs:73:5:76:5 | struct MyThing |
| main.rs:121:40:121:40 | y | A | main.rs:80:5:81:14 | struct S2 |
| main.rs:137:15:137:18 | SelfParam | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:137:15:137:18 | SelfParam | A | main.rs:136:19:136:19 | A |
| main.rs:139:15:139:18 | SelfParam | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:139:15:139:18 | SelfParam | A | main.rs:136:19:136:19 | A |
| main.rs:142:9:144:9 | { ... } | | main.rs:136:19:136:19 | A |
| main.rs:143:13:143:16 | self | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:143:13:143:16 | self | A | main.rs:136:19:136:19 | A |
| main.rs:143:13:143:21 | self.m1(...) | | main.rs:136:19:136:19 | A |
| main.rs:147:43:147:43 | x | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:147:43:147:43 | x | | main.rs:147:26:147:40 | T2 |
| main.rs:147:43:147:43 | x | A | main.rs:147:22:147:23 | T1 |
| main.rs:147:56:149:5 | { ... } | | main.rs:147:22:147:23 | T1 |
| main.rs:148:9:148:9 | x | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:148:9:148:9 | x | | main.rs:147:26:147:40 | T2 |
| main.rs:148:9:148:9 | x | A | main.rs:147:22:147:23 | T1 |
| main.rs:148:9:148:14 | x.m1(...) | | main.rs:147:22:147:23 | T1 |
| main.rs:152:15:152:18 | SelfParam | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:152:15:152:18 | SelfParam | A | main.rs:151:10:151:10 | T |
| main.rs:152:26:154:9 | { ... } | | main.rs:151:10:151:10 | T |
| main.rs:153:13:153:16 | self | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:153:13:153:16 | self | A | main.rs:151:10:151:10 | T |
| main.rs:153:13:153:18 | self.a | | main.rs:151:10:151:10 | T |
| main.rs:158:13:158:13 | x | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:158:13:158:13 | x | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:158:17:158:33 | MyThing {...} | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:158:17:158:33 | MyThing {...} | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:158:30:158:31 | S1 | | main.rs:131:5:132:14 | struct S1 |
| main.rs:159:13:159:13 | y | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:159:13:159:13 | y | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:159:17:159:33 | MyThing {...} | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:159:17:159:33 | MyThing {...} | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:159:30:159:31 | S2 | | main.rs:133:5:134:14 | struct S2 |
| main.rs:161:26:161:26 | x | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:161:26:161:26 | x | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:161:26:161:31 | x.m1(...) | | main.rs:131:5:132:14 | struct S1 |
| main.rs:162:26:162:26 | y | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:162:26:162:26 | y | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:162:26:162:31 | y.m1(...) | | main.rs:133:5:134:14 | struct S2 |
| main.rs:164:13:164:13 | x | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:164:13:164:13 | x | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:164:13:164:13 | x | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:164:13:164:13 | x | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:164:17:164:33 | MyThing {...} | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:164:17:164:33 | MyThing {...} | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:164:17:164:33 | MyThing {...} | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:164:17:164:33 | MyThing {...} | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:164:30:164:31 | S1 | | main.rs:131:5:132:14 | struct S1 |
| main.rs:165:13:165:13 | y | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:165:13:165:13 | y | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:165:13:165:13 | y | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:165:13:165:13 | y | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:165:17:165:33 | MyThing {...} | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:165:17:165:33 | MyThing {...} | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:165:17:165:33 | MyThing {...} | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:165:17:165:33 | MyThing {...} | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:165:30:165:31 | S2 | | main.rs:133:5:134:14 | struct S2 |
| main.rs:167:26:167:26 | x | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:167:26:167:26 | x | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:167:26:167:26 | x | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:167:26:167:26 | x | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:167:26:167:31 | x.m2(...) | | main.rs:131:5:132:14 | struct S1 |
| main.rs:168:26:168:26 | y | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:168:26:168:26 | y | | main.rs:136:5:145:5 | trait MyTrait |
| main.rs:168:26:168:26 | y | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:168:26:168:26 | y | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:168:26:168:31 | y.m2(...) | | main.rs:133:5:134:14 | struct S2 |
| main.rs:170:13:170:13 | x | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:170:13:170:13 | x | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:170:17:170:33 | MyThing {...} | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:170:17:170:33 | MyThing {...} | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:170:30:170:31 | S1 | | main.rs:131:5:132:14 | struct S1 |
| main.rs:171:13:171:13 | y | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:171:13:171:13 | y | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:171:17:171:33 | MyThing {...} | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:171:17:171:33 | MyThing {...} | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:171:30:171:31 | S2 | | main.rs:133:5:134:14 | struct S2 |
| main.rs:173:40:173:40 | x | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:173:40:173:40 | x | A | main.rs:131:5:132:14 | struct S1 |
| main.rs:174:40:174:40 | y | | main.rs:126:5:129:5 | struct MyThing |
| main.rs:174:40:174:40 | y | A | main.rs:133:5:134:14 | struct S2 |
| main.rs:182:15:182:18 | SelfParam | | main.rs:179:5:191:5 | trait MyTrait |
| main.rs:184:15:184:18 | SelfParam | | main.rs:179:5:191:5 | trait MyTrait |
| main.rs:199:15:199:18 | SelfParam | | main.rs:193:5:194:13 | struct S |
| main.rs:199:45:201:9 | { ... } | | main.rs:193:5:194:13 | struct S |
| main.rs:200:13:200:13 | S | | main.rs:193:5:194:13 | struct S |
| main.rs:205:13:205:13 | x | | main.rs:193:5:194:13 | struct S |
| main.rs:205:17:205:17 | S | | main.rs:193:5:194:13 | struct S |
| main.rs:206:26:206:26 | x | | main.rs:193:5:194:13 | struct S |
| main.rs:206:26:206:31 | x.m1(...) | | main.rs:193:5:194:13 | struct S |
| main.rs:208:13:208:13 | x | | main.rs:179:5:191:5 | trait MyTrait |
| main.rs:208:13:208:13 | x | | main.rs:193:5:194:13 | struct S |
| main.rs:208:17:208:17 | S | | main.rs:179:5:191:5 | trait MyTrait |
| main.rs:208:17:208:17 | S | | main.rs:193:5:194:13 | struct S |
| main.rs:209:26:209:26 | x | | main.rs:179:5:191:5 | trait MyTrait |
| main.rs:209:26:209:26 | x | | main.rs:193:5:194:13 | struct S |
| main.rs:226:15:226:18 | SelfParam | | main.rs:214:5:218:5 | enum MyEnum |
| main.rs:226:15:226:18 | SelfParam | A | main.rs:225:10:225:10 | T |
| main.rs:226:26:231:9 | { ... } | | main.rs:225:10:225:10 | T |
| main.rs:227:13:230:13 | match self { ... } | | main.rs:225:10:225:10 | T |
| main.rs:227:19:227:22 | self | | main.rs:214:5:218:5 | enum MyEnum |
| main.rs:227:19:227:22 | self | A | main.rs:225:10:225:10 | T |
| main.rs:235:13:235:13 | x | | main.rs:214:5:218:5 | enum MyEnum |
| main.rs:235:13:235:13 | x | A | main.rs:220:5:221:14 | struct S1 |
| main.rs:235:17:235:30 | ...::C1(...) | | main.rs:214:5:218:5 | enum MyEnum |
| main.rs:235:17:235:30 | ...::C1(...) | A | main.rs:220:5:221:14 | struct S1 |
| main.rs:235:28:235:29 | S1 | | main.rs:220:5:221:14 | struct S1 |
| main.rs:236:13:236:13 | y | | main.rs:214:5:218:5 | enum MyEnum |
| main.rs:236:13:236:13 | y | A | main.rs:222:5:223:14 | struct S2 |
| main.rs:236:17:236:36 | ...::C2 {...} | | main.rs:214:5:218:5 | enum MyEnum |
| main.rs:236:17:236:36 | ...::C2 {...} | A | main.rs:222:5:223:14 | struct S2 |
| main.rs:236:33:236:34 | S2 | | main.rs:222:5:223:14 | struct S2 |
| main.rs:238:26:238:26 | x | | main.rs:214:5:218:5 | enum MyEnum |
| main.rs:238:26:238:26 | x | A | main.rs:220:5:221:14 | struct S1 |
| main.rs:238:26:238:31 | x.m1(...) | | main.rs:220:5:221:14 | struct S1 |
| main.rs:239:26:239:26 | y | | main.rs:214:5:218:5 | enum MyEnum |
| main.rs:239:26:239:26 | y | A | main.rs:222:5:223:14 | struct S2 |
| main.rs:239:26:239:31 | y.m1(...) | | main.rs:222:5:223:14 | struct S2 |
| main.rs:260:15:260:18 | SelfParam | | main.rs:259:5:261:5 | trait MyTrait1 |
| main.rs:260:15:260:18 | SelfParam | A | main.rs:259:20:259:20 | A |
| main.rs:264:15:264:18 | SelfParam | | main.rs:259:5:261:5 | trait MyTrait1 |
| main.rs:264:15:264:18 | SelfParam | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:264:15:264:18 | SelfParam | A | main.rs:263:20:263:20 | A |
| main.rs:264:15:264:18 | SelfParam | A | main.rs:263:20:263:20 | A |
| main.rs:267:9:273:9 | { ... } | | main.rs:263:20:263:20 | A |
| main.rs:268:13:272:13 | if ... {...} else {...} | | main.rs:263:20:263:20 | A |
| main.rs:268:26:270:13 | { ... } | | main.rs:263:20:263:20 | A |
| main.rs:269:17:269:20 | self | | main.rs:259:5:261:5 | trait MyTrait1 |
| main.rs:269:17:269:20 | self | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:269:17:269:20 | self | A | main.rs:263:20:263:20 | A |
| main.rs:269:17:269:20 | self | A | main.rs:263:20:263:20 | A |
| main.rs:269:17:269:25 | self.m1(...) | | main.rs:263:20:263:20 | A |
| main.rs:270:20:272:13 | { ... } | | main.rs:263:20:263:20 | A |
| main.rs:271:17:271:30 | ...::m1(...) | | main.rs:263:20:263:20 | A |
| main.rs:271:26:271:29 | self | | main.rs:259:5:261:5 | trait MyTrait1 |
| main.rs:271:26:271:29 | self | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:271:26:271:29 | self | A | main.rs:263:20:263:20 | A |
| main.rs:271:26:271:29 | self | A | main.rs:263:20:263:20 | A |
| main.rs:277:15:277:18 | SelfParam | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:277:15:277:18 | SelfParam | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:277:15:277:18 | SelfParam | A | main.rs:244:5:247:5 | struct MyThing |
| main.rs:277:15:277:18 | SelfParam | A | main.rs:276:20:276:20 | A |
| main.rs:277:15:277:18 | SelfParam | A.A | main.rs:276:20:276:20 | A |
| main.rs:280:9:286:9 | { ... } | | main.rs:276:20:276:20 | A |
| main.rs:281:13:285:13 | if ... {...} else {...} | | main.rs:276:20:276:20 | A |
| main.rs:281:26:283:13 | { ... } | | main.rs:276:20:276:20 | A |
| main.rs:282:17:282:20 | self | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:282:17:282:20 | self | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:282:17:282:20 | self | A | main.rs:244:5:247:5 | struct MyThing |
| main.rs:282:17:282:20 | self | A | main.rs:276:20:276:20 | A |
| main.rs:282:17:282:20 | self | A.A | main.rs:276:20:276:20 | A |
| main.rs:282:17:282:25 | self.m2(...) | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:282:17:282:25 | self.m2(...) | A | main.rs:276:20:276:20 | A |
| main.rs:282:17:282:27 | ... .a | | main.rs:276:20:276:20 | A |
| main.rs:283:20:285:13 | { ... } | | main.rs:276:20:276:20 | A |
| main.rs:284:17:284:30 | ...::m2(...) | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:284:17:284:30 | ...::m2(...) | A | main.rs:276:20:276:20 | A |
| main.rs:284:17:284:32 | ... .a | | main.rs:276:20:276:20 | A |
| main.rs:284:26:284:29 | self | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:284:26:284:29 | self | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:284:26:284:29 | self | A | main.rs:244:5:247:5 | struct MyThing |
| main.rs:284:26:284:29 | self | A | main.rs:276:20:276:20 | A |
| main.rs:284:26:284:29 | self | A.A | main.rs:276:20:276:20 | A |
| main.rs:290:15:290:18 | SelfParam | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:290:15:290:18 | SelfParam | A | main.rs:289:10:289:10 | T |
| main.rs:290:26:292:9 | { ... } | | main.rs:289:10:289:10 | T |
| main.rs:291:13:291:16 | self | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:291:13:291:16 | self | A | main.rs:289:10:289:10 | T |
| main.rs:291:13:291:18 | self.a | | main.rs:289:10:289:10 | T |
| main.rs:298:15:298:18 | SelfParam | | main.rs:249:5:252:5 | struct MyThing2 |
| main.rs:298:15:298:18 | SelfParam | A | main.rs:297:10:297:10 | T |
| main.rs:298:35:300:9 | { ... } | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:298:35:300:9 | { ... } | A | main.rs:297:10:297:10 | T |
| main.rs:299:13:299:33 | MyThing {...} | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:299:13:299:33 | MyThing {...} | A | main.rs:297:10:297:10 | T |
| main.rs:299:26:299:29 | self | | main.rs:249:5:252:5 | struct MyThing2 |
| main.rs:299:26:299:29 | self | A | main.rs:297:10:297:10 | T |
| main.rs:299:26:299:31 | self.a | | main.rs:297:10:297:10 | T |
| main.rs:308:13:308:13 | x | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:308:13:308:13 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:308:17:308:33 | MyThing {...} | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:308:17:308:33 | MyThing {...} | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:308:30:308:31 | S1 | | main.rs:254:5:255:14 | struct S1 |
| main.rs:309:13:309:13 | y | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:309:13:309:13 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:309:17:309:33 | MyThing {...} | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:309:17:309:33 | MyThing {...} | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:309:30:309:31 | S2 | | main.rs:256:5:257:14 | struct S2 |
| main.rs:311:26:311:26 | x | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:311:26:311:26 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:311:26:311:31 | x.m1(...) | | main.rs:254:5:255:14 | struct S1 |
| main.rs:312:26:312:26 | y | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:312:26:312:26 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:312:26:312:31 | y.m1(...) | | main.rs:256:5:257:14 | struct S2 |
| main.rs:314:13:314:13 | x | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:314:13:314:13 | x | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:314:13:314:13 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:314:13:314:13 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:314:17:314:33 | MyThing {...} | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:314:17:314:33 | MyThing {...} | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:314:17:314:33 | MyThing {...} | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:314:17:314:33 | MyThing {...} | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:314:30:314:31 | S1 | | main.rs:254:5:255:14 | struct S1 |
| main.rs:315:13:315:13 | y | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:315:13:315:13 | y | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:315:13:315:13 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:315:13:315:13 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:315:17:315:33 | MyThing {...} | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:315:17:315:33 | MyThing {...} | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:315:17:315:33 | MyThing {...} | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:315:17:315:33 | MyThing {...} | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:315:30:315:31 | S2 | | main.rs:256:5:257:14 | struct S2 |
| main.rs:317:26:317:26 | x | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:317:26:317:26 | x | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:317:26:317:26 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:317:26:317:26 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:317:26:317:31 | x.m2(...) | | main.rs:254:5:255:14 | struct S1 |
| main.rs:318:26:318:26 | y | | main.rs:244:5:247:5 | struct MyThing |
| main.rs:318:26:318:26 | y | | main.rs:263:5:274:5 | trait MyTrait2 |
| main.rs:318:26:318:26 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:318:26:318:26 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:318:26:318:31 | y.m2(...) | | main.rs:256:5:257:14 | struct S2 |
| main.rs:320:13:320:13 | x | | main.rs:249:5:252:5 | struct MyThing2 |
| main.rs:320:13:320:13 | x | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:320:13:320:13 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:320:13:320:13 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:320:17:320:34 | MyThing2 {...} | | main.rs:249:5:252:5 | struct MyThing2 |
| main.rs:320:17:320:34 | MyThing2 {...} | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:320:17:320:34 | MyThing2 {...} | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:320:17:320:34 | MyThing2 {...} | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:320:31:320:32 | S1 | | main.rs:254:5:255:14 | struct S1 |
| main.rs:321:13:321:13 | y | | main.rs:249:5:252:5 | struct MyThing2 |
| main.rs:321:13:321:13 | y | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:321:13:321:13 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:321:13:321:13 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:321:17:321:34 | MyThing2 {...} | | main.rs:249:5:252:5 | struct MyThing2 |
| main.rs:321:17:321:34 | MyThing2 {...} | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:321:17:321:34 | MyThing2 {...} | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:321:17:321:34 | MyThing2 {...} | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:321:31:321:32 | S2 | | main.rs:256:5:257:14 | struct S2 |
| main.rs:323:26:323:26 | x | | main.rs:249:5:252:5 | struct MyThing2 |
| main.rs:323:26:323:26 | x | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:323:26:323:26 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:323:26:323:26 | x | A | main.rs:254:5:255:14 | struct S1 |
| main.rs:323:26:323:31 | x.m3(...) | | main.rs:254:5:255:14 | struct S1 |
| main.rs:324:26:324:26 | y | | main.rs:249:5:252:5 | struct MyThing2 |
| main.rs:324:26:324:26 | y | | main.rs:276:5:287:5 | trait MyTrait3 |
| main.rs:324:26:324:26 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:324:26:324:26 | y | A | main.rs:256:5:257:14 | struct S2 |
| main.rs:324:26:324:31 | y.m3(...) | | main.rs:256:5:257:14 | struct S2 |
| main.rs:342:22:342:22 | x | | file://:0:0:0:0 | & |
| main.rs:342:22:342:22 | x | &T | main.rs:342:11:342:19 | T |
| main.rs:342:35:344:5 | { ... } | | file://:0:0:0:0 | & |
| main.rs:342:35:344:5 | { ... } | &T | main.rs:342:11:342:19 | T |
| main.rs:343:9:343:9 | x | | file://:0:0:0:0 | & |
| main.rs:343:9:343:9 | x | &T | main.rs:342:11:342:19 | T |
| main.rs:347:17:347:20 | SelfParam | | main.rs:332:5:333:14 | struct S1 |
| main.rs:347:29:349:9 | { ... } | | main.rs:335:5:336:14 | struct S2 |
| main.rs:348:13:348:14 | S2 | | main.rs:335:5:336:14 | struct S2 |
| main.rs:352:21:352:21 | x | | main.rs:352:13:352:14 | T1 |
| main.rs:355:5:357:5 | { ... } | | main.rs:352:17:352:18 | T2 |
| main.rs:356:9:356:9 | x | | main.rs:352:13:352:14 | T1 |
| main.rs:356:9:356:16 | x.into(...) | | main.rs:352:17:352:18 | T2 |
| main.rs:360:13:360:13 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:360:17:360:18 | S1 | | main.rs:332:5:333:14 | struct S1 |
| main.rs:361:26:361:31 | id(...) | | file://:0:0:0:0 | & |
| main.rs:361:26:361:31 | id(...) | &T | main.rs:332:5:333:14 | struct S1 |
| main.rs:361:29:361:30 | &x | | file://:0:0:0:0 | & |
| main.rs:361:29:361:30 | &x | &T | main.rs:332:5:333:14 | struct S1 |
| main.rs:361:30:361:30 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:363:13:363:13 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:363:17:363:18 | S1 | | main.rs:332:5:333:14 | struct S1 |
| main.rs:364:26:364:37 | id::<...>(...) | | file://:0:0:0:0 | & |
| main.rs:364:26:364:37 | id::<...>(...) | &T | main.rs:332:5:333:14 | struct S1 |
| main.rs:364:35:364:36 | &x | | file://:0:0:0:0 | & |
| main.rs:364:35:364:36 | &x | &T | main.rs:332:5:333:14 | struct S1 |
| main.rs:364:36:364:36 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:366:13:366:13 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:366:17:366:18 | S1 | | main.rs:332:5:333:14 | struct S1 |
| main.rs:367:26:367:44 | id::<...>(...) | | file://:0:0:0:0 | & |
| main.rs:367:26:367:44 | id::<...>(...) | &T | main.rs:332:5:333:14 | struct S1 |
| main.rs:367:42:367:43 | &x | | file://:0:0:0:0 | & |
| main.rs:367:42:367:43 | &x | &T | main.rs:332:5:333:14 | struct S1 |
| main.rs:367:43:367:43 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:369:13:369:13 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:369:17:369:18 | S1 | | main.rs:332:5:333:14 | struct S1 |
| main.rs:370:9:370:25 | into::<...>(...) | | main.rs:335:5:336:14 | struct S2 |
| main.rs:370:24:370:24 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:372:13:372:13 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:372:17:372:18 | S1 | | main.rs:332:5:333:14 | struct S1 |
| main.rs:373:13:373:13 | y | | main.rs:335:5:336:14 | struct S2 |
| main.rs:373:21:373:27 | into(...) | | main.rs:335:5:336:14 | struct S2 |
| main.rs:373:26:373:26 | x | | main.rs:332:5:333:14 | struct S1 |
| main.rs:385:16:385:24 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:385:16:385:24 | SelfParam | &T | main.rs:384:5:390:5 | trait MyTrait |
| main.rs:385:16:385:24 | SelfParam | &T.S | main.rs:384:19:384:19 | S |
| main.rs:385:27:385:31 | value | | main.rs:384:19:384:19 | S |
| main.rs:385:27:385:31 | value | | main.rs:411:5:412:13 | struct S |
| main.rs:387:21:387:29 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:387:21:387:29 | SelfParam | &T | main.rs:384:5:390:5 | trait MyTrait |
| main.rs:387:21:387:29 | SelfParam | &T.S | main.rs:384:19:384:19 | S |
| main.rs:387:21:387:29 | SelfParam | &T.S | main.rs:411:5:412:13 | struct S |
| main.rs:387:32:387:36 | value | | main.rs:384:19:384:19 | S |
| main.rs:387:32:387:36 | value | | main.rs:411:5:412:13 | struct S |
| main.rs:388:13:388:16 | self | | file://:0:0:0:0 | & |
| main.rs:388:13:388:16 | self | &T | main.rs:384:5:390:5 | trait MyTrait |
| main.rs:388:13:388:16 | self | &T.S | main.rs:384:19:384:19 | S |
| main.rs:388:13:388:16 | self | &T.S | main.rs:411:5:412:13 | struct S |
| main.rs:388:22:388:26 | value | | main.rs:384:19:384:19 | S |
| main.rs:388:22:388:26 | value | | main.rs:411:5:412:13 | struct S |
| main.rs:393:16:393:24 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:393:16:393:24 | SelfParam | &T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:393:16:393:24 | SelfParam | &T.T | main.rs:392:10:392:10 | T |
| main.rs:393:27:393:31 | value | | main.rs:392:10:392:10 | T |
| main.rs:397:26:399:9 | { ... } | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:397:26:399:9 | { ... } | T | main.rs:396:10:396:10 | T |
| main.rs:398:13:398:30 | ...::MyNone(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:398:13:398:30 | ...::MyNone(...) | T | main.rs:396:10:396:10 | T |
| main.rs:403:20:403:23 | SelfParam | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:403:20:403:23 | SelfParam | T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:403:20:403:23 | SelfParam | T.T | main.rs:402:10:402:10 | T |
| main.rs:403:41:408:9 | { ... } | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:403:41:408:9 | { ... } | T | main.rs:402:10:402:10 | T |
| main.rs:404:13:407:13 | match self { ... } | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:404:13:407:13 | match self { ... } | T | main.rs:402:10:402:10 | T |
| main.rs:404:19:404:22 | self | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:404:19:404:22 | self | T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:404:19:404:22 | self | T.T | main.rs:402:10:402:10 | T |
| main.rs:405:39:405:56 | ...::MyNone(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:415:13:415:14 | x1 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:415:18:415:37 | ...::new(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:416:26:416:27 | x1 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:418:13:418:18 | mut x2 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:418:13:418:18 | mut x2 | T | main.rs:411:5:412:13 | struct S |
| main.rs:418:22:418:36 | ...::new(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:418:22:418:36 | ...::new(...) | T | main.rs:411:5:412:13 | struct S |
| main.rs:419:9:419:10 | x2 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:419:9:419:10 | x2 | T | main.rs:411:5:412:13 | struct S |
| main.rs:419:16:419:16 | S | | main.rs:411:5:412:13 | struct S |
| main.rs:420:26:420:27 | x2 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:420:26:420:27 | x2 | T | main.rs:411:5:412:13 | struct S |
| main.rs:422:13:422:18 | mut x3 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:422:13:422:18 | mut x3 | | main.rs:384:5:390:5 | trait MyTrait |
| main.rs:422:13:422:18 | mut x3 | S | main.rs:411:5:412:13 | struct S |
| main.rs:422:22:422:36 | ...::new(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:422:22:422:36 | ...::new(...) | | main.rs:384:5:390:5 | trait MyTrait |
| main.rs:422:22:422:36 | ...::new(...) | S | main.rs:411:5:412:13 | struct S |
| main.rs:423:9:423:10 | x3 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:423:9:423:10 | x3 | | main.rs:384:5:390:5 | trait MyTrait |
| main.rs:423:9:423:10 | x3 | S | main.rs:411:5:412:13 | struct S |
| main.rs:423:21:423:21 | S | | main.rs:411:5:412:13 | struct S |
| main.rs:424:26:424:27 | x3 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:424:26:424:27 | x3 | | main.rs:384:5:390:5 | trait MyTrait |
| main.rs:424:26:424:27 | x3 | S | main.rs:411:5:412:13 | struct S |
| main.rs:426:13:426:18 | mut x4 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:426:13:426:18 | mut x4 | T | main.rs:411:5:412:13 | struct S |
| main.rs:426:22:426:36 | ...::new(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:426:22:426:36 | ...::new(...) | T | main.rs:411:5:412:13 | struct S |
| main.rs:427:23:427:29 | &mut x4 | | file://:0:0:0:0 | & |
| main.rs:427:23:427:29 | &mut x4 | &T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:427:23:427:29 | &mut x4 | &T.T | main.rs:411:5:412:13 | struct S |
| main.rs:427:28:427:29 | x4 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:427:28:427:29 | x4 | T | main.rs:411:5:412:13 | struct S |
| main.rs:427:32:427:32 | S | | main.rs:411:5:412:13 | struct S |
| main.rs:428:26:428:27 | x4 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:428:26:428:27 | x4 | T | main.rs:411:5:412:13 | struct S |
| main.rs:430:13:430:14 | x5 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:430:13:430:14 | x5 | T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:430:13:430:14 | x5 | T.T | main.rs:411:5:412:13 | struct S |
| main.rs:430:18:430:58 | ...::MySome(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:430:18:430:58 | ...::MySome(...) | T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:430:18:430:58 | ...::MySome(...) | T.T | main.rs:411:5:412:13 | struct S |
| main.rs:430:35:430:57 | ...::MyNone(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:430:35:430:57 | ...::MyNone(...) | T | main.rs:411:5:412:13 | struct S |
| main.rs:431:26:431:27 | x5 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:431:26:431:27 | x5 | T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:431:26:431:27 | x5 | T.T | main.rs:411:5:412:13 | struct S |
| main.rs:433:13:433:14 | x6 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:433:13:433:14 | x6 | T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:433:13:433:14 | x6 | T.T | main.rs:411:5:412:13 | struct S |
| main.rs:433:18:433:58 | ...::MySome(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:433:18:433:58 | ...::MySome(...) | T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:433:18:433:58 | ...::MySome(...) | T.T | main.rs:411:5:412:13 | struct S |
| main.rs:433:35:433:57 | ...::MyNone(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:433:35:433:57 | ...::MyNone(...) | T | main.rs:411:5:412:13 | struct S |
| main.rs:434:26:434:61 | ...::flatten(...) | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:434:26:434:61 | ...::flatten(...) | T | main.rs:411:5:412:13 | struct S |
| main.rs:434:59:434:60 | x6 | | main.rs:378:5:382:5 | enum MyOption |
| main.rs:434:59:434:60 | x6 | T | main.rs:378:5:382:5 | enum MyOption |
| main.rs:434:59:434:60 | x6 | T.T | main.rs:411:5:412:13 | struct S |
| main.rs:447:15:447:18 | SelfParam | | main.rs:440:5:441:19 | struct S |
| main.rs:447:15:447:18 | SelfParam | T | main.rs:446:10:446:10 | T |
| main.rs:447:26:449:9 | { ... } | | main.rs:446:10:446:10 | T |
| main.rs:448:13:448:16 | self | | main.rs:440:5:441:19 | struct S |
| main.rs:448:13:448:16 | self | T | main.rs:446:10:446:10 | T |
| main.rs:448:13:448:18 | self.0 | | main.rs:446:10:446:10 | T |
| main.rs:451:15:451:19 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:451:15:451:19 | SelfParam | &T | main.rs:440:5:441:19 | struct S |
| main.rs:451:15:451:19 | SelfParam | &T.T | main.rs:446:10:446:10 | T |
| main.rs:451:28:453:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:451:28:453:9 | { ... } | &T | main.rs:446:10:446:10 | T |
| main.rs:452:13:452:19 | &... | | file://:0:0:0:0 | & |
| main.rs:452:13:452:19 | &... | &T | main.rs:446:10:446:10 | T |
| main.rs:452:14:452:17 | self | | file://:0:0:0:0 | & |
| main.rs:452:14:452:17 | self | &T | main.rs:440:5:441:19 | struct S |
| main.rs:452:14:452:17 | self | &T.T | main.rs:446:10:446:10 | T |
| main.rs:452:14:452:19 | self.0 | | main.rs:446:10:446:10 | T |
| main.rs:455:15:455:25 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:455:15:455:25 | SelfParam | &T | main.rs:440:5:441:19 | struct S |
| main.rs:455:15:455:25 | SelfParam | &T.T | main.rs:446:10:446:10 | T |
| main.rs:455:34:457:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:455:34:457:9 | { ... } | &T | main.rs:446:10:446:10 | T |
| main.rs:456:13:456:19 | &... | | file://:0:0:0:0 | & |
| main.rs:456:13:456:19 | &... | &T | main.rs:446:10:446:10 | T |
| main.rs:456:14:456:17 | self | | file://:0:0:0:0 | & |
| main.rs:456:14:456:17 | self | &T | main.rs:440:5:441:19 | struct S |
| main.rs:456:14:456:17 | self | &T.T | main.rs:446:10:446:10 | T |
| main.rs:456:14:456:19 | self.0 | | main.rs:446:10:446:10 | T |
| main.rs:461:13:461:14 | x1 | | main.rs:440:5:441:19 | struct S |
| main.rs:461:13:461:14 | x1 | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:461:18:461:22 | S(...) | | main.rs:440:5:441:19 | struct S |
| main.rs:461:18:461:22 | S(...) | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:461:20:461:21 | S2 | | main.rs:443:5:444:14 | struct S2 |
| main.rs:462:26:462:27 | x1 | | main.rs:440:5:441:19 | struct S |
| main.rs:462:26:462:27 | x1 | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:462:26:462:32 | x1.m1(...) | | main.rs:443:5:444:14 | struct S2 |
| main.rs:464:13:464:14 | x2 | | main.rs:440:5:441:19 | struct S |
| main.rs:464:13:464:14 | x2 | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:464:18:464:22 | S(...) | | main.rs:440:5:441:19 | struct S |
| main.rs:464:18:464:22 | S(...) | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:464:20:464:21 | S2 | | main.rs:443:5:444:14 | struct S2 |
| main.rs:466:26:466:27 | x2 | | main.rs:440:5:441:19 | struct S |
| main.rs:466:26:466:27 | x2 | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:466:26:466:32 | x2.m2(...) | | file://:0:0:0:0 | & |
| main.rs:466:26:466:32 | x2.m2(...) | &T | main.rs:443:5:444:14 | struct S2 |
| main.rs:467:26:467:27 | x2 | | main.rs:440:5:441:19 | struct S |
| main.rs:467:26:467:27 | x2 | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:467:26:467:32 | x2.m3(...) | | file://:0:0:0:0 | & |
| main.rs:467:26:467:32 | x2.m3(...) | &T | main.rs:443:5:444:14 | struct S2 |
| main.rs:469:13:469:14 | x3 | | main.rs:440:5:441:19 | struct S |
| main.rs:469:13:469:14 | x3 | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:469:18:469:22 | S(...) | | main.rs:440:5:441:19 | struct S |
| main.rs:469:18:469:22 | S(...) | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:469:20:469:21 | S2 | | main.rs:443:5:444:14 | struct S2 |
| main.rs:471:26:471:41 | ...::m2(...) | | file://:0:0:0:0 | & |
| main.rs:471:26:471:41 | ...::m2(...) | &T | main.rs:443:5:444:14 | struct S2 |
| main.rs:471:38:471:40 | &x3 | | file://:0:0:0:0 | & |
| main.rs:471:38:471:40 | &x3 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:471:38:471:40 | &x3 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:471:39:471:40 | x3 | | main.rs:440:5:441:19 | struct S |
| main.rs:471:39:471:40 | x3 | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:472:26:472:41 | ...::m3(...) | | file://:0:0:0:0 | & |
| main.rs:472:26:472:41 | ...::m3(...) | &T | main.rs:443:5:444:14 | struct S2 |
| main.rs:472:38:472:40 | &x3 | | file://:0:0:0:0 | & |
| main.rs:472:38:472:40 | &x3 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:472:38:472:40 | &x3 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:472:39:472:40 | x3 | | main.rs:440:5:441:19 | struct S |
| main.rs:472:39:472:40 | x3 | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:474:13:474:14 | x4 | | file://:0:0:0:0 | & |
| main.rs:474:13:474:14 | x4 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:474:13:474:14 | x4 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:474:18:474:23 | &... | | file://:0:0:0:0 | & |
| main.rs:474:18:474:23 | &... | &T | main.rs:440:5:441:19 | struct S |
| main.rs:474:18:474:23 | &... | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:474:19:474:23 | S(...) | | main.rs:440:5:441:19 | struct S |
| main.rs:474:19:474:23 | S(...) | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:474:21:474:22 | S2 | | main.rs:443:5:444:14 | struct S2 |
| main.rs:476:26:476:27 | x4 | | file://:0:0:0:0 | & |
| main.rs:476:26:476:27 | x4 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:476:26:476:27 | x4 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:476:26:476:32 | x4.m2(...) | | file://:0:0:0:0 | & |
| main.rs:476:26:476:32 | x4.m2(...) | &T | main.rs:443:5:444:14 | struct S2 |
| main.rs:477:26:477:27 | x4 | | file://:0:0:0:0 | & |
| main.rs:477:26:477:27 | x4 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:477:26:477:27 | x4 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:477:26:477:32 | x4.m3(...) | | file://:0:0:0:0 | & |
| main.rs:477:26:477:32 | x4.m3(...) | &T | main.rs:443:5:444:14 | struct S2 |
| main.rs:479:13:479:14 | x5 | | file://:0:0:0:0 | & |
| main.rs:479:13:479:14 | x5 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:479:13:479:14 | x5 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:479:18:479:23 | &... | | file://:0:0:0:0 | & |
| main.rs:479:18:479:23 | &... | &T | main.rs:440:5:441:19 | struct S |
| main.rs:479:18:479:23 | &... | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:479:19:479:23 | S(...) | | main.rs:440:5:441:19 | struct S |
| main.rs:479:19:479:23 | S(...) | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:479:21:479:22 | S2 | | main.rs:443:5:444:14 | struct S2 |
| main.rs:481:26:481:27 | x5 | | file://:0:0:0:0 | & |
| main.rs:481:26:481:27 | x5 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:481:26:481:27 | x5 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:481:26:481:32 | x5.m1(...) | | main.rs:443:5:444:14 | struct S2 |
| main.rs:482:26:482:27 | x5 | | file://:0:0:0:0 | & |
| main.rs:482:26:482:27 | x5 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:482:26:482:27 | x5 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:482:26:482:29 | x5.0 | | main.rs:443:5:444:14 | struct S2 |
| main.rs:484:13:484:14 | x6 | | file://:0:0:0:0 | & |
| main.rs:484:13:484:14 | x6 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:484:13:484:14 | x6 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:484:18:484:23 | &... | | file://:0:0:0:0 | & |
| main.rs:484:18:484:23 | &... | &T | main.rs:440:5:441:19 | struct S |
| main.rs:484:18:484:23 | &... | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:484:19:484:23 | S(...) | | main.rs:440:5:441:19 | struct S |
| main.rs:484:19:484:23 | S(...) | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:484:21:484:22 | S2 | | main.rs:443:5:444:14 | struct S2 |
| main.rs:486:26:486:30 | (...) | | main.rs:440:5:441:19 | struct S |
| main.rs:486:26:486:30 | (...) | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:486:26:486:35 | ... .m1(...) | | main.rs:443:5:444:14 | struct S2 |
| main.rs:486:27:486:29 | * ... | | main.rs:440:5:441:19 | struct S |
| main.rs:486:27:486:29 | * ... | T | main.rs:443:5:444:14 | struct S2 |
| main.rs:486:28:486:29 | x6 | | file://:0:0:0:0 | & |
| main.rs:486:28:486:29 | x6 | &T | main.rs:440:5:441:19 | struct S |
| main.rs:486:28:486:29 | x6 | &T.T | main.rs:443:5:444:14 | struct S2 |
| main.rs:492:16:492:20 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:492:16:492:20 | SelfParam | &T | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:494:16:494:20 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:494:16:494:20 | SelfParam | &T | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:494:32:496:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:494:32:496:9 | { ... } | &T | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:495:13:495:16 | self | | file://:0:0:0:0 | & |
| main.rs:495:13:495:16 | self | &T | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:495:13:495:22 | self.foo(...) | | file://:0:0:0:0 | & |
| main.rs:495:13:495:22 | self.foo(...) | &T | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:502:16:502:20 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:502:16:502:20 | SelfParam | &T | main.rs:499:5:499:20 | struct MyStruct |
| main.rs:502:36:504:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:502:36:504:9 | { ... } | &T | main.rs:499:5:499:20 | struct MyStruct |
| main.rs:503:13:503:16 | self | | file://:0:0:0:0 | & |
| main.rs:503:13:503:16 | self | &T | main.rs:499:5:499:20 | struct MyStruct |
| main.rs:508:13:508:13 | x | | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:508:13:508:13 | x | | main.rs:499:5:499:20 | struct MyStruct |
| main.rs:508:17:508:24 | MyStruct | | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:508:17:508:24 | MyStruct | | main.rs:499:5:499:20 | struct MyStruct |
| main.rs:509:9:509:9 | x | | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:509:9:509:9 | x | | main.rs:499:5:499:20 | struct MyStruct |
| main.rs:509:9:509:15 | x.bar(...) | | file://:0:0:0:0 | & |
| main.rs:509:9:509:15 | x.bar(...) | &T | main.rs:491:5:497:5 | trait MyTrait |
| main.rs:509:9:509:15 | x.bar(...) | &T | main.rs:499:5:499:20 | struct MyStruct |
| main.rs:519:16:519:20 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:519:16:519:20 | SelfParam | &T | main.rs:516:5:516:26 | struct MyStruct |
| main.rs:519:16:519:20 | SelfParam | &T.T | main.rs:518:10:518:10 | T |
| main.rs:519:32:521:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:519:32:521:9 | { ... } | &T | main.rs:516:5:516:26 | struct MyStruct |
| main.rs:519:32:521:9 | { ... } | &T.T | main.rs:518:10:518:10 | T |
| main.rs:520:13:520:16 | self | | file://:0:0:0:0 | & |
| main.rs:520:13:520:16 | self | &T | main.rs:516:5:516:26 | struct MyStruct |
| main.rs:520:13:520:16 | self | &T.T | main.rs:518:10:518:10 | T |
| main.rs:525:13:525:13 | x | | main.rs:516:5:516:26 | struct MyStruct |
| main.rs:525:13:525:13 | x | T | main.rs:514:5:514:13 | struct S |
| main.rs:525:17:525:27 | MyStruct(...) | | main.rs:516:5:516:26 | struct MyStruct |
| main.rs:525:17:525:27 | MyStruct(...) | T | main.rs:514:5:514:13 | struct S |
| main.rs:525:26:525:26 | S | | main.rs:514:5:514:13 | struct S |
| main.rs:526:9:526:9 | x | | main.rs:516:5:516:26 | struct MyStruct |
| main.rs:526:9:526:9 | x | T | main.rs:514:5:514:13 | struct S |
| main.rs:526:9:526:15 | x.foo(...) | | file://:0:0:0:0 | & |
| main.rs:526:9:526:15 | x.foo(...) | &T | main.rs:516:5:516:26 | struct MyStruct |
| main.rs:526:9:526:15 | x.foo(...) | &T.T | main.rs:514:5:514:13 | struct S |
| main.rs:534:15:534:19 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:534:15:534:19 | SelfParam | &T | main.rs:531:5:531:13 | struct S |
| main.rs:534:31:536:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:534:31:536:9 | { ... } | &T | main.rs:531:5:531:13 | struct S |
| main.rs:535:13:535:19 | &... | | file://:0:0:0:0 | & |
| main.rs:535:13:535:19 | &... | &T | main.rs:531:5:531:13 | struct S |
| main.rs:535:14:535:19 | &... | | file://:0:0:0:0 | & |
| main.rs:535:14:535:19 | &... | &T | main.rs:531:5:531:13 | struct S |
| main.rs:535:15:535:19 | &self | | file://:0:0:0:0 | & |
| main.rs:535:15:535:19 | &self | &T | main.rs:531:5:531:13 | struct S |
| main.rs:535:16:535:19 | self | | file://:0:0:0:0 | & |
| main.rs:535:16:535:19 | self | &T | main.rs:531:5:531:13 | struct S |
| main.rs:538:15:538:25 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:538:15:538:25 | SelfParam | &T | main.rs:531:5:531:13 | struct S |
| main.rs:538:37:540:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:538:37:540:9 | { ... } | &T | main.rs:531:5:531:13 | struct S |
| main.rs:539:13:539:19 | &... | | file://:0:0:0:0 | & |
| main.rs:539:13:539:19 | &... | &T | main.rs:531:5:531:13 | struct S |
| main.rs:539:14:539:19 | &... | | file://:0:0:0:0 | & |
| main.rs:539:14:539:19 | &... | &T | main.rs:531:5:531:13 | struct S |
| main.rs:539:15:539:19 | &self | | file://:0:0:0:0 | & |
| main.rs:539:15:539:19 | &self | &T | main.rs:531:5:531:13 | struct S |
| main.rs:539:16:539:19 | self | | file://:0:0:0:0 | & |
| main.rs:539:16:539:19 | self | &T | main.rs:531:5:531:13 | struct S |
| main.rs:542:15:542:15 | x | | file://:0:0:0:0 | & |
| main.rs:542:15:542:15 | x | &T | main.rs:531:5:531:13 | struct S |
| main.rs:542:34:544:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:542:34:544:9 | { ... } | &T | main.rs:531:5:531:13 | struct S |
| main.rs:543:13:543:13 | x | | file://:0:0:0:0 | & |
| main.rs:543:13:543:13 | x | &T | main.rs:531:5:531:13 | struct S |
| main.rs:546:15:546:15 | x | | file://:0:0:0:0 | & |
| main.rs:546:15:546:15 | x | &T | main.rs:531:5:531:13 | struct S |
| main.rs:546:34:548:9 | { ... } | | file://:0:0:0:0 | & |
| main.rs:546:34:548:9 | { ... } | &T | main.rs:531:5:531:13 | struct S |
| main.rs:547:13:547:16 | &... | | file://:0:0:0:0 | & |
| main.rs:547:13:547:16 | &... | &T | main.rs:531:5:531:13 | struct S |
| main.rs:547:14:547:16 | &... | | file://:0:0:0:0 | & |
| main.rs:547:14:547:16 | &... | &T | main.rs:531:5:531:13 | struct S |
| main.rs:547:15:547:16 | &x | | file://:0:0:0:0 | & |
| main.rs:547:15:547:16 | &x | &T | main.rs:531:5:531:13 | struct S |
| main.rs:547:16:547:16 | x | | file://:0:0:0:0 | & |
| main.rs:547:16:547:16 | x | &T | main.rs:531:5:531:13 | struct S |
| main.rs:552:13:552:13 | x | | main.rs:531:5:531:13 | struct S |
| main.rs:552:17:552:17 | S | | main.rs:531:5:531:13 | struct S |
| main.rs:553:9:553:9 | x | | main.rs:531:5:531:13 | struct S |
| main.rs:553:9:553:14 | x.f1(...) | | file://:0:0:0:0 | & |
| main.rs:553:9:553:14 | x.f1(...) | &T | main.rs:531:5:531:13 | struct S |
| main.rs:554:9:554:9 | x | | main.rs:531:5:531:13 | struct S |
| main.rs:554:9:554:14 | x.f2(...) | | file://:0:0:0:0 | & |
| main.rs:554:9:554:14 | x.f2(...) | &T | main.rs:531:5:531:13 | struct S |
| main.rs:555:9:555:17 | ...::f3(...) | | file://:0:0:0:0 | & |
| main.rs:555:9:555:17 | ...::f3(...) | &T | main.rs:531:5:531:13 | struct S |
| main.rs:555:15:555:16 | &x | | file://:0:0:0:0 | & |
| main.rs:555:15:555:16 | &x | &T | main.rs:531:5:531:13 | struct S |
| main.rs:555:16:555:16 | x | | main.rs:531:5:531:13 | struct S |
| main.rs:560:5:560:11 | ...::f(...) | | main.rs:2:5:2:21 | struct Foo |
| main.rs:561:5:561:33 | ...::g(...) | | main.rs:2:5:2:21 | struct Foo |
| main.rs:561:11:561:20 | ...::Foo {...} | | main.rs:2:5:2:21 | struct Foo |
| main.rs:561:23:561:32 | ...::Foo {...} | | main.rs:2:5:2:21 | struct Foo |
resolveMethodCallExpr
| main.rs:23:9:23:14 | x.m1(...) | main.rs:5:9:7:9 | fn m1 |
| main.rs:24:9:24:14 | y.m2(...) | main.rs:9:9:11:9 | fn m2 |
| main.rs:67:26:67:31 | x.m2(...) | main.rs:52:9:54:9 | fn m2 |
| main.rs:68:26:68:31 | y.m2(...) | main.rs:52:9:54:9 | fn m2 |
| main.rs:95:9:95:14 | x.m1(...) | main.rs:84:9:84:25 | fn m1 |
| main.rs:143:13:143:21 | self.m1(...) | main.rs:137:9:137:25 | fn m1 |
| main.rs:148:9:148:14 | x.m1(...) | main.rs:137:9:137:25 | fn m1 |
| main.rs:161:26:161:31 | x.m1(...) | main.rs:152:9:154:9 | fn m1 |
| main.rs:162:26:162:31 | y.m1(...) | main.rs:152:9:154:9 | fn m1 |
| main.rs:167:26:167:31 | x.m2(...) | main.rs:139:9:144:9 | fn m2 |
| main.rs:168:26:168:31 | y.m2(...) | main.rs:139:9:144:9 | fn m2 |
| main.rs:206:26:206:31 | x.m1(...) | main.rs:199:9:201:9 | fn m1 |
| main.rs:209:26:209:31 | x.m2(...) | main.rs:184:9:190:9 | fn m2 |
| main.rs:238:26:238:31 | x.m1(...) | main.rs:226:9:231:9 | fn m1 |
| main.rs:239:26:239:31 | y.m1(...) | main.rs:226:9:231:9 | fn m1 |
| main.rs:269:17:269:25 | self.m1(...) | main.rs:260:9:260:25 | fn m1 |
| main.rs:282:17:282:25 | self.m2(...) | main.rs:264:9:273:9 | fn m2 |
| main.rs:311:26:311:31 | x.m1(...) | main.rs:290:9:292:9 | fn m1 |
| main.rs:312:26:312:31 | y.m1(...) | main.rs:290:9:292:9 | fn m1 |
| main.rs:317:26:317:31 | x.m2(...) | main.rs:264:9:273:9 | fn m2 |
| main.rs:318:26:318:31 | y.m2(...) | main.rs:264:9:273:9 | fn m2 |
| main.rs:323:26:323:31 | x.m3(...) | main.rs:277:9:286:9 | fn m3 |
| main.rs:324:26:324:31 | y.m3(...) | main.rs:277:9:286:9 | fn m3 |
| main.rs:388:13:388:27 | self.set(...) | main.rs:385:9:385:36 | fn set |
| main.rs:419:9:419:17 | x2.set(...) | main.rs:393:9:393:38 | fn set |
| main.rs:423:9:423:22 | x3.call_set(...) | main.rs:387:9:389:9 | fn call_set |
| main.rs:462:26:462:32 | x1.m1(...) | main.rs:447:9:449:9 | fn m1 |
| main.rs:466:26:466:32 | x2.m2(...) | main.rs:451:9:453:9 | fn m2 |
| main.rs:467:26:467:32 | x2.m3(...) | main.rs:455:9:457:9 | fn m3 |
| main.rs:476:26:476:32 | x4.m2(...) | main.rs:451:9:453:9 | fn m2 |
| main.rs:477:26:477:32 | x4.m3(...) | main.rs:455:9:457:9 | fn m3 |
| main.rs:481:26:481:32 | x5.m1(...) | main.rs:447:9:449:9 | fn m1 |
| main.rs:486:26:486:35 | ... .m1(...) | main.rs:447:9:449:9 | fn m1 |
| main.rs:495:13:495:22 | self.foo(...) | main.rs:492:9:492:31 | fn foo |
| main.rs:509:9:509:15 | x.bar(...) | main.rs:494:9:496:9 | fn bar |
| main.rs:526:9:526:15 | x.foo(...) | main.rs:519:9:521:9 | fn foo |
| main.rs:553:9:553:14 | x.f1(...) | main.rs:534:9:536:9 | fn f1 |
| main.rs:554:9:554:14 | x.f2(...) | main.rs:538:9:540:9 | fn f2 |
resolveFieldExpr
| main.rs:41:13:41:18 | self.a | main.rs:31:9:31:12 | RecordField |
| main.rs:47:23:47:28 | self.a | main.rs:31:9:31:12 | RecordField |
| main.rs:53:13:53:18 | self.a | main.rs:31:9:31:12 | RecordField |
| main.rs:100:13:100:18 | self.a | main.rs:75:9:75:12 | RecordField |
| main.rs:106:23:106:28 | self.a | main.rs:75:9:75:12 | RecordField |
| main.rs:153:13:153:18 | self.a | main.rs:128:9:128:12 | RecordField |
| main.rs:282:17:282:27 | ... .a | main.rs:246:9:246:12 | RecordField |
| main.rs:284:17:284:32 | ... .a | main.rs:246:9:246:12 | RecordField |
| main.rs:291:13:291:18 | self.a | main.rs:246:9:246:12 | RecordField |
| main.rs:299:26:299:31 | self.a | main.rs:251:9:251:12 | RecordField |
| main.rs:448:13:448:18 | self.0 | main.rs:441:17:441:17 | TupleField |
| main.rs:452:14:452:19 | self.0 | main.rs:441:17:441:17 | TupleField |
| main.rs:456:14:456:19 | self.0 | main.rs:441:17:441:17 | TupleField |
| main.rs:482:26:482:29 | x5.0 | main.rs:441:17:441:17 | TupleField |

View File

@@ -0,0 +1,18 @@
import rust
import codeql.rust.elements.internal.TypeInference as TypeInference
import TypeInference
import utils.test.InlineExpectationsTest
query predicate resolveType(AstNode n, TypePath path, Type t) {
t = TypeInference::resolveType(n, path)
}
query predicate resolveMethodCallExpr(MethodCallExpr mce, Function f) {
f = resolveMethodCallExpr(mce)
}
query predicate resolveFieldExpr(FieldExpr fe, AstNode target) {
target = resolveRecordFieldExpr(fe)
or
target = resolveTupleFieldExpr(fe)
}