mirror of
https://github.com/github/codeql.git
synced 2026-04-21 06:55:31 +02:00
Rust: Implement basic type inference in QL
This commit is contained in:
1
rust/ql/.generated.list
generated
1
rust/ql/.generated.list
generated
@@ -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
1
rust/ql/.gitattributes
generated
vendored
@@ -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
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(_) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(_) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
329
rust/ql/lib/codeql/rust/elements/internal/Type.qll
Normal file
329
rust/ql/lib/codeql/rust/elements/internal/Type.qll
Normal 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 }
|
||||
}
|
||||
999
rust/ql/lib/codeql/rust/elements/internal/TypeInference.qll
Normal file
999
rust/ql/lib/codeql/rust/elements/internal/TypeInference.qll
Normal 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()) }
|
||||
173
rust/ql/lib/codeql/rust/elements/internal/TypeMention.qll
Normal file
173
rust/ql/lib/codeql/rust/elements/internal/TypeMention.qll
Normal 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)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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() }
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ dependencies:
|
||||
codeql/mad: ${workspace}
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/typeinference: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
dataExtensions:
|
||||
- /**/*.model.yml
|
||||
|
||||
@@ -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 | <...> |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
574
rust/ql/test/library-tests/type-inference/main.rs
Normal file
574
rust/ql/test/library-tests/type-inference/main.rs
Normal 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();
|
||||
}
|
||||
@@ -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 |
|
||||
18
rust/ql/test/library-tests/type-inference/type-inference.ql
Normal file
18
rust/ql/test/library-tests/type-inference/type-inference.ql
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user