mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Rust: Generalize certain type inference logic
This commit is contained in:
@@ -15,6 +15,14 @@ private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
|
||||
|
||||
class Type = T::Type;
|
||||
|
||||
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().getTypeArg(pos))
|
||||
} or
|
||||
TTypeParamTypeArgumentPosition(TypeParam tp)
|
||||
|
||||
private module Input1 implements InputSig1<Location> {
|
||||
private import Type as T
|
||||
private import codeql.rust.elements.internal.generated.Raw
|
||||
@@ -26,14 +34,6 @@ private module Input1 implements InputSig1<Location> {
|
||||
|
||||
class TypeAbstraction = T::TypeAbstraction;
|
||||
|
||||
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().getTypeArg(pos))
|
||||
} or
|
||||
TTypeParamTypeArgumentPosition(TypeParam tp)
|
||||
|
||||
class TypeArgumentPosition extends TTypeArgumentPosition {
|
||||
int asMethodTypeArgumentPosition() { this = TMethodTypeArgumentPosition(result) }
|
||||
|
||||
@@ -257,75 +257,59 @@ private Type inferAnnotatedType(AstNode n, TypePath path) {
|
||||
|
||||
/** Module for inferring certain type information. */
|
||||
private module CertainTypeInference {
|
||||
/** Holds if the type mention does not contain any inferred types `_`. */
|
||||
predicate typeMentionIsComplete(TypeMention tm) {
|
||||
not exists(InferTypeRepr t | t.getParentNode*() = tm)
|
||||
pragma[nomagic]
|
||||
private predicate callResolvesTo(CallExpr ce, Path p, Function f) {
|
||||
p = CallExprImpl::getFunctionPath(ce) and
|
||||
f = resolvePath(p)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `ce` is a call where we can infer the type with certainty and if
|
||||
* `f` is the target of the call and `p` the path invoked by the call.
|
||||
*
|
||||
* Necessary conditions for this are:
|
||||
* - We are certain of the call target (i.e., the call target can not depend on type information).
|
||||
* - The declared type of the function does not contain any generics that we
|
||||
* need to infer.
|
||||
* - The call does not contain any arguments, as arguments in calls are coercion sites.
|
||||
*
|
||||
* The current requirements are made to allow for call to `new` functions such
|
||||
* as `Vec<Foo>::new()` but not much more.
|
||||
*/
|
||||
predicate certainCallExprTarget(CallExpr ce, Function f, Path p) {
|
||||
p = CallExprImpl::getFunctionPath(ce) and
|
||||
f = resolvePath(p) and
|
||||
// The function is not in a trait
|
||||
not any(TraitItemNode t).getAnAssocItem() = f and
|
||||
// The function is not in a trait implementation
|
||||
not any(ImplItemNode impl | impl.(Impl).hasTrait()).getAnAssocItem() = f and
|
||||
// The function does not have parameters.
|
||||
not f.getParamList().hasSelfParam() and
|
||||
f.getParamList().getNumberOfParams() = 0 and
|
||||
// The function is not async.
|
||||
not f.isAsync() and
|
||||
// For now, exclude functions in macro expansions.
|
||||
not ce.isInMacroExpansion() and
|
||||
// The function has no type parameters.
|
||||
not f.hasGenericParamList() and
|
||||
// The function does not have `impl` types among its parameters (these are type parameters).
|
||||
not any(ImplTraitTypeRepr itt | not itt.isInReturnPos()).getFunction() = f and
|
||||
(
|
||||
not exists(ImplItemNode impl | impl.getAnAssocItem() = f)
|
||||
or
|
||||
// If the function is in an impl then the impl block has no type
|
||||
// parameters or all the type parameters are given explicitly.
|
||||
exists(ImplItemNode impl | impl.getAnAssocItem() = f |
|
||||
not impl.(Impl).hasGenericParamList() or
|
||||
impl.(Impl).getGenericParamList().getNumberOfGenericParams() =
|
||||
p.getQualifier().getSegment().getGenericArgList().getNumberOfGenericArgs()
|
||||
)
|
||||
pragma[nomagic]
|
||||
private Type getCallExprType(
|
||||
CallExpr ce, Path p, CallExprBaseMatchingInput::FunctionDecl f, TypePath tp
|
||||
) {
|
||||
callResolvesTo(ce, p, f) and
|
||||
result = f.getReturnType(tp)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type getCertainCallExprType(CallExpr ce, Path p, TypePath tp) {
|
||||
forex(Function f | callResolvesTo(ce, p, f) | result = getCallExprType(ce, p, f, tp))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private TypePath getPathToImplSelfTypeParam(TypeParam tp) {
|
||||
exists(ImplItemNode impl |
|
||||
tp = impl.getTypeParam(_) and
|
||||
TTypeParamTypeParameter(tp) = impl.(Impl).getSelfTy().(TypeMention).resolveTypeAt(result)
|
||||
)
|
||||
}
|
||||
|
||||
private ImplItemNode getFunctionImpl(FunctionItemNode f) { result.getAnAssocItem() = f }
|
||||
|
||||
pragma[nomagic]
|
||||
Type inferCertainCallExprType(CallExpr ce, TypePath path) {
|
||||
exists(Function f, Type ty, TypePath prefix, Path p |
|
||||
certainCallExprTarget(ce, f, p) and
|
||||
ty = f.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(prefix)
|
||||
|
|
||||
if ty.(TypeParamTypeParameter).getTypeParam() = getFunctionImpl(f).getTypeParam(_)
|
||||
then
|
||||
exists(TypePath pathToTp, TypePath suffix |
|
||||
// For type parameters of the `impl` block we must resolve their
|
||||
// instantiation from the path. For instance, for `impl<A> for Foo<A>`
|
||||
// and the path `Foo<i64>::bar` we must resolve `A` to `i64`.
|
||||
ty = getFunctionImpl(f).(Impl).getSelfTy().(TypeMention).resolveTypeAt(pathToTp) and
|
||||
result = p.getQualifier().(TypeMention).resolveTypeAt(pathToTp.appendInverse(suffix)) and
|
||||
path = prefix.append(suffix)
|
||||
exists(Type ty, TypePath prefix, Path p | ty = getCertainCallExprType(ce, p, prefix) |
|
||||
exists(TypePath suffix, TypeParam tp |
|
||||
tp = ty.(TypeParamTypeParameter).getTypeParam() and
|
||||
path = prefix.append(suffix)
|
||||
|
|
||||
// For type parameters of the `impl` block we must resolve their
|
||||
// instantiation from the path. For instance, for `impl<A> for Foo<A>`
|
||||
// and the path `Foo<i64>::bar` we must resolve `A` to `i64`.
|
||||
exists(TypePath pathToTp |
|
||||
pathToTp = getPathToImplSelfTypeParam(tp) and
|
||||
result = p.getQualifier().(TypeMention).resolveTypeAt(pathToTp.appendInverse(suffix))
|
||||
)
|
||||
else (
|
||||
result = ty and path = prefix
|
||||
or
|
||||
// For type parameters of the function we must resolve their
|
||||
// instantiation from the path. For instance, for `fn bar<A>(a: A) -> A`
|
||||
// and the path `bar<i64>`, we must resolve `A` to `i64`.
|
||||
result =
|
||||
ce.(CallExprBaseMatchingInput::Access)
|
||||
.getTypeArgument(TTypeParamTypeArgumentPosition(tp), suffix)
|
||||
)
|
||||
or
|
||||
not ty instanceof TypeParameter and
|
||||
result = ty and
|
||||
path = prefix
|
||||
)
|
||||
}
|
||||
|
||||
@@ -343,6 +327,8 @@ private module CertainTypeInference {
|
||||
let.getPat() = n1 and
|
||||
let.getInitializer() = n2
|
||||
)
|
||||
or
|
||||
n1 = n2.(ParenExpr).getExpr()
|
||||
)
|
||||
or
|
||||
n1 =
|
||||
@@ -373,13 +359,57 @@ private module CertainTypeInference {
|
||||
Type inferCertainType(AstNode n, TypePath path) {
|
||||
exists(TypeMention tm |
|
||||
tm = getTypeAnnotation(n) and
|
||||
typeMentionIsComplete(tm) and
|
||||
result = tm.resolveTypeAt(path)
|
||||
)
|
||||
or
|
||||
result = inferCertainCallExprType(n, path)
|
||||
or
|
||||
result = inferCertainTypeEquality(n, path)
|
||||
or
|
||||
result = inferLiteralType(n, path, true)
|
||||
or
|
||||
infersCertainTypeAt(n, path, result.getATypeParameter())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` has complete and certain type information at the type path
|
||||
* `prefix.tp`. This entails that the type at `prefix` must be the type
|
||||
* that declares `tp`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate infersCertainTypeAt(AstNode n, TypePath prefix, TypeParameter tp) {
|
||||
exists(TypePath path |
|
||||
exists(inferCertainType(n, path)) and
|
||||
path.isSnoc(prefix, tp)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` has complete and certain type information at _some_ type path.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate hasInferredCertainType(AstNode n) { exists(inferCertainType(n, _)) }
|
||||
|
||||
/**
|
||||
* Holds if `n` having type `t` at `path` conflicts with certain type information.
|
||||
*/
|
||||
bindingset[n, path, t]
|
||||
pragma[inline_late]
|
||||
predicate certainTypeConflict(AstNode n, TypePath path, Type t) {
|
||||
inferCertainType(n, path) != t
|
||||
or
|
||||
// If we infer that `n` has _some_ type at `T1.T2....Tn`, and we also
|
||||
// know that `n` certainly has type `certainType` at `T1.T2...Ti`, `i <=0 < n`,
|
||||
// then it must be the case that `T(i+1)` is a type parameter of `certainType`,
|
||||
// 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 |
|
||||
path = prefix.appendInverse(suffix) and
|
||||
tp = suffix.getHead() and
|
||||
inferCertainType(n, prefix) = certainType and
|
||||
not certainType.getATypeParameter() = tp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,8 +462,6 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
|
||||
let.getInitializer() = n2
|
||||
)
|
||||
or
|
||||
n1 = n2.(ParenExpr).getExpr()
|
||||
or
|
||||
n1 = n2.(IfExpr).getABranch()
|
||||
or
|
||||
n1 = n2.(MatchExpr).getAnArm().getExpr()
|
||||
@@ -531,9 +559,6 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferTypeEquality(AstNode n, TypePath path) {
|
||||
// Don't propagate type information into a node for which we already have
|
||||
// certain type information.
|
||||
not exists(CertainTypeInference::inferCertainType(n, _)) and
|
||||
exists(TypePath prefix1, AstNode n2, TypePath prefix2, TypePath suffix |
|
||||
result = inferType(n2, prefix2.appendInverse(suffix)) and
|
||||
path = prefix1.append(suffix)
|
||||
@@ -842,7 +867,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
|
||||
}
|
||||
}
|
||||
|
||||
private class FunctionDecl extends Declaration, Function {
|
||||
additional class FunctionDecl extends Declaration, Function {
|
||||
override TypeParameter getTypeParameter(TypeParameterPosition ppos) {
|
||||
typeParamMatchPosition(this.getGenericParamList().getATypeParam(), result, ppos)
|
||||
or
|
||||
@@ -944,8 +969,6 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
|
||||
}
|
||||
|
||||
final class Access extends Call {
|
||||
Access() { not CertainTypeInference::certainCallExprTarget(this, _, _) }
|
||||
|
||||
pragma[nomagic]
|
||||
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
|
||||
exists(TypeMention arg | result = arg.resolveTypeAt(path) |
|
||||
@@ -1308,17 +1331,22 @@ pragma[nomagic]
|
||||
private StructType getStrStruct() { result = TStruct(any(Builtins::Str s)) }
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferLiteralType(LiteralExpr le, TypePath path) {
|
||||
private Type inferLiteralType(LiteralExpr le, TypePath path, boolean certain) {
|
||||
path.isEmpty() and
|
||||
exists(Builtins::BuiltinType t | result = TStruct(t) |
|
||||
le instanceof CharLiteralExpr and
|
||||
t instanceof Builtins::Char
|
||||
t instanceof Builtins::Char and
|
||||
certain = true
|
||||
or
|
||||
le =
|
||||
any(NumberLiteralExpr ne |
|
||||
t.getName() = ne.getSuffix()
|
||||
t.getName() = ne.getSuffix() and
|
||||
certain = true
|
||||
or
|
||||
// When a number literal has no suffix, the type may depend on the context.
|
||||
// For simplicity, we assume either `i32` or `f64`.
|
||||
not exists(ne.getSuffix()) and
|
||||
certain = false and
|
||||
(
|
||||
ne instanceof IntegerLiteralExpr and
|
||||
t instanceof Builtins::I32
|
||||
@@ -1329,7 +1357,8 @@ private Type inferLiteralType(LiteralExpr le, TypePath path) {
|
||||
)
|
||||
or
|
||||
le instanceof BooleanLiteralExpr and
|
||||
t instanceof Builtins::Bool
|
||||
t instanceof Builtins::Bool and
|
||||
certain = true
|
||||
)
|
||||
or
|
||||
le instanceof StringLiteralExpr and
|
||||
@@ -1338,7 +1367,8 @@ private Type inferLiteralType(LiteralExpr le, TypePath path) {
|
||||
or
|
||||
path = TypePath::singleton(TRefTypeParameter()) and
|
||||
result = getStrStruct()
|
||||
)
|
||||
) and
|
||||
certain = true
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -2282,62 +2312,71 @@ private module Cached {
|
||||
Stages::TypeInferenceStage::ref() and
|
||||
result = CertainTypeInference::inferCertainType(n, path)
|
||||
or
|
||||
result = inferAnnotatedType(n, path)
|
||||
or
|
||||
result = inferLogicalOperationType(n, path)
|
||||
or
|
||||
result = inferAssignmentOperationType(n, path)
|
||||
or
|
||||
result = inferTypeEquality(n, path)
|
||||
or
|
||||
result = inferImplicitSelfType(n, path)
|
||||
or
|
||||
result = inferStructExprType(n, path)
|
||||
or
|
||||
result = inferTupleRootType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferPathExprType(n, path)
|
||||
or
|
||||
result = inferCallExprBaseType(n, path)
|
||||
or
|
||||
result = inferFieldExprType(n, path)
|
||||
or
|
||||
result = inferTupleIndexExprType(n, path)
|
||||
or
|
||||
result = inferTupleContainerExprType(n, path)
|
||||
or
|
||||
result = inferRefNodeType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferTryExprType(n, path)
|
||||
or
|
||||
result = inferLiteralType(n, path)
|
||||
or
|
||||
result = inferAsyncBlockExprRootType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferAwaitExprType(n, path)
|
||||
or
|
||||
result = inferArrayExprType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferRangeExprType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferIndexExprType(n, path)
|
||||
or
|
||||
result = inferForLoopExprType(n, path)
|
||||
or
|
||||
result = inferDynamicCallExprType(n, path)
|
||||
or
|
||||
result = inferClosureExprType(n, path)
|
||||
or
|
||||
result = inferCastExprType(n, path)
|
||||
or
|
||||
result = inferStructPatType(n, path)
|
||||
or
|
||||
result = inferTupleStructPatType(n, path)
|
||||
// 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()
|
||||
) and
|
||||
(
|
||||
result = inferAnnotatedType(n, path)
|
||||
or
|
||||
result = inferLogicalOperationType(n, path)
|
||||
or
|
||||
result = inferAssignmentOperationType(n, path)
|
||||
or
|
||||
result = inferTypeEquality(n, path)
|
||||
or
|
||||
result = inferImplicitSelfType(n, path)
|
||||
or
|
||||
result = inferStructExprType(n, path)
|
||||
or
|
||||
result = inferTupleRootType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferPathExprType(n, path)
|
||||
or
|
||||
result = inferCallExprBaseType(n, path)
|
||||
or
|
||||
result = inferFieldExprType(n, path)
|
||||
or
|
||||
result = inferTupleIndexExprType(n, path)
|
||||
or
|
||||
result = inferTupleContainerExprType(n, path)
|
||||
or
|
||||
result = inferRefNodeType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferTryExprType(n, path)
|
||||
or
|
||||
result = inferLiteralType(n, path, false)
|
||||
or
|
||||
result = inferAsyncBlockExprRootType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferAwaitExprType(n, path)
|
||||
or
|
||||
result = inferArrayExprType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferRangeExprType(n) and
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferIndexExprType(n, path)
|
||||
or
|
||||
result = inferForLoopExprType(n, path)
|
||||
or
|
||||
result = inferDynamicCallExprType(n, path)
|
||||
or
|
||||
result = inferClosureExprType(n, path)
|
||||
or
|
||||
result = inferCastExprType(n, path)
|
||||
or
|
||||
result = inferStructPatType(n, path)
|
||||
or
|
||||
result = inferTupleStructPatType(n, path)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2438,6 +2477,11 @@ private module Debug {
|
||||
c = max(countTypePaths(_, _, _))
|
||||
}
|
||||
|
||||
Type debugInferCertainType(AstNode n, TypePath path) {
|
||||
n = getRelevantLocatable() and
|
||||
result = CertainTypeInference::inferCertainType(n, path)
|
||||
}
|
||||
|
||||
Type debugInferCertainNonUniqueType(AstNode n, TypePath path) {
|
||||
n = getRelevantLocatable() and
|
||||
Consistency::nonUniqueCertainType(n, path) and
|
||||
|
||||
@@ -2074,7 +2074,7 @@ mod indexers {
|
||||
// implicit dereference. We cannot currently handle a position that is
|
||||
// both implicitly dereferenced and implicitly borrowed, so the extra
|
||||
// type sneaks in.
|
||||
let x = slice[0].foo(); // $ target=foo type=x:S target=index SPURIOUS: type=slice:[]
|
||||
let x = slice[0].foo(); // $ target=foo type=x:S target=index
|
||||
}
|
||||
|
||||
pub fn f() {
|
||||
|
||||
@@ -288,7 +288,6 @@ inferType
|
||||
| dereference.rs:60:14:60:17 | &'a' | &T | {EXTERNAL LOCATION} | char |
|
||||
| dereference.rs:60:14:60:17 | &'a' | &T | file://:0:0:0:0 | & |
|
||||
| dereference.rs:60:15:60:17 | 'a' | | {EXTERNAL LOCATION} | char |
|
||||
| dereference.rs:60:15:60:17 | 'a' | | file://:0:0:0:0 | & |
|
||||
| dereference.rs:61:9:61:11 | _f1 | | file://:0:0:0:0 | & |
|
||||
| dereference.rs:61:15:61:16 | e1 | | file://:0:0:0:0 | & |
|
||||
| dereference.rs:61:15:61:16 | e1 | &T | {EXTERNAL LOCATION} | char |
|
||||
@@ -401,7 +400,6 @@ inferType
|
||||
| dereference.rs:123:32:123:41 | key_to_key | K | file://:0:0:0:0 | & |
|
||||
| dereference.rs:123:32:123:41 | key_to_key | K.&T | dereference.rs:99:5:100:21 | Key |
|
||||
| dereference.rs:123:32:123:41 | key_to_key | S | {EXTERNAL LOCATION} | RandomState |
|
||||
| dereference.rs:123:32:123:41 | key_to_key | V | dereference.rs:99:5:100:21 | Key |
|
||||
| dereference.rs:123:32:123:41 | key_to_key | V | file://:0:0:0:0 | & |
|
||||
| dereference.rs:123:32:123:41 | key_to_key | V.&T | dereference.rs:99:5:100:21 | Key |
|
||||
| dereference.rs:123:32:123:50 | key_to_key.get(...) | | {EXTERNAL LOCATION} | Option |
|
||||
@@ -425,13 +423,9 @@ inferType
|
||||
| dereference.rs:127:9:127:18 | key_to_key | | {EXTERNAL LOCATION} | HashMap |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | K | file://:0:0:0:0 | & |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | K.&T | dereference.rs:99:5:100:21 | Key |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | K.&T | file://:0:0:0:0 | & |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | K.&T.&T | dereference.rs:99:5:100:21 | Key |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | S | {EXTERNAL LOCATION} | RandomState |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | V | file://:0:0:0:0 | & |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | V.&T | dereference.rs:99:5:100:21 | Key |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | V.&T | file://:0:0:0:0 | & |
|
||||
| dereference.rs:127:9:127:18 | key_to_key | V.&T.&T | dereference.rs:99:5:100:21 | Key |
|
||||
| dereference.rs:127:9:127:35 | key_to_key.insert(...) | | {EXTERNAL LOCATION} | Option |
|
||||
| dereference.rs:127:9:127:35 | key_to_key.insert(...) | T | file://:0:0:0:0 | & |
|
||||
| dereference.rs:127:9:127:35 | key_to_key.insert(...) | T.&T | dereference.rs:99:5:100:21 | Key |
|
||||
@@ -3941,7 +3935,6 @@ inferType
|
||||
| main.rs:2070:22:2070:26 | slice | &T.[T] | main.rs:2037:5:2038:13 | S |
|
||||
| main.rs:2077:13:2077:13 | x | | main.rs:2037:5:2038:13 | S |
|
||||
| main.rs:2077:17:2077:21 | slice | | file://:0:0:0:0 | & |
|
||||
| main.rs:2077:17:2077:21 | slice | | file://:0:0:0:0 | [] |
|
||||
| main.rs:2077:17:2077:21 | slice | &T | file://:0:0:0:0 | [] |
|
||||
| main.rs:2077:17:2077:21 | slice | &T.[T] | main.rs:2037:5:2038:13 | S |
|
||||
| main.rs:2077:17:2077:24 | slice[0] | | main.rs:2037:5:2038:13 | S |
|
||||
@@ -4031,7 +4024,6 @@ inferType
|
||||
| main.rs:2144:16:2144:19 | self | T | main.rs:2139:10:2139:17 | T |
|
||||
| main.rs:2144:16:2144:21 | self.0 | | main.rs:2139:10:2139:17 | T |
|
||||
| main.rs:2144:31:2144:35 | other | | main.rs:2137:5:2137:19 | S |
|
||||
| main.rs:2144:31:2144:35 | other | T | main.rs:2099:5:2104:5 | Self [trait MyAdd] |
|
||||
| main.rs:2144:31:2144:35 | other | T | main.rs:2139:10:2139:17 | T |
|
||||
| main.rs:2144:31:2144:37 | other.0 | | main.rs:2099:5:2104:5 | Self [trait MyAdd] |
|
||||
| main.rs:2144:31:2144:37 | other.0 | | main.rs:2139:10:2139:17 | T |
|
||||
@@ -4047,7 +4039,6 @@ inferType
|
||||
| main.rs:2153:16:2153:19 | self | | main.rs:2137:5:2137:19 | S |
|
||||
| main.rs:2153:16:2153:19 | self | T | main.rs:2148:10:2148:17 | T |
|
||||
| main.rs:2153:16:2153:21 | self.0 | | main.rs:2148:10:2148:17 | T |
|
||||
| main.rs:2153:31:2153:35 | other | | main.rs:2099:5:2104:5 | Self [trait MyAdd] |
|
||||
| main.rs:2153:31:2153:35 | other | | main.rs:2148:10:2148:17 | T |
|
||||
| main.rs:2164:19:2164:22 | SelfParam | | main.rs:2137:5:2137:19 | S |
|
||||
| main.rs:2164:19:2164:22 | SelfParam | T | main.rs:2157:14:2157:14 | T |
|
||||
@@ -4215,7 +4206,6 @@ inferType
|
||||
| main.rs:2295:21:2295:31 | [...] | | file://:0:0:0:0 | [] |
|
||||
| main.rs:2295:21:2295:31 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2295:21:2295:31 | [...] | [T;...] | {EXTERNAL LOCATION} | u8 |
|
||||
| main.rs:2295:22:2295:24 | 1u8 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2295:22:2295:24 | 1u8 | | {EXTERNAL LOCATION} | u8 |
|
||||
| main.rs:2295:27:2295:27 | 2 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2295:27:2295:27 | 2 | | {EXTERNAL LOCATION} | u8 |
|
||||
@@ -4366,7 +4356,6 @@ inferType
|
||||
| main.rs:2338:18:2338:26 | [...] | [T;...] | {EXTERNAL LOCATION} | Range |
|
||||
| main.rs:2338:18:2338:26 | [...] | [T;...].Idx | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2338:18:2338:26 | [...] | [T;...].Idx | {EXTERNAL LOCATION} | u8 |
|
||||
| main.rs:2338:19:2338:21 | 0u8 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2338:19:2338:21 | 0u8 | | {EXTERNAL LOCATION} | u8 |
|
||||
| main.rs:2338:19:2338:25 | 0u8..10 | | {EXTERNAL LOCATION} | Range |
|
||||
| main.rs:2338:19:2338:25 | 0u8..10 | Idx | {EXTERNAL LOCATION} | i32 |
|
||||
@@ -4405,7 +4394,6 @@ inferType
|
||||
| main.rs:2354:32:2354:52 | ... .to_vec() | | {EXTERNAL LOCATION} | Vec |
|
||||
| main.rs:2354:32:2354:52 | ... .to_vec() | A | {EXTERNAL LOCATION} | Global |
|
||||
| main.rs:2354:32:2354:52 | ... .to_vec() | T | {EXTERNAL LOCATION} | u16 |
|
||||
| main.rs:2354:33:2354:36 | 1u16 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2354:33:2354:36 | 1u16 | | {EXTERNAL LOCATION} | u16 |
|
||||
| main.rs:2354:39:2354:39 | 2 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2354:39:2354:39 | 2 | | {EXTERNAL LOCATION} | u16 |
|
||||
@@ -4419,7 +4407,6 @@ inferType
|
||||
| main.rs:2357:22:2357:33 | [...] | | file://:0:0:0:0 | [] |
|
||||
| main.rs:2357:22:2357:33 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2357:22:2357:33 | [...] | [T;...] | {EXTERNAL LOCATION} | u16 |
|
||||
| main.rs:2357:23:2357:26 | 1u16 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2357:23:2357:26 | 1u16 | | {EXTERNAL LOCATION} | u16 |
|
||||
| main.rs:2357:29:2357:29 | 2 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2357:29:2357:29 | 2 | | {EXTERNAL LOCATION} | u16 |
|
||||
@@ -4436,7 +4423,6 @@ inferType
|
||||
| main.rs:2360:31:2360:42 | [...] | | file://:0:0:0:0 | [] |
|
||||
| main.rs:2360:31:2360:42 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2360:31:2360:42 | [...] | [T;...] | {EXTERNAL LOCATION} | u32 |
|
||||
| main.rs:2360:32:2360:35 | 1u32 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2360:32:2360:35 | 1u32 | | {EXTERNAL LOCATION} | u32 |
|
||||
| main.rs:2360:38:2360:38 | 2 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2360:38:2360:38 | 2 | | {EXTERNAL LOCATION} | u32 |
|
||||
@@ -4460,7 +4446,6 @@ inferType
|
||||
| main.rs:2363:32:2363:60 | ... .collect() | A | {EXTERNAL LOCATION} | Global |
|
||||
| main.rs:2363:32:2363:60 | ... .collect() | T | file://:0:0:0:0 | & |
|
||||
| main.rs:2363:32:2363:60 | ... .collect() | T.&T | {EXTERNAL LOCATION} | u64 |
|
||||
| main.rs:2363:33:2363:36 | 1u64 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2363:33:2363:36 | 1u64 | | {EXTERNAL LOCATION} | u64 |
|
||||
| main.rs:2363:39:2363:39 | 2 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:2363:39:2363:39 | 2 | | {EXTERNAL LOCATION} | u64 |
|
||||
@@ -5737,10 +5722,8 @@ inferType
|
||||
| pattern_matching.rs:444:17:444:36 | TupleExpr | 2(3) | {EXTERNAL LOCATION} | f32 |
|
||||
| pattern_matching.rs:444:17:444:36 | TupleExpr | 2(3) | {EXTERNAL LOCATION} | f64 |
|
||||
| pattern_matching.rs:444:18:444:21 | 1i32 | | {EXTERNAL LOCATION} | i32 |
|
||||
| pattern_matching.rs:444:24:444:27 | 2i64 | | {EXTERNAL LOCATION} | i32 |
|
||||
| pattern_matching.rs:444:24:444:27 | 2i64 | | {EXTERNAL LOCATION} | i64 |
|
||||
| pattern_matching.rs:444:30:444:35 | 3.0f32 | | {EXTERNAL LOCATION} | f32 |
|
||||
| pattern_matching.rs:444:30:444:35 | 3.0f32 | | {EXTERNAL LOCATION} | f64 |
|
||||
| pattern_matching.rs:447:11:447:15 | tuple | | file://:0:0:0:0 | (T_3) |
|
||||
| pattern_matching.rs:447:11:447:15 | tuple | 0(3) | {EXTERNAL LOCATION} | i32 |
|
||||
| pattern_matching.rs:447:11:447:15 | tuple | 1(3) | {EXTERNAL LOCATION} | i32 |
|
||||
|
||||
@@ -334,7 +334,19 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
/** Holds if this path starts with `tp`, followed by `suffix`. */
|
||||
bindingset[this]
|
||||
predicate isCons(TypeParameter tp, TypePath suffix) {
|
||||
suffix = this.stripPrefix(TypePath::singleton(tp))
|
||||
exists(string regexp | regexp = "([0-9]+)\\.(.*)" |
|
||||
tp = TypeParameter::decode(this.regexpCapture(regexp, 1)) and
|
||||
suffix = this.regexpCapture(regexp, 2)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this path starts with `prefix`, followed by `tp`. */
|
||||
bindingset[this]
|
||||
predicate isSnoc(TypePath prefix, TypeParameter tp) {
|
||||
exists(string regexp | regexp = "(|.+\\.)([0-9]+)\\." |
|
||||
prefix = this.regexpCapture(regexp, 1) and
|
||||
tp = TypeParameter::decode(this.regexpCapture(regexp, 2))
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the head of this path, if any. */
|
||||
|
||||
Reference in New Issue
Block a user