Rust: Reimplement type inference for impl Traits and await expressions

This commit is contained in:
Tom Hvitved
2025-06-02 12:58:51 +02:00
parent f2832712bc
commit c6efc05de1
9 changed files with 327 additions and 162 deletions

View File

@@ -5,6 +5,7 @@
private import rust
private import codeql.rust.elements.internal.generated.ParentChild
private import codeql.rust.internal.CachedStages
private import codeql.rust.frameworks.stdlib.Bultins as Builtins
private newtype TNamespace =
TTypeNamespace() or
@@ -178,6 +179,8 @@ abstract class ItemNode extends Locatable {
or
// type parameters have access to the associated items of its bounds
result = this.(TypeParamItemNode).resolveABound().getASuccessorRec(name).(AssocItemNode)
or
result = this.(ImplTraitTypeReprItemNode).resolveABound().getASuccessorRec(name).(AssocItemNode)
}
/**
@@ -645,6 +648,28 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
}
}
private class ImplTraitTypeReprItemNode extends ItemNode instanceof ImplTraitTypeRepr {
pragma[nomagic]
Path getABoundPath() {
result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath()
}
pragma[nomagic]
ItemNode resolveABound() { result = resolvePathFull(this.getABoundPath()) }
override string getName() { result = "(impl trait)" }
override Namespace getNamespace() { result.isType() }
override Visibility getVisibility() { none() }
override TypeParam getTypeParam(int i) { none() }
override predicate hasCanonicalPath(Crate c) { none() }
override string getCanonicalPath(Crate c) { none() }
}
private class MacroCallItemNode extends AssocItemNode instanceof MacroCall {
override string getName() { result = "(macro call)" }
@@ -1093,14 +1118,21 @@ private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
not i instanceof Crate
}
private class BuiltinSourceFile extends SourceFileItemNode {
BuiltinSourceFile() { this.getFile().getParentContainer() instanceof Builtins::BuiltinsFolder }
}
/**
* Holds if `file` depends on crate `dep` named `name`.
*/
pragma[nomagic]
private predicate crateDependencyEdge(SourceFileItemNode file, string name, CrateItemNode dep) {
exists(CrateItemNode c |
dep = c.(Crate).getDependency(name) and
file = c.getASourceFile()
)
exists(CrateItemNode c | dep = c.(Crate).getDependency(name) | file = c.getASourceFile())
or
// Give builtin files, such as `await.rs`, access to `std`
file instanceof BuiltinSourceFile and
dep.getName() = name and
name = "std"
}
private predicate useTreeDeclares(UseTree tree, string name) {
@@ -1461,9 +1493,14 @@ private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItem
* [1]: https://doc.rust-lang.org/core/prelude/index.html
* [2]: https://doc.rust-lang.org/std/prelude/index.html
*/
pragma[nomagic]
private predicate preludeEdge(SourceFile f, string name, ItemNode i) {
exists(Crate stdOrCore, ModuleLikeNode mod, ModuleItemNode prelude, ModuleItemNode rust |
f = any(Crate c0 | stdOrCore = c0.getDependency(_) or stdOrCore = c0).getASourceFile() and
f = any(Crate c0 | stdOrCore = c0.getDependency(_) or stdOrCore = c0).getASourceFile()
or
// Give builtin files, such as `await.rs`, access to the prelude
f instanceof BuiltinSourceFile
|
stdOrCore.getName() = ["std", "core"] and
mod = stdOrCore.getSourceFile() and
prelude = mod.getASuccessorRec("prelude") and
@@ -1473,12 +1510,10 @@ private predicate preludeEdge(SourceFile f, string name, ItemNode i) {
)
}
private import codeql.rust.frameworks.stdlib.Bultins as Builtins
pragma[nomagic]
private predicate builtin(string name, ItemNode i) {
exists(SourceFileItemNode builtins |
builtins.getFile().getParentContainer() instanceof Builtins::BuiltinsFolder and
exists(BuiltinSourceFile builtins |
builtins.getFile().getBaseName() = "types.rs" and
i = builtins.getASuccessorRec(name)
)
}

View File

@@ -15,14 +15,11 @@ newtype TType =
TTrait(Trait t) or
TArrayType() or // todo: add size?
TRefType() or // todo: add mut?
TImplTraitType(int bounds) {
bounds = any(ImplTraitTypeRepr impl).getTypeBoundList().getNumberOfBounds()
} or
TImplTraitType(ImplTraitTypeRepr impl) or
TTypeParamTypeParameter(TypeParam t) or
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
TRefTypeParameter() or
TSelfTypeParameter(Trait t) or
TImplTraitTypeParameter(ImplTraitType t, int i) { i in [0 .. t.getNumberOfBounds() - 1] }
TSelfTypeParameter(Trait t)
/**
* A type without type arguments.
@@ -184,30 +181,50 @@ class RefType extends Type, TRefType {
}
/**
* An [`impl Trait`][1] type.
* An [impl Trait][1] type.
*
* We represent `impl Trait` types as generic types with as many type parameters
* as there are bounds.
* Each syntactic `impl Trait` type gives rise to its own type, even if
* two `impl Trait` types have the same bounds.
*
* [1] https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
* [1]: https://doc.rust-lang.org/reference/types/impl-trait.html
*/
class ImplTraitType extends Type, TImplTraitType {
private int bounds;
ImplTraitTypeRepr impl;
ImplTraitType() { this = TImplTraitType(bounds) }
ImplTraitType() { this = TImplTraitType(impl) }
/** Gets the number of bounds of this `impl Trait` type. */
int getNumberOfBounds() { result = bounds }
/** Gets the underlying AST node. */
ImplTraitTypeRepr getImplTraitTypeRepr() { result = impl }
/** Gets the function that this `impl Trait` belongs to. */
abstract Function getFunction();
override StructField getStructField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override TypeParameter getTypeParameter(int i) { result = TImplTraitTypeParameter(this, i) }
override TypeParameter getTypeParameter(int i) { none() }
override string toString() { result = "impl Trait ..." }
override string toString() { result = impl.toString() }
override Location getLocation() { result instanceof EmptyLocation }
override Location getLocation() { result = impl.getLocation() }
}
/**
* An [impl Trait in return position][1] type, for example:
*
* ```rust
* fn foo() -> impl Trait
* ```
*
* [1]: https://doc.rust-lang.org/reference/types/impl-trait.html#r-type.impl-trait.return
*/
class ImplTraitReturnType extends ImplTraitType {
private Function function;
ImplTraitReturnType() { impl = function.getRetType().getTypeRepr() }
override Function getFunction() { result = function }
}
/** A type parameter. */
@@ -219,7 +236,7 @@ abstract class TypeParameter extends Type {
override TypeParameter getTypeParameter(int i) { none() }
}
private class RawTypeParameter = @type_param or @trait or @type_alias;
private class RawTypeParameter = @type_param or @trait or @type_alias or @impl_trait_type_repr;
private predicate id(RawTypeParameter x, RawTypeParameter y) { x = y }
@@ -316,23 +333,34 @@ class SelfTypeParameter extends TypeParameter, TSelfTypeParameter {
}
/**
* An `impl Trait` type parameter.
* An [impl Trait in argument position][1] type, for example:
*
* ```rust
* fn foo(arg: impl Trait)
* ```
*
* Such types are syntactic sugar for type parameters, that is
*
* ```rust
* fn foo<T: Trait>(arg: T)
* ```
*
* so we model them as type parameters.
*
* [1]: https://doc.rust-lang.org/reference/types/impl-trait.html#r-type.impl-trait.param
*/
class ImplTraitTypeParameter extends TypeParameter, TImplTraitTypeParameter {
private ImplTraitType implTraitType;
private int i;
class ImplTraitTypeTypeParameter extends ImplTraitType, TypeParameter {
private Function function;
ImplTraitTypeParameter() { this = TImplTraitTypeParameter(implTraitType, i) }
ImplTraitTypeTypeParameter() { impl = function.getParamList().getAParam().getTypeRepr() }
/** Gets the `impl Trait` type that this parameter belongs to. */
ImplTraitType getImplTraitType() { result = implTraitType }
override Function getFunction() { result = function }
/** Gets the index of this type parameter. */
int getIndex() { result = i }
override StructField getStructField(string name) { none() }
override string toString() { result = "impl Trait<" + i.toString() + ">" }
override TupleField getTupleField(int i) { none() }
override Location getLocation() { result instanceof EmptyLocation }
override TypeParameter getTypeParameter(int i) { none() }
}
/**
@@ -370,3 +398,7 @@ final class SelfTypeBoundTypeAbstraction extends TypeAbstraction, Name {
override TypeParamTypeParameter getATypeParameter() { none() }
}
final class ImplTraitTypeReprAbstraction extends TypeAbstraction, ImplTraitTypeRepr {
override TypeParamTypeParameter getATypeParameter() { none() }
}

View File

@@ -77,16 +77,6 @@ private module Input1 implements InputSig1<Location> {
apos.asMethodTypeArgumentPosition() = ppos.asTypeParam().getPosition()
}
private int getImplTraitTypeParameterId(ImplTraitTypeParameter tp) {
tp =
rank[result](ImplTraitTypeParameter tp0, int bounds, int i |
bounds = tp0.getImplTraitType().getNumberOfBounds() and
i = tp0.getIndex()
|
tp0 order by bounds, i
)
}
int getTypeParameterId(TypeParameter tp) {
tp =
rank[result](TypeParameter tp0, int kind, int id |
@@ -98,11 +88,9 @@ private module Input1 implements InputSig1<Location> {
exists(AstNode node | id = idOfTypeParameterAstNode(node) |
node = tp0.(TypeParamTypeParameter).getTypeParam() or
node = tp0.(AssociatedTypeTypeParameter).getTypeAlias() or
node = tp0.(SelfTypeParameter).getTrait()
node = tp0.(SelfTypeParameter).getTrait() or
node = tp0.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr()
)
or
kind = 2 and
id = getImplTraitTypeParameterId(tp0)
|
tp0 order by kind, id
)
@@ -124,12 +112,22 @@ private module Input2 implements InputSig2 {
class TypeMention = TM::TypeMention;
TypeMention getABaseTypeMention(Type t) { none() }
TypeMention getABaseTypeMention(Type t) {
result =
t.(ImplTraitReturnType).getImplTraitTypeRepr().getTypeBoundList().getABound().getTypeRepr()
}
TypeMention getATypeParameterConstraint(TypeParameter tp) {
result = tp.(TypeParamTypeParameter).getTypeParam().getTypeBoundList().getABound().getTypeRepr()
or
result = tp.(SelfTypeParameter).getTrait()
or
result =
tp.(ImplTraitTypeTypeParameter)
.getImplTraitTypeRepr()
.getTypeBoundList()
.getABound()
.getTypeRepr()
}
/**
@@ -169,6 +167,12 @@ private module Input2 implements InputSig2 {
condition = self and
constraint = self.getTrait()
)
or
exists(ImplTraitTypeRepr impl |
abs = impl and
condition = impl and
constraint = impl.getTypeBoundList().getABound().getTypeRepr()
)
}
}
@@ -241,12 +245,6 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
or
n1 = n2.(ParenExpr).getExpr()
or
n2 =
any(BlockExpr be |
not be.isAsync() and
n1 = be.getStmtList().getTailExpr()
)
or
n1 = n2.(IfExpr).getABranch()
or
n1 = n2.(MatchExpr).getAnArm().getExpr()
@@ -265,6 +263,19 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
n1 = n2.(DerefExpr).getExpr() and
prefix1 = TypePath::singleton(TRefTypeParameter()) and
prefix2.isEmpty()
or
exists(BlockExpr be |
n1 = be and
n2 = be.getStmtList().getTailExpr() and
if be.isAsync()
then
prefix1 = TypePath::singleton(getFutureOutputTypeParameter()) and
prefix2.isEmpty()
else (
prefix1.isEmpty() and
prefix2.isEmpty()
)
)
}
pragma[nomagic]
@@ -580,6 +591,9 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
ppos.isImplicit() and
result.(AssociatedTypeTypeParameter).getTrait() = trait
)
or
ppos.isImplicit() and
this = result.(ImplTraitTypeTypeParameter).getFunction()
}
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
@@ -599,9 +613,22 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
)
}
override Type getReturnType(TypePath path) {
private Type resolveRetType(TypePath path) {
result = this.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path)
}
override Type getReturnType(TypePath path) {
if this.isAsync()
then
path.isEmpty() and
result = getFutureTraitType()
or
exists(TypePath suffix |
result = this.resolveRetType(suffix) and
path = TypePath::cons(getFutureOutputTypeParameter(), suffix)
)
else result = this.resolveRetType(path)
}
}
private predicate argPos(CallExprBase call, Expr e, int pos, boolean isMethodCall) {
@@ -1027,26 +1054,110 @@ private StructType inferLiteralType(LiteralExpr le) {
)
}
pragma[nomagic]
private TraitType getFutureTraitType() { result.getTrait() instanceof FutureTrait }
pragma[nomagic]
private AssociatedTypeTypeParameter getFutureOutputTypeParameter() {
result.getTypeAlias() = any(FutureTrait ft).getOutputType()
}
pragma[nomagic]
private Type inferAwaitExprType(AwaitExpr ae, TypePath path) {
exists(TypePath exprPath | result = inferType(ae.getExpr(), exprPath) |
exprPath
.isCons(TImplTraitTypeParameter(_, _),
any(TypePath path0 | path0.isCons(getFutureOutputTypeParameter(), path)))
/**
* A matching configuration for resolving types of `.await` expressions.
*/
private module AwaitExprMatchingInput implements MatchingInputSig {
private newtype TDeclarationPosition =
TSelfDeclarationPosition() or
TOutputPos()
class DeclarationPosition extends TDeclarationPosition {
predicate isSelf() { this = TSelfDeclarationPosition() }
predicate isOutput() { this = TOutputPos() }
string toString() {
this.isSelf() and
result = "self"
or
path = exprPath and
not (
exprPath = TypePath::singleton(TImplTraitTypeParameter(_, _)) and
result.(TraitType).getTrait() instanceof FutureTrait
) and
not exprPath
.isCons(TImplTraitTypeParameter(_, _),
any(TypePath path0 | path0.isCons(getFutureOutputTypeParameter(), _)))
this.isOutput() and
result = "(output)"
}
}
private class BuiltinsAwaitFile extends File {
BuiltinsAwaitFile() {
this.getBaseName() = "await.rs" and
this.getParentContainer() instanceof Builtins::BuiltinsFolder
}
}
class Declaration extends Function {
Declaration() {
this.getFile() instanceof BuiltinsAwaitFile and
this.getName().getText() = "await_type_matching"
}
TypeParameter getTypeParameter(TypeParameterPosition ppos) {
typeParamMatchPosition(this.getGenericParamList().getATypeParam(), result, ppos)
}
Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
dpos.isSelf() and
result = this.getParamList().getParam(0).getTypeRepr().(TypeMention).resolveTypeAt(path)
or
dpos.isOutput() and
result = this.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path)
}
}
class AccessPosition = DeclarationPosition;
class Access extends AwaitExpr {
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
AstNode getNodeAt(AccessPosition apos) {
result = this.getExpr() and
apos.isSelf()
or
result = this and
apos.isOutput()
}
Type getInferredType(AccessPosition apos, TypePath path) {
result = inferType(this.getNodeAt(apos), path)
}
Declaration getTarget() { exists(this) and exists(result) }
}
predicate accessDeclarationPositionMatch(AccessPosition apos, DeclarationPosition dpos) {
apos = dpos
}
}
pragma[nomagic]
private TraitType inferAsyncBlockExprRootType(AsyncBlockExpr abe) {
// `typeEquality` handles the non-root case
exists(abe) and
result = getFutureTraitType()
}
private module AwaitExprMatching = Matching<AwaitExprMatchingInput>;
pragma[nomagic]
private Type inferAwaitExprType(AstNode n, TypePath path) {
exists(AwaitExprMatchingInput::Access a, AwaitExprMatchingInput::AccessPosition apos |
n = a.getNodeAt(apos) and
result = AwaitExprMatching::inferAccessType(a, apos, path)
)
or
// This case is needed for `async` functions and blocks, where we assign
// the type `Future<Output = T>` directly instead of `impl Future<Output = T>`
//
// TODO: It would be better if we could handle this in the shared library
exists(TypePath exprPath |
result = inferType(n.(AwaitExpr).getExpr(), exprPath) and
exprPath.isCons(getFutureOutputTypeParameter(), path)
)
}
@@ -1196,6 +1307,8 @@ private Function getTypeParameterMethod(TypeParameter tp, string name) {
result = getMethodSuccessor(tp.(TypeParamTypeParameter).getTypeParam(), name)
or
result = getMethodSuccessor(tp.(SelfTypeParameter).getTrait(), name)
or
result = getMethodSuccessor(tp.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr(), name)
}
/** Gets a method from an `impl` block that matches the method call `mc`. */
@@ -1208,8 +1321,8 @@ private Function getMethodFromImpl(MethodCall mc) {
bindingset[trait, name]
pragma[inline_late]
private Function getTraitMethod(TraitType trait, string name) {
result = getMethodSuccessor(trait.getTrait(), name)
private Function getTraitMethod(ImplTraitReturnType trait, string name) {
result = getMethodSuccessor(trait.getImplTraitTypeRepr(), name)
}
/**
@@ -1225,9 +1338,7 @@ private Function inferMethodCallTarget(MethodCall mc) {
result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
or
// The type of the receiver is an `impl Trait` type.
result =
getTraitMethod(mc.getTypeAt(TypePath::singleton(TImplTraitTypeParameter(_, _))),
mc.getMethodName())
result = getTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
}
cached
@@ -1404,6 +1515,9 @@ private module Cached {
result = inferLiteralType(n) and
path.isEmpty()
or
result = inferAsyncBlockExprRootType(n) and
path.isEmpty()
or
result = inferAwaitExprType(n, path)
}
}
@@ -1421,7 +1535,7 @@ private module Debug {
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
filepath.matches("%/main.rs") and
startline = 1334
startline = 1718
)
}

View File

@@ -191,13 +191,9 @@ class PathTypeReprMention extends TypeMention instanceof PathTypeRepr {
}
class ImplTraitTypeReprMention extends TypeMention instanceof ImplTraitTypeRepr {
override TypeMention getTypeArgument(int i) {
result = super.getTypeBoundList().getBound(i).getTypeRepr()
}
override TypeMention getTypeArgument(int i) { none() }
override ImplTraitType resolveType() {
result.getNumberOfBounds() = super.getTypeBoundList().getNumberOfBounds()
}
override ImplTraitType resolveType() { result.getImplTraitTypeRepr() = this }
}
private TypeParameter pathGetTypeParameter(TypeAlias alias, int i) {

View File

@@ -1667,11 +1667,11 @@ mod async_ {
f1().await.f(); // $ method=S1f
f2().await.f(); // $ method=S1f
f3().await.f(); // $ method=S1f
S2.await.f(); // $ MISSING: method=S1f
S2.await.f(); // $ method=S1f
let b = async {
S1
};
b.await.f(); // $ MISSING: method=S1f
b.await.f(); // $ method=S1f
}
}
@@ -1727,10 +1727,10 @@ mod impl_trait {
x.f1(); // $ method=Trait1f1
x.f2(); // $ method=Trait2f2
let a = get_a_my_trait();
let b = uses_my_trait1(a); // $ MISSING: type=b:S2
let b = uses_my_trait1(a); // $ type=b:S2
let a = get_a_my_trait();
let c = uses_my_trait2(a); // $ type=c:S2
let d = uses_my_trait2(S1); // $ MISSING: type=d:S2
let d = uses_my_trait2(S1); // $ type=d:S2
}
}

View File

@@ -2377,12 +2377,12 @@ inferType
| main.rs:1639:18:1639:21 | SelfParam | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1642:25:1644:5 | { ... } | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1643:9:1643:10 | S1 | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1646:41:1650:5 | { ... } | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1646:41:1650:5 | { ... } | impl Trait<0> | {EXTERNAL LOCATION} | trait Future |
| main.rs:1646:41:1650:5 | { ... } | impl Trait<0>.Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1647:9:1649:9 | { ... } | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1647:9:1649:9 | { ... } | impl Trait<0> | {EXTERNAL LOCATION} | trait Future |
| main.rs:1647:9:1649:9 | { ... } | impl Trait<0>.Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1646:41:1650:5 | { ... } | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1646:41:1650:5 | { ... } | | main.rs:1646:16:1646:39 | ImplTraitTypeRepr |
| main.rs:1646:41:1650:5 | { ... } | Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1647:9:1649:9 | { ... } | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1647:9:1649:9 | { ... } | | main.rs:1646:16:1646:39 | ImplTraitTypeRepr |
| main.rs:1647:9:1649:9 | { ... } | Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1648:13:1648:14 | S1 | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1657:17:1657:46 | SelfParam | | {EXTERNAL LOCATION} | Pin |
| main.rs:1657:17:1657:46 | SelfParam | Ptr | file://:0:0:0:0 | & |
@@ -2394,29 +2394,27 @@ inferType
| main.rs:1658:13:1658:38 | ...::Ready(...) | | {EXTERNAL LOCATION} | Poll |
| main.rs:1658:13:1658:38 | ...::Ready(...) | T | main.rs:1636:5:1636:14 | S1 |
| main.rs:1658:36:1658:37 | S1 | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1662:41:1664:5 | { ... } | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1662:41:1664:5 | { ... } | | main.rs:1652:5:1652:14 | S2 |
| main.rs:1662:41:1664:5 | { ... } | impl Trait<0> | {EXTERNAL LOCATION} | trait Future |
| main.rs:1662:41:1664:5 | { ... } | impl Trait<0>.Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1663:9:1663:10 | S2 | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1662:41:1664:5 | { ... } | | main.rs:1662:16:1662:39 | ImplTraitTypeRepr |
| main.rs:1663:9:1663:10 | S2 | | main.rs:1652:5:1652:14 | S2 |
| main.rs:1663:9:1663:10 | S2 | impl Trait<0> | {EXTERNAL LOCATION} | trait Future |
| main.rs:1663:9:1663:10 | S2 | impl Trait<0>.Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1667:9:1667:12 | f1(...) | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1663:9:1663:10 | S2 | | main.rs:1662:16:1662:39 | ImplTraitTypeRepr |
| main.rs:1667:9:1667:12 | f1(...) | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1667:9:1667:12 | f1(...) | Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1667:9:1667:18 | await ... | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1668:9:1668:12 | f2(...) | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1668:9:1668:12 | f2(...) | impl Trait<0> | {EXTERNAL LOCATION} | trait Future |
| main.rs:1668:9:1668:12 | f2(...) | impl Trait<0>.Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1668:9:1668:18 | await ... | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1668:9:1668:12 | f2(...) | | main.rs:1646:16:1646:39 | ImplTraitTypeRepr |
| main.rs:1668:9:1668:18 | await ... | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1669:9:1669:12 | f3(...) | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1669:9:1669:12 | f3(...) | impl Trait<0> | {EXTERNAL LOCATION} | trait Future |
| main.rs:1669:9:1669:12 | f3(...) | impl Trait<0>.Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1669:9:1669:18 | await ... | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1669:9:1669:12 | f3(...) | | main.rs:1662:16:1662:39 | ImplTraitTypeRepr |
| main.rs:1669:9:1669:18 | await ... | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1670:9:1670:10 | S2 | | main.rs:1652:5:1652:14 | S2 |
| main.rs:1670:9:1670:16 | await S2 | | main.rs:1652:5:1652:14 | S2 |
| main.rs:1670:9:1670:16 | await S2 | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1671:13:1671:13 | b | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1671:13:1671:13 | b | Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1671:17:1673:9 | { ... } | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1671:17:1673:9 | { ... } | Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1672:13:1672:14 | S1 | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1674:9:1674:9 | b | | {EXTERNAL LOCATION} | trait Future |
| main.rs:1674:9:1674:9 | b | Output | main.rs:1636:5:1636:14 | S1 |
| main.rs:1674:9:1674:15 | await b | | main.rs:1636:5:1636:14 | S1 |
| main.rs:1684:15:1684:19 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:1684:15:1684:19 | SelfParam | &T | main.rs:1683:5:1685:5 | Self [trait Trait1] |
| main.rs:1688:15:1688:19 | SelfParam | | file://:0:0:0:0 | & |
@@ -2425,77 +2423,48 @@ inferType
| main.rs:1692:15:1692:19 | SelfParam | &T | main.rs:1680:5:1680:14 | S1 |
| main.rs:1696:15:1696:19 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:1696:15:1696:19 | SelfParam | &T | main.rs:1680:5:1680:14 | S1 |
| main.rs:1699:37:1701:5 | { ... } | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1699:37:1701:5 | { ... } | | main.rs:1680:5:1680:14 | S1 |
| main.rs:1699:37:1701:5 | { ... } | impl Trait<0> | main.rs:1683:5:1685:5 | trait Trait1 |
| main.rs:1699:37:1701:5 | { ... } | impl Trait<1> | main.rs:1687:5:1689:5 | trait Trait2 |
| main.rs:1700:9:1700:10 | S1 | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1699:37:1701:5 | { ... } | | main.rs:1699:16:1699:35 | ImplTraitTypeRepr |
| main.rs:1700:9:1700:10 | S1 | | main.rs:1680:5:1680:14 | S1 |
| main.rs:1700:9:1700:10 | S1 | impl Trait<0> | main.rs:1683:5:1685:5 | trait Trait1 |
| main.rs:1700:9:1700:10 | S1 | impl Trait<1> | main.rs:1687:5:1689:5 | trait Trait2 |
| main.rs:1700:9:1700:10 | S1 | | main.rs:1699:16:1699:35 | ImplTraitTypeRepr |
| main.rs:1704:18:1704:22 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:1704:18:1704:22 | SelfParam | &T | main.rs:1703:5:1705:5 | Self [trait MyTrait] |
| main.rs:1708:18:1708:22 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:1708:18:1708:22 | SelfParam | &T | main.rs:1680:5:1680:14 | S1 |
| main.rs:1708:31:1710:9 | { ... } | | main.rs:1681:5:1681:14 | S2 |
| main.rs:1709:13:1709:14 | S2 | | main.rs:1681:5:1681:14 | S2 |
| main.rs:1713:45:1715:5 | { ... } | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1713:45:1715:5 | { ... } | | main.rs:1680:5:1680:14 | S1 |
| main.rs:1713:45:1715:5 | { ... } | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1713:45:1715:5 | { ... } | impl Trait<0>.A | main.rs:1681:5:1681:14 | S2 |
| main.rs:1714:9:1714:10 | S1 | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1713:45:1715:5 | { ... } | | main.rs:1713:28:1713:43 | ImplTraitTypeRepr |
| main.rs:1714:9:1714:10 | S1 | | main.rs:1680:5:1680:14 | S1 |
| main.rs:1714:9:1714:10 | S1 | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1714:9:1714:10 | S1 | impl Trait<0>.A | main.rs:1681:5:1681:14 | S2 |
| main.rs:1714:9:1714:10 | S1 | | main.rs:1713:28:1713:43 | ImplTraitTypeRepr |
| main.rs:1717:41:1717:41 | t | | main.rs:1717:26:1717:38 | B |
| main.rs:1717:52:1719:5 | { ... } | | main.rs:1717:23:1717:23 | A |
| main.rs:1718:9:1718:9 | t | | main.rs:1717:26:1717:38 | B |
| main.rs:1718:9:1718:17 | t.get_a() | | main.rs:1717:23:1717:23 | A |
| main.rs:1721:26:1721:26 | t | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1721:26:1721:26 | t | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1721:26:1721:26 | t | impl Trait<0>.A | main.rs:1721:23:1721:23 | A |
| main.rs:1721:26:1721:26 | t | | main.rs:1721:29:1721:43 | ImplTraitTypeRepr |
| main.rs:1721:51:1723:5 | { ... } | | main.rs:1721:23:1721:23 | A |
| main.rs:1722:9:1722:9 | t | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1722:9:1722:9 | t | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1722:9:1722:9 | t | impl Trait<0>.A | main.rs:1721:23:1721:23 | A |
| main.rs:1722:9:1722:9 | t | | main.rs:1721:29:1721:43 | ImplTraitTypeRepr |
| main.rs:1722:9:1722:17 | t.get_a() | | main.rs:1721:23:1721:23 | A |
| main.rs:1726:13:1726:13 | x | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1726:13:1726:13 | x | impl Trait<0> | main.rs:1683:5:1685:5 | trait Trait1 |
| main.rs:1726:13:1726:13 | x | impl Trait<1> | main.rs:1687:5:1689:5 | trait Trait2 |
| main.rs:1726:17:1726:20 | f1(...) | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1726:17:1726:20 | f1(...) | impl Trait<0> | main.rs:1683:5:1685:5 | trait Trait1 |
| main.rs:1726:17:1726:20 | f1(...) | impl Trait<1> | main.rs:1687:5:1689:5 | trait Trait2 |
| main.rs:1727:9:1727:9 | x | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1727:9:1727:9 | x | impl Trait<0> | main.rs:1683:5:1685:5 | trait Trait1 |
| main.rs:1727:9:1727:9 | x | impl Trait<1> | main.rs:1687:5:1689:5 | trait Trait2 |
| main.rs:1728:9:1728:9 | x | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1728:9:1728:9 | x | impl Trait<0> | main.rs:1683:5:1685:5 | trait Trait1 |
| main.rs:1728:9:1728:9 | x | impl Trait<1> | main.rs:1687:5:1689:5 | trait Trait2 |
| main.rs:1729:13:1729:13 | a | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1729:13:1729:13 | a | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1729:13:1729:13 | a | impl Trait<0>.A | main.rs:1681:5:1681:14 | S2 |
| main.rs:1729:17:1729:32 | get_a_my_trait(...) | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1729:17:1729:32 | get_a_my_trait(...) | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1729:17:1729:32 | get_a_my_trait(...) | impl Trait<0>.A | main.rs:1681:5:1681:14 | S2 |
| main.rs:1730:32:1730:32 | a | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1730:32:1730:32 | a | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1730:32:1730:32 | a | impl Trait<0>.A | main.rs:1681:5:1681:14 | S2 |
| main.rs:1731:13:1731:13 | a | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1731:13:1731:13 | a | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1731:13:1731:13 | a | impl Trait<0>.A | main.rs:1681:5:1681:14 | S2 |
| main.rs:1731:17:1731:32 | get_a_my_trait(...) | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1731:17:1731:32 | get_a_my_trait(...) | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1731:17:1731:32 | get_a_my_trait(...) | impl Trait<0>.A | main.rs:1681:5:1681:14 | S2 |
| main.rs:1726:13:1726:13 | x | | main.rs:1699:16:1699:35 | ImplTraitTypeRepr |
| main.rs:1726:17:1726:20 | f1(...) | | main.rs:1699:16:1699:35 | ImplTraitTypeRepr |
| main.rs:1727:9:1727:9 | x | | main.rs:1699:16:1699:35 | ImplTraitTypeRepr |
| main.rs:1728:9:1728:9 | x | | main.rs:1699:16:1699:35 | ImplTraitTypeRepr |
| main.rs:1729:13:1729:13 | a | | main.rs:1713:28:1713:43 | ImplTraitTypeRepr |
| main.rs:1729:17:1729:32 | get_a_my_trait(...) | | main.rs:1713:28:1713:43 | ImplTraitTypeRepr |
| main.rs:1730:13:1730:13 | b | | main.rs:1681:5:1681:14 | S2 |
| main.rs:1730:17:1730:33 | uses_my_trait1(...) | | main.rs:1681:5:1681:14 | S2 |
| main.rs:1730:32:1730:32 | a | | main.rs:1713:28:1713:43 | ImplTraitTypeRepr |
| main.rs:1731:13:1731:13 | a | | main.rs:1713:28:1713:43 | ImplTraitTypeRepr |
| main.rs:1731:17:1731:32 | get_a_my_trait(...) | | main.rs:1713:28:1713:43 | ImplTraitTypeRepr |
| main.rs:1732:13:1732:13 | c | | main.rs:1681:5:1681:14 | S2 |
| main.rs:1732:17:1732:33 | uses_my_trait2(...) | | main.rs:1681:5:1681:14 | S2 |
| main.rs:1732:32:1732:32 | a | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1732:32:1732:32 | a | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1732:32:1732:32 | a | impl Trait<0>.A | main.rs:1681:5:1681:14 | S2 |
| main.rs:1733:32:1733:33 | S1 | | file://:0:0:0:0 | impl Trait ... |
| main.rs:1732:32:1732:32 | a | | main.rs:1713:28:1713:43 | ImplTraitTypeRepr |
| main.rs:1733:13:1733:13 | d | | main.rs:1681:5:1681:14 | S2 |
| main.rs:1733:17:1733:34 | uses_my_trait2(...) | | main.rs:1681:5:1681:14 | S2 |
| main.rs:1733:32:1733:33 | S1 | | main.rs:1680:5:1680:14 | S1 |
| main.rs:1733:32:1733:33 | S1 | impl Trait<0> | main.rs:1703:5:1705:5 | trait MyTrait |
| main.rs:1739:5:1739:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo |
| main.rs:1740:5:1740:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo |
| main.rs:1740:20:1740:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
| main.rs:1740:41:1740:59 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
| main.rs:1756:5:1756:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
testFailures

View File

@@ -4,6 +4,8 @@ multiplePathResolutions
| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from |
@@ -14,6 +16,8 @@ multiplePathResolutions
| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from |
@@ -24,6 +28,8 @@ multiplePathResolutions
| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from |
@@ -34,6 +40,8 @@ multiplePathResolutions
| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from |
| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from |

View File

@@ -0,0 +1,7 @@
use std::future::Future;
fn await_type_matching<T1, T2: Future<Output = T1>>(x: T2) -> T1 {
panic!(
"This function exists only in order to implement type inference for `.await` expressions."
);
}

View File

@@ -220,6 +220,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
predicate isCons(TypeParameter tp, TypePath suffix) {
suffix = this.stripPrefix(TypePath::singleton(tp))
}
/** Gets the head of this path, if any. */
bindingset[this]
TypeParameter getHead() { result = this.getTypeParameter(0) }
}
/** Provides predicates for constructing `TypePath`s. */
@@ -1110,7 +1114,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
Declaration decl, DeclarationPosition dpos, Type base, TypePath path, TypeParameter tp
) {
tp = decl.getDeclaredType(dpos, path) and
path.isCons(base.getATypeParameter(), _)
base.getATypeParameter() = path.getHead()
}
/**