mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
Merge pull request #21464 from hvitved/rust/type-inference-trait-bound-impl-overlap
Rust: Disambiguate types inferred from trait bounds
This commit is contained in:
@@ -103,7 +103,7 @@ module SatisfiesBlanketConstraint<
|
||||
}
|
||||
|
||||
private module SatisfiesBlanketConstraintInput implements
|
||||
SatisfiesConstraintInputSig<ArgumentTypeAndBlanketOffset>
|
||||
SatisfiesTypeInputSig<ArgumentTypeAndBlanketOffset>
|
||||
{
|
||||
pragma[nomagic]
|
||||
additional predicate relevantConstraint(
|
||||
@@ -123,7 +123,7 @@ module SatisfiesBlanketConstraint<
|
||||
}
|
||||
|
||||
private module SatisfiesBlanketConstraint =
|
||||
SatisfiesConstraint<ArgumentTypeAndBlanketOffset, SatisfiesBlanketConstraintInput>;
|
||||
SatisfiesType<ArgumentTypeAndBlanketOffset, SatisfiesBlanketConstraintInput>;
|
||||
|
||||
/**
|
||||
* Holds if the argument type `at` satisfies the first non-trivial blanket
|
||||
|
||||
@@ -13,68 +13,105 @@ private import TypeMention
|
||||
private import TypeInference
|
||||
private import FunctionType
|
||||
|
||||
pragma[nomagic]
|
||||
private Type resolveNonTypeParameterTypeAt(TypeMention tm, TypePath path) {
|
||||
result = tm.getTypeAt(path) and
|
||||
not result instanceof TypeParameter
|
||||
}
|
||||
|
||||
bindingset[t1, t2]
|
||||
private predicate typeMentionEqual(TypeMention t1, TypeMention t2) {
|
||||
forex(TypePath path, Type type | resolveNonTypeParameterTypeAt(t1, path) = type |
|
||||
resolveNonTypeParameterTypeAt(t2, path) = type
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate implSiblingCandidate(
|
||||
Impl impl, TraitItemNode trait, Type rootType, TypeMention selfTy
|
||||
) {
|
||||
trait = impl.(ImplItemNode).resolveTraitTy() and
|
||||
selfTy = impl.getSelfTy() and
|
||||
rootType = selfTy.getType()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate blanketImplSiblingCandidate(ImplItemNode impl, Trait trait) {
|
||||
impl.isBlanketImplementation() and
|
||||
trait = impl.resolveTraitTy()
|
||||
}
|
||||
private signature Type resolveTypeMentionAtSig(AstNode tm, TypePath path);
|
||||
|
||||
/**
|
||||
* Holds if `impl1` and `impl2` are a sibling implementations of `trait`. We
|
||||
* consider implementations to be siblings if they implement the same trait for
|
||||
* the same type. In that case `Self` is the same type in both implementations,
|
||||
* and method calls to the implementations cannot be resolved unambiguously
|
||||
* based only on the receiver type.
|
||||
* Provides logic for identifying sibling implementations, parameterized over
|
||||
* how to resolve type mentions (`PreTypeMention` vs. `TypeMention`).
|
||||
*/
|
||||
pragma[inline]
|
||||
private predicate implSiblings(TraitItemNode trait, Impl impl1, Impl impl2) {
|
||||
impl1 != impl2 and
|
||||
(
|
||||
exists(Type rootType, TypeMention selfTy1, TypeMention selfTy2 |
|
||||
implSiblingCandidate(impl1, trait, rootType, selfTy1) and
|
||||
implSiblingCandidate(impl2, trait, rootType, selfTy2) and
|
||||
// In principle the second conjunct below should be superflous, but we still
|
||||
// have ill-formed type mentions for types that we don't understand. For
|
||||
// those checking both directions restricts further. Note also that we check
|
||||
// syntactic equality, whereas equality up to renaming would be more
|
||||
// correct.
|
||||
typeMentionEqual(selfTy1, selfTy2) and
|
||||
typeMentionEqual(selfTy2, selfTy1)
|
||||
private module MkSiblingImpls<resolveTypeMentionAtSig/2 resolveTypeMentionAt> {
|
||||
pragma[nomagic]
|
||||
private Type resolveNonTypeParameterTypeAt(AstNode tm, TypePath path) {
|
||||
result = resolveTypeMentionAt(tm, path) and
|
||||
not result instanceof TypeParameter
|
||||
}
|
||||
|
||||
bindingset[t1, t2]
|
||||
private predicate typeMentionEqual(AstNode t1, AstNode t2) {
|
||||
forex(TypePath path, Type type | resolveNonTypeParameterTypeAt(t1, path) = type |
|
||||
resolveNonTypeParameterTypeAt(t2, path) = type
|
||||
)
|
||||
or
|
||||
blanketImplSiblingCandidate(impl1, trait) and
|
||||
blanketImplSiblingCandidate(impl2, trait)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate implSiblingCandidate(
|
||||
Impl impl, TraitItemNode trait, Type rootType, AstNode selfTy
|
||||
) {
|
||||
trait = impl.(ImplItemNode).resolveTraitTy() and
|
||||
selfTy = impl.getSelfTy() and
|
||||
rootType = resolveTypeMentionAt(selfTy, TypePath::nil())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate blanketImplSiblingCandidate(ImplItemNode impl, Trait trait) {
|
||||
impl.isBlanketImplementation() and
|
||||
trait = impl.resolveTraitTy()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `impl1` and `impl2` are sibling implementations of `trait`. We
|
||||
* consider implementations to be siblings if they implement the same trait for
|
||||
* the same type. In that case `Self` is the same type in both implementations,
|
||||
* and method calls to the implementations cannot be resolved unambiguously
|
||||
* based only on the receiver type.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate implSiblings(TraitItemNode trait, Impl impl1, Impl impl2) {
|
||||
impl1 != impl2 and
|
||||
(
|
||||
exists(Type rootType, AstNode selfTy1, AstNode selfTy2 |
|
||||
implSiblingCandidate(impl1, trait, rootType, selfTy1) and
|
||||
implSiblingCandidate(impl2, trait, rootType, selfTy2) and
|
||||
// In principle the second conjunct below should be superfluous, but we still
|
||||
// have ill-formed type mentions for types that we don't understand. For
|
||||
// those checking both directions restricts further. Note also that we check
|
||||
// syntactic equality, whereas equality up to renaming would be more
|
||||
// correct.
|
||||
typeMentionEqual(selfTy1, selfTy2) and
|
||||
typeMentionEqual(selfTy2, selfTy1)
|
||||
)
|
||||
or
|
||||
blanketImplSiblingCandidate(impl1, trait) and
|
||||
blanketImplSiblingCandidate(impl2, trait)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `impl` is an implementation of `trait` and if another implementation
|
||||
* exists for the same type.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate implHasSibling(ImplItemNode impl, Trait trait) { implSiblings(trait, impl, _) }
|
||||
|
||||
pragma[nomagic]
|
||||
predicate implHasAmbiguousSiblingAt(ImplItemNode impl, Trait trait, TypePath path) {
|
||||
exists(ImplItemNode impl2, Type t1, Type t2 |
|
||||
implSiblings(trait, impl, impl2) and
|
||||
t1 = resolveTypeMentionAt(impl.getTraitPath(), path) and
|
||||
t2 = resolveTypeMentionAt(impl2.getTraitPath(), path) and
|
||||
t1 != t2
|
||||
|
|
||||
not t1 instanceof TypeParameter or
|
||||
not t2 instanceof TypeParameter
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `impl` is an implementation of `trait` and if another implementation
|
||||
* exists for the same type.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate implHasSibling(ImplItemNode impl, Trait trait) { implSiblings(trait, impl, _) }
|
||||
private Type resolvePreTypeMention(AstNode tm, TypePath path) {
|
||||
result = tm.(PreTypeMention).getTypeAt(path)
|
||||
}
|
||||
|
||||
private module PreSiblingImpls = MkSiblingImpls<resolvePreTypeMention/2>;
|
||||
|
||||
predicate preImplHasAmbiguousSiblingAt = PreSiblingImpls::implHasAmbiguousSiblingAt/3;
|
||||
|
||||
private Type resolveTypeMention(AstNode tm, TypePath path) {
|
||||
result = tm.(TypeMention).getTypeAt(path)
|
||||
}
|
||||
|
||||
private module SiblingImpls = MkSiblingImpls<resolveTypeMention/2>;
|
||||
|
||||
import SiblingImpls
|
||||
|
||||
/**
|
||||
* Holds if `f` is a function declared inside `trait`, and the type of `f` at
|
||||
|
||||
@@ -439,11 +439,11 @@ class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter {
|
||||
*/
|
||||
class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypeParameter {
|
||||
private Trait trait;
|
||||
private TypeAlias typeAlias;
|
||||
private AssocType typeAlias;
|
||||
|
||||
AssociatedTypeTypeParameter() { this = TAssociatedTypeTypeParameter(trait, typeAlias) }
|
||||
|
||||
TypeAlias getTypeAlias() { result = typeAlias }
|
||||
AssocType getTypeAlias() { result = typeAlias }
|
||||
|
||||
/** Gets the trait that contains this associated type declaration. */
|
||||
TraitItemNode getTrait() { result = trait }
|
||||
@@ -457,7 +457,13 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara
|
||||
override ItemNode getDeclaringItem() { result = trait }
|
||||
|
||||
override string toString() {
|
||||
result = typeAlias.getName().getText() + "[" + trait.getName().toString() + "]"
|
||||
exists(string fromString, TraitItemNode trait2 |
|
||||
result = typeAlias.getName().getText() + "[" + trait.getName() + fromString + "]" and
|
||||
trait2 = typeAlias.getTrait() and
|
||||
if trait = trait2
|
||||
then fromString = ""
|
||||
else fromString = " (inherited from " + trait2.getName() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override Location getLocation() { result = typeAlias.getLocation() }
|
||||
|
||||
@@ -30,7 +30,7 @@ private newtype TTypeArgumentPosition =
|
||||
} or
|
||||
TTypeParamTypeArgumentPosition(TypeParam tp)
|
||||
|
||||
private module Input implements InputSig1<Location>, InputSig2<PreTypeMention> {
|
||||
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
|
||||
@@ -122,22 +122,36 @@ private module Input implements InputSig1<Location>, InputSig2<PreTypeMention> {
|
||||
tp0 order by kind, id1, id2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
int getTypePathLimit() { result = 10 }
|
||||
private import Input1
|
||||
|
||||
PreTypeMention getABaseTypeMention(Type t) { none() }
|
||||
private module M1 = Make1<Location, Input1>;
|
||||
|
||||
Type getATypeParameterConstraint(TypeParameter tp, TypePath path) {
|
||||
exists(TypeMention tm | result = tm.getTypeAt(path) |
|
||||
tm = tp.(TypeParamTypeParameter).getTypeParam().getATypeBound().getTypeRepr() or
|
||||
tm = tp.(SelfTypeParameter).getTrait() or
|
||||
tm =
|
||||
tp.(ImplTraitTypeTypeParameter)
|
||||
.getImplTraitTypeRepr()
|
||||
.getTypeBoundList()
|
||||
.getABound()
|
||||
.getTypeRepr()
|
||||
)
|
||||
import M1
|
||||
|
||||
predicate getTypePathLimit = Input1::getTypePathLimit/0;
|
||||
|
||||
predicate getTypeParameterId = Input1::getTypeParameterId/1;
|
||||
|
||||
class TypePath = M1::TypePath;
|
||||
|
||||
module TypePath = M1::TypePath;
|
||||
|
||||
/**
|
||||
* Provides shared logic for implementing `InputSig2<PreTypeMention>` and
|
||||
* `InputSig2<TypeMention>`.
|
||||
*/
|
||||
private module Input2Common {
|
||||
AstNode getATypeParameterConstraint(TypeParameter tp) {
|
||||
result = tp.(TypeParamTypeParameter).getTypeParam().getATypeBound().getTypeRepr() or
|
||||
result = tp.(SelfTypeParameter).getTrait() or
|
||||
result =
|
||||
tp.(ImplTraitTypeTypeParameter)
|
||||
.getImplTraitTypeRepr()
|
||||
.getTypeBoundList()
|
||||
.getABound()
|
||||
.getTypeRepr()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +162,7 @@ private module Input implements InputSig1<Location>, InputSig2<PreTypeMention> {
|
||||
* inference module for more information.
|
||||
*/
|
||||
predicate conditionSatisfiesConstraint(
|
||||
TypeAbstraction abs, PreTypeMention condition, PreTypeMention constraint, boolean transitive
|
||||
TypeAbstraction abs, AstNode condition, AstNode constraint, boolean transitive
|
||||
) {
|
||||
// `impl` blocks implementing traits
|
||||
transitive = false and
|
||||
@@ -196,23 +210,64 @@ private module Input implements InputSig1<Location>, InputSig2<PreTypeMention> {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeParameterIsFunctionallyDetermined(TypeParameter tp) {
|
||||
tp instanceof AssociatedTypeTypeParameter
|
||||
}
|
||||
}
|
||||
|
||||
private import Input
|
||||
private module PreInput2 implements InputSig2<PreTypeMention> {
|
||||
PreTypeMention getABaseTypeMention(Type t) { none() }
|
||||
|
||||
private module M1 = Make1<Location, Input>;
|
||||
PreTypeMention getATypeParameterConstraint(TypeParameter tp) {
|
||||
result = Input2Common::getATypeParameterConstraint(tp)
|
||||
}
|
||||
|
||||
import M1
|
||||
predicate conditionSatisfiesConstraint(
|
||||
TypeAbstraction abs, PreTypeMention condition, PreTypeMention constraint, boolean transitive
|
||||
) {
|
||||
Input2Common::conditionSatisfiesConstraint(abs, condition, constraint, transitive)
|
||||
}
|
||||
|
||||
predicate getTypePathLimit = Input::getTypePathLimit/0;
|
||||
predicate typeAbstractionHasAmbiguousConstraintAt(
|
||||
TypeAbstraction abs, Type constraint, TypePath path
|
||||
) {
|
||||
FunctionOverloading::preImplHasAmbiguousSiblingAt(abs, constraint.(TraitType).getTrait(), path)
|
||||
}
|
||||
|
||||
predicate getTypeParameterId = Input::getTypeParameterId/1;
|
||||
predicate typeParameterIsFunctionallyDetermined =
|
||||
Input2Common::typeParameterIsFunctionallyDetermined/1;
|
||||
}
|
||||
|
||||
class TypePath = M1::TypePath;
|
||||
/** Provides an instantiation of the shared type inference library for `PreTypeMention`s. */
|
||||
module PreM2 = Make2<PreTypeMention, PreInput2>;
|
||||
|
||||
module TypePath = M1::TypePath;
|
||||
private module Input2 implements InputSig2<TypeMention> {
|
||||
TypeMention getABaseTypeMention(Type t) { none() }
|
||||
|
||||
private module M2 = Make2<PreTypeMention, Input>;
|
||||
TypeMention getATypeParameterConstraint(TypeParameter tp) {
|
||||
result = Input2Common::getATypeParameterConstraint(tp)
|
||||
}
|
||||
|
||||
predicate conditionSatisfiesConstraint(
|
||||
TypeAbstraction abs, TypeMention condition, TypeMention constraint, boolean transitive
|
||||
) {
|
||||
Input2Common::conditionSatisfiesConstraint(abs, condition, constraint, transitive)
|
||||
}
|
||||
|
||||
predicate typeAbstractionHasAmbiguousConstraintAt(
|
||||
TypeAbstraction abs, Type constraint, TypePath path
|
||||
) {
|
||||
FunctionOverloading::implHasAmbiguousSiblingAt(abs, constraint.(TraitType).getTrait(), path)
|
||||
}
|
||||
|
||||
predicate typeParameterIsFunctionallyDetermined =
|
||||
Input2Common::typeParameterIsFunctionallyDetermined/1;
|
||||
}
|
||||
|
||||
private import Input2
|
||||
|
||||
private module M2 = Make2<TypeMention, Input2>;
|
||||
|
||||
import M2
|
||||
|
||||
@@ -598,17 +653,18 @@ module CertainTypeInference {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` has complete and certain type information at _some_ type path.
|
||||
* Holds if `n` has complete and certain type information at `path`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate hasInferredCertainType(AstNode n) { exists(inferCertainType(n, _)) }
|
||||
predicate hasInferredCertainType(AstNode n, TypePath path) { exists(inferCertainType(n, path)) }
|
||||
|
||||
/**
|
||||
* Holds if `n` having type `t` at `path` conflicts with certain type information.
|
||||
* Holds if `n` having type `t` at `path` conflicts with certain type information
|
||||
* at `prefix`.
|
||||
*/
|
||||
bindingset[n, path, t]
|
||||
bindingset[n, prefix, path, t]
|
||||
pragma[inline_late]
|
||||
predicate certainTypeConflict(AstNode n, TypePath path, Type t) {
|
||||
predicate certainTypeConflict(AstNode n, TypePath prefix, TypePath path, Type t) {
|
||||
inferCertainType(n, path) != t
|
||||
or
|
||||
// If we infer that `n` has _some_ type at `T1.T2....Tn`, and we also
|
||||
@@ -617,7 +673,7 @@ module CertainTypeInference {
|
||||
// otherwise there is a conflict.
|
||||
//
|
||||
// Below, `prefix` is `T1.T2...Ti` and `tp` is `T(i+1)`.
|
||||
exists(TypePath prefix, TypePath suffix, TypeParameter tp, Type certainType |
|
||||
exists(TypePath suffix, TypeParameter tp, Type certainType |
|
||||
path = prefix.appendInverse(suffix) and
|
||||
tp = suffix.getHead() and
|
||||
inferCertainType(n, prefix) = certainType and
|
||||
@@ -988,7 +1044,7 @@ private module ContextTyping {
|
||||
or
|
||||
exists(TypeParameter mid |
|
||||
assocFunctionMentionsTypeParameterAtNonRetPos(i, f, mid) and
|
||||
tp = getATypeParameterConstraint(mid, _)
|
||||
tp = getATypeParameterConstraint(mid).getTypeAt(_)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1056,9 +1112,12 @@ private module ContextTyping {
|
||||
pragma[nomagic]
|
||||
private predicate hasUnknownType(AstNode n) { hasUnknownTypeAt(n, _) }
|
||||
|
||||
signature Type inferCallTypeSig(
|
||||
AstNode n, FunctionPosition pos, boolean hasReceiver, TypePath path
|
||||
);
|
||||
newtype FunctionPositionKind =
|
||||
SelfKind() or
|
||||
ReturnKind() or
|
||||
PositionalKind()
|
||||
|
||||
signature Type inferCallTypeSig(AstNode n, FunctionPositionKind kind, TypePath path);
|
||||
|
||||
/**
|
||||
* Given a predicate `inferCallType` for inferring the type of a call at a given
|
||||
@@ -1066,35 +1125,28 @@ private module ContextTyping {
|
||||
* predicate and checks that types are only propagated into arguments when they
|
||||
* are context-typed.
|
||||
*/
|
||||
module CheckContextTyping<inferCallTypeSig/4 inferCallType> {
|
||||
module CheckContextTyping<inferCallTypeSig/3 inferCallType> {
|
||||
pragma[nomagic]
|
||||
private Type inferCallNonReturnType(
|
||||
AstNode n, FunctionPosition pos, boolean hasReceiver, TypePath path
|
||||
AstNode n, FunctionPositionKind kind, TypePath prefix, TypePath path
|
||||
) {
|
||||
result = inferCallType(n, pos, hasReceiver, path) and
|
||||
not pos.isReturn()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferCallNonReturnType(
|
||||
AstNode n, FunctionPosition pos, boolean hasReceiver, TypePath prefix, TypePath path
|
||||
) {
|
||||
result = inferCallNonReturnType(n, pos, hasReceiver, path) and
|
||||
result = inferCallType(n, kind, path) and
|
||||
hasUnknownType(n) and
|
||||
kind != ReturnKind() and
|
||||
prefix = path.getAPrefix()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
Type check(AstNode n, TypePath path) {
|
||||
result = inferCallType(n, any(FunctionPosition pos | pos.isReturn()), _, path)
|
||||
result = inferCallType(n, ReturnKind(), path)
|
||||
or
|
||||
exists(FunctionPosition pos, boolean hasReceiver, TypePath prefix |
|
||||
result = inferCallNonReturnType(n, pos, hasReceiver, prefix, path) and
|
||||
exists(FunctionPositionKind kind, TypePath prefix |
|
||||
result = inferCallNonReturnType(n, kind, prefix, path) and
|
||||
hasUnknownTypeAt(n, prefix)
|
||||
|
|
||||
// Never propagate type information directly into the receiver, since its type
|
||||
// must already have been known in order to resolve the call
|
||||
if pos.asPosition() = 0 and hasReceiver = true then not prefix.isEmpty() else any()
|
||||
if kind = SelfKind() then not prefix.isEmpty() else any()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -2362,8 +2414,7 @@ private module AssocFunctionResolution {
|
||||
Location getLocation() { result = afc.getLocation() }
|
||||
}
|
||||
|
||||
private module CallSatisfiesDerefConstraintInput implements
|
||||
SatisfiesConstraintInputSig<CallDerefCand>
|
||||
private module CallSatisfiesDerefConstraintInput implements SatisfiesTypeInputSig<CallDerefCand>
|
||||
{
|
||||
pragma[nomagic]
|
||||
predicate relevantConstraint(CallDerefCand mc, Type constraint) {
|
||||
@@ -2373,7 +2424,7 @@ private module AssocFunctionResolution {
|
||||
}
|
||||
|
||||
private module CallSatisfiesDerefConstraint =
|
||||
SatisfiesConstraint<CallDerefCand, CallSatisfiesDerefConstraintInput>;
|
||||
SatisfiesType<CallDerefCand, CallSatisfiesDerefConstraintInput>;
|
||||
|
||||
pragma[nomagic]
|
||||
private AssociatedTypeTypeParameter getDerefTargetTypeParameter() {
|
||||
@@ -2880,17 +2931,20 @@ private Type inferFunctionCallTypeSelf(
|
||||
}
|
||||
|
||||
private Type inferFunctionCallTypePreCheck(
|
||||
AstNode n, FunctionPosition pos, boolean hasReceiver, TypePath path
|
||||
AstNode n, ContextTyping::FunctionPositionKind kind, TypePath path
|
||||
) {
|
||||
result = inferFunctionCallTypeNonSelf(n, pos, path) and
|
||||
hasReceiver = false
|
||||
exists(FunctionPosition pos |
|
||||
result = inferFunctionCallTypeNonSelf(n, pos, path) and
|
||||
if pos.isPosition()
|
||||
then kind = ContextTyping::PositionalKind()
|
||||
else kind = ContextTyping::ReturnKind()
|
||||
)
|
||||
or
|
||||
exists(FunctionCallMatchingInput::Access a |
|
||||
result = inferFunctionCallTypeSelf(a, n, DerefChain::nil(), path) and
|
||||
pos.asPosition() = 0 and
|
||||
if a.(AssocFunctionResolution::AssocFunctionCall).hasReceiver()
|
||||
then hasReceiver = true
|
||||
else hasReceiver = false
|
||||
then kind = ContextTyping::SelfKind()
|
||||
else kind = ContextTyping::PositionalKind()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2899,7 +2953,7 @@ private Type inferFunctionCallTypePreCheck(
|
||||
* argument/receiver of a function call.
|
||||
*/
|
||||
private predicate inferFunctionCallType =
|
||||
ContextTyping::CheckContextTyping<inferFunctionCallTypePreCheck/4>::check/2;
|
||||
ContextTyping::CheckContextTyping<inferFunctionCallTypePreCheck/3>::check/2;
|
||||
|
||||
abstract private class Constructor extends Addressable {
|
||||
final TypeParameter getTypeParameter(TypeParameterPosition ppos) {
|
||||
@@ -3060,10 +3114,14 @@ private module ConstructionMatching = Matching<ConstructionMatchingInput>;
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferConstructionTypePreCheck(
|
||||
AstNode n, FunctionPosition pos, boolean hasReceiver, TypePath path
|
||||
AstNode n, ContextTyping::FunctionPositionKind kind, TypePath path
|
||||
) {
|
||||
hasReceiver = false and
|
||||
exists(ConstructionMatchingInput::Access a | n = a.getNodeAt(pos) |
|
||||
exists(ConstructionMatchingInput::Access a, FunctionPosition pos |
|
||||
n = a.getNodeAt(pos) and
|
||||
if pos.isPosition()
|
||||
then kind = ContextTyping::PositionalKind()
|
||||
else kind = ContextTyping::ReturnKind()
|
||||
|
|
||||
result = ConstructionMatching::inferAccessType(a, pos, path)
|
||||
or
|
||||
a.hasUnknownTypeAt(pos, path) and
|
||||
@@ -3072,7 +3130,7 @@ private Type inferConstructionTypePreCheck(
|
||||
}
|
||||
|
||||
private predicate inferConstructionType =
|
||||
ContextTyping::CheckContextTyping<inferConstructionTypePreCheck/4>::check/2;
|
||||
ContextTyping::CheckContextTyping<inferConstructionTypePreCheck/3>::check/2;
|
||||
|
||||
/**
|
||||
* A matching configuration for resolving types of operations like `a + b`.
|
||||
@@ -3138,17 +3196,22 @@ private module OperationMatching = Matching<OperationMatchingInput>;
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferOperationTypePreCheck(
|
||||
AstNode n, FunctionPosition pos, boolean hasReceiver, TypePath path
|
||||
AstNode n, ContextTyping::FunctionPositionKind kind, TypePath path
|
||||
) {
|
||||
exists(OperationMatchingInput::Access a |
|
||||
exists(OperationMatchingInput::Access a, FunctionPosition pos |
|
||||
n = a.getNodeAt(pos) and
|
||||
result = OperationMatching::inferAccessType(a, pos, path) and
|
||||
hasReceiver = true
|
||||
if pos.asPosition() = 0
|
||||
then kind = ContextTyping::SelfKind()
|
||||
else
|
||||
if pos.isPosition()
|
||||
then kind = ContextTyping::PositionalKind()
|
||||
else kind = ContextTyping::ReturnKind()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate inferOperationType =
|
||||
ContextTyping::CheckContextTyping<inferOperationTypePreCheck/4>::check/2;
|
||||
ContextTyping::CheckContextTyping<inferOperationTypePreCheck/3>::check/2;
|
||||
|
||||
pragma[nomagic]
|
||||
private Type getFieldExprLookupType(FieldExpr fe, string name, DerefChain derefChain) {
|
||||
@@ -3468,7 +3531,7 @@ final private class AwaitTarget extends Expr {
|
||||
Type getTypeAt(TypePath path) { result = inferType(this, path) }
|
||||
}
|
||||
|
||||
private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInputSig<AwaitTarget> {
|
||||
private module AwaitSatisfiesTypeInput implements SatisfiesTypeInputSig<AwaitTarget> {
|
||||
pragma[nomagic]
|
||||
predicate relevantConstraint(AwaitTarget term, Type constraint) {
|
||||
exists(term) and
|
||||
@@ -3476,13 +3539,12 @@ private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInput
|
||||
}
|
||||
}
|
||||
|
||||
private module AwaitSatisfiesConstraint =
|
||||
SatisfiesConstraint<AwaitTarget, AwaitSatisfiesConstraintInput>;
|
||||
private module AwaitSatisfiesType = SatisfiesType<AwaitTarget, AwaitSatisfiesTypeInput>;
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferAwaitExprType(AstNode n, TypePath path) {
|
||||
exists(TypePath exprPath |
|
||||
AwaitSatisfiesConstraint::satisfiesConstraintType(n.(AwaitExpr).getExpr(), _, exprPath, result) and
|
||||
AwaitSatisfiesType::satisfiesConstraintType(n.(AwaitExpr).getExpr(), _, exprPath, result) and
|
||||
exprPath.isCons(getFutureOutputTypeParameter(), path)
|
||||
)
|
||||
}
|
||||
@@ -3620,9 +3682,7 @@ final private class ForIterableExpr extends Expr {
|
||||
Type getTypeAt(TypePath path) { result = inferType(this, path) }
|
||||
}
|
||||
|
||||
private module ForIterableSatisfiesConstraintInput implements
|
||||
SatisfiesConstraintInputSig<ForIterableExpr>
|
||||
{
|
||||
private module ForIterableSatisfiesTypeInput implements SatisfiesTypeInputSig<ForIterableExpr> {
|
||||
predicate relevantConstraint(ForIterableExpr term, Type constraint) {
|
||||
exists(term) and
|
||||
exists(Trait t | t = constraint.(TraitType).getTrait() |
|
||||
@@ -3643,15 +3703,15 @@ private AssociatedTypeTypeParameter getIntoIteratorItemTypeParameter() {
|
||||
result = getAssociatedTypeTypeParameter(any(IntoIteratorTrait t).getItemType())
|
||||
}
|
||||
|
||||
private module ForIterableSatisfiesConstraint =
|
||||
SatisfiesConstraint<ForIterableExpr, ForIterableSatisfiesConstraintInput>;
|
||||
private module ForIterableSatisfiesType =
|
||||
SatisfiesType<ForIterableExpr, ForIterableSatisfiesTypeInput>;
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferForLoopExprType(AstNode n, TypePath path) {
|
||||
// type of iterable -> type of pattern (loop variable)
|
||||
exists(ForExpr fe, TypePath exprPath, AssociatedTypeTypeParameter tp |
|
||||
n = fe.getPat() and
|
||||
ForIterableSatisfiesConstraint::satisfiesConstraintType(fe.getIterable(), _, exprPath, result) and
|
||||
ForIterableSatisfiesType::satisfiesConstraintType(fe.getIterable(), _, exprPath, result) and
|
||||
exprPath.isCons(tp, path)
|
||||
|
|
||||
tp = getIntoIteratorItemTypeParameter()
|
||||
@@ -3677,8 +3737,7 @@ final private class InvokedClosureExpr extends Expr {
|
||||
CallExpr getCall() { result = call }
|
||||
}
|
||||
|
||||
private module InvokedClosureSatisfiesConstraintInput implements
|
||||
SatisfiesConstraintInputSig<InvokedClosureExpr>
|
||||
private module InvokedClosureSatisfiesTypeInput implements SatisfiesTypeInputSig<InvokedClosureExpr>
|
||||
{
|
||||
predicate relevantConstraint(InvokedClosureExpr term, Type constraint) {
|
||||
exists(term) and
|
||||
@@ -3686,12 +3745,12 @@ private module InvokedClosureSatisfiesConstraintInput implements
|
||||
}
|
||||
}
|
||||
|
||||
private module InvokedClosureSatisfiesConstraint =
|
||||
SatisfiesConstraint<InvokedClosureExpr, InvokedClosureSatisfiesConstraintInput>;
|
||||
private module InvokedClosureSatisfiesType =
|
||||
SatisfiesType<InvokedClosureExpr, InvokedClosureSatisfiesTypeInput>;
|
||||
|
||||
/** Gets the type of `ce` when viewed as an implementation of `FnOnce`. */
|
||||
private Type invokedClosureFnTypeAt(InvokedClosureExpr ce, TypePath path) {
|
||||
InvokedClosureSatisfiesConstraint::satisfiesConstraintType(ce, _, path, result)
|
||||
InvokedClosureSatisfiesType::satisfiesConstraintType(ce, _, path, result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3911,10 +3970,11 @@ private module Cached {
|
||||
or
|
||||
// Don't propagate type information into a node which conflicts with certain
|
||||
// type information.
|
||||
(
|
||||
if CertainTypeInference::hasInferredCertainType(n)
|
||||
then not CertainTypeInference::certainTypeConflict(n, path, result)
|
||||
else any()
|
||||
forall(TypePath prefix |
|
||||
CertainTypeInference::hasInferredCertainType(n, prefix) and
|
||||
prefix.isPrefixOf(path)
|
||||
|
|
||||
not CertainTypeInference::certainTypeConflict(n, prefix, path, result)
|
||||
) and
|
||||
(
|
||||
result = inferAssignmentOperationType(n, path)
|
||||
@@ -3981,7 +4041,7 @@ private module Debug {
|
||||
TypeAbstraction abs, TypeMention condition, TypeMention constraint, boolean transitive
|
||||
) {
|
||||
abs = getRelevantLocatable() and
|
||||
Input::conditionSatisfiesConstraint(abs, condition, constraint, transitive)
|
||||
Input2::conditionSatisfiesConstraint(abs, condition, constraint, transitive)
|
||||
}
|
||||
|
||||
predicate debugInferShorthandSelfType(ShorthandSelfParameterMention self, TypePath path, Type t) {
|
||||
|
||||
@@ -205,6 +205,13 @@ private module MkTypeMention<getAdditionalPathTypeAtSig/2 getAdditionalPathTypeA
|
||||
)
|
||||
or
|
||||
exists(TypeParamItemNode tp | this = tp.getABoundPath() and result = tp)
|
||||
or
|
||||
// `<result as this>::...`
|
||||
exists(PathTypeRepr typeRepr, PathTypeRepr traitRepr |
|
||||
pathTypeAsTraitAssoc(_, typeRepr, traitRepr, _, _) and
|
||||
this = traitRepr.getPath() and
|
||||
result = typeRepr.getPath()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -696,16 +703,26 @@ private module PreTypeMention = MkTypeMention<preGetAdditionalPathTypeAt/2>;
|
||||
|
||||
class PreTypeMention = PreTypeMention::TypeMention;
|
||||
|
||||
private class TraitOrTmTrait extends AstNode {
|
||||
Type getTypeAt(TypePath path) {
|
||||
pathTypeAsTraitAssoc(_, _, this, _, _) and
|
||||
result = this.(PreTypeMention).getTypeAt(path)
|
||||
or
|
||||
result = TTrait(this) and
|
||||
path.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `path` accesses an associated type `alias` from `trait` on a
|
||||
* concrete type given by `tm`.
|
||||
*
|
||||
* `implOrTmTrait` is either the mention that resolves to `trait` when `path`
|
||||
* is of the form `<Type as Trait>::AssocType`, or the enclosing `impl` block
|
||||
* when `path` is of the form `Self::AssocType`.
|
||||
* `traitOrTmTrait` is either the mention that resolves to `trait` when `path`
|
||||
* is of the form `<Type as Trait>::AssocType`, or the trait being implemented
|
||||
* when `path` is of the form `Self::AssocType` within an `impl` block.
|
||||
*/
|
||||
private predicate pathConcreteTypeAssocType(
|
||||
Path path, PreTypeMention tm, TraitItemNode trait, AstNode implOrTmTrait, TypeAlias alias
|
||||
Path path, PreTypeMention tm, TraitItemNode trait, TraitOrTmTrait traitOrTmTrait, TypeAlias alias
|
||||
) {
|
||||
exists(Path qualifier |
|
||||
qualifier = path.getQualifier() and
|
||||
@@ -713,31 +730,34 @@ private predicate pathConcreteTypeAssocType(
|
||||
|
|
||||
// path of the form `<Type as Trait>::AssocType`
|
||||
// ^^^ tm ^^^^^^^^^ name
|
||||
// ^^^^^ traitOrTmTrait
|
||||
exists(string name |
|
||||
pathTypeAsTraitAssoc(path, tm, implOrTmTrait, trait, name) and
|
||||
pathTypeAsTraitAssoc(path, tm, traitOrTmTrait, trait, name) and
|
||||
getTraitAssocType(trait, name) = alias
|
||||
)
|
||||
or
|
||||
// path of the form `Self::AssocType` within an `impl` block
|
||||
// tm ^^^^ ^^^^^^^^^ name
|
||||
implOrTmTrait =
|
||||
any(ImplItemNode impl |
|
||||
alias = resolvePath(path) and
|
||||
qualifier = impl.getASelfPath() and
|
||||
tm = impl.(Impl).getSelfTy() and
|
||||
trait.getAnAssocItem() = alias
|
||||
)
|
||||
exists(ImplItemNode impl |
|
||||
alias = resolvePath(path) and
|
||||
qualifier = impl.getASelfPath() and
|
||||
tm = impl.(Impl).getSelfTy() and
|
||||
trait.getAnAssocItem() = alias and
|
||||
traitOrTmTrait = trait
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private module PathSatisfiesConstraintInput implements SatisfiesConstraintInputSig<PreTypeMention> {
|
||||
predicate relevantConstraint(PreTypeMention tm, Type constraint) {
|
||||
pathConcreteTypeAssocType(_, tm, constraint.(TraitType).getTrait(), _, _)
|
||||
private module PathSatisfiesConstraintInput implements
|
||||
PreM2::SatisfiesConstraintInputSig<PreTypeMention, TraitOrTmTrait>
|
||||
{
|
||||
predicate relevantConstraint(PreTypeMention tm, TraitOrTmTrait constraint) {
|
||||
pathConcreteTypeAssocType(_, tm, _, constraint, _)
|
||||
}
|
||||
}
|
||||
|
||||
private module PathSatisfiesConstraint =
|
||||
SatisfiesConstraint<PreTypeMention, PathSatisfiesConstraintInput>;
|
||||
PreM2::SatisfiesConstraint<PreTypeMention, TraitOrTmTrait, PathSatisfiesConstraintInput>;
|
||||
|
||||
/**
|
||||
* Gets the type of `path` at `typePath` when `path` accesses an associated type
|
||||
@@ -745,26 +765,12 @@ private module PathSatisfiesConstraint =
|
||||
*/
|
||||
private Type getPathConcreteAssocTypeAt(Path path, TypePath typePath) {
|
||||
exists(
|
||||
PreTypeMention tm, ImplItemNode impl, TraitItemNode trait, TraitType t, AstNode implOrTmTrait,
|
||||
PreTypeMention tm, ImplItemNode impl, TraitItemNode trait, TraitOrTmTrait traitOrTmTrait,
|
||||
TypeAlias alias, TypePath path0
|
||||
|
|
||||
pathConcreteTypeAssocType(path, tm, trait, implOrTmTrait, alias) and
|
||||
t = TTrait(trait) and
|
||||
PathSatisfiesConstraint::satisfiesConstraintTypeThrough(tm, impl, t, path0, result) and
|
||||
pathConcreteTypeAssocType(path, tm, trait, traitOrTmTrait, alias) and
|
||||
PathSatisfiesConstraint::satisfiesConstraintTypeThrough(tm, impl, traitOrTmTrait, path0, result) and
|
||||
path0.isCons(TAssociatedTypeTypeParameter(trait, alias), typePath)
|
||||
|
|
||||
implOrTmTrait instanceof Impl
|
||||
or
|
||||
// When `path` is of the form `<Type as Trait>::AssocType` we need to check
|
||||
// that `impl` is not more specific than the mentioned trait
|
||||
implOrTmTrait =
|
||||
any(PreTypeMention tmTrait |
|
||||
not exists(TypePath path1, Type t1 |
|
||||
t1 = impl.getTraitPath().(PreTypeMention).getTypeAt(path1) and
|
||||
not t1 instanceof TypeParameter and
|
||||
t1 != tmTrait.getTypeAt(path1)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -449,3 +449,75 @@ mod inherent_before_trait {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod trait_bound_impl_overlap {
|
||||
trait MyTrait<T> {
|
||||
fn f(&self) -> T;
|
||||
}
|
||||
|
||||
trait MyTrait2<T = Self> {
|
||||
type Output;
|
||||
|
||||
fn f(&self, x: T) -> Self::Output;
|
||||
}
|
||||
|
||||
struct S<T>(T);
|
||||
|
||||
impl MyTrait<i32> for S<i32> {
|
||||
fn f(&self) -> i32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl MyTrait<i64> for S<i32> {
|
||||
fn f(&self) -> i64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl MyTrait2<S<i32>> for S<i32> {
|
||||
type Output = i32;
|
||||
|
||||
fn f(&self, x: S<i32>) -> Self::Output {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl MyTrait2<S<i64>> for S<i32> {
|
||||
type Output = <Self as MyTrait2<S<bool>>>::Output;
|
||||
|
||||
fn f(&self, x: S<i64>) -> Self::Output {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl MyTrait2<S<bool>> for S<i32> {
|
||||
type Output = i64;
|
||||
|
||||
fn f(&self, x: S<bool>) -> Self::Output {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn call_f<T1, T2: MyTrait<T1>>(x: T2) -> T1 {
|
||||
x.f() // $ target=f
|
||||
}
|
||||
|
||||
fn call_f2<T1, T2: MyTrait2<T1>>(x: T1, y: T2) -> T2::Output {
|
||||
y.f(x) // $ target=f
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let x = S(0);
|
||||
let y = call_f(x); // $ target=call_f type=y:i32
|
||||
let z: i32 = y;
|
||||
|
||||
let x = S(0);
|
||||
let y = call_f::<i32, _>(x); // $ target=call_f type=y:i32
|
||||
|
||||
let x = S(0);
|
||||
let y = call_f2(S(0i32), x); // $ target=call_f2 type=y:i32
|
||||
let x = S(0);
|
||||
let y = call_f2(S(0i64), x); // $ target=call_f2 type=y:i64
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,15 +209,15 @@ inferCertainType
|
||||
| associated_types.rs:454:24:454:28 | SelfParam | TRef | associated_types.rs:452:5:455:5 | Self [trait Subtrait] |
|
||||
| associated_types.rs:463:23:463:27 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| associated_types.rs:463:23:463:27 | SelfParam | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] |
|
||||
| associated_types.rs:463:30:463:31 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] |
|
||||
| associated_types.rs:463:48:463:49 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] |
|
||||
| associated_types.rs:463:30:463:31 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] |
|
||||
| associated_types.rs:463:48:463:49 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] |
|
||||
| associated_types.rs:463:66:466:9 | { ... } | | {EXTERNAL LOCATION} | () |
|
||||
| associated_types.rs:464:13:464:16 | self | | {EXTERNAL LOCATION} | & |
|
||||
| associated_types.rs:464:13:464:16 | self | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] |
|
||||
| associated_types.rs:464:22:464:23 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] |
|
||||
| associated_types.rs:464:22:464:23 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] |
|
||||
| associated_types.rs:465:13:465:16 | self | | {EXTERNAL LOCATION} | & |
|
||||
| associated_types.rs:465:13:465:16 | self | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] |
|
||||
| associated_types.rs:465:22:465:23 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] |
|
||||
| associated_types.rs:465:22:465:23 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] |
|
||||
| associated_types.rs:474:16:474:20 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| associated_types.rs:474:16:474:20 | SelfParam | TRef | associated_types.rs:469:5:469:24 | MyType |
|
||||
| associated_types.rs:474:16:474:20 | SelfParam | TRef.T | associated_types.rs:471:10:471:16 | T |
|
||||
@@ -4079,6 +4079,51 @@ inferCertainType
|
||||
| overloading.rs:448:13:448:16 | self | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:448:13:448:16 | self | TRef | overloading.rs:405:5:405:19 | S |
|
||||
| overloading.rs:448:13:448:16 | self | TRef.T | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:455:14:455:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:455:14:455:18 | SelfParam | TRef | overloading.rs:454:5:456:5 | Self [trait MyTrait] |
|
||||
| overloading.rs:461:14:461:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:461:14:461:18 | SelfParam | TRef | overloading.rs:458:5:462:5 | Self [trait MyTrait2] |
|
||||
| overloading.rs:461:21:461:21 | x | | overloading.rs:458:20:458:27 | T |
|
||||
| overloading.rs:467:14:467:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:467:14:467:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:467:14:467:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:467:28:469:9 | { ... } | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:473:14:473:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:473:14:473:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:473:14:473:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:473:28:475:9 | { ... } | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:481:14:481:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:481:14:481:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:481:14:481:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:481:21:481:21 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:481:21:481:21 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:481:48:483:9 | { ... } | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:489:14:489:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:489:14:489:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:489:14:489:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:489:21:489:21 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:489:21:489:21 | x | T | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:489:48:491:9 | { ... } | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:497:14:497:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:497:14:497:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:497:14:497:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:497:21:497:21 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:497:21:497:21 | x | T | {EXTERNAL LOCATION} | bool |
|
||||
| overloading.rs:497:49:499:9 | { ... } | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:502:36:502:36 | x | | overloading.rs:502:19:502:33 | T2 |
|
||||
| overloading.rs:502:49:504:5 | { ... } | | overloading.rs:502:15:502:16 | T1 |
|
||||
| overloading.rs:503:9:503:9 | x | | overloading.rs:502:19:502:33 | T2 |
|
||||
| overloading.rs:506:38:506:38 | x | | overloading.rs:506:16:506:17 | T1 |
|
||||
| overloading.rs:506:45:506:45 | y | | overloading.rs:506:20:506:35 | T2 |
|
||||
| overloading.rs:506:66:508:5 | { ... } | | overloading.rs:506:20:506:35 | T2::Output[MyTrait2] |
|
||||
| overloading.rs:507:9:507:9 | y | | overloading.rs:506:20:506:35 | T2 |
|
||||
| overloading.rs:507:13:507:13 | x | | overloading.rs:506:16:506:17 | T1 |
|
||||
| overloading.rs:510:15:522:5 | { ... } | | {EXTERNAL LOCATION} | () |
|
||||
| overloading.rs:513:13:513:13 | z | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:516:13:516:13 | y | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:516:17:516:35 | call_f::<...>(...) | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:519:27:519:30 | 0i32 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:521:27:521:30 | 0i64 | | {EXTERNAL LOCATION} | i64 |
|
||||
| pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option |
|
||||
| pattern_matching.rs:13:26:133:1 | { ... } | T | {EXTERNAL LOCATION} | () |
|
||||
| pattern_matching.rs:15:5:18:5 | if ... {...} | | {EXTERNAL LOCATION} | () |
|
||||
@@ -5396,17 +5441,17 @@ inferType
|
||||
| associated_types.rs:454:24:454:28 | SelfParam | TRef | associated_types.rs:452:5:455:5 | Self [trait Subtrait] |
|
||||
| associated_types.rs:463:23:463:27 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| associated_types.rs:463:23:463:27 | SelfParam | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] |
|
||||
| associated_types.rs:463:30:463:31 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] |
|
||||
| associated_types.rs:463:48:463:49 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] |
|
||||
| associated_types.rs:463:30:463:31 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] |
|
||||
| associated_types.rs:463:48:463:49 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] |
|
||||
| associated_types.rs:463:66:466:9 | { ... } | | {EXTERNAL LOCATION} | () |
|
||||
| associated_types.rs:464:13:464:16 | self | | {EXTERNAL LOCATION} | & |
|
||||
| associated_types.rs:464:13:464:16 | self | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] |
|
||||
| associated_types.rs:464:13:464:24 | self.set(...) | | {EXTERNAL LOCATION} | () |
|
||||
| associated_types.rs:464:22:464:23 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] |
|
||||
| associated_types.rs:464:22:464:23 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] |
|
||||
| associated_types.rs:465:13:465:16 | self | | {EXTERNAL LOCATION} | & |
|
||||
| associated_types.rs:465:13:465:16 | self | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] |
|
||||
| associated_types.rs:465:13:465:24 | self.set(...) | | {EXTERNAL LOCATION} | () |
|
||||
| associated_types.rs:465:22:465:23 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] |
|
||||
| associated_types.rs:465:22:465:23 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] |
|
||||
| associated_types.rs:474:16:474:20 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| associated_types.rs:474:16:474:20 | SelfParam | TRef | associated_types.rs:469:5:469:24 | MyType |
|
||||
| associated_types.rs:474:16:474:20 | SelfParam | TRef.T | associated_types.rs:471:10:471:16 | T |
|
||||
@@ -10730,7 +10775,6 @@ inferType
|
||||
| main.rs:2032:56:2034:9 | { ... } | | {EXTERNAL LOCATION} | & |
|
||||
| main.rs:2032:56:2034:9 | { ... } | TRef | main.rs:2028:10:2028:10 | T |
|
||||
| main.rs:2033:13:2033:29 | &... | | {EXTERNAL LOCATION} | & |
|
||||
| main.rs:2033:13:2033:29 | &... | TRef | {EXTERNAL LOCATION} | u8 |
|
||||
| main.rs:2033:13:2033:29 | &... | TRef | main.rs:2028:10:2028:10 | T |
|
||||
| main.rs:2033:14:2033:17 | self | | {EXTERNAL LOCATION} | & |
|
||||
| main.rs:2033:14:2033:17 | self | TRef | main.rs:2013:5:2016:5 | MyVec |
|
||||
@@ -10738,7 +10782,6 @@ inferType
|
||||
| main.rs:2033:14:2033:22 | self.data | | {EXTERNAL LOCATION} | Vec |
|
||||
| main.rs:2033:14:2033:22 | self.data | A | {EXTERNAL LOCATION} | Global |
|
||||
| main.rs:2033:14:2033:22 | self.data | T | main.rs:2028:10:2028:10 | T |
|
||||
| main.rs:2033:14:2033:29 | ...[index] | | {EXTERNAL LOCATION} | u8 |
|
||||
| main.rs:2033:14:2033:29 | ...[index] | | main.rs:2028:10:2028:10 | T |
|
||||
| main.rs:2033:24:2033:28 | index | | {EXTERNAL LOCATION} | usize |
|
||||
| main.rs:2037:22:2037:26 | slice | | {EXTERNAL LOCATION} | & |
|
||||
@@ -12830,6 +12873,100 @@ inferType
|
||||
| overloading.rs:448:13:448:16 | self | TRef | overloading.rs:405:5:405:19 | S |
|
||||
| overloading.rs:448:13:448:16 | self | TRef.T | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:448:13:448:22 | self.bar() | | {EXTERNAL LOCATION} | () |
|
||||
| overloading.rs:455:14:455:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:455:14:455:18 | SelfParam | TRef | overloading.rs:454:5:456:5 | Self [trait MyTrait] |
|
||||
| overloading.rs:461:14:461:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:461:14:461:18 | SelfParam | TRef | overloading.rs:458:5:462:5 | Self [trait MyTrait2] |
|
||||
| overloading.rs:461:21:461:21 | x | | overloading.rs:458:20:458:27 | T |
|
||||
| overloading.rs:467:14:467:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:467:14:467:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:467:14:467:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:467:28:469:9 | { ... } | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:468:13:468:13 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:473:14:473:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:473:14:473:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:473:14:473:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:473:28:475:9 | { ... } | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:474:13:474:13 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:474:13:474:13 | 0 | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:481:14:481:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:481:14:481:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:481:14:481:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:481:21:481:21 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:481:21:481:21 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:481:48:483:9 | { ... } | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:482:13:482:13 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:489:14:489:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:489:14:489:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:489:14:489:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:489:21:489:21 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:489:21:489:21 | x | T | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:489:48:491:9 | { ... } | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:490:13:490:13 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:490:13:490:13 | 0 | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:497:14:497:18 | SelfParam | | {EXTERNAL LOCATION} | & |
|
||||
| overloading.rs:497:14:497:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:497:14:497:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:497:21:497:21 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:497:21:497:21 | x | T | {EXTERNAL LOCATION} | bool |
|
||||
| overloading.rs:497:49:499:9 | { ... } | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:498:13:498:13 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:498:13:498:13 | 0 | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:502:36:502:36 | x | | overloading.rs:502:19:502:33 | T2 |
|
||||
| overloading.rs:502:49:504:5 | { ... } | | overloading.rs:502:15:502:16 | T1 |
|
||||
| overloading.rs:503:9:503:9 | x | | overloading.rs:502:19:502:33 | T2 |
|
||||
| overloading.rs:503:9:503:13 | x.f() | | overloading.rs:502:15:502:16 | T1 |
|
||||
| overloading.rs:506:38:506:38 | x | | overloading.rs:506:16:506:17 | T1 |
|
||||
| overloading.rs:506:45:506:45 | y | | overloading.rs:506:20:506:35 | T2 |
|
||||
| overloading.rs:506:66:508:5 | { ... } | | overloading.rs:506:20:506:35 | T2::Output[MyTrait2] |
|
||||
| overloading.rs:507:9:507:9 | y | | overloading.rs:506:20:506:35 | T2 |
|
||||
| overloading.rs:507:9:507:14 | y.f(...) | | overloading.rs:506:20:506:35 | T2::Output[MyTrait2] |
|
||||
| overloading.rs:507:13:507:13 | x | | overloading.rs:506:16:506:17 | T1 |
|
||||
| overloading.rs:510:15:522:5 | { ... } | | {EXTERNAL LOCATION} | () |
|
||||
| overloading.rs:511:13:511:13 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:511:13:511:13 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:511:17:511:20 | S(...) | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:511:17:511:20 | S(...) | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:511:19:511:19 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:512:13:512:13 | y | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:512:17:512:25 | call_f(...) | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:512:24:512:24 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:512:24:512:24 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:513:13:513:13 | z | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:513:22:513:22 | y | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:515:13:515:13 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:515:13:515:13 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:515:17:515:20 | S(...) | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:515:17:515:20 | S(...) | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:515:19:515:19 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:516:13:516:13 | y | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:516:17:516:35 | call_f::<...>(...) | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:516:34:516:34 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:516:34:516:34 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:518:13:518:13 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:518:13:518:13 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:518:17:518:20 | S(...) | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:518:17:518:20 | S(...) | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:518:19:518:19 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:519:13:519:13 | y | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:519:17:519:35 | call_f2(...) | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:519:25:519:31 | S(...) | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:519:25:519:31 | S(...) | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:519:27:519:30 | 0i32 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:519:34:519:34 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:519:34:519:34 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:520:13:520:13 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:520:13:520:13 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:520:17:520:20 | S(...) | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:520:17:520:20 | S(...) | T | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:520:19:520:19 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| overloading.rs:521:13:521:13 | y | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:521:17:521:35 | call_f2(...) | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:521:25:521:31 | S(...) | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:521:25:521:31 | S(...) | T | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:521:27:521:30 | 0i64 | | {EXTERNAL LOCATION} | i64 |
|
||||
| overloading.rs:521:34:521:34 | x | | overloading.rs:464:5:464:19 | S |
|
||||
| overloading.rs:521:34:521:34 | x | T | {EXTERNAL LOCATION} | i32 |
|
||||
| pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option |
|
||||
| pattern_matching.rs:13:26:133:1 | { ... } | T | {EXTERNAL LOCATION} | () |
|
||||
| pattern_matching.rs:14:9:14:13 | value | | {EXTERNAL LOCATION} | Option |
|
||||
|
||||
Reference in New Issue
Block a user