diff --git a/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll index ea76293a1bd9..f22c95759d6e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll @@ -12,7 +12,7 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl * the canonical path `path` and the method name `method`, and if it borrows its * first `borrows` arguments. */ -private predicate isOverloaded(string op, int arity, string path, string method, int borrows) { +predicate isOverloaded(string op, int arity, string path, string method, int borrows) { arity = 1 and ( // Negation diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index a0d52a34ecea..a856638c0d29 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -726,7 +726,7 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl { } } -private class ImplTraitTypeReprItemNode extends TypeItemNode instanceof ImplTraitTypeRepr { +class ImplTraitTypeReprItemNode extends TypeItemNode instanceof ImplTraitTypeRepr { pragma[nomagic] Path getABoundPath() { result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath() @@ -832,6 +832,8 @@ class TraitItemNode extends ImplOrTraitItemNode, TypeItemNode instanceof Trait { pragma[nomagic] ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) } + predicate hasLoop() { this.resolveABound+() = this } + override AssocItemNode getAnAssocItem() { result = this.getADescendant() } override string getName() { result = Trait.super.getName().getText() } diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 2dd5b3346fac..71acfe837d11 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -584,50 +584,15 @@ private Type inferTypeEquality(AstNode n, TypePath path) { ) } -/** - * Gets the type of the implicitly typed `self` parameter, taking into account - * whether the parameter is passed by value or by reference. - */ -bindingset[self, suffix, t] -pragma[inline_late] -private Type getRefAdjustImplicitSelfType(SelfParam self, TypePath suffix, Type t, TypePath path) { - not self.hasTypeRepr() and - ( - if self.isRef() - then - // `fn f(&self, ...)` - path.isEmpty() and - result = TRefType() - or - path = TypePath::cons(TRefTypeParameter(), suffix) and - result = t - else ( - // `fn f(self, ...)` - path = suffix and - result = t - ) - ) -} - -pragma[nomagic] -private Type resolveImplSelfType(Impl i, TypePath path) { - result = i.getSelfTy().(TypeMention).resolveTypeAt(path) -} - -/** Gets the type at `path` of the implicitly typed `self` parameter. */ -pragma[nomagic] -private Type inferImplicitSelfType(SelfParam self, TypePath path) { - exists(ImplOrTraitItemNode i, Function f, TypePath suffix, Type t | - f = i.getAnAssocItem() and - self = f.getParamList().getSelfParam() and - result = getRefAdjustImplicitSelfType(self, suffix, t, path) - | - t = resolveImplSelfType(i, suffix) - or - t = TSelfTypeParameter(i) and suffix.isEmpty() - ) -} - +// // todo +// // /** Gets the type at `path` of the implicitly typed `self` parameter. */ +// pragma[nomagic] +// private Type resolveImplType(ImplOrTraitItemNode i, TypePath path) { +// result = resolveImplSelfType(i, path) +// or +// result = TSelfTypeParameter(i) and path.isEmpty() +// } +// todo /** * A matching configuration for resolving types of struct expressions * like `Foo { bar = baz }`. @@ -785,7 +750,7 @@ private Type getTypeQualifier(CallExpr ce, TypePath path) { * A matching configuration for resolving types of call expressions * like `foo::bar(baz)` and `foo.bar(baz)`. */ -private module CallExprBaseMatchingInput implements MatchingInputSig { +private module CallExprBaseMatchingInput implements MatchingWithStateInputSig { private predicate paramPos(ParamList pl, Param p, int pos) { p = pl.getParam(pos) } private newtype TDeclarationPosition = @@ -823,6 +788,12 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { dpos.isReturn() and result = this.getReturnType(path) } + + private Type testgetDeclaredType(DeclarationPosition dpos, TypePath path) { + result = this.getDeclaredType(dpos, path) and + this.getLocation().getStartLine() = 11 and + this.fromSource() + } } abstract additional class TupleDeclaration extends Declaration { @@ -882,6 +853,8 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { } } + private import codeql.rust.elements.internal.OperationImpl as OperationImpl + additional class FunctionDecl extends Declaration, Function { override TypeParameter getTypeParameter(TypeParameterPosition ppos) { typeParamMatchPosition(this.getGenericParamList().getATypeParam(), result, ppos) @@ -899,22 +872,48 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { this = result.(ImplTraitTypeTypeParameter).getFunction() } + pragma[nomagic] + private predicate borrowsAt(int pos) { + exists(TraitItemNode t, Function f, string path, string method | + ( + f = this + or + this.implements(f) + ) and + f = t.getAssocItem(method) and + path = t.getCanonicalPath(_) + | + // pos.isSelf() and borrows >= 1 + // or + exists(int borrows | + OperationImpl::isOverloaded(_, _, path, method, borrows) and + pos = 0 and + borrows >= 2 + ) + // or + // path= "core::ops::index::Index" and + // method = "index" and + // pos = + ) + } + override Type getParameterType(DeclarationPosition dpos, TypePath path) { - exists(Param p, int i | + exists(Param p, int i, TypePath path0 | paramPos(this.getParamList(), p, i) and i = dpos.asPosition() and - result = p.getTypeRepr().(TypeMention).resolveTypeAt(path) + result = p.getTypeRepr().(TypeMention).resolveTypeAt(path0) and + if this.borrowsAt(i) then path0.isCons(TRefTypeParameter(), path) else path0 = path ) or + dpos.isSelf() and exists(SelfParam self | self = pragma[only_bind_into](this.getParamList().getSelfParam()) and - dpos.isSelf() - | - result = inferAnnotatedType(self, path) // `self` parameter with type annotation - or - result = inferImplicitSelfType(self, path) // `self` parameter without type annotation + result = getSelfParamTypeMention(self).resolveTypeAt(path) ) or + // or + // todo: add special case for operations with implicit borrows + // // For associated functions, we may also need to match type arguments against // the `Self` type. For example, in // @@ -931,15 +930,31 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { // ``` // // we need to match `i32` against the type parameter `T` of the `impl` block. + //todo: share code with `resolveSelfType` exists(ImplOrTraitItemNode i | this = i.getAnAssocItem() and dpos.isSelf() and - not this.getParamList().hasSelfParam() + not this.getParamList().hasSelfParam() and + result = resolveImplType(i, path) + ) + } + + pragma[nomagic] + private predicate derefsReturn() { + exists(TraitItemNode t, Function f, string path, string method | + ( + f = this + or + this.implements(f) + ) and + f = t.getAssocItem(method) and + path = t.getCanonicalPath(_) | - result = TSelfTypeParameter(i) and - path.isEmpty() + path = "core::ops::index::Index" and + method = "index" or - result = resolveImplSelfType(i, path) + path = "core::ops::deref::Deref" and + method = "deref" ) } @@ -958,24 +973,26 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { path = TypePath::cons(getFutureOutputTypeParameter(), suffix) ) else result = this.resolveRetType(path) + // exists(TypePath path0 | + // result = this.resolveRetType(path0) and + // if this.derefsReturn() then path0.isCons(TRefTypeParameter(), path) else path0 = path + // ) } } private newtype TAccessPosition = - TArgumentAccessPosition(ArgumentPosition pos, Boolean borrowed, Boolean certain) or + TArgumentAccessPosition(ArgumentPosition pos) or TReturnAccessPosition() class AccessPosition extends TAccessPosition { - ArgumentPosition getArgumentPosition() { this = TArgumentAccessPosition(result, _, _) } - - predicate isBorrowed(boolean certain) { this = TArgumentAccessPosition(_, true, certain) } + ArgumentPosition getArgumentPosition() { this = TArgumentAccessPosition(result) } predicate isReturn() { this = TReturnAccessPosition() } string toString() { - exists(ArgumentPosition pos, boolean borrowed, boolean certain | - this = TArgumentAccessPosition(pos, borrowed, certain) and - result = pos + ":" + borrowed + ":" + certain + exists(ArgumentPosition pos | + this = TArgumentAccessPosition(pos) and + result = pos.toString() ) or this.isReturn() and @@ -983,6 +1000,11 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { } } + class State = string; + + // private newtype TAccess = + // TMethodCallAccess(MethodCallDerefChainRef mcd) or + // TFunctionCallAccess(FunctionCallExpr fce) final class Access extends Call { pragma[nomagic] Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { @@ -999,32 +1021,157 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { } AstNode getNodeAt(AccessPosition apos) { - exists(ArgumentPosition pos, boolean borrowed, boolean certain | - apos = TArgumentAccessPosition(pos, borrowed, certain) and + exists(ArgumentPosition pos | + apos = TArgumentAccessPosition(pos) and result = this.getArgument(pos) - | - if this.implicitBorrowAt(pos, _) - then borrowed = true and this.implicitBorrowAt(pos, certain) - else ( - borrowed = false and certain = true - ) ) or result = this and apos.isReturn() } - Type getInferredType(AccessPosition apos, TypePath path) { - result = inferType(this.getNodeAt(apos), path) + private Type testgetInferredType(State state, AccessPosition apos, TypePath path) { + exists(this.getTarget(state)) and + this.getLocation().getStartLine() = 1355 and + this.fromSource() and + result = this.getInferredType(state, apos, path) + } + + pragma[nomagic] + private Type testgetInferredSelfType(State state, TypePath path) { + this.getLocation().getStartLine() = 1355 and + this.fromSource() and + result = this.getInferredSelfType(state, path) + } + + pragma[nomagic] + private Type getInferredSelfType(State state, TypePath path) { + exists(State state0, TypePath path0 | + result = MkMethodCallDerefChainRef(this, state0).(MethodCallDerefChainRef).getTypeAt(path0) + | + state = state0 and + path = path0 + // or + // state = state0 + ";borrow" and + // path = TypePath::cons(TRefTypeParameter(), path0) and + // not path0.getHead() = TRefTypeParameter() + ) + } + + pragma[nomagic] + Type getInferredType(State state, AccessPosition apos, TypePath path) { + exists(ArgumentPosition pos | + apos = TArgumentAccessPosition(pos) and + pos.isSelf() + | + result = this.getInferredSelfType(state, path) + or + // The `Self` type is supplied explicitly as a type qualifier, e.g. `Foo::::baz()` + exists(this.getTarget(state)) and + result = getTypeQualifier(this, path) + ) or - // The `Self` type is supplied explicitly as a type qualifier, e.g. `Foo::::baz()` - apos = TArgumentAccessPosition(CallImpl::TSelfArgumentPosition(), false, false) and - result = getTypeQualifier(this, path) + exists(this.getTarget(state)) and + not apos.getArgumentPosition().isSelf() and + exists(Type t0, TypePath path0 | t0 = inferType(this.getNodeAt(apos), path0) | + if + apos.isReturn() and + (this instanceof DerefExpr or this instanceof IndexExpr) + then ( + path.isEmpty() and + result = TRefType() + or + path = TypePath::cons(TRefTypeParameter(), path0) and + result = t0 + ) else ( + path = path0 and + result = t0 + ) + ) } - Declaration getTarget() { - result = resolveMethodCallTarget(this) // mutual recursion; resolving method calls requires resolving types and vice versa + // bindingset[state] + // Type getInferredType(State state, AccessPosition apos, TypePath path) { + // exists(Type t0, TypePath path0 | + // this.implicitBorrowAt(apos.getArgumentPosition(true), _) and + // // this.mayImplicitBorrowAt(state, apos, true) and + // ( + // path.isEmpty() and + // result = TRefType() + // or + // path = TypePath::cons(TRefTypeParameter(), path0) and + // // not path0.isCons(TRefTypeParameter(), _) and + // // not (path0.isEmpty() and result = TRefType()) and + // result = t0 + // ) + // or + // exists(ArgumentPosition pos | + // pos = apos.getArgumentPosition(false) and + // not this.implicitBorrowAt(pos, true) + // ) and + // result = t0 and + // path = path0 + // | + // t0 = this.getInferredType0(state, apos, path0) + // // if apos.getArgumentPosition(_).isSelf() + // // then + // // t0 = this.getInferredSelfType(state, path0) + // // or + // // // The `Self` type is supplied explicitly as a type qualifier, e.g. `Foo::::baz()` + // // t0 = getTypeQualifier(this, path0) and + // // apos.getArgumentPosition(false).isSelf() and + // // exists(state) + // // else ( + // // t0 = inferType(this.getNodeAt(apos), path0) and exists(state) + // // ) + // ) + // } + // bindingset[state] + // pragma[nomagic] + // predicate mayImplicitBorrowAt_(State state, AccessPosition apos, boolean borrowed) { + // exists(boolean certain | this.implicitBorrowAt(apos.getArgumentPosition(borrowed), certain) | + // this.getInferredType0(state, apos, TypePath::nil()) != TRefType() + // ) + // } + // pragma[nomagic] + // private predicate mayNotImplicitBorrowAt0(State state, AccessPosition apos) { + // not this.implicitBorrowAt(apos.getArgumentPosition(_), true) and + // this.implicitBorrowAt(apos.getArgumentPosition(_), _) and + // this.getInferredType0(state, apos, TypePath::nil()) = TRefType() + // } + // bindingset[state] + // predicate mayNotImplicitBorrowAt(State state, AccessPosition apos) { + // // not this.implicitBorrowAt(apos.getArgumentPosition(_), true) and + // if this.implicitBorrowAt(apos.getArgumentPosition(_), _) + // then this.mayNotImplicitBorrowAt0(state, apos) + // else any() + // } + Declaration getTarget(State state) { + exists(State state0 | + result = resolveMethodCallTarget(MkMethodCallDerefChainRef(this, state0)) // mutual recursion; resolving method calls requires resolving types and vice versa + | + state = state0 //or + // state = state0 + ";borrow" + ) or - result = resolveFunctionCallTarget(this) // potential mutual recursion; resolving some associated function calls requires resolving types + result = resolveFunctionCallTarget(this) and // potential mutual recursion; resolving some associated function calls requires resolving types + state = "" + } + + private Declaration testgetTarget(State state) { + this.getLocation().getStartLine() = 1286 and + this.fromSource() and + result = this.getTarget(state) + } + + private Function testgetTarget( + State state, Function f, TraitItemNode trait, string can, string name + ) { + this.getLocation().getStartLine() = 2071 and + this.fromSource() and + result.implements(f) and + result = this.getTarget(state) and + f = trait.getAssocItem(name) and + can = trait.getCanonicalPath(_) } } @@ -1033,64 +1180,116 @@ private module CallExprBaseMatchingInput implements MatchingInputSig { or apos.isReturn() and dpos.isReturn() } + // bindingset[apos, target, path, t] + // pragma[inline_late] + // predicate adjustAccessType( + // AccessPosition apos, Declaration target, TypePath path, Type t, TypePath pathAdj, Type tAdj + // ) { + // apos.isBorrowed(true) and + // pathAdj = TypePath::cons(TRefTypeParameter(), path) and + // tAdj = t + // or + // apos.isBorrowed(false) and + // exists(Type selfParamType | + // selfParamType = + // target + // .getParameterType(TArgumentDeclarationPosition(apos.getArgumentPosition()), + // TypePath::nil()) + // | + // if selfParamType = TRefType() + // then + // if t != TRefType() and path.isEmpty() + // then + // // adjust for implicit borrow + // pathAdj.isEmpty() and + // tAdj = TRefType() + // or + // // adjust for implicit borrow + // pathAdj = TypePath::singleton(TRefTypeParameter()) and + // tAdj = t + // else + // if path.isCons(TRefTypeParameter(), _) + // then + // pathAdj = path and + // tAdj = t + // else ( + // // adjust for implicit borrow + // not (t = TRefType() and path.isEmpty()) and + // pathAdj = TypePath::cons(TRefTypeParameter(), path) and + // tAdj = t + // ) + // else ( + // // adjust for implicit deref + // path.isCons(TRefTypeParameter(), pathAdj) and + // tAdj = t + // or + // not path.isCons(TRefTypeParameter(), _) and + // not (t = TRefType() and path.isEmpty()) and + // pathAdj = path and + // tAdj = t + // ) + // ) + // or + // not apos.isBorrowed(_) and + // pathAdj = path and + // tAdj = t + // } +} + +private module CallExprBaseMatching = MatchingWithState; + +bindingset[s] +private predicate isBorrowed(string s) { exists(s.splitAt(";", 1)) } + +private predicate sdf() { isBorrowed(";ref") } - bindingset[apos, target, path, t] - pragma[inline_late] - predicate adjustAccessType( - AccessPosition apos, Declaration target, TypePath path, Type t, TypePath pathAdj, Type tAdj - ) { - apos.isBorrowed(true) and - pathAdj = TypePath::cons(TRefTypeParameter(), path) and - tAdj = t - or - apos.isBorrowed(false) and - exists(Type selfParamType | - selfParamType = - target - .getParameterType(TArgumentDeclarationPosition(apos.getArgumentPosition()), - TypePath::nil()) - | - if selfParamType = TRefType() - then - if t != TRefType() and path.isEmpty() - then - // adjust for implicit borrow - pathAdj.isEmpty() and - tAdj = TRefType() - or - // adjust for implicit borrow - pathAdj = TypePath::singleton(TRefTypeParameter()) and - tAdj = t - else - if path.isCons(TRefTypeParameter(), _) - then - pathAdj = path and - tAdj = t - else ( - // adjust for implicit borrow - not (t = TRefType() and path.isEmpty()) and - pathAdj = TypePath::cons(TRefTypeParameter(), path) and - tAdj = t - ) - else ( - // adjust for implicit deref - path.isCons(TRefTypeParameter(), pathAdj) and - tAdj = t - or - not path.isCons(TRefTypeParameter(), _) and - not (t = TRefType() and path.isEmpty()) and - pathAdj = path and - tAdj = t - ) - ) - or - not apos.isBorrowed(_) and - pathAdj = path and - tAdj = t - } +pragma[nomagic] +private Type testinferCallExprBaseType( + CallExprBaseMatchingInput::Access a, string state, CallExprBaseMatchingInput::AccessPosition apos, + TypePath path +) { + // a.getLocation().getStartLine() = 73 and + // a.fromSource() and + a = Debug::getRelevantLocatable() and + result = CallExprBaseMatching::inferAccessType(a, state, apos, path) +} + +private Type testinferCallExprBaseType0( + CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos, AstNode n, + string state, TypePath path +) { + n.getLocation().getStartLine() = 708 and + n.fromSource() and + result = inferCallExprBaseType0(a, apos, n, state, path) +} + +pragma[nomagic] +private Type inferCallExprBaseType0( + CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos, AstNode n, + string state, TypePath path +) { + // a = Debug::getRelevantLocatable() and // todo: remove + exists(TypePath path0 | + n = a.getNodeAt(apos) and + result = CallExprBaseMatching::inferAccessType(a, state, apos, path0) + | + if + apos.isReturn() and + (a instanceof DerefExpr or a instanceof IndexExpr) + then + // The desugaring of the unary `*e` is `*Deref::deref(&e)` and the + // desugaring of `a[b]` is `*Index::index(&a, b)`. To handle the deref + // expression after the call we must strip a `&` from the type at the + // return position. + path0.isCons(TRefTypeParameter(), path) + else path = path0 + ) } -private module CallExprBaseMatching = Matching; +private Type testinferCallExprBaseType(AstNode n, TypePath path) { + n = Debug::getRelevantLocatable() and + result = inferCallExprBaseType(n, path) +} /** * Gets the type of `n` at `path`, where `n` is either a call or an @@ -1100,53 +1299,72 @@ pragma[nomagic] private Type inferCallExprBaseType(AstNode n, TypePath path) { exists( CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos, - TypePath path0 + string state, TypePath path0 | - n = a.getNodeAt(apos) and - result = CallExprBaseMatching::inferAccessType(a, apos, path0) + result = inferCallExprBaseType0(a, apos, n, state, path0) | - if - apos.isBorrowed(true) + // n = a.getNodeAt(apos) and + // result = CallExprBaseMatching::inferAccessType(a, state, apos, path0) + // state = ["", ";", ".ref;ref"] and + ( + not apos.getArgumentPosition().isSelf() or - // The desugaring of the unary `*e` is `*Deref::deref(&e)` and the - // desugaring of `a[b]` is `*Index::index(&a, b)`. To handle the deref - // expression after the call we must strip a `&` from the type at the - // return position. - apos.isReturn() and - (a instanceof DerefExpr or a instanceof IndexExpr) - then path0.isCons(TRefTypeParameter(), path) - else - if apos.isBorrowed(false) - then - exists(Type argType | argType = inferType(n) | - if argType = TRefType() - then - path = path0 and - path0.isCons(TRefTypeParameter(), _) - or - // adjust for implicit deref - not path0.isCons(TRefTypeParameter(), _) and - not (path0.isEmpty() and result = TRefType()) and - path = TypePath::cons(TRefTypeParameter(), path0) - else ( - not ( - argType.(StructType).asItemNode() instanceof StringStruct and - result.(StructType).asItemNode() instanceof Builtins::Str - ) and - ( - not path0.isCons(TRefTypeParameter(), _) and - not (path0.isEmpty() and result = TRefType()) and - path = path0 - or - // adjust for implicit borrow - path0.isCons(TRefTypeParameter(), path) - ) - ) - ) - else ( - not apos.isBorrowed(_) and - path = path0 - ) + state = ["", ";"] + ) and + path = path0 + or + // or + // ( + // state = ";;borrow" + // or + // // isBorrowed(state) + // // apos.isBorrowed(true) + // // The desugaring of the unary `*e` is `*Deref::deref(&e)` and the + // // desugaring of `a[b]` is `*Index::index(&a, b)`. To handle the deref + // // expression after the call we must strip a `&` from the type at the + // // return position. + // apos.isReturn() and + // (a instanceof DerefExpr or a instanceof IndexExpr) + // ) and + // path0.isCons(TRefTypeParameter(), path) + apos.getArgumentPosition().isSelf() and + state = ".ref;" and + // adjust for implicit deref + // not path0.isCons(TRefTypeParameter(), _) and + // not (path0.isEmpty() and result = TRefType()) and + path = TypePath::cons(TRefTypeParameter(), path0) + // if isBorrowed(state) //apos.isBorrowed(false) + // then + // exists(Type argType | argType = inferType(n) | + // if argType = TRefType() + // then + // path = path0 and + // path0.isCons(TRefTypeParameter(), _) + // or + // // adjust for implicit deref + // not path0.isCons(TRefTypeParameter(), _) and + // not (path0.isEmpty() and result = TRefType()) and + // path = TypePath::cons(TRefTypeParameter(), path0) + // else ( + // not ( + // argType.(StructType).asItemNode() instanceof StringStruct and + // result.(StructType).asItemNode() instanceof Builtins::Str + // ) and + // ( + // not path0.isCons(TRefTypeParameter(), _) and + // not (path0.isEmpty() and result = TRefType()) and + // path = path0 + // or + // // adjust for implicit borrow + // path0.isCons(TRefTypeParameter(), path) + // ) + // ) + // ) + // else ( + // not isBorrowed(state) and + // // not apos.isBorrowed(_) and + // path = path0 + // ) ) } @@ -1814,30 +2032,46 @@ final class MethodCall extends Call { result = getTypeQualifier(this, path) } - /** Gets the type of the receiver of the method call at `path`. */ - Type getTypeAt(TypePath path) { - if - this.receiverImplicitlyBorrowed() or - this.(CallImpl::CallExprMethodCall).hasExplicitSelfBorrow() - then - exists(TypePath path0, Type t0 | - t0 = this.getReceiverTypeAt(path0) and - ( - path0.isCons(TRefTypeParameter(), path) - or - ( - not path0.isCons(TRefTypeParameter(), _) and - not (path0.isEmpty() and result = TRefType()) - or - // Ideally we should find all methods on reference types, but as - // that currently causes a blowup we limit this to the `deref` - // method in order to make dereferencing work. - this.getMethodName() = "deref" - ) and - path = path0 - ) - | - result = t0 + pragma[nomagic] + predicate isMethodCall(string name, int arity) { + name = this.getMethodName() and + arity = this.getNumberOfArguments() + } + + pragma[nomagic] + private predicate isMethodCall0(Type rootType, string name, int arity, string derefChain) { + rootType = this.getACandidateReceiverTypeRefsAt(TypePath::nil(), derefChain) and //, mcd.getTypeAt(TypePath::singleton(TRefTypeParameter()))] and + this.isMethodCall(name, arity) + } + + private predicate testisMethodCall0(Type rootType, string name, int arity, string derefChain) { + this.isMethodCall0(rootType, name, arity, derefChain) and + this = Debug::getRelevantLocatable() + } + + /** + * Gets a [candidate receiver type][1] of this method call. + * + * We do not yet model the `Deref` trait, so we hard-code the fact that `String` + * dereferences to `str` here. This allows us e.g. to resolve `x.parse::()` + * to the function `::parse` when `x` has type `String`. + * + * [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers + */ + pragma[nomagic] + private Type getACandidateReceiverTypeAt(TypePath path, string derefChain) { + result = this.getReceiverTypeAt(path) and + derefChain = "" + or + exists(TypePath path0, Type t0, string derefChain0 | + t0 = this.getACandidateReceiverTypeAtRefNoMatch(path0, derefChain0) + | + //or + // this.(CallImpl::CallExprMethodCall).hasExplicitSelfBorrow() + ( + path0.isCons(TRefTypeParameter(), path) and + result = t0 and + derefChain = derefChain0 + ".ref" or // We do not yet model the `Deref` trait, so we hard-code the fact that // `String` dereferences to `str` here. This allows us e.g. to resolve @@ -1845,12 +2079,193 @@ final class MethodCall extends Call { // type `String`. // // See also https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.autoref-deref - path.isEmpty() and + path0.isEmpty() and + path = path0 and t0.(StructType).asItemNode() instanceof StringStruct and - result.(StructType).asItemNode() instanceof Builtins::Str + result.(StructType).asItemNode() instanceof Builtins::Str and + derefChain = derefChain0 + ".str" + ) + ) + } + + pragma[nomagic] + private Type testgetACandidateReceiverTypeAt(TypePath path, string derefChain) { + result = this.getACandidateReceiverTypeAt(path, derefChain) and + this.getLocation().getStartLine() = 1286 and + this.fromSource() + } + + pragma[nomagic] + private Type testgetACandidateReceiverTypeAtNoMatch(TypePath path, string derefChain) { + result = this.getACandidateReceiverTypeAtNoMatch(path, derefChain) and + this = Debug::getRelevantLocatable() + } + + pragma[nomagic] + private Type testgetACandidateReceiverTypeAtNoMatch( + TypePath path, string derefChain, Type rootType, string name, int arity, Trait trait, + SelfParamType self + ) { + this = Debug::getRelevantLocatable() and + this.receiverImplicitlyBorrowed() and + result = this.getACandidateReceiverTypeAt(path, derefChain) and + this.isMethodCall0(rootType, name, arity, derefChain + ";") and + traitMethodCandidate(rootType, name, arity, trait, self) and + methodCallHasTraitCandidate0(MkMethodCallDerefChainRef(this, derefChain + ";"), trait, _, self, + _) + } + + pragma[nomagic] + private Type getACandidateReceiverTypeAtNoMatch(TypePath path, string derefChain) { + this.receiverImplicitlyBorrowed() and + result = this.getACandidateReceiverTypeAt(path, derefChain) and + exists(Type rootType, string name, int arity | + this.isMethodCall0(rootType, name, arity, derefChain + ";") + | + forall(Impl impl, SelfParamType self | + methodCandidateTrait(rootType, this.getTrait(), name, arity, impl, self) + or + not exists(this.getTrait()) and + methodCandidate(rootType, name, arity, impl, self) + | + IsInstantiationOf::isNotInstantiationOfStrict(MkMethodCallDerefChainRef(this, + derefChain + ";"), impl, self) + ) and + forall(Trait trait, SelfParamType self | + traitMethodCandidate(rootType, name, arity, trait, self) + | + IsInstantiationOf::isNotInstantiationOfStrict(MkMethodCallDerefChainRef(this, + derefChain + ";"), trait, self) + or + exists(Type t | + methodCallHasTraitCandidate0(MkMethodCallDerefChainRef(this, derefChain + ";"), trait, t, + self, _) and + not trait = getATraitBound(t) + ) + ) + // not exists(resolveNonImplMethodCallTarget(rootType, name, arity)) + ) + } + + pragma[nomagic] + private Type getACandidateReceiverTypeAtRef(TypePath path, string derefChain) { + // exists(TypePath path0, Type t0, string derefChain | + // t0 = this.getACandidateReceiverTypeAt(path0, derefChain) + // | + // path = path0 and + // derefChainRef = derefChain + ";" and + // result = t0 + // ) + // or + exists(TypePath path0, Type t0 | + t0 = this.getACandidateReceiverTypeAtNoMatch(path0, derefChain) + | + // this.isNotRef(derefChain) and + // not path0.isCons(TRefTypeParameter(), _) and + // not (path0.isEmpty() and result = TRefType()) and + // derefChainRef = derefChain + ";ref" and + ( + path.isEmpty() and + result = TRefType() + or + path = TypePath::cons(TRefTypeParameter(), path0) and + result = t0 ) - else result = this.getReceiverTypeAt(path) + ) } + + pragma[nomagic] + private Type testgetACandidateReceiverTypeAtRef(TypePath path, string derefChain) { + result = this.getACandidateReceiverTypeAtRef(path, derefChain) and + this = Debug::getRelevantLocatable() + } + + pragma[nomagic] + private Type testgetACandidateReceiverTypeAtRefNoMatch(TypePath path, string derefChain) { + result = this.getACandidateReceiverTypeAtRefNoMatch(path, derefChain) and + this = Debug::getRelevantLocatable() + } + + pragma[nomagic] + private Type testgetACandidateReceiverTypeAtRefNoMatch2( + TypePath path, string derefChain, Type rootType, string name, int arity + ) { + result = this.getACandidateReceiverTypeAtNoMatch(path, derefChain) and + this.isMethodCall0(rootType, name, arity, derefChain) and + this = Debug::getRelevantLocatable() + } + + pragma[nomagic] + private Type getACandidateReceiverTypeAtRefNoMatch(TypePath path, string derefChain) { + result = this.getACandidateReceiverTypeAtNoMatch(path, derefChain) and + exists(Type rootType, string name, int arity | + this.isMethodCall0(rootType, name, arity, derefChain + ";ref") + | + forall(Impl impl, SelfParamType self | + methodCandidateTrait(rootType, this.getTrait(), name, arity, impl, self) + or + not exists(this.getTrait()) and + methodCandidate(rootType, name, arity, impl, self) + | + IsInstantiationOf::isNotInstantiationOfStrict(MkMethodCallDerefChainRef(this, + derefChain + ";ref"), impl, self) + ) and + forall(Trait trait, SelfParamType self | + traitMethodCandidate(rootType, name, arity, trait, self) + | + IsInstantiationOf::isNotInstantiationOfStrict(MkMethodCallDerefChainRef(this, + derefChain + ";ref"), trait, self) + or + exists(Type t | + methodCallHasTraitCandidate0(MkMethodCallDerefChainRef(this, derefChain + ";ref"), trait, + t, self, _) and + not trait = getATraitBound(t) + ) + ) + // not exists(resolveNonImplMethodCallTarget(rootType, name, arity)) + ) + } + + pragma[nomagic] + private predicate isNotRef(string derefChain) { + this.getACandidateReceiverTypeAt(TypePath::nil(), derefChain) != TRefType() + } + + /** + * Gets a [candidate receiver type][1] of this method call, including reference types. + * + * [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers-refs + */ + pragma[nomagic] + Type getACandidateReceiverTypeRefsAt(TypePath path, string derefChainRef) { + exists(string derefChain | + result = this.getACandidateReceiverTypeAt(path, derefChain) and + derefChainRef = derefChain + ";" + ) + or + exists(TypePath path0, Type t0, string derefChain | + t0 = this.getACandidateReceiverTypeAtRef(path0, derefChain) and + derefChainRef = derefChain + ";ref" + | + // path.isEmpty() and + // result = TRefType() + // or + // path = TypePath::cons(TRefTypeParameter(), path0) and + // result = t0 + path = path0 and + result = t0 + ) + } + + pragma[nomagic] + private Type testgetACandidateReceiverTypeRefsAt(TypePath path, string derefChain) { + result = this.getACandidateReceiverTypeRefsAt(path, derefChain) and + this = Debug::getRelevantLocatable() + // this.getLocation().getStartLine() = 1286 and + // this.fromSource() + } + // /** An alias for `getCandidateReceiverTypeAt`, needed to implement `HasTypeTreeSig`. */ + // Type getTypeAt(TypePath path) { result = this.getACandidateReceiverTypeRefsAt(path) } } /** @@ -1858,65 +2273,229 @@ final class MethodCall extends Call { * exists in `impl`. */ pragma[nomagic] -private predicate methodCandidate(Type type, string name, int arity, Impl impl) { - type = impl.getSelfTy().(TypeMention).resolveType() and - exists(Function f | +private predicate methodCandidate(Type type, string name, int arity, Impl impl, SelfParamType self) { + exists(Function f, SelfParam param | f = impl.(ImplItemNode).getASuccessor(name) and - f.getParamList().hasSelfParam() and - arity = f.getParamList().getNumberOfParams() + param = f.getParamList().getSelfParam() and + arity = f.getParamList().getNumberOfParams() and + type = self.getTypeAt(TypePath::nil()) and + f = self.getFunction(impl) ) } +/** + * Holds if a method for `type` with the name `name` and the arity `arity` + * exists in `trait`. + */ +pragma[nomagic] +private predicate traitMethodCandidate0( + Type type, string name, int arity, Trait trait, SelfParamType self +) { + exists(Function f, SelfParam param | + f = trait.(TraitItemNode).getASuccessor(name) and + param = f.getParamList().getSelfParam() and + arity = f.getParamList().getNumberOfParams() and + f = self.getFunction(trait) and + type = self.getTypeAt(TypePath::nil()) + ) +} + +/** + * Holds if a method for `type` with the name `name` and the arity `arity` + * exists in `trait`. + */ +pragma[inline] +private predicate traitMethodCandidate( + Type type, string name, int arity, Trait trait, SelfParamType self +) { + traitMethodCandidate0(type, name, arity, trait, self) + or + traitMethodCandidate0(TSelfTypeParameter(trait), name, arity, trait, self) and + exists(type) +} + /** * Holds if a method for `type` for `trait` with the name `name` and the arity * `arity` exists in `impl`. */ -pragma[nomagic] -private predicate methodCandidateTrait(Type type, Trait trait, string name, int arity, Impl impl) { +// pragma[nomagic] +pragma[inline] +private predicate methodCandidateTrait( + Type type, Trait trait, string name, int arity, Impl impl, SelfParamType self +) { trait = resolvePath(impl.(ImplItemNode).getTraitPath()) and - methodCandidate(type, name, arity, impl) + methodCandidate(type, name, arity, impl, self) +} + +private newtype TMethodCallDerefChainRef = + MkMethodCallDerefChainRef(MethodCall mc, string derefChainRef) { + exists(mc.getACandidateReceiverTypeRefsAt(_, derefChainRef)) + } + +private class MethodCallDerefChainRef extends MkMethodCallDerefChainRef { + MethodCall mc; + string derefChainRef; + + MethodCallDerefChainRef() { this = MkMethodCallDerefChainRef(mc, derefChainRef) } + + MethodCall getMethodCall() { result = mc } + + Type getTypeAt(TypePath path) { result = mc.getACandidateReceiverTypeRefsAt(path, derefChainRef) } + + string toString() { result = mc.toString() + "[" + derefChainRef + "]" } + + Location getLocation() { result = mc.getLocation() } } pragma[nomagic] -private predicate isMethodCall(MethodCall mc, Type rootType, string name, int arity) { - rootType = mc.getTypeAt(TypePath::nil()) and - name = mc.getMethodName() and - arity = mc.getNumberOfArguments() +private predicate isMethodCall( + MethodCallDerefChainRef mcd, MethodCall mc, Type rootType, string name, int arity +) { + mc = mcd.getMethodCall() and + rootType = [mcd.getTypeAt(TypePath::nil())] and //, mcd.getTypeAt(TypePath::singleton(TRefTypeParameter()))] and + mc.isMethodCall(name, arity) } -private module IsInstantiationOfInput implements IsInstantiationOfInputSig { +private newtype TSelfParamType = + MkSelfParam(SelfParam self, ImplOrTraitItemNode i) { + exists(Function f | + self = f.getParamList().getSelfParam() and + f = i.getAnAssocItem() + ) + } or + MkInheritedSelfParam(SelfParamType inherited, ImplOrTraitItemNode i) { + exists(Function f, ImplOrTraitItemNode parent | + f = inherited.getFunction(parent) and + f = i.getASuccessor(_) + | + parent = i.(ImplItemNode).resolveTraitTy() + or + parent = i.(TraitItemNode).resolveABound() and + not i.(TraitItemNode).hasLoop() + ) + } + +private class SelfParamType extends TSelfParamType { + Function getFunction(ImplOrTraitItemNode i) { + this = MkSelfParam(result.getParamList().getSelfParam(), i) + or + exists(SelfParamType inherited | + this = MkInheritedSelfParam(inherited, i) and + result = inherited.getFunction(_) + ) + } + + private Type testgetTypeAt(TypePath path, ImplOrTraitItemNode i) { + result = this.getTypeAt(path) and + exists(this.getFunction(i)) and + i.getLocation().getStartLine() = 946 + } + + Type getTypeAt(TypePath path) { + exists(SelfParam self | + this.asSelfParam(self, _) and + result = getSelfParamTypeMention(self).resolveTypeAt(path) + ) + or + exists(SelfParamType inherited, ImplOrTraitItemNode i | + this.asInheritedSelfParam(inherited, i) + | + result = inherited.getTypeAt(path) and + not result instanceof TSelfTypeParameter + or + exists(TypePath prefix, TypePath suffix | + inherited.getTypeAt(prefix) = TSelfTypeParameter(_) and + result = resolveImplType(i, suffix) and + path = prefix.append(suffix) + ) + ) + } + + predicate asSelfParam(SelfParam self, ImplOrTraitItemNode i) { this = MkSelfParam(self, i) } + + predicate asInheritedSelfParam(SelfParamType inherited, ImplOrTraitItemNode i) { + this = MkInheritedSelfParam(inherited, i) + } + + string toString() { + exists(SelfParam self | + this.asSelfParam(self, _) and + result = self.toString() + ) + or + exists(SelfParamType inherited, ImplOrTraitItemNode i | + this.asInheritedSelfParam(inherited, i) and + result = inherited.toString() + " (inherited)" + ) + } + + Location getLocation() { + exists(SelfParam self | + this.asSelfParam(self, _) and + result = self.getLocation() + ) + or + exists(SelfParamType inherited | + this.asInheritedSelfParam(inherited, _) and + result = inherited.getLocation() + ) + } +} + +private module IsInstantiationOfInput implements + IsInstantiationOfInputSig +{ pragma[nomagic] - predicate potentialInstantiationOf(MethodCall mc, TypeAbstraction impl, TypeMention constraint) { - exists(Type rootType, string name, int arity | - isMethodCall(mc, rootType, name, arity) and - constraint = impl.(ImplTypeAbstraction).getSelfTy() + predicate potentialInstantiationOf( + MethodCallDerefChainRef mc, TypeAbstraction abs, SelfParamType constraint + ) { + // mc.getMethodCall() = Debug::getRelevantLocatable() and + exists(Type rootType, string name, int arity, MethodCall mc0 | + isMethodCall(mc, mc0, rootType, name, arity) //and | - methodCandidateTrait(rootType, mc.getTrait(), name, arity, impl) + // constraint = getSelfParamTypeMention(self) + methodCandidateTrait(rootType, mc0.getTrait(), name, arity, abs, constraint) + or + not exists(mc0.getTrait()) and + methodCandidate(rootType, name, arity, abs, constraint) or - not exists(mc.getTrait()) and - methodCandidate(rootType, name, arity, impl) + traitMethodCandidate(rootType, name, arity, abs, constraint) //and + // getATraitBound(mc.getTypeAt(_)) = abs + ) + } + + pragma[nomagic] + predicate blah(MethodCallDerefChainRef mc, TypeAbstraction abs, SelfParamType constraint) { + mc.getMethodCall() = Debug::getRelevantLocatable() and + exists(Type rootType, string name, int arity, MethodCall mc0 | + isMethodCall(mc, mc0, rootType, name, arity) //and + | + traitMethodCandidate(rootType, name, arity, abs, constraint) //and + // getATraitBound(mc.getTypeAt(_)) = abs ) } - predicate relevantTypeMention(TypeMention constraint) { - exists(Impl impl | methodCandidate(_, _, _, impl) and constraint = impl.getSelfTy()) + predicate relevantTypeMention(SelfParamType constraint) { + methodCandidate(_, _, _, _, constraint) or + traitMethodCandidate(_, _, _, _, constraint) } } bindingset[item, name] pragma[inline_late] -private Function getMethodSuccessor(ItemNode item, string name) { - result = item.getASuccessor(name) +private Function getMethodSuccessor(ItemNode item, string name, int arity) { + result = item.getASuccessor(name) and + arity = result.getParamList().getNumberOfParams() } -bindingset[tp, name] +bindingset[tp, name, arity] pragma[inline_late] -private Function getTypeParameterMethod(TypeParameter tp, string name) { - result = getMethodSuccessor(tp.(TypeParamTypeParameter).getTypeParam(), name) +private Function getTypeParameterMethod(TypeParameter tp, string name, int arity) { + result = getMethodSuccessor(tp.(TypeParamTypeParameter).getTypeParam(), name, arity) or - result = getMethodSuccessor(tp.(SelfTypeParameter).getTrait(), name) + result = getMethodSuccessor(tp.(SelfTypeParameter).getTrait(), name, arity) or - result = getMethodSuccessor(tp.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr(), name) + result = getMethodSuccessor(tp.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr(), name, arity) } pragma[nomagic] @@ -2052,73 +2631,165 @@ private predicate functionResolutionDependsOnArgument( * resolve to a method in an `impl` block for the type of the receiver. */ pragma[nomagic] -private predicate methodCallHasNoInherentTarget(MethodCall mc) { +private predicate methodCallHasNoInherentTarget(MethodCallDerefChainRef mc) { exists(Type rootType, string name, int arity | - isMethodCall(mc, rootType, name, arity) and + isMethodCall(mc, _, rootType, name, arity) and forall(Impl impl | - methodCandidate(rootType, name, arity, impl) and + methodCandidate(rootType, name, arity, impl, _) and not impl.hasTrait() | - IsInstantiationOf::isNotInstantiationOf(mc, impl, _) + IsInstantiationOf::isNotInstantiationOf(mc, + impl, _) ) ) } pragma[nomagic] -private predicate methodCallHasImplCandidate(MethodCall mc, Impl impl) { - IsInstantiationOf::isInstantiationOf(mc, impl, _) and - if impl.hasTrait() and not exists(mc.getTrait()) - then - // inherent methods take precedence over trait methods, so only allow - // trait methods when there are no matching inherent methods - methodCallHasNoInherentTarget(mc) - else any() +private predicate testmethodCallHasImplCandidate(MethodCallDerefChainRef mc, Impl impl) { + mc.getMethodCall() = Debug::getRelevantLocatable() and + IsInstantiationOf::isInstantiationOf(mc, + impl, _) //and + // exists(MethodCall mc0 | + // mc0 = mc.getMethodCall() and + // if + // impl.hasTrait() and + // not mc0.hasTrait() + // then + // // inherent methods take precedence over trait methods, so only allow + // // trait methods when there are no matching inherent methods + // methodCallHasNoInherentTarget(mc) + // else any() + // ) +} + +pragma[nomagic] +private predicate methodCallHasImplCandidate(MethodCallDerefChainRef mc, Impl impl) { + IsInstantiationOf::isInstantiationOf(mc, + impl, _) and + exists(MethodCall mc0 | + mc0 = mc.getMethodCall() and + if + impl.hasTrait() and + not mc0.hasTrait() + then + // inherent methods take precedence over trait methods, so only allow + // trait methods when there are no matching inherent methods + methodCallHasNoInherentTarget(mc) + else any() + ) +} + +private Trait getATraitBound(Type t) { + result = t.(TypeParamTypeParameter).getTypeParam().(TypeParamItemNode).resolveABound() + or + result = t.(SelfTypeParameter).getTrait() + or + result = t.(ImplTraitType).getImplTraitTypeRepr().(ImplTraitTypeReprItemNode).resolveABound() + or + result = t.(DynTraitType).getTrait() +} + +pragma[nomagic] +private predicate sdf(MethodCallDerefChainRef mc, Trait trait, TypePath path) { + mc.getMethodCall() = Debug::getRelevantLocatable() and + trait = getATraitBound(mc.getTypeAt(path)) +} + +pragma[nomagic] +private predicate methodCallHasTraitCandidate0( + MethodCallDerefChainRef mc, Trait trait, Type t, SelfParamType self, Function f +) { + exists(string name, int arity, TypePath path | + // self = getSelfParamTypeMention(f.getParamList().getSelfParam()) and + f = self.getFunction(trait) and + // self.asSelfParam(f.getParamList().getSelfParam(), trait) and + IsInstantiationOf::isInstantiationOf(mc, + trait, self) and + mc.getMethodCall().isMethodCall(name, arity) and + TSelfTypeParameter(trait) = self.getTypeAt(path) and + t = mc.getTypeAt(path) + // | + // self = + // getSelfParamTypeMention(getTypeParameterMethod(t, name, arity).getParamList().getSelfParam()) + ) +} + +pragma[nomagic] +private predicate methodCallHasTraitCandidate( + MethodCallDerefChainRef mc, Trait trait, Type t, SelfParamType self, Function f +) { + mc.getMethodCall() = Debug::getRelevantLocatable() and + methodCallHasTraitCandidate0(mc, trait, t, self, f) and + trait = getATraitBound(t) + // | + // self = + // getSelfParamTypeMention(getTypeParameterMethod(t, name, arity).getParamList().getSelfParam()) } /** Gets a method from an `impl` block that matches the method call `mc`. */ pragma[nomagic] -private Function getMethodFromImpl(MethodCall mc) { - exists(Impl impl, string name | +private Function getMethodFromImpl(MethodCallDerefChainRef mc) { + exists(Impl impl, string name, MethodCall mc0 | methodCallHasImplCandidate(mc, impl) and - name = mc.getMethodName() and - result = getMethodSuccessor(impl, name) + mc0 = mc.getMethodCall() and + name = mc0.getMethodName() and + result = getMethodSuccessor(impl, name, _) | not functionResolutionDependsOnArgument(impl, name, _, _, _, _) or exists(int pos, TypePath path, Type type | functionResolutionDependsOnArgument(impl, name, result, pos, pragma[only_bind_into](path), type) and - inferType(mc.getPositionalArgument(pos), pragma[only_bind_into](path)) = type + inferType(mc0.getPositionalArgument(pos), pragma[only_bind_into](path)) = type ) ) } bindingset[trait, name] pragma[inline_late] -private Function getImplTraitMethod(ImplTraitReturnType trait, string name) { - result = getMethodSuccessor(trait.getImplTraitTypeRepr(), name) +private Function getImplTraitMethod(ImplTraitReturnType trait, string name, int arity) { + result = getMethodSuccessor(trait.getImplTraitTypeRepr(), name, arity) } bindingset[traitObject, name] pragma[inline_late] -private Function getDynTraitMethod(DynTraitType traitObject, string name) { - result = getMethodSuccessor(traitObject.getTrait(), name) +private Function getDynTraitMethod(DynTraitType traitObject, string name, int arity) { + result = getMethodSuccessor(traitObject.getTrait(), name, arity) } -pragma[nomagic] -private Function resolveMethodCallTarget(MethodCall mc) { - // The method comes from an `impl` block targeting the type of the receiver. - result = getMethodFromImpl(mc) - or +bindingset[t, name, arity] +pragma[inline_late] +private Function resolveNonImplMethodCallTarget(Type t, string name, int arity) { // The type of the receiver is a type parameter and the method comes from a // trait bound on the type parameter. - result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName()) + result = getTypeParameterMethod(t, name, arity) or // The type of the receiver is an `impl Trait` type. - result = getImplTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName()) + result = getImplTraitMethod(t, name, arity) or // The type of the receiver is a trait object `dyn Trait` type. - result = getDynTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName()) + result = getDynTraitMethod(t, name, arity) +} + +pragma[nomagic] +private Function resolveMethodCallTarget(MethodCallDerefChainRef mcd) { + // The method comes from an `impl` block targeting the type of the receiver. + result = getMethodFromImpl(mcd) + or + exists(Trait trait, Type t | + methodCallHasTraitCandidate0(mcd, trait, t, _, result) and + trait = getATraitBound(t) + ) + // exists(Type rootType, string name, int arity | + // isMethodCall(mcd, _, rootType, name, arity) and + // result = resolveNonImplMethodCallTarget(rootType, name, arity) + // ) +} + +private Function testresolveMethodCallTarget(MethodCallDerefChainRef mcd) { + // result = resolveMethodCallTarget(mcd) and + result = resolveMethodCallTarget(mcd) and + mcd.getMethodCall() = Debug::getRelevantLocatable() } pragma[nomagic] @@ -2207,11 +2878,11 @@ private class AmbigousAssocFunctionCallExpr extends MkAmbigousAssocFunctionCallE } private module AmbigousAssocFuncIsInstantiationOfInput implements - IsInstantiationOfInputSig + IsInstantiationOfInputSig { pragma[nomagic] predicate potentialInstantiationOf( - AmbigousAssocFunctionCallExpr ce, TypeAbstraction impl, TypeMention constraint + AmbigousAssocFunctionCallExpr ce, TypeAbstraction impl, TypeMentionTypeTree constraint ) { exists(FunctionCallExpr call, Function resolved, Function cand, int pos | ce = MkAmbigousAssocFunctionCallExpr(call, resolved, pos) and @@ -2237,7 +2908,7 @@ private ItemNode resolveUnambigousFunctionCallTarget(FunctionCallExpr call) { pragma[nomagic] private Function resolveAmbigousFunctionCallTargetFromIndex(FunctionCallExpr call, int index) { exists(Impl impl, int pos, Function resolved | - IsInstantiationOf::isInstantiationOf(MkAmbigousAssocFunctionCallExpr(call, + IsInstantiationOf::isInstantiationOf(MkAmbigousAssocFunctionCallExpr(call, resolved, pos), impl, _) and result = call.getAnAmbigousCandidateRanked(impl, pos, resolved, index) | @@ -2271,31 +2942,33 @@ private module Cached { /** Holds if `receiver` is the receiver of a method call with an implicit dereference. */ cached predicate receiverHasImplicitDeref(AstNode receiver) { - exists(CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos | - apos.getArgumentPosition().isSelf() and - apos.isBorrowed(_) and - receiver = a.getNodeAt(apos) and - inferType(receiver) = TRefType() and - CallExprBaseMatching::inferAccessType(a, apos, TypePath::nil()) != TRefType() - ) + none() // todo + // exists(CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos | + // apos.getArgumentPosition().isSelf() and + // apos.isBorrowed(_) and + // receiver = a.getNodeAt(apos) and + // inferType(receiver) = TRefType() and + // CallExprBaseMatching::inferAccessType(a, apos, TypePath::nil()) != TRefType() + // ) } /** Holds if `receiver` is the receiver of a method call with an implicit borrow. */ cached predicate receiverHasImplicitBorrow(AstNode receiver) { - exists(CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos | - apos.getArgumentPosition().isSelf() and - apos.isBorrowed(_) and - receiver = a.getNodeAt(apos) and - CallExprBaseMatching::inferAccessType(a, apos, TypePath::nil()) = TRefType() and - inferType(receiver) != TRefType() - ) + none() // todo + // exists(CallExprBaseMatchingInput::Access a, CallExprBaseMatchingInput::AccessPosition apos | + // apos.getArgumentPosition().isSelf() and + // apos.isBorrowed(_) and + // receiver = a.getNodeAt(apos) and + // CallExprBaseMatching::inferAccessType(a, apos, TypePath::nil()) = TRefType() and + // inferType(receiver) != TRefType() + // ) } /** Gets a function that `call` resolves to, if any. */ cached Function resolveCallTarget(Call call) { - result = resolveMethodCallTarget(call) + result = resolveMethodCallTarget(any(MethodCallDerefChainRef mcd | call = mcd.getMethodCall())) or result = resolveFunctionCallTarget(call) } @@ -2376,7 +3049,7 @@ private module Cached { or result = inferTypeEquality(n, path) or - result = inferImplicitSelfType(n, path) + result = n.(SelfParameterImplicitMention).resolveTypeAt(path) or result = inferStructExprType(n, path) or @@ -2419,11 +3092,13 @@ Type inferType(AstNode n) { result = inferType(n, TypePath::nil()) } /** Provides predicates for debugging the type inference implementation. */ private module Debug { - private Locatable getRelevantLocatable() { + Locatable getRelevantLocatable() { exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and - filepath.matches("%/sqlx.rs") and - startline = [56 .. 60] + // filepath.matches("%/crates/wdk-macros/src/lib.rs") and + // endline = [255 .. 256] + filepath.matches("%/main.rs") and + startline = 953 ) } @@ -2444,11 +3119,10 @@ private module Debug { Input2::conditionSatisfiesConstraint(abs, condition, constraint) } - predicate debugInferImplicitSelfType(SelfParam self, TypePath path, Type t) { - self = getRelevantLocatable() and - t = inferImplicitSelfType(self, path) - } - + // predicate debugInferImplicitSelfType(SelfParam self, TypePath path, Type t) { + // self = getRelevantLocatable() and + // t = inferImplicitSelfType(self, path) + // } predicate debugInferCallExprBaseType(AstNode n, TypePath path, Type t) { n = getRelevantLocatable() and t = inferCallExprBaseType(n, path) @@ -2516,4 +3190,12 @@ private module Debug { n = getRelevantLocatable() and Consistency::nonUniqueCertainType(n, path, result) } + // predicate debugisMethodCall(MethodCall mc, Type rootType, string name, int arity) { + // mc = getRelevantLocatable() and + // isMethodCall(mc, rootType, name, arity) + // } + // predicate debugMethodCallHasImplCandidate(MethodCall mc, Impl impl) { + // mc = getRelevantLocatable() and + // methodCallHasImplCandidate(mc, impl) + // } } diff --git a/rust/ql/lib/codeql/rust/internal/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/TypeMention.qll index c36e19842377..b8082cf0301d 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeMention.qll @@ -12,6 +12,7 @@ abstract class TypeMention extends AstNode { abstract Type resolveTypeAt(TypePath path); /** Gets the type that this node resolves to, if any. */ + pragma[nomagic] final Type resolveType() { result = this.resolveTypeAt(TypePath::nil()) } } @@ -327,6 +328,81 @@ class SelfTypeParameterMention extends TypeMention instanceof Name { } } +pragma[nomagic] +Type resolveImplSelfType(Impl i, TypePath path) { + result = i.getSelfTy().(TypeMention).resolveTypeAt(path) +} + +pragma[nomagic] +Type resolveImplType(ImplOrTraitItemNode i, TypePath path) { + result = resolveImplSelfType(i, path) + or + result = TSelfTypeParameter(i) and path.isEmpty() +} + +/** Gets the type at `path` of the implicitly typed `self` parameter. */ +pragma[nomagic] +private Type resolveSelfType(SelfParam self, TypePath path) { + exists(ImplOrTraitItemNode i, Function f | + f = i.getAnAssocItem() and + self = f.getParamList().getSelfParam() and + result = resolveImplType(i, path) + ) +} + +/** Gets the type at `path` of the implicitly typed `self` parameter. */ +pragma[nomagic] +private Type inferImplicitSelfType(SelfParam self, TypePath path) { + exists(TypePath suffix, Type t | + t = resolveSelfType(self, suffix) and + result = getRefAdjustImplicitSelfType(self, suffix, t, path) + ) +} + +/** + * Gets the type of the implicitly typed `self` parameter, taking into account + * whether the parameter is passed by value or by reference. + */ +bindingset[self, suffix, t] +pragma[inline_late] +private Type getRefAdjustImplicitSelfType(SelfParam self, TypePath suffix, Type t, TypePath path) { + not self.hasTypeRepr() and + ( + if self.isRef() + then + // `fn f(&self, ...)` + path.isEmpty() and + result = TRefType() + or + path = TypePath::cons(TRefTypeParameter(), suffix) and + result = t + else ( + // `fn f(self, ...)` + path = suffix and + result = t + ) + ) +} + +class SelfParameterImplicitMention extends TypeMention instanceof SelfParam { + SelfParameterImplicitMention() { not super.hasTypeRepr() } + + override Type resolveTypeAt(TypePath typePath) { result = inferImplicitSelfType(this, typePath) } +} + +pragma[nomagic] +TypeMention getSelfParamTypeMention(SelfParam self) { + result = self.(SelfParameterImplicitMention) + or + result = self.getTypeRepr() +} + +// pragma[nomagic] +// Type resolveSelfParamType(SelfParam self, TypePath path) { +// result = getSelfParamTypeMention(self.(SelfParameterImplicitMention).resolveTypeAt(path) +// or +// result = self.getTypeRepr().(TypeMention).resolveTypeAt(path) +// } class DynTraitTypeReprMention extends TypeMention instanceof DynTraitTypeRepr { private DynTraitType dynType; diff --git a/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected index d2fded7a0730..5a8fee7e3423 100644 --- a/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected +++ b/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected @@ -1,5 +1,11 @@ multipleCallTargets -| dereference.rs:61:15:61:24 | e1.deref() | +| dereference.rs:69:15:69:24 | e1.deref() | +| dereference.rs:182:17:182:26 | ... .foo() | +| dereference.rs:183:17:183:23 | S.foo() | +| dereference.rs:184:17:184:30 | ... .foo() | +| dereference.rs:186:17:186:25 | S.bar(...) | +| dereference.rs:187:17:187:29 | S.bar(...) | +| main.rs:1754:13:1754:63 | ... .partial_cmp(...) | | main.rs:2308:13:2308:31 | ...::from(...) | | main.rs:2309:13:2309:31 | ...::from(...) | | main.rs:2310:13:2310:31 | ...::from(...) | diff --git a/rust/ql/test/library-tests/type-inference/dereference.rs b/rust/ql/test/library-tests/type-inference/dereference.rs index f4d9d68a0995..bdc42180a63d 100644 --- a/rust/ql/test/library-tests/type-inference/dereference.rs +++ b/rust/ql/test/library-tests/type-inference/dereference.rs @@ -27,6 +27,14 @@ impl Deref for MySmartPointer { } } +struct S(T); + +impl S { + fn foo(&self) -> &T { + &self.0 // $ fieldof=S + } +} + fn explicit_monomorphic_dereference() { // Dereference with method call let a1 = MyIntPointer { value: 34i64 }; @@ -58,7 +66,7 @@ fn explicit_polymorphic_dereference() { fn explicit_ref_dereference() { // Explicit dereference with type parameter let e1 = &'a'; - let _f1 = e1.deref(); // $ target=deref MISSING: type=_f1:&T.char + let _f1 = e1.deref(); // $ target=deref type=_f1:&T.char // Explicit dereference with type parameter let e2 = &'a'; @@ -91,6 +99,9 @@ fn implicit_dereference() { // Call method on implicitly dereferenced value let x = MySmartPointer { value: 34i64 }; let _y = x.is_positive(); // $ MISSING: target=is_positive type=_y:bool + + let z = MySmartPointer { value: S(0i64) }; + let z_ = z.foo(); // $ MISSING: target=foo type=z_:&T.i64 } mod implicit_deref_coercion_cycle { @@ -128,6 +139,83 @@ mod implicit_deref_coercion_cycle { } } +mod ref_vs_mut_ref { + trait MyTrait1 { + fn foo(self) -> T; + } + + struct S; + + impl MyTrait1 for &S { + // MyTrait1::foo1 + fn foo(self) -> S { + S + } + } + + impl MyTrait1 for &mut S { + // MyTrait1::foo2 + fn foo(self) -> i64 { + 42 + } + } + + trait MyTrait2 { + fn bar(self, arg: T1) -> T2; + } + + impl MyTrait2<&S, S> for S { + // MyTrait2::bar1 + fn bar(self, arg: &S) -> S { + S + } + } + + impl MyTrait2<&mut S, i64> for S { + // MyTrait2::bar2 + fn bar(self, arg: &mut S) -> i64 { + 42 + } + } + + pub fn test() { + let x = (&S).foo(); // $ target=MyTrait1::foo1 type=x:S $ SPURIOUS: target=MyTrait1::foo2 + let y = S.foo(); // $ target=MyTrait1::foo1 type=y:S $ SPURIOUS: target=MyTrait1::foo2 + let z = (&mut S).foo(); // $ target=MyTrait1::foo2 type=z:i64 $ SPURIOUS: target=MyTrait1::foo1 + + let x = S.bar(&S); // $ target=MyTrait2::bar1 type=x:S $ SPURIOUS: target=MyTrait2::bar2 + let y = S.bar(&mut S); // $ target=MyTrait2::bar2 type=y:i64 $ SPURIOUS: target=MyTrait2::bar1 + } +} + +// from https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-search +mod rust_reference_example { + struct Foo {} + + trait Bar { + fn bar(&self); + } + + impl Foo { + // bar1 + fn bar(&mut self) { + println!("In struct impl!") + } + } + + impl Bar for Foo { + // bar2 + fn bar(&self) { + println!("In trait impl!") + } + } + + pub fn main() { + let mut f = Foo {}; + f.bar(); // $ SPURIOUS: target=bar1 $ MISSING: target=bar2 + } +} + pub fn test() { explicit_monomorphic_dereference(); // $ target=explicit_monomorphic_dereference explicit_polymorphic_dereference(); // $ target=explicit_polymorphic_dereference @@ -135,4 +223,6 @@ pub fn test() { explicit_box_dereference(); // $ target=explicit_box_dereference implicit_dereference(); // $ target=implicit_dereference implicit_deref_coercion_cycle::test(); // $ target=test + ref_vs_mut_ref::test(); // $ target=test + rust_reference_example::main(); // $ target=main } diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index e6dc211060cc..1f3b1ab14b5f 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -909,19 +909,19 @@ mod generic_enum { } mod method_supertraits { - #[derive(Debug)] + #[derive(Debug, Clone, Copy)] struct MyThing { a: A, } - #[derive(Debug)] + #[derive(Debug, Clone, Copy)] struct MyThing2 { a: A, } - #[derive(Debug)] + #[derive(Debug, Clone, Copy)] struct S1; - #[derive(Debug)] + #[derive(Debug, Clone, Copy)] struct S2; trait MyTrait1 { @@ -929,16 +929,16 @@ mod method_supertraits { fn m1(self) -> Tr1; } - trait MyTrait2: MyTrait1 { + trait MyTrait2: MyTrait1 + Copy { #[rustfmt::skip] - fn m2(self) -> Tr2 + fn m2(&self) -> Tr2 where Self: Sized, { if 3 > 2 { // $ target=gt self.m1() // $ target=MyTrait1::m1 } else { - Self::m1(self) // $ target=MyTrait1::m1 + Self::m1(*self) // $ target=deref target=MyTrait1::m1 } } } @@ -952,7 +952,7 @@ mod method_supertraits { if 3 > 2 { // $ target=gt self.m2().a // $ target=m2 $ fieldof=MyThing } else { - Self::m2(self).a // $ target=m2 fieldof=MyThing + Self::m2(&self).a // $ target=m2 fieldof=MyThing } } } @@ -964,7 +964,7 @@ mod method_supertraits { } } - impl MyTrait2 for MyThing {} + impl MyTrait2 for MyThing {} impl MyTrait1> for MyThing2 { // MyThing2::m1 @@ -973,9 +973,9 @@ mod method_supertraits { } } - impl MyTrait2> for MyThing2 {} + impl MyTrait2> for MyThing2 {} - impl MyTrait3 for MyThing2 {} + impl MyTrait3 for MyThing2 {} fn call_trait_m1>(x: T2) -> T1 { x.m1() // $ target=MyTrait1::m1 @@ -1335,12 +1335,12 @@ mod method_call_type_conversion { let my_thing = &MyInt { a: 37 }; // implicit borrow of a `&` - let a = my_thing.method_on_borrow(); // $ MISSING: target=MyInt::method_on_borrow + let a = my_thing.method_on_borrow(); // $ target=MyInt::method_on_borrow println!("{:?}", a); // no implicit borrow let my_thing = &MyInt { a: 38 }; - let a = my_thing.method_not_on_borrow(); // $ MISSING: target=MyInt::method_not_on_borrow + let a = my_thing.method_not_on_borrow(); // $ target=MyInt::method_not_on_borrow println!("{:?}", a); } } @@ -2558,12 +2558,11 @@ pub mod exec { pub mod path_buf { // a highly simplified model of `PathBuf::canonicalize` - pub struct Path { - } + pub struct Path {} impl Path { pub const fn new() -> Path { - Path { } + Path {} } pub fn canonicalize(&self) -> Result { @@ -2571,12 +2570,11 @@ pub mod path_buf { } } - pub struct PathBuf { - } + pub struct PathBuf {} impl PathBuf { pub const fn new() -> PathBuf { - PathBuf { } + PathBuf {} } } @@ -2587,7 +2585,7 @@ pub mod path_buf { #[inline] fn deref(&self) -> &Path { // (very much not a real implementation) - static path : Path = Path::new(); // $ target=new + static path: Path = Path::new(); // $ target=new &path } } diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index cf33947be67e..735ecbfd5c25 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -228,217 +228,318 @@ inferType | dereference.rs:26:10:26:13 | self | &T | dereference.rs:17:1:19:1 | MySmartPointer | | dereference.rs:26:10:26:13 | self | &T.T | dereference.rs:21:6:21:6 | T | | dereference.rs:26:10:26:19 | self.value | | dereference.rs:21:6:21:6 | T | -| dereference.rs:32:9:32:10 | a1 | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:32:14:32:42 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:32:36:32:40 | 34i64 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:33:9:33:11 | _b1 | | file://:0:0:0:0 | & | -| dereference.rs:33:9:33:11 | _b1 | &T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:33:15:33:16 | a1 | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:33:15:33:24 | a1.deref() | | file://:0:0:0:0 | & | -| dereference.rs:33:15:33:24 | a1.deref() | &T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:36:9:36:10 | a2 | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:36:14:36:42 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:36:36:36:40 | 34i64 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:37:9:37:11 | _b2 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:37:15:37:17 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:37:16:37:17 | a2 | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:40:9:40:10 | a3 | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:33:12:33:16 | SelfParam | | file://:0:0:0:0 | & | +| dereference.rs:33:12:33:16 | SelfParam | &T | dereference.rs:30:1:30:15 | S | +| dereference.rs:33:12:33:16 | SelfParam | &T.T | dereference.rs:32:6:32:6 | T | +| dereference.rs:33:25:35:5 | { ... } | | file://:0:0:0:0 | & | +| dereference.rs:33:25:35:5 | { ... } | &T | dereference.rs:32:6:32:6 | T | +| dereference.rs:34:9:34:15 | &... | | file://:0:0:0:0 | & | +| dereference.rs:34:9:34:15 | &... | &T | dereference.rs:32:6:32:6 | T | +| dereference.rs:34:10:34:13 | self | | file://:0:0:0:0 | & | +| dereference.rs:34:10:34:13 | self | &T | dereference.rs:30:1:30:15 | S | +| dereference.rs:34:10:34:13 | self | &T.T | dereference.rs:32:6:32:6 | T | +| dereference.rs:34:10:34:15 | self.0 | | dereference.rs:32:6:32:6 | T | +| dereference.rs:40:9:40:10 | a1 | | dereference.rs:4:1:6:1 | MyIntPointer | | dereference.rs:40:14:40:42 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | | dereference.rs:40:36:40:40 | 34i64 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:41:9:41:11 | _b3 | | {EXTERNAL LOCATION} | bool | -| dereference.rs:41:15:41:19 | (...) | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:41:15:41:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | -| dereference.rs:41:16:41:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:41:17:41:18 | a3 | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:46:9:46:10 | c1 | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:46:9:46:10 | c1 | T | {EXTERNAL LOCATION} | char | -| dereference.rs:46:14:46:42 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:46:14:46:42 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | char | -| dereference.rs:46:38:46:40 | 'a' | | {EXTERNAL LOCATION} | char | -| dereference.rs:47:9:47:11 | _d1 | | file://:0:0:0:0 | & | -| dereference.rs:47:9:47:11 | _d1 | &T | {EXTERNAL LOCATION} | char | -| dereference.rs:47:15:47:16 | c1 | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:47:15:47:16 | c1 | T | {EXTERNAL LOCATION} | char | -| dereference.rs:47:15:47:24 | c1.deref() | | file://:0:0:0:0 | & | -| dereference.rs:47:15:47:24 | c1.deref() | &T | {EXTERNAL LOCATION} | char | -| dereference.rs:50:9:50:10 | c2 | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:50:9:50:10 | c2 | T | {EXTERNAL LOCATION} | char | -| dereference.rs:50:14:50:42 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:50:14:50:42 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | char | -| dereference.rs:50:38:50:40 | 'a' | | {EXTERNAL LOCATION} | char | -| dereference.rs:51:9:51:11 | _d2 | | {EXTERNAL LOCATION} | char | -| dereference.rs:51:15:51:17 | * ... | | {EXTERNAL LOCATION} | char | -| dereference.rs:51:16:51:17 | c2 | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:51:16:51:17 | c2 | T | {EXTERNAL LOCATION} | char | -| dereference.rs:54:9:54:10 | c3 | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:54:9:54:10 | c3 | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:54:14:54:44 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:54:14:54:44 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:54:38:54:42 | 34i64 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:55:9:55:11 | _d3 | | {EXTERNAL LOCATION} | bool | -| dereference.rs:55:15:55:19 | (...) | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:55:15:55:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | -| dereference.rs:55:16:55:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:55:17:55:18 | c3 | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:55:17:55:18 | c3 | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:60:9:60:10 | e1 | | file://:0:0:0:0 | & | -| dereference.rs:60:9:60:10 | e1 | &T | {EXTERNAL LOCATION} | char | -| dereference.rs:60:9:60:10 | e1 | &T | file://:0:0:0:0 | & | -| dereference.rs:60:14:60:17 | &'a' | | file://:0:0:0:0 | & | -| 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: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 | -| dereference.rs:61:15:61:16 | e1 | &T | file://:0:0:0:0 | & | -| dereference.rs:61:15:61:24 | e1.deref() | | file://:0:0:0:0 | & | -| dereference.rs:64:9:64:10 | e2 | | file://:0:0:0:0 | & | -| dereference.rs:64:9:64:10 | e2 | &T | {EXTERNAL LOCATION} | char | -| dereference.rs:64:14:64:17 | &'a' | | file://:0:0:0:0 | & | -| dereference.rs:64:14:64:17 | &'a' | &T | {EXTERNAL LOCATION} | char | -| dereference.rs:64:15:64:17 | 'a' | | {EXTERNAL LOCATION} | char | -| dereference.rs:65:9:65:11 | _f2 | | {EXTERNAL LOCATION} | char | -| dereference.rs:65:15:65:17 | * ... | | {EXTERNAL LOCATION} | char | -| dereference.rs:65:16:65:17 | e2 | | file://:0:0:0:0 | & | -| dereference.rs:65:16:65:17 | e2 | &T | {EXTERNAL LOCATION} | char | -| dereference.rs:68:9:68:10 | e3 | | file://:0:0:0:0 | & | -| dereference.rs:68:9:68:10 | e3 | &T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:68:14:68:19 | &34i64 | | file://:0:0:0:0 | & | -| dereference.rs:68:14:68:19 | &34i64 | &T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:68:15:68:19 | 34i64 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:69:9:69:11 | _f3 | | {EXTERNAL LOCATION} | bool | -| dereference.rs:69:15:69:19 | (...) | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:69:15:69:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | -| dereference.rs:69:16:69:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:69:17:69:18 | e3 | | file://:0:0:0:0 | & | -| dereference.rs:69:17:69:18 | e3 | &T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:74:9:74:10 | g1 | | {EXTERNAL LOCATION} | Box | -| dereference.rs:74:9:74:10 | g1 | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:74:9:74:10 | g1 | T | {EXTERNAL LOCATION} | char | -| dereference.rs:74:25:74:37 | ...::new(...) | | {EXTERNAL LOCATION} | Box | -| dereference.rs:74:25:74:37 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:74:25:74:37 | ...::new(...) | T | {EXTERNAL LOCATION} | char | -| dereference.rs:74:34:74:36 | 'a' | | {EXTERNAL LOCATION} | char | -| dereference.rs:75:9:75:11 | _h1 | | file://:0:0:0:0 | & | -| dereference.rs:75:9:75:11 | _h1 | &T | {EXTERNAL LOCATION} | char | -| dereference.rs:75:15:75:16 | g1 | | {EXTERNAL LOCATION} | Box | -| dereference.rs:75:15:75:16 | g1 | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:75:15:75:16 | g1 | T | {EXTERNAL LOCATION} | char | -| dereference.rs:75:15:75:24 | g1.deref() | | file://:0:0:0:0 | & | -| dereference.rs:75:15:75:24 | g1.deref() | &T | {EXTERNAL LOCATION} | char | -| dereference.rs:78:9:78:10 | g2 | | {EXTERNAL LOCATION} | Box | -| dereference.rs:78:9:78:10 | g2 | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:78:9:78:10 | g2 | T | {EXTERNAL LOCATION} | char | -| dereference.rs:78:25:78:37 | ...::new(...) | | {EXTERNAL LOCATION} | Box | -| dereference.rs:78:25:78:37 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:78:25:78:37 | ...::new(...) | T | {EXTERNAL LOCATION} | char | -| dereference.rs:78:34:78:36 | 'a' | | {EXTERNAL LOCATION} | char | -| dereference.rs:79:9:79:11 | _h2 | | {EXTERNAL LOCATION} | char | -| dereference.rs:79:15:79:17 | * ... | | {EXTERNAL LOCATION} | char | -| dereference.rs:79:16:79:17 | g2 | | {EXTERNAL LOCATION} | Box | -| dereference.rs:79:16:79:17 | g2 | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:79:16:79:17 | g2 | T | {EXTERNAL LOCATION} | char | -| dereference.rs:82:9:82:10 | g3 | | {EXTERNAL LOCATION} | Box | -| dereference.rs:82:9:82:10 | g3 | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:82:9:82:10 | g3 | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:82:24:82:38 | ...::new(...) | | {EXTERNAL LOCATION} | Box | -| dereference.rs:82:24:82:38 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:82:24:82:38 | ...::new(...) | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:82:33:82:37 | 34i64 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:83:9:83:11 | _h3 | | {EXTERNAL LOCATION} | bool | -| dereference.rs:83:15:83:19 | (...) | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:83:15:83:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | -| dereference.rs:83:16:83:18 | * ... | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:83:17:83:18 | g3 | | {EXTERNAL LOCATION} | Box | -| dereference.rs:83:17:83:18 | g3 | A | {EXTERNAL LOCATION} | Global | -| dereference.rs:83:17:83:18 | g3 | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:88:9:88:9 | x | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:88:13:88:41 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:88:35:88:39 | 34i64 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:89:14:89:14 | x | | dereference.rs:4:1:6:1 | MyIntPointer | -| dereference.rs:92:9:92:9 | x | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:92:9:92:9 | x | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:92:13:92:43 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:92:13:92:43 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:92:37:92:41 | 34i64 | | {EXTERNAL LOCATION} | i64 | -| dereference.rs:93:14:93:14 | x | | dereference.rs:17:1:19:1 | MySmartPointer | -| dereference.rs:93:14:93:14 | x | T | {EXTERNAL LOCATION} | i64 | -| dereference.rs:121:17:121:26 | key_to_key | | {EXTERNAL LOCATION} | HashMap | -| dereference.rs:121:17:121:26 | key_to_key | K | file://:0:0:0:0 | & | -| dereference.rs:121:17:121:26 | key_to_key | K.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:121:17:121:26 | key_to_key | S | {EXTERNAL LOCATION} | RandomState | -| dereference.rs:121:17:121:26 | key_to_key | V | file://:0:0:0:0 | & | -| dereference.rs:121:17:121:26 | key_to_key | V.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:121:30:121:57 | ...::new(...) | | {EXTERNAL LOCATION} | HashMap | -| dereference.rs:121:30:121:57 | ...::new(...) | K | file://:0:0:0:0 | & | -| dereference.rs:121:30:121:57 | ...::new(...) | K.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:121:30:121:57 | ...::new(...) | S | {EXTERNAL LOCATION} | RandomState | -| dereference.rs:121:30:121:57 | ...::new(...) | V | file://:0:0:0:0 | & | -| dereference.rs:121:30:121:57 | ...::new(...) | V.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:122:17:122:19 | key | | file://:0:0:0:0 | & | -| dereference.rs:122:17:122:19 | key | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:122:17:122:19 | key | &T | file://:0:0:0:0 | & | -| dereference.rs:122:17:122:19 | key | &T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:122:23:122:29 | &... | | file://:0:0:0:0 | & | -| dereference.rs:122:23:122:29 | &... | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:122:23:122:29 | &... | &T | file://:0:0:0:0 | & | -| dereference.rs:122:23:122:29 | &... | &T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:122:24:122:29 | Key {...} | | dereference.rs:99:5:100:21 | Key | -| dereference.rs:122:24:122:29 | Key {...} | | file://:0:0:0:0 | & | -| dereference.rs:122:24:122:29 | Key {...} | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:123:16:123:28 | Some(...) | | {EXTERNAL LOCATION} | Option | -| dereference.rs:123:16:123:28 | Some(...) | T | file://:0:0:0:0 | & | -| dereference.rs:123:16:123:28 | Some(...) | T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:123:16:123:28 | Some(...) | T.&T | file://:0:0:0:0 | & | -| dereference.rs:123:16:123:28 | Some(...) | T.&T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:123:21:123:27 | ref_key | | file://:0:0:0:0 | & | -| dereference.rs:123:21:123:27 | ref_key | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:123:21:123:27 | ref_key | &T | file://:0:0:0:0 | & | -| dereference.rs:123:21:123:27 | ref_key | &T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:123:32:123:41 | key_to_key | | {EXTERNAL LOCATION} | HashMap | -| 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 | 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 | -| dereference.rs:123:32:123:50 | key_to_key.get(...) | T | file://:0:0:0:0 | & | -| dereference.rs:123:32:123:50 | key_to_key.get(...) | T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:123:32:123:50 | key_to_key.get(...) | T.&T | file://:0:0:0:0 | & | -| dereference.rs:123:32:123:50 | key_to_key.get(...) | T.&T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:123:47:123:49 | key | | file://:0:0:0:0 | & | -| dereference.rs:123:47:123:49 | key | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:123:47:123:49 | key | &T | file://:0:0:0:0 | & | -| dereference.rs:123:47:123:49 | key | &T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:125:13:125:15 | key | | file://:0:0:0:0 | & | -| dereference.rs:125:13:125:15 | key | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:125:13:125:15 | key | &T | file://:0:0:0:0 | & | -| dereference.rs:125:13:125:15 | key | &T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:125:13:125:25 | ... = ... | | file://:0:0:0:0 | () | -| dereference.rs:125:19:125:25 | ref_key | | file://:0:0:0:0 | & | -| dereference.rs:125:19:125:25 | ref_key | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:125:19:125:25 | ref_key | &T | file://:0:0:0:0 | & | -| dereference.rs:125:19:125:25 | ref_key | &T.&T | dereference.rs:99:5:100:21 | Key | -| 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 | 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: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 | -| dereference.rs:127:9:127:35 | key_to_key.insert(...) | T.&T | file://:0:0:0:0 | & | -| dereference.rs:127:9:127:35 | key_to_key.insert(...) | T.&T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:127:27:127:29 | key | | file://:0:0:0:0 | & | -| dereference.rs:127:27:127:29 | key | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:127:27:127:29 | key | &T | file://:0:0:0:0 | & | -| dereference.rs:127:27:127:29 | key | &T.&T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:127:32:127:34 | key | | file://:0:0:0:0 | & | -| dereference.rs:127:32:127:34 | key | &T | dereference.rs:99:5:100:21 | Key | -| dereference.rs:127:32:127:34 | key | &T | file://:0:0:0:0 | & | -| dereference.rs:127:32:127:34 | key | &T.&T | dereference.rs:99:5:100:21 | Key | +| dereference.rs:41:9:41:11 | _b1 | | file://:0:0:0:0 | & | +| dereference.rs:41:9:41:11 | _b1 | &T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:41:15:41:16 | a1 | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:41:15:41:24 | a1.deref() | | file://:0:0:0:0 | & | +| dereference.rs:41:15:41:24 | a1.deref() | &T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:44:9:44:10 | a2 | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:44:14:44:42 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:44:36:44:40 | 34i64 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:45:9:45:11 | _b2 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:45:15:45:17 | * ... | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:45:16:45:17 | a2 | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:48:9:48:10 | a3 | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:48:14:48:42 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:48:36:48:40 | 34i64 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:49:9:49:11 | _b3 | | {EXTERNAL LOCATION} | bool | +| dereference.rs:49:15:49:19 | (...) | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:49:15:49:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | +| dereference.rs:49:16:49:18 | * ... | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:49:17:49:18 | a3 | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:54:9:54:10 | c1 | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:54:9:54:10 | c1 | T | {EXTERNAL LOCATION} | char | +| dereference.rs:54:14:54:42 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:54:14:54:42 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | char | +| dereference.rs:54:38:54:40 | 'a' | | {EXTERNAL LOCATION} | char | +| dereference.rs:55:9:55:11 | _d1 | | file://:0:0:0:0 | & | +| dereference.rs:55:9:55:11 | _d1 | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:55:15:55:16 | c1 | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:55:15:55:16 | c1 | T | {EXTERNAL LOCATION} | char | +| dereference.rs:55:15:55:24 | c1.deref() | | file://:0:0:0:0 | & | +| dereference.rs:55:15:55:24 | c1.deref() | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:58:9:58:10 | c2 | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:58:9:58:10 | c2 | T | {EXTERNAL LOCATION} | char | +| dereference.rs:58:14:58:42 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:58:14:58:42 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | char | +| dereference.rs:58:38:58:40 | 'a' | | {EXTERNAL LOCATION} | char | +| dereference.rs:59:9:59:11 | _d2 | | {EXTERNAL LOCATION} | char | +| dereference.rs:59:15:59:17 | * ... | | {EXTERNAL LOCATION} | char | +| dereference.rs:59:16:59:17 | c2 | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:59:16:59:17 | c2 | T | {EXTERNAL LOCATION} | char | +| dereference.rs:62:9:62:10 | c3 | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:62:9:62:10 | c3 | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:62:14:62:44 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:62:14:62:44 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:62:38:62:42 | 34i64 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:63:9:63:11 | _d3 | | {EXTERNAL LOCATION} | bool | +| dereference.rs:63:15:63:19 | (...) | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:63:15:63:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | +| dereference.rs:63:16:63:18 | * ... | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:63:17:63:18 | c3 | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:63:17:63:18 | c3 | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:68:9:68:10 | e1 | | file://:0:0:0:0 | & | +| dereference.rs:68:9:68:10 | e1 | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:68:14:68:17 | &'a' | | file://:0:0:0:0 | & | +| dereference.rs:68:14:68:17 | &'a' | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:68:15:68:17 | 'a' | | {EXTERNAL LOCATION} | char | +| dereference.rs:69:9:69:11 | _f1 | | file://:0:0:0:0 | & | +| dereference.rs:69:9:69:11 | _f1 | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:69:15:69:16 | e1 | | file://:0:0:0:0 | & | +| dereference.rs:69:15:69:16 | e1 | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:69:15:69:24 | e1.deref() | | file://:0:0:0:0 | & | +| dereference.rs:69:15:69:24 | e1.deref() | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:72:9:72:10 | e2 | | file://:0:0:0:0 | & | +| dereference.rs:72:9:72:10 | e2 | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:72:14:72:17 | &'a' | | file://:0:0:0:0 | & | +| dereference.rs:72:14:72:17 | &'a' | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:72:15:72:17 | 'a' | | {EXTERNAL LOCATION} | char | +| dereference.rs:73:9:73:11 | _f2 | | {EXTERNAL LOCATION} | char | +| dereference.rs:73:15:73:17 | * ... | | {EXTERNAL LOCATION} | char | +| dereference.rs:73:16:73:17 | e2 | | file://:0:0:0:0 | & | +| dereference.rs:73:16:73:17 | e2 | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:76:9:76:10 | e3 | | file://:0:0:0:0 | & | +| dereference.rs:76:9:76:10 | e3 | &T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:76:14:76:19 | &34i64 | | file://:0:0:0:0 | & | +| dereference.rs:76:14:76:19 | &34i64 | &T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:76:15:76:19 | 34i64 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:77:9:77:11 | _f3 | | {EXTERNAL LOCATION} | bool | +| dereference.rs:77:15:77:19 | (...) | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:77:15:77:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | +| dereference.rs:77:16:77:18 | * ... | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:77:17:77:18 | e3 | | file://:0:0:0:0 | & | +| dereference.rs:77:17:77:18 | e3 | &T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:82:9:82:10 | g1 | | {EXTERNAL LOCATION} | Box | +| dereference.rs:82:9:82:10 | g1 | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:82:9:82:10 | g1 | T | {EXTERNAL LOCATION} | char | +| dereference.rs:82:25:82:37 | ...::new(...) | | {EXTERNAL LOCATION} | Box | +| dereference.rs:82:25:82:37 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:82:25:82:37 | ...::new(...) | T | {EXTERNAL LOCATION} | char | +| dereference.rs:82:34:82:36 | 'a' | | {EXTERNAL LOCATION} | char | +| dereference.rs:83:9:83:11 | _h1 | | file://:0:0:0:0 | & | +| dereference.rs:83:9:83:11 | _h1 | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:83:15:83:16 | g1 | | {EXTERNAL LOCATION} | Box | +| dereference.rs:83:15:83:16 | g1 | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:83:15:83:16 | g1 | T | {EXTERNAL LOCATION} | char | +| dereference.rs:83:15:83:24 | g1.deref() | | file://:0:0:0:0 | & | +| dereference.rs:83:15:83:24 | g1.deref() | &T | {EXTERNAL LOCATION} | char | +| dereference.rs:86:9:86:10 | g2 | | {EXTERNAL LOCATION} | Box | +| dereference.rs:86:9:86:10 | g2 | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:86:9:86:10 | g2 | T | {EXTERNAL LOCATION} | char | +| dereference.rs:86:25:86:37 | ...::new(...) | | {EXTERNAL LOCATION} | Box | +| dereference.rs:86:25:86:37 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:86:25:86:37 | ...::new(...) | T | {EXTERNAL LOCATION} | char | +| dereference.rs:86:34:86:36 | 'a' | | {EXTERNAL LOCATION} | char | +| dereference.rs:87:9:87:11 | _h2 | | {EXTERNAL LOCATION} | char | +| dereference.rs:87:15:87:17 | * ... | | {EXTERNAL LOCATION} | char | +| dereference.rs:87:16:87:17 | g2 | | {EXTERNAL LOCATION} | Box | +| dereference.rs:87:16:87:17 | g2 | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:87:16:87:17 | g2 | T | {EXTERNAL LOCATION} | char | +| dereference.rs:90:9:90:10 | g3 | | {EXTERNAL LOCATION} | Box | +| dereference.rs:90:9:90:10 | g3 | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:90:9:90:10 | g3 | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:90:24:90:38 | ...::new(...) | | {EXTERNAL LOCATION} | Box | +| dereference.rs:90:24:90:38 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:90:24:90:38 | ...::new(...) | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:90:33:90:37 | 34i64 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:91:9:91:11 | _h3 | | {EXTERNAL LOCATION} | bool | +| dereference.rs:91:15:91:19 | (...) | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:91:15:91:33 | ... .is_positive() | | {EXTERNAL LOCATION} | bool | +| dereference.rs:91:16:91:18 | * ... | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:91:17:91:18 | g3 | | {EXTERNAL LOCATION} | Box | +| dereference.rs:91:17:91:18 | g3 | A | {EXTERNAL LOCATION} | Global | +| dereference.rs:91:17:91:18 | g3 | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:96:9:96:9 | x | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:96:13:96:41 | MyIntPointer {...} | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:96:35:96:39 | 34i64 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:97:14:97:14 | x | | dereference.rs:4:1:6:1 | MyIntPointer | +| dereference.rs:100:9:100:9 | x | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:100:9:100:9 | x | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:100:13:100:43 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:100:13:100:43 | MySmartPointer {...} | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:100:37:100:41 | 34i64 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:101:14:101:14 | x | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:101:14:101:14 | x | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:103:9:103:9 | z | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:103:9:103:9 | z | T | dereference.rs:30:1:30:15 | S | +| dereference.rs:103:9:103:9 | z | T.T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:103:13:103:45 | MySmartPointer {...} | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:103:13:103:45 | MySmartPointer {...} | T | dereference.rs:30:1:30:15 | S | +| dereference.rs:103:13:103:45 | MySmartPointer {...} | T.T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:103:37:103:43 | S(...) | | dereference.rs:30:1:30:15 | S | +| dereference.rs:103:37:103:43 | S(...) | T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:103:39:103:42 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:104:14:104:14 | z | | dereference.rs:17:1:19:1 | MySmartPointer | +| dereference.rs:104:14:104:14 | z | T | dereference.rs:30:1:30:15 | S | +| dereference.rs:104:14:104:14 | z | T.T | {EXTERNAL LOCATION} | i64 | +| dereference.rs:132:17:132:26 | key_to_key | | {EXTERNAL LOCATION} | HashMap | +| dereference.rs:132:17:132:26 | key_to_key | K | file://:0:0:0:0 | & | +| dereference.rs:132:17:132:26 | key_to_key | K.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:132:17:132:26 | key_to_key | S | {EXTERNAL LOCATION} | RandomState | +| dereference.rs:132:17:132:26 | key_to_key | V | file://:0:0:0:0 | & | +| dereference.rs:132:17:132:26 | key_to_key | V.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:132:30:132:57 | ...::new(...) | | {EXTERNAL LOCATION} | HashMap | +| dereference.rs:132:30:132:57 | ...::new(...) | K | file://:0:0:0:0 | & | +| dereference.rs:132:30:132:57 | ...::new(...) | K.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:132:30:132:57 | ...::new(...) | S | {EXTERNAL LOCATION} | RandomState | +| dereference.rs:132:30:132:57 | ...::new(...) | V | file://:0:0:0:0 | & | +| dereference.rs:132:30:132:57 | ...::new(...) | V.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:133:17:133:19 | key | | file://:0:0:0:0 | & | +| dereference.rs:133:17:133:19 | key | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:133:17:133:19 | key | &T | file://:0:0:0:0 | & | +| dereference.rs:133:17:133:19 | key | &T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:133:23:133:29 | &... | | file://:0:0:0:0 | & | +| dereference.rs:133:23:133:29 | &... | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:133:23:133:29 | &... | &T | file://:0:0:0:0 | & | +| dereference.rs:133:23:133:29 | &... | &T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:133:24:133:29 | Key {...} | | dereference.rs:110:5:111:21 | Key | +| dereference.rs:133:24:133:29 | Key {...} | | file://:0:0:0:0 | & | +| dereference.rs:133:24:133:29 | Key {...} | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:16:134:28 | Some(...) | | {EXTERNAL LOCATION} | Option | +| dereference.rs:134:16:134:28 | Some(...) | T | file://:0:0:0:0 | & | +| dereference.rs:134:16:134:28 | Some(...) | T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:16:134:28 | Some(...) | T.&T | file://:0:0:0:0 | & | +| dereference.rs:134:16:134:28 | Some(...) | T.&T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:21:134:27 | ref_key | | file://:0:0:0:0 | & | +| dereference.rs:134:21:134:27 | ref_key | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:21:134:27 | ref_key | &T | file://:0:0:0:0 | & | +| dereference.rs:134:21:134:27 | ref_key | &T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:32:134:41 | key_to_key | | {EXTERNAL LOCATION} | HashMap | +| dereference.rs:134:32:134:41 | key_to_key | K | file://:0:0:0:0 | & | +| dereference.rs:134:32:134:41 | key_to_key | K.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:32:134:41 | key_to_key | S | {EXTERNAL LOCATION} | RandomState | +| dereference.rs:134:32:134:41 | key_to_key | V | file://:0:0:0:0 | & | +| dereference.rs:134:32:134:41 | key_to_key | V.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:32:134:50 | key_to_key.get(...) | | {EXTERNAL LOCATION} | Option | +| dereference.rs:134:32:134:50 | key_to_key.get(...) | T | file://:0:0:0:0 | & | +| dereference.rs:134:32:134:50 | key_to_key.get(...) | T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:32:134:50 | key_to_key.get(...) | T.&T | file://:0:0:0:0 | & | +| dereference.rs:134:32:134:50 | key_to_key.get(...) | T.&T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:47:134:49 | key | | file://:0:0:0:0 | & | +| dereference.rs:134:47:134:49 | key | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:134:47:134:49 | key | &T | file://:0:0:0:0 | & | +| dereference.rs:134:47:134:49 | key | &T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:136:13:136:15 | key | | file://:0:0:0:0 | & | +| dereference.rs:136:13:136:15 | key | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:136:13:136:15 | key | &T | file://:0:0:0:0 | & | +| dereference.rs:136:13:136:15 | key | &T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:136:13:136:25 | ... = ... | | file://:0:0:0:0 | () | +| dereference.rs:136:19:136:25 | ref_key | | file://:0:0:0:0 | & | +| dereference.rs:136:19:136:25 | ref_key | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:136:19:136:25 | ref_key | &T | file://:0:0:0:0 | & | +| dereference.rs:136:19:136:25 | ref_key | &T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:138:9:138:18 | key_to_key | | {EXTERNAL LOCATION} | HashMap | +| dereference.rs:138:9:138:18 | key_to_key | K | file://:0:0:0:0 | & | +| dereference.rs:138:9:138:18 | key_to_key | K.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:138:9:138:18 | key_to_key | S | {EXTERNAL LOCATION} | RandomState | +| dereference.rs:138:9:138:18 | key_to_key | V | file://:0:0:0:0 | & | +| dereference.rs:138:9:138:18 | key_to_key | V.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:138:9:138:35 | key_to_key.insert(...) | | {EXTERNAL LOCATION} | Option | +| dereference.rs:138:9:138:35 | key_to_key.insert(...) | T | file://:0:0:0:0 | & | +| dereference.rs:138:9:138:35 | key_to_key.insert(...) | T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:138:9:138:35 | key_to_key.insert(...) | T.&T | file://:0:0:0:0 | & | +| dereference.rs:138:9:138:35 | key_to_key.insert(...) | T.&T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:138:27:138:29 | key | | file://:0:0:0:0 | & | +| dereference.rs:138:27:138:29 | key | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:138:27:138:29 | key | &T | file://:0:0:0:0 | & | +| dereference.rs:138:27:138:29 | key | &T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:138:32:138:34 | key | | file://:0:0:0:0 | & | +| dereference.rs:138:32:138:34 | key | &T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:138:32:138:34 | key | &T | file://:0:0:0:0 | & | +| dereference.rs:138:32:138:34 | key | &T.&T | dereference.rs:110:5:111:21 | Key | +| dereference.rs:144:16:144:19 | SelfParam | | dereference.rs:143:5:145:5 | Self [trait MyTrait1] | +| dereference.rs:151:16:151:19 | SelfParam | | file://:0:0:0:0 | & | +| dereference.rs:151:16:151:19 | SelfParam | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:151:27:153:9 | { ... } | | dereference.rs:147:5:147:13 | S | +| dereference.rs:152:13:152:13 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:158:16:158:19 | SelfParam | | file://:0:0:0:0 | & | +| dereference.rs:158:16:158:19 | SelfParam | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:158:29:160:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:159:13:159:14 | 42 | | {EXTERNAL LOCATION} | i32 | +| dereference.rs:159:13:159:14 | 42 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:164:16:164:19 | SelfParam | | dereference.rs:163:5:165:5 | Self [trait MyTrait2] | +| dereference.rs:164:22:164:24 | arg | | dereference.rs:163:20:163:21 | T1 | +| dereference.rs:169:16:169:19 | SelfParam | | dereference.rs:147:5:147:13 | S | +| dereference.rs:169:22:169:24 | arg | | file://:0:0:0:0 | & | +| dereference.rs:169:22:169:24 | arg | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:169:36:171:9 | { ... } | | dereference.rs:147:5:147:13 | S | +| dereference.rs:170:13:170:13 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:176:16:176:19 | SelfParam | | dereference.rs:147:5:147:13 | S | +| dereference.rs:176:22:176:24 | arg | | file://:0:0:0:0 | & | +| dereference.rs:176:22:176:24 | arg | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:176:42:178:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:177:13:177:14 | 42 | | {EXTERNAL LOCATION} | i32 | +| dereference.rs:177:13:177:14 | 42 | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:182:13:182:13 | x | | dereference.rs:147:5:147:13 | S | +| dereference.rs:182:13:182:13 | x | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:182:17:182:20 | (...) | | file://:0:0:0:0 | & | +| dereference.rs:182:17:182:20 | (...) | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:182:17:182:26 | ... .foo() | | dereference.rs:147:5:147:13 | S | +| dereference.rs:182:17:182:26 | ... .foo() | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:182:18:182:19 | &S | | file://:0:0:0:0 | & | +| dereference.rs:182:18:182:19 | &S | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:182:19:182:19 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:183:13:183:13 | y | | dereference.rs:147:5:147:13 | S | +| dereference.rs:183:13:183:13 | y | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:183:17:183:17 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:183:17:183:23 | S.foo() | | dereference.rs:147:5:147:13 | S | +| dereference.rs:183:17:183:23 | S.foo() | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:184:13:184:13 | z | | dereference.rs:147:5:147:13 | S | +| dereference.rs:184:13:184:13 | z | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:184:17:184:24 | (...) | | file://:0:0:0:0 | & | +| dereference.rs:184:17:184:24 | (...) | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:184:17:184:30 | ... .foo() | | dereference.rs:147:5:147:13 | S | +| dereference.rs:184:17:184:30 | ... .foo() | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:184:18:184:23 | &mut S | | file://:0:0:0:0 | & | +| dereference.rs:184:18:184:23 | &mut S | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:184:23:184:23 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:186:13:186:13 | x | | dereference.rs:147:5:147:13 | S | +| dereference.rs:186:13:186:13 | x | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:186:17:186:17 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:186:17:186:25 | S.bar(...) | | dereference.rs:147:5:147:13 | S | +| dereference.rs:186:17:186:25 | S.bar(...) | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:186:23:186:24 | &S | | file://:0:0:0:0 | & | +| dereference.rs:186:23:186:24 | &S | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:186:24:186:24 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:187:13:187:13 | y | | dereference.rs:147:5:147:13 | S | +| dereference.rs:187:13:187:13 | y | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:187:17:187:17 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:187:17:187:29 | S.bar(...) | | dereference.rs:147:5:147:13 | S | +| dereference.rs:187:17:187:29 | S.bar(...) | | {EXTERNAL LOCATION} | i64 | +| dereference.rs:187:23:187:28 | &mut S | | file://:0:0:0:0 | & | +| dereference.rs:187:23:187:28 | &mut S | &T | dereference.rs:147:5:147:13 | S | +| dereference.rs:187:28:187:28 | S | | dereference.rs:147:5:147:13 | S | +| dereference.rs:196:16:196:20 | SelfParam | | file://:0:0:0:0 | & | +| dereference.rs:196:16:196:20 | SelfParam | &T | dereference.rs:195:5:197:5 | Self [trait Bar] | +| dereference.rs:201:16:201:24 | SelfParam | | file://:0:0:0:0 | & | +| dereference.rs:201:16:201:24 | SelfParam | &T | dereference.rs:193:5:193:17 | Foo | +| dereference.rs:202:22:202:38 | "In struct impl!\\n" | | file://:0:0:0:0 | & | +| dereference.rs:202:22:202:38 | "In struct impl!\\n" | &T | {EXTERNAL LOCATION} | str | +| dereference.rs:202:22:202:38 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments | +| dereference.rs:202:22:202:38 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | +| dereference.rs:208:16:208:20 | SelfParam | | file://:0:0:0:0 | & | +| dereference.rs:208:16:208:20 | SelfParam | &T | dereference.rs:193:5:193:17 | Foo | +| dereference.rs:209:22:209:37 | "In trait impl!\\n" | | file://:0:0:0:0 | & | +| dereference.rs:209:22:209:37 | "In trait impl!\\n" | &T | {EXTERNAL LOCATION} | str | +| dereference.rs:209:22:209:37 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments | +| dereference.rs:209:22:209:37 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | +| dereference.rs:214:17:214:17 | f | | dereference.rs:193:5:193:17 | Foo | +| dereference.rs:214:21:214:26 | Foo {...} | | dereference.rs:193:5:193:17 | Foo | +| dereference.rs:215:9:215:9 | f | | dereference.rs:193:5:193:17 | Foo | | dyn_type.rs:7:10:7:14 | SelfParam | | file://:0:0:0:0 | & | | dyn_type.rs:7:10:7:14 | SelfParam | &T | dyn_type.rs:5:1:8:1 | Self [trait MyTrait1] | | dyn_type.rs:12:12:12:16 | SelfParam | | file://:0:0:0:0 | & | @@ -629,12 +730,15 @@ inferType | dyn_type.rs:103:28:105:5 | &... | | file://:0:0:0:0 | & | | dyn_type.rs:103:28:105:5 | &... | &T | dyn_type.rs:10:1:13:1 | dyn GenericGet | | dyn_type.rs:103:28:105:5 | &... | &T | dyn_type.rs:33:1:36:1 | GenStruct | +| dyn_type.rs:103:28:105:5 | &... | &T.A | {EXTERNAL LOCATION} | String | | dyn_type.rs:103:28:105:5 | &... | &T.dyn(A) | {EXTERNAL LOCATION} | String | | dyn_type.rs:103:29:105:5 | GenStruct {...} | | dyn_type.rs:10:1:13:1 | dyn GenericGet | | dyn_type.rs:103:29:105:5 | GenStruct {...} | | dyn_type.rs:33:1:36:1 | GenStruct | +| dyn_type.rs:103:29:105:5 | GenStruct {...} | A | {EXTERNAL LOCATION} | String | | dyn_type.rs:103:29:105:5 | GenStruct {...} | dyn(A) | {EXTERNAL LOCATION} | String | | dyn_type.rs:104:16:104:17 | "" | | file://:0:0:0:0 | & | | dyn_type.rs:104:16:104:17 | "" | &T | {EXTERNAL LOCATION} | str | +| dyn_type.rs:104:16:104:29 | "".to_string() | | {EXTERNAL LOCATION} | String | | dyn_type.rs:107:21:107:45 | &... | | file://:0:0:0:0 | & | | dyn_type.rs:107:21:107:45 | &... | &T | dyn_type.rs:15:1:19:1 | dyn AssocTrait | | dyn_type.rs:107:21:107:45 | &... | &T | dyn_type.rs:33:1:36:1 | GenStruct | @@ -1869,23 +1973,29 @@ inferType | main.rs:907:26:907:26 | y | A | main.rs:890:5:891:14 | S2 | | main.rs:907:26:907:31 | y.m1() | | main.rs:890:5:891:14 | S2 | | main.rs:929:15:929:18 | SelfParam | | main.rs:927:5:930:5 | Self [trait MyTrait1] | -| main.rs:934:15:934:18 | SelfParam | | main.rs:932:5:944:5 | Self [trait MyTrait2] | +| main.rs:934:15:934:19 | SelfParam | | file://:0:0:0:0 | & | +| main.rs:934:15:934:19 | SelfParam | &T | main.rs:932:5:944:5 | Self [trait MyTrait2] | | main.rs:937:9:943:9 | { ... } | | main.rs:932:20:932:22 | Tr2 | | main.rs:938:13:942:13 | if ... {...} else {...} | | main.rs:932:20:932:22 | Tr2 | | main.rs:938:16:938:16 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:938:16:938:20 | ... > ... | | {EXTERNAL LOCATION} | bool | +| main.rs:938:20:938:20 | 2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:938:20:938:20 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:938:22:940:13 | { ... } | | main.rs:932:20:932:22 | Tr2 | -| main.rs:939:17:939:20 | self | | main.rs:932:5:944:5 | Self [trait MyTrait2] | +| main.rs:939:17:939:20 | self | | file://:0:0:0:0 | & | +| main.rs:939:17:939:20 | self | &T | main.rs:932:5:944:5 | Self [trait MyTrait2] | | main.rs:939:17:939:25 | self.m1() | | main.rs:932:20:932:22 | Tr2 | | main.rs:940:20:942:13 | { ... } | | main.rs:932:20:932:22 | Tr2 | -| main.rs:941:17:941:30 | ...::m1(...) | | main.rs:932:20:932:22 | Tr2 | -| main.rs:941:26:941:29 | self | | main.rs:932:5:944:5 | Self [trait MyTrait2] | +| main.rs:941:17:941:31 | ...::m1(...) | | main.rs:932:20:932:22 | Tr2 | +| main.rs:941:26:941:30 | * ... | | main.rs:932:5:944:5 | Self [trait MyTrait2] | +| main.rs:941:27:941:30 | self | | file://:0:0:0:0 | & | +| main.rs:941:27:941:30 | self | &T | main.rs:932:5:944:5 | Self [trait MyTrait2] | | main.rs:948:15:948:18 | SelfParam | | main.rs:946:5:958:5 | Self [trait MyTrait3] | | main.rs:951:9:957:9 | { ... } | | main.rs:946:20:946:22 | Tr3 | | main.rs:952:13:956:13 | if ... {...} else {...} | | main.rs:946:20:946:22 | Tr3 | | main.rs:952:16:952:16 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:952:16:952:20 | ... > ... | | {EXTERNAL LOCATION} | bool | +| main.rs:952:20:952:20 | 2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:952:20:952:20 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:952:22:954:13 | { ... } | | main.rs:946:20:946:22 | Tr3 | | main.rs:953:17:953:20 | self | | main.rs:946:5:958:5 | Self [trait MyTrait3] | @@ -1893,10 +2003,12 @@ inferType | main.rs:953:17:953:25 | self.m2() | A | main.rs:946:20:946:22 | Tr3 | | main.rs:953:17:953:27 | ... .a | | main.rs:946:20:946:22 | Tr3 | | main.rs:954:20:956:13 | { ... } | | main.rs:946:20:946:22 | Tr3 | -| main.rs:955:17:955:30 | ...::m2(...) | | main.rs:912:5:915:5 | MyThing | -| main.rs:955:17:955:30 | ...::m2(...) | A | main.rs:946:20:946:22 | Tr3 | -| main.rs:955:17:955:32 | ... .a | | main.rs:946:20:946:22 | Tr3 | -| main.rs:955:26:955:29 | self | | main.rs:946:5:958:5 | Self [trait MyTrait3] | +| main.rs:955:17:955:31 | ...::m2(...) | | main.rs:912:5:915:5 | MyThing | +| main.rs:955:17:955:31 | ...::m2(...) | A | main.rs:946:20:946:22 | Tr3 | +| main.rs:955:17:955:33 | ... .a | | main.rs:946:20:946:22 | Tr3 | +| main.rs:955:26:955:30 | &self | | file://:0:0:0:0 | & | +| main.rs:955:26:955:30 | &self | &T | main.rs:946:5:958:5 | Self [trait MyTrait3] | +| main.rs:955:27:955:30 | self | | main.rs:946:5:958:5 | Self [trait MyTrait3] | | main.rs:962:15:962:18 | SelfParam | | main.rs:912:5:915:5 | MyThing | | main.rs:962:15:962:18 | SelfParam | A | main.rs:960:10:960:10 | T | | main.rs:962:26:964:9 | { ... } | | main.rs:960:10:960:10 | T | @@ -2280,18 +2392,14 @@ inferType | main.rs:1203:26:1203:27 | x1 | | main.rs:1163:5:1167:5 | MyOption | | main.rs:1203:26:1203:27 | x1 | T | main.rs:1198:5:1199:13 | S | | main.rs:1205:17:1205:18 | x2 | | main.rs:1163:5:1167:5 | MyOption | -| main.rs:1205:17:1205:18 | x2 | T | main.rs:1198:5:1199:13 | S | | main.rs:1205:22:1205:36 | ...::new(...) | | main.rs:1163:5:1167:5 | MyOption | -| main.rs:1205:22:1205:36 | ...::new(...) | T | main.rs:1198:5:1199:13 | S | | main.rs:1206:9:1206:10 | x2 | | main.rs:1163:5:1167:5 | MyOption | -| main.rs:1206:9:1206:10 | x2 | T | main.rs:1198:5:1199:13 | S | | main.rs:1206:16:1206:16 | S | | main.rs:1198:5:1199:13 | S | | main.rs:1207:18:1207:23 | "{:?}\\n" | | file://:0:0:0:0 | & | | main.rs:1207:18:1207:23 | "{:?}\\n" | &T | {EXTERNAL LOCATION} | str | | main.rs:1207:18:1207:27 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments | | main.rs:1207:18:1207:27 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | | main.rs:1207:26:1207:27 | x2 | | main.rs:1163:5:1167:5 | MyOption | -| main.rs:1207:26:1207:27 | x2 | T | main.rs:1198:5:1199:13 | S | | main.rs:1210:17:1210:18 | x3 | | main.rs:1163:5:1167:5 | MyOption | | main.rs:1210:22:1210:36 | ...::new(...) | | main.rs:1163:5:1167:5 | MyOption | | main.rs:1211:9:1211:10 | x3 | | main.rs:1163:5:1167:5 | MyOption | @@ -2357,6 +2465,7 @@ inferType | main.rs:1225:23:1229:9 | if ... {...} else {...} | T | main.rs:1198:5:1199:13 | S | | main.rs:1225:26:1225:26 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:1225:26:1225:30 | ... > ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1225:30:1225:30 | 2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1225:30:1225:30 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:1225:32:1227:9 | { ... } | | main.rs:1163:5:1167:5 | MyOption | | main.rs:1225:32:1227:9 | { ... } | T | main.rs:1198:5:1199:13 | S | @@ -2379,6 +2488,7 @@ inferType | main.rs:1233:26:1236:9 | match ... { ... } | T | main.rs:1198:5:1199:13 | S | | main.rs:1233:32:1233:32 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:1233:32:1233:36 | ... > ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1233:36:1233:36 | 2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1233:36:1233:36 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:1234:13:1234:16 | true | | {EXTERNAL LOCATION} | bool | | main.rs:1234:21:1234:38 | ...::MyNone(...) | | main.rs:1163:5:1167:5 | MyOption | @@ -2399,6 +2509,7 @@ inferType | main.rs:1240:25:1245:9 | loop { ... } | T | main.rs:1198:5:1199:13 | S | | main.rs:1241:16:1241:16 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:1241:16:1241:20 | ... > ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1241:20:1241:20 | 2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1241:20:1241:20 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:1242:23:1242:40 | ...::MyNone(...) | | main.rs:1163:5:1167:5 | MyOption | | main.rs:1242:23:1242:40 | ...::MyNone(...) | T | main.rs:1198:5:1199:13 | S | @@ -2444,21 +2555,13 @@ inferType | main.rs:1279:33:1279:36 | SelfParam | | main.rs:1277:5:1280:5 | Self [trait ATrait] | | main.rs:1285:29:1285:33 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1285:29:1285:33 | SelfParam | &T | file://:0:0:0:0 | & | -| main.rs:1285:29:1285:33 | SelfParam | &T | main.rs:1258:5:1261:5 | MyInt | | main.rs:1285:29:1285:33 | SelfParam | &T.&T | main.rs:1258:5:1261:5 | MyInt | | main.rs:1285:43:1287:9 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1286:13:1286:22 | (...) | | main.rs:1258:5:1261:5 | MyInt | | main.rs:1286:13:1286:24 | ... .a | | {EXTERNAL LOCATION} | i64 | -| main.rs:1286:14:1286:21 | * ... | | main.rs:1258:5:1261:5 | MyInt | -| main.rs:1286:15:1286:21 | (...) | | file://:0:0:0:0 | & | | main.rs:1286:15:1286:21 | (...) | | main.rs:1258:5:1261:5 | MyInt | -| main.rs:1286:15:1286:21 | (...) | &T | main.rs:1258:5:1261:5 | MyInt | -| main.rs:1286:16:1286:20 | * ... | | file://:0:0:0:0 | & | | main.rs:1286:16:1286:20 | * ... | | main.rs:1258:5:1261:5 | MyInt | -| main.rs:1286:16:1286:20 | * ... | &T | main.rs:1258:5:1261:5 | MyInt | | main.rs:1286:17:1286:20 | self | | file://:0:0:0:0 | & | | main.rs:1286:17:1286:20 | self | &T | file://:0:0:0:0 | & | -| main.rs:1286:17:1286:20 | self | &T | main.rs:1258:5:1261:5 | MyInt | | main.rs:1286:17:1286:20 | self | &T.&T | main.rs:1258:5:1261:5 | MyInt | | main.rs:1290:33:1290:36 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1290:33:1290:36 | SelfParam | &T | main.rs:1258:5:1261:5 | MyInt | @@ -2640,12 +2743,15 @@ inferType | main.rs:1336:25:1336:39 | MyInt {...} | | main.rs:1258:5:1261:5 | MyInt | | main.rs:1336:36:1336:37 | 37 | | {EXTERNAL LOCATION} | i32 | | main.rs:1336:36:1336:37 | 37 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1338:13:1338:13 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:1338:17:1338:24 | my_thing | | file://:0:0:0:0 | & | | main.rs:1338:17:1338:24 | my_thing | &T | main.rs:1258:5:1261:5 | MyInt | +| main.rs:1338:17:1338:43 | my_thing.method_on_borrow() | | {EXTERNAL LOCATION} | i64 | | main.rs:1339:18:1339:23 | "{:?}\\n" | | file://:0:0:0:0 | & | | main.rs:1339:18:1339:23 | "{:?}\\n" | &T | {EXTERNAL LOCATION} | str | | main.rs:1339:18:1339:26 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments | | main.rs:1339:18:1339:26 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | +| main.rs:1339:26:1339:26 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:1342:13:1342:20 | my_thing | | file://:0:0:0:0 | & | | main.rs:1342:13:1342:20 | my_thing | &T | main.rs:1258:5:1261:5 | MyInt | | main.rs:1342:24:1342:39 | &... | | file://:0:0:0:0 | & | @@ -2653,12 +2759,15 @@ inferType | main.rs:1342:25:1342:39 | MyInt {...} | | main.rs:1258:5:1261:5 | MyInt | | main.rs:1342:36:1342:37 | 38 | | {EXTERNAL LOCATION} | i32 | | main.rs:1342:36:1342:37 | 38 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1343:13:1343:13 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:1343:17:1343:24 | my_thing | | file://:0:0:0:0 | & | | main.rs:1343:17:1343:24 | my_thing | &T | main.rs:1258:5:1261:5 | MyInt | +| main.rs:1343:17:1343:47 | my_thing.method_not_on_borrow() | | {EXTERNAL LOCATION} | i64 | | main.rs:1344:18:1344:23 | "{:?}\\n" | | file://:0:0:0:0 | & | | main.rs:1344:18:1344:23 | "{:?}\\n" | &T | {EXTERNAL LOCATION} | str | | main.rs:1344:18:1344:26 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments | | main.rs:1344:18:1344:26 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | +| main.rs:1344:26:1344:26 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:1351:16:1351:20 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1351:16:1351:20 | SelfParam | &T | main.rs:1349:5:1357:5 | Self [trait MyTrait] | | main.rs:1354:16:1354:20 | SelfParam | | file://:0:0:0:0 | & | @@ -2785,28 +2894,18 @@ inferType | main.rs:1427:15:1427:16 | &x | | file://:0:0:0:0 | & | | main.rs:1427:15:1427:16 | &x | &T | main.rs:1403:5:1403:13 | S | | main.rs:1427:16:1427:16 | x | | main.rs:1403:5:1403:13 | S | -| main.rs:1429:13:1429:13 | n | | {EXTERNAL LOCATION} | bool | -| main.rs:1429:17:1429:24 | * ... | | {EXTERNAL LOCATION} | bool | | main.rs:1429:18:1429:24 | * ... | | {EXTERNAL LOCATION} | bool | -| main.rs:1429:18:1429:24 | * ... | | file://:0:0:0:0 | & | -| main.rs:1429:18:1429:24 | * ... | &T | {EXTERNAL LOCATION} | bool | | main.rs:1429:19:1429:24 | &... | | file://:0:0:0:0 | & | -| main.rs:1429:19:1429:24 | &... | &T | {EXTERNAL LOCATION} | bool | | main.rs:1429:19:1429:24 | &... | &T | file://:0:0:0:0 | & | | main.rs:1429:19:1429:24 | &... | &T.&T | {EXTERNAL LOCATION} | bool | | main.rs:1429:20:1429:24 | &true | | file://:0:0:0:0 | & | | main.rs:1429:20:1429:24 | &true | &T | {EXTERNAL LOCATION} | bool | | main.rs:1429:21:1429:24 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:1433:17:1433:20 | flag | | main.rs:1392:5:1395:5 | MyFlag | -| main.rs:1433:24:1433:41 | ...::default(...) | | main.rs:1392:5:1395:5 | MyFlag | | main.rs:1434:22:1434:30 | &mut flag | | file://:0:0:0:0 | & | -| main.rs:1434:22:1434:30 | &mut flag | &T | main.rs:1392:5:1395:5 | MyFlag | -| main.rs:1434:27:1434:30 | flag | | main.rs:1392:5:1395:5 | MyFlag | | main.rs:1435:18:1435:23 | "{:?}\\n" | | file://:0:0:0:0 | & | | main.rs:1435:18:1435:23 | "{:?}\\n" | &T | {EXTERNAL LOCATION} | str | | main.rs:1435:18:1435:29 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments | | main.rs:1435:18:1435:29 | MacroExpr | | {EXTERNAL LOCATION} | Arguments | -| main.rs:1435:26:1435:29 | flag | | main.rs:1392:5:1395:5 | MyFlag | | main.rs:1450:43:1453:5 | { ... } | | {EXTERNAL LOCATION} | Result | | main.rs:1450:43:1453:5 | { ... } | E | main.rs:1442:5:1443:14 | S1 | | main.rs:1450:43:1453:5 | { ... } | T | main.rs:1442:5:1443:14 | S1 | @@ -3328,6 +3427,9 @@ inferType | main.rs:1748:13:1748:50 | ... \|\| ... | | {EXTERNAL LOCATION} | bool | | main.rs:1748:23:1748:27 | other | | file://:0:0:0:0 | & | | main.rs:1748:23:1748:27 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1748:23:1748:29 | other.x | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1748:23:1748:29 | other.x | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | +| main.rs:1748:23:1748:29 | other.x | | {EXTERNAL LOCATION} | Self [trait BytewiseEq] | | main.rs:1748:23:1748:29 | other.x | | {EXTERNAL LOCATION} | i64 | | main.rs:1748:34:1748:37 | self | | file://:0:0:0:0 | & | | main.rs:1748:34:1748:37 | self | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3335,6 +3437,9 @@ inferType | main.rs:1748:34:1748:50 | ... != ... | | {EXTERNAL LOCATION} | bool | | main.rs:1748:44:1748:48 | other | | file://:0:0:0:0 | & | | main.rs:1748:44:1748:48 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1748:44:1748:50 | other.y | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1748:44:1748:50 | other.y | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | +| main.rs:1748:44:1748:50 | other.y | | {EXTERNAL LOCATION} | Self [trait BytewiseEq] | | main.rs:1748:44:1748:50 | other.y | | {EXTERNAL LOCATION} | i64 | | main.rs:1753:24:1753:28 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1753:24:1753:28 | SelfParam | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3374,6 +3479,7 @@ inferType | main.rs:1758:13:1758:48 | ... && ... | | {EXTERNAL LOCATION} | bool | | main.rs:1758:22:1758:26 | other | | file://:0:0:0:0 | & | | main.rs:1758:22:1758:26 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1758:22:1758:28 | other.x | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1758:22:1758:28 | other.x | | {EXTERNAL LOCATION} | i64 | | main.rs:1758:33:1758:36 | self | | file://:0:0:0:0 | & | | main.rs:1758:33:1758:36 | self | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3381,6 +3487,7 @@ inferType | main.rs:1758:33:1758:48 | ... < ... | | {EXTERNAL LOCATION} | bool | | main.rs:1758:42:1758:46 | other | | file://:0:0:0:0 | & | | main.rs:1758:42:1758:46 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1758:42:1758:48 | other.y | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1758:42:1758:48 | other.y | | {EXTERNAL LOCATION} | i64 | | main.rs:1761:15:1761:19 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1761:15:1761:19 | SelfParam | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3394,6 +3501,7 @@ inferType | main.rs:1762:13:1762:50 | ... && ... | | {EXTERNAL LOCATION} | bool | | main.rs:1762:23:1762:27 | other | | file://:0:0:0:0 | & | | main.rs:1762:23:1762:27 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1762:23:1762:29 | other.x | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1762:23:1762:29 | other.x | | {EXTERNAL LOCATION} | i64 | | main.rs:1762:34:1762:37 | self | | file://:0:0:0:0 | & | | main.rs:1762:34:1762:37 | self | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3401,6 +3509,7 @@ inferType | main.rs:1762:34:1762:50 | ... <= ... | | {EXTERNAL LOCATION} | bool | | main.rs:1762:44:1762:48 | other | | file://:0:0:0:0 | & | | main.rs:1762:44:1762:48 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1762:44:1762:50 | other.y | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1762:44:1762:50 | other.y | | {EXTERNAL LOCATION} | i64 | | main.rs:1765:15:1765:19 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1765:15:1765:19 | SelfParam | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3414,6 +3523,7 @@ inferType | main.rs:1766:13:1766:48 | ... && ... | | {EXTERNAL LOCATION} | bool | | main.rs:1766:22:1766:26 | other | | file://:0:0:0:0 | & | | main.rs:1766:22:1766:26 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1766:22:1766:28 | other.x | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1766:22:1766:28 | other.x | | {EXTERNAL LOCATION} | i64 | | main.rs:1766:33:1766:36 | self | | file://:0:0:0:0 | & | | main.rs:1766:33:1766:36 | self | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3421,6 +3531,7 @@ inferType | main.rs:1766:33:1766:48 | ... > ... | | {EXTERNAL LOCATION} | bool | | main.rs:1766:42:1766:46 | other | | file://:0:0:0:0 | & | | main.rs:1766:42:1766:46 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1766:42:1766:48 | other.y | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1766:42:1766:48 | other.y | | {EXTERNAL LOCATION} | i64 | | main.rs:1769:15:1769:19 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1769:15:1769:19 | SelfParam | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3434,6 +3545,7 @@ inferType | main.rs:1770:13:1770:50 | ... && ... | | {EXTERNAL LOCATION} | bool | | main.rs:1770:23:1770:27 | other | | file://:0:0:0:0 | & | | main.rs:1770:23:1770:27 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1770:23:1770:29 | other.x | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1770:23:1770:29 | other.x | | {EXTERNAL LOCATION} | i64 | | main.rs:1770:34:1770:37 | self | | file://:0:0:0:0 | & | | main.rs:1770:34:1770:37 | self | &T | main.rs:1537:5:1542:5 | Vec2 | @@ -3441,6 +3553,7 @@ inferType | main.rs:1770:34:1770:50 | ... >= ... | | {EXTERNAL LOCATION} | bool | | main.rs:1770:44:1770:48 | other | | file://:0:0:0:0 | & | | main.rs:1770:44:1770:48 | other | &T | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1770:44:1770:50 | other.y | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1770:44:1770:50 | other.y | | {EXTERNAL LOCATION} | i64 | | main.rs:1777:13:1777:18 | i64_eq | | {EXTERNAL LOCATION} | bool | | main.rs:1777:22:1777:35 | (...) | | {EXTERNAL LOCATION} | bool | @@ -3574,7 +3687,11 @@ inferType | main.rs:1834:28:1834:28 | 1 | | {EXTERNAL LOCATION} | i64 | | main.rs:1834:34:1834:34 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:1834:34:1834:34 | 2 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1835:13:1835:14 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1835:13:1835:14 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1835:13:1835:14 | v2 | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1835:18:1835:36 | Vec2 {...} | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1835:18:1835:36 | Vec2 {...} | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1835:18:1835:36 | Vec2 {...} | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1835:28:1835:28 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:1835:28:1835:28 | 3 | | {EXTERNAL LOCATION} | i64 | @@ -3583,83 +3700,121 @@ inferType | main.rs:1838:13:1838:19 | vec2_eq | | {EXTERNAL LOCATION} | bool | | main.rs:1838:23:1838:24 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1838:23:1838:30 | ... == ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1838:29:1838:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1838:29:1838:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1838:29:1838:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1839:13:1839:19 | vec2_ne | | {EXTERNAL LOCATION} | bool | | main.rs:1839:23:1839:24 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1839:23:1839:30 | ... != ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1839:29:1839:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1839:29:1839:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1839:29:1839:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1840:13:1840:19 | vec2_lt | | {EXTERNAL LOCATION} | bool | | main.rs:1840:23:1840:24 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1840:23:1840:29 | ... < ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1840:28:1840:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1840:28:1840:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1840:28:1840:29 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1841:13:1841:19 | vec2_le | | {EXTERNAL LOCATION} | bool | | main.rs:1841:23:1841:24 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1841:23:1841:30 | ... <= ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1841:29:1841:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1841:29:1841:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1841:29:1841:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1842:13:1842:19 | vec2_gt | | {EXTERNAL LOCATION} | bool | | main.rs:1842:23:1842:24 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1842:23:1842:29 | ... > ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1842:28:1842:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1842:28:1842:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1842:28:1842:29 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1843:13:1843:19 | vec2_ge | | {EXTERNAL LOCATION} | bool | | main.rs:1843:23:1843:24 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1843:23:1843:30 | ... >= ... | | {EXTERNAL LOCATION} | bool | +| main.rs:1843:29:1843:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1843:29:1843:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1843:29:1843:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1846:13:1846:20 | vec2_add | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1846:24:1846:25 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1846:24:1846:30 | ... + ... | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1846:29:1846:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1846:29:1846:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1846:29:1846:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1847:13:1847:20 | vec2_sub | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1847:24:1847:25 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1847:24:1847:30 | ... - ... | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1847:29:1847:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1847:29:1847:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1847:29:1847:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1848:13:1848:20 | vec2_mul | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1848:24:1848:25 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1848:24:1848:30 | ... * ... | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1848:29:1848:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1848:29:1848:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1848:29:1848:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1849:13:1849:20 | vec2_div | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1849:24:1849:25 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1849:24:1849:30 | ... / ... | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1849:29:1849:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1849:29:1849:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1849:29:1849:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1850:13:1850:20 | vec2_rem | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1850:24:1850:25 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1850:24:1850:30 | ... % ... | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1850:29:1850:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1850:29:1850:30 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1850:29:1850:30 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1853:17:1853:31 | vec2_add_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1853:35:1853:36 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1854:9:1854:23 | vec2_add_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1854:9:1854:29 | ... += ... | | file://:0:0:0:0 | () | +| main.rs:1854:28:1854:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1854:28:1854:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1854:28:1854:29 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1856:17:1856:31 | vec2_sub_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1856:35:1856:36 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1857:9:1857:23 | vec2_sub_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1857:9:1857:29 | ... -= ... | | file://:0:0:0:0 | () | +| main.rs:1857:28:1857:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1857:28:1857:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1857:28:1857:29 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1859:17:1859:31 | vec2_mul_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1859:35:1859:36 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1860:9:1860:23 | vec2_mul_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1860:9:1860:29 | ... *= ... | | file://:0:0:0:0 | () | +| main.rs:1860:28:1860:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1860:28:1860:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1860:28:1860:29 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1862:17:1862:31 | vec2_div_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1862:35:1862:36 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1863:9:1863:23 | vec2_div_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1863:9:1863:29 | ... /= ... | | file://:0:0:0:0 | () | +| main.rs:1863:28:1863:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1863:28:1863:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1863:28:1863:29 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1865:17:1865:31 | vec2_rem_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1865:35:1865:36 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1866:9:1866:23 | vec2_rem_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1866:9:1866:29 | ... %= ... | | file://:0:0:0:0 | () | +| main.rs:1866:28:1866:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1866:28:1866:29 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1866:28:1866:29 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1869:13:1869:23 | vec2_bitand | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1869:27:1869:28 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1869:27:1869:33 | ... & ... | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1869:32:1869:33 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1869:32:1869:33 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1869:32:1869:33 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1870:13:1870:22 | vec2_bitor | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1870:26:1870:27 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1870:26:1870:32 | ... \| ... | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1870:31:1870:32 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1870:31:1870:32 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1870:31:1870:32 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1871:13:1871:23 | vec2_bitxor | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1871:27:1871:28 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1871:27:1871:33 | ... ^ ... | | main.rs:1537:5:1542:5 | Vec2 | +| main.rs:1871:32:1871:33 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1871:32:1871:33 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1871:32:1871:33 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1872:13:1872:20 | vec2_shl | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1872:24:1872:25 | v1 | | main.rs:1537:5:1542:5 | Vec2 | @@ -3673,16 +3828,22 @@ inferType | main.rs:1876:38:1876:39 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1877:9:1877:26 | vec2_bitand_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1877:9:1877:32 | ... &= ... | | file://:0:0:0:0 | () | +| main.rs:1877:31:1877:32 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1877:31:1877:32 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1877:31:1877:32 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1879:17:1879:33 | vec2_bitor_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1879:37:1879:38 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1880:9:1880:25 | vec2_bitor_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1880:9:1880:31 | ... \|= ... | | file://:0:0:0:0 | () | +| main.rs:1880:30:1880:31 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1880:30:1880:31 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1880:30:1880:31 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1882:17:1882:34 | vec2_bitxor_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1882:38:1882:39 | v1 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1883:9:1883:26 | vec2_bitxor_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1883:9:1883:32 | ... ^= ... | | file://:0:0:0:0 | () | +| main.rs:1883:31:1883:32 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialEq] | +| main.rs:1883:31:1883:32 | v2 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:1883:31:1883:32 | v2 | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1885:17:1885:31 | vec2_shl_assign | | main.rs:1537:5:1542:5 | Vec2 | | main.rs:1885:35:1885:36 | v1 | | main.rs:1537:5:1542:5 | Vec2 | @@ -3936,16 +4097,10 @@ inferType | main.rs:2071:17:2071:30 | ... .foo() | | main.rs:2037:5:2038:13 | S | | main.rs:2071:23:2071:23 | 0 | | {EXTERNAL LOCATION} | i32 | | main.rs:2075:17:2075:19 | vec | | main.rs:2046:5:2049:5 | MyVec | -| main.rs:2075:17:2075:19 | vec | T | main.rs:2037:5:2038:13 | S | | main.rs:2075:23:2075:34 | ...::new(...) | | main.rs:2046:5:2049:5 | MyVec | -| main.rs:2075:23:2075:34 | ...::new(...) | T | main.rs:2037:5:2038:13 | S | | main.rs:2076:9:2076:11 | vec | | main.rs:2046:5:2049:5 | MyVec | -| main.rs:2076:9:2076:11 | vec | T | main.rs:2037:5:2038:13 | S | | main.rs:2076:18:2076:18 | S | | main.rs:2037:5:2038:13 | S | | main.rs:2077:9:2077:11 | vec | | main.rs:2046:5:2049:5 | MyVec | -| main.rs:2077:9:2077:11 | vec | T | main.rs:2037:5:2038:13 | S | -| main.rs:2077:9:2077:14 | vec[0] | | main.rs:2037:5:2038:13 | S | -| main.rs:2077:9:2077:20 | ... .foo() | | main.rs:2037:5:2038:13 | S | | main.rs:2077:13:2077:13 | 0 | | {EXTERNAL LOCATION} | i32 | | main.rs:2077:13:2077:13 | 0 | | {EXTERNAL LOCATION} | usize | | main.rs:2079:13:2079:14 | xs | | file://:0:0:0:0 | [] | @@ -4454,44 +4609,24 @@ inferType | main.rs:2358:18:2358:22 | vals6 | T.&T | {EXTERNAL LOCATION} | u64 | | main.rs:2360:17:2360:21 | vals7 | | {EXTERNAL LOCATION} | Vec | | main.rs:2360:17:2360:21 | vals7 | A | {EXTERNAL LOCATION} | Global | -| main.rs:2360:17:2360:21 | vals7 | T | {EXTERNAL LOCATION} | u8 | | main.rs:2360:25:2360:34 | ...::new(...) | | {EXTERNAL LOCATION} | Vec | | main.rs:2360:25:2360:34 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2360:25:2360:34 | ...::new(...) | T | {EXTERNAL LOCATION} | u8 | | main.rs:2361:9:2361:13 | vals7 | | {EXTERNAL LOCATION} | Vec | | main.rs:2361:9:2361:13 | vals7 | A | {EXTERNAL LOCATION} | Global | -| main.rs:2361:9:2361:13 | vals7 | T | {EXTERNAL LOCATION} | u8 | | main.rs:2361:20:2361:22 | 1u8 | | {EXTERNAL LOCATION} | u8 | -| main.rs:2362:13:2362:13 | u | | {EXTERNAL LOCATION} | u8 | | main.rs:2362:13:2362:13 | u | | file://:0:0:0:0 | & | | main.rs:2362:18:2362:22 | vals7 | | {EXTERNAL LOCATION} | Vec | | main.rs:2362:18:2362:22 | vals7 | A | {EXTERNAL LOCATION} | Global | -| main.rs:2362:18:2362:22 | vals7 | T | {EXTERNAL LOCATION} | u8 | | main.rs:2364:33:2364:33 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2364:36:2364:36 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:2364:45:2364:45 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2364:48:2364:48 | 4 | | {EXTERNAL LOCATION} | i32 | | main.rs:2371:17:2371:20 | map1 | | {EXTERNAL LOCATION} | HashMap | -| main.rs:2371:17:2371:20 | map1 | K | {EXTERNAL LOCATION} | i32 | | main.rs:2371:17:2371:20 | map1 | S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2371:17:2371:20 | map1 | V | {EXTERNAL LOCATION} | Box | -| main.rs:2371:17:2371:20 | map1 | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2371:17:2371:20 | map1 | V.T | file://:0:0:0:0 | & | -| main.rs:2371:17:2371:20 | map1 | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2371:24:2371:55 | ...::new(...) | | {EXTERNAL LOCATION} | HashMap | -| main.rs:2371:24:2371:55 | ...::new(...) | K | {EXTERNAL LOCATION} | i32 | | main.rs:2371:24:2371:55 | ...::new(...) | S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2371:24:2371:55 | ...::new(...) | V | {EXTERNAL LOCATION} | Box | -| main.rs:2371:24:2371:55 | ...::new(...) | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2371:24:2371:55 | ...::new(...) | V.T | file://:0:0:0:0 | & | -| main.rs:2371:24:2371:55 | ...::new(...) | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2372:9:2372:12 | map1 | | {EXTERNAL LOCATION} | HashMap | -| main.rs:2372:9:2372:12 | map1 | K | {EXTERNAL LOCATION} | i32 | | main.rs:2372:9:2372:12 | map1 | S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2372:9:2372:12 | map1 | V | {EXTERNAL LOCATION} | Box | -| main.rs:2372:9:2372:12 | map1 | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2372:9:2372:12 | map1 | V.T | file://:0:0:0:0 | & | -| main.rs:2372:9:2372:12 | map1 | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2372:9:2372:39 | map1.insert(...) | | {EXTERNAL LOCATION} | Option | | main.rs:2372:9:2372:39 | map1.insert(...) | T | {EXTERNAL LOCATION} | Box | | main.rs:2372:9:2372:39 | map1.insert(...) | T.A | {EXTERNAL LOCATION} | Global | @@ -4505,12 +4640,7 @@ inferType | main.rs:2372:33:2372:37 | "one" | | file://:0:0:0:0 | & | | main.rs:2372:33:2372:37 | "one" | &T | {EXTERNAL LOCATION} | str | | main.rs:2373:9:2373:12 | map1 | | {EXTERNAL LOCATION} | HashMap | -| main.rs:2373:9:2373:12 | map1 | K | {EXTERNAL LOCATION} | i32 | | main.rs:2373:9:2373:12 | map1 | S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2373:9:2373:12 | map1 | V | {EXTERNAL LOCATION} | Box | -| main.rs:2373:9:2373:12 | map1 | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2373:9:2373:12 | map1 | V.T | file://:0:0:0:0 | & | -| main.rs:2373:9:2373:12 | map1 | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2373:9:2373:39 | map1.insert(...) | | {EXTERNAL LOCATION} | Option | | main.rs:2373:9:2373:39 | map1.insert(...) | T | {EXTERNAL LOCATION} | Box | | main.rs:2373:9:2373:39 | map1.insert(...) | T.A | {EXTERNAL LOCATION} | Global | @@ -4525,102 +4655,38 @@ inferType | main.rs:2373:33:2373:37 | "two" | &T | {EXTERNAL LOCATION} | str | | main.rs:2374:13:2374:15 | key | | {EXTERNAL LOCATION} | Item | | main.rs:2374:13:2374:15 | key | | file://:0:0:0:0 | & | -| main.rs:2374:13:2374:15 | key | &T | {EXTERNAL LOCATION} | i32 | | main.rs:2374:20:2374:23 | map1 | | {EXTERNAL LOCATION} | HashMap | -| main.rs:2374:20:2374:23 | map1 | K | {EXTERNAL LOCATION} | i32 | | main.rs:2374:20:2374:23 | map1 | S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2374:20:2374:23 | map1 | V | {EXTERNAL LOCATION} | Box | -| main.rs:2374:20:2374:23 | map1 | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2374:20:2374:23 | map1 | V.T | file://:0:0:0:0 | & | -| main.rs:2374:20:2374:23 | map1 | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2374:20:2374:30 | map1.keys() | | {EXTERNAL LOCATION} | Keys | -| main.rs:2374:20:2374:30 | map1.keys() | K | {EXTERNAL LOCATION} | i32 | -| main.rs:2374:20:2374:30 | map1.keys() | V | {EXTERNAL LOCATION} | Box | -| main.rs:2374:20:2374:30 | map1.keys() | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2374:20:2374:30 | map1.keys() | V.T | file://:0:0:0:0 | & | -| main.rs:2374:20:2374:30 | map1.keys() | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2375:13:2375:17 | value | | {EXTERNAL LOCATION} | Item | | main.rs:2375:13:2375:17 | value | | file://:0:0:0:0 | & | -| main.rs:2375:13:2375:17 | value | &T | {EXTERNAL LOCATION} | Box | -| main.rs:2375:13:2375:17 | value | &T.A | {EXTERNAL LOCATION} | Global | -| main.rs:2375:13:2375:17 | value | &T.T | file://:0:0:0:0 | & | -| main.rs:2375:13:2375:17 | value | &T.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2375:22:2375:25 | map1 | | {EXTERNAL LOCATION} | HashMap | -| main.rs:2375:22:2375:25 | map1 | K | {EXTERNAL LOCATION} | i32 | | main.rs:2375:22:2375:25 | map1 | S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2375:22:2375:25 | map1 | V | {EXTERNAL LOCATION} | Box | -| main.rs:2375:22:2375:25 | map1 | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2375:22:2375:25 | map1 | V.T | file://:0:0:0:0 | & | -| main.rs:2375:22:2375:25 | map1 | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2375:22:2375:34 | map1.values() | | {EXTERNAL LOCATION} | Values | -| main.rs:2375:22:2375:34 | map1.values() | K | {EXTERNAL LOCATION} | i32 | -| main.rs:2375:22:2375:34 | map1.values() | V | {EXTERNAL LOCATION} | Box | -| main.rs:2375:22:2375:34 | map1.values() | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2375:22:2375:34 | map1.values() | V.T | file://:0:0:0:0 | & | -| main.rs:2375:22:2375:34 | map1.values() | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2376:13:2376:24 | TuplePat | | file://:0:0:0:0 | (T_2) | | main.rs:2376:13:2376:24 | TuplePat | 0(2) | file://:0:0:0:0 | & | -| main.rs:2376:13:2376:24 | TuplePat | 0(2).&T | {EXTERNAL LOCATION} | i32 | | main.rs:2376:13:2376:24 | TuplePat | 1(2) | file://:0:0:0:0 | & | -| main.rs:2376:13:2376:24 | TuplePat | 1(2).&T | {EXTERNAL LOCATION} | Box | -| main.rs:2376:13:2376:24 | TuplePat | 1(2).&T.A | {EXTERNAL LOCATION} | Global | -| main.rs:2376:13:2376:24 | TuplePat | 1(2).&T.T | file://:0:0:0:0 | & | -| main.rs:2376:13:2376:24 | TuplePat | 1(2).&T.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2376:14:2376:16 | key | | file://:0:0:0:0 | & | -| main.rs:2376:14:2376:16 | key | &T | {EXTERNAL LOCATION} | i32 | | main.rs:2376:19:2376:23 | value | | file://:0:0:0:0 | & | -| main.rs:2376:19:2376:23 | value | &T | {EXTERNAL LOCATION} | Box | -| main.rs:2376:19:2376:23 | value | &T.A | {EXTERNAL LOCATION} | Global | -| main.rs:2376:19:2376:23 | value | &T.T | file://:0:0:0:0 | & | -| main.rs:2376:19:2376:23 | value | &T.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2376:29:2376:32 | map1 | | {EXTERNAL LOCATION} | HashMap | -| main.rs:2376:29:2376:32 | map1 | K | {EXTERNAL LOCATION} | i32 | | main.rs:2376:29:2376:32 | map1 | S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2376:29:2376:32 | map1 | V | {EXTERNAL LOCATION} | Box | -| main.rs:2376:29:2376:32 | map1 | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2376:29:2376:32 | map1 | V.T | file://:0:0:0:0 | & | -| main.rs:2376:29:2376:32 | map1 | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2376:29:2376:39 | map1.iter() | | {EXTERNAL LOCATION} | Iter | -| main.rs:2376:29:2376:39 | map1.iter() | K | {EXTERNAL LOCATION} | i32 | -| main.rs:2376:29:2376:39 | map1.iter() | V | {EXTERNAL LOCATION} | Box | -| main.rs:2376:29:2376:39 | map1.iter() | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2376:29:2376:39 | map1.iter() | V.T | file://:0:0:0:0 | & | -| main.rs:2376:29:2376:39 | map1.iter() | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2377:13:2377:24 | TuplePat | | file://:0:0:0:0 | (T_2) | | main.rs:2377:13:2377:24 | TuplePat | 0(2) | file://:0:0:0:0 | & | -| main.rs:2377:13:2377:24 | TuplePat | 0(2).&T | {EXTERNAL LOCATION} | i32 | | main.rs:2377:13:2377:24 | TuplePat | 1(2) | file://:0:0:0:0 | & | -| main.rs:2377:13:2377:24 | TuplePat | 1(2).&T | {EXTERNAL LOCATION} | Box | -| main.rs:2377:13:2377:24 | TuplePat | 1(2).&T.A | {EXTERNAL LOCATION} | Global | -| main.rs:2377:13:2377:24 | TuplePat | 1(2).&T.T | file://:0:0:0:0 | & | -| main.rs:2377:13:2377:24 | TuplePat | 1(2).&T.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2377:14:2377:16 | key | | file://:0:0:0:0 | & | -| main.rs:2377:14:2377:16 | key | &T | {EXTERNAL LOCATION} | i32 | | main.rs:2377:19:2377:23 | value | | file://:0:0:0:0 | & | -| main.rs:2377:19:2377:23 | value | &T | {EXTERNAL LOCATION} | Box | -| main.rs:2377:19:2377:23 | value | &T.A | {EXTERNAL LOCATION} | Global | -| main.rs:2377:19:2377:23 | value | &T.T | file://:0:0:0:0 | & | -| main.rs:2377:19:2377:23 | value | &T.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2377:29:2377:33 | &map1 | | file://:0:0:0:0 | & | | main.rs:2377:29:2377:33 | &map1 | &T | {EXTERNAL LOCATION} | HashMap | -| main.rs:2377:29:2377:33 | &map1 | &T.K | {EXTERNAL LOCATION} | i32 | | main.rs:2377:29:2377:33 | &map1 | &T.S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2377:29:2377:33 | &map1 | &T.V | {EXTERNAL LOCATION} | Box | -| main.rs:2377:29:2377:33 | &map1 | &T.V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2377:29:2377:33 | &map1 | &T.V.T | file://:0:0:0:0 | & | -| main.rs:2377:29:2377:33 | &map1 | &T.V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2377:30:2377:33 | map1 | | {EXTERNAL LOCATION} | HashMap | -| main.rs:2377:30:2377:33 | map1 | K | {EXTERNAL LOCATION} | i32 | | main.rs:2377:30:2377:33 | map1 | S | {EXTERNAL LOCATION} | RandomState | -| main.rs:2377:30:2377:33 | map1 | V | {EXTERNAL LOCATION} | Box | -| main.rs:2377:30:2377:33 | map1 | V.A | {EXTERNAL LOCATION} | Global | -| main.rs:2377:30:2377:33 | map1 | V.T | file://:0:0:0:0 | & | -| main.rs:2377:30:2377:33 | map1 | V.T.&T | {EXTERNAL LOCATION} | str | | main.rs:2381:17:2381:17 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:2381:26:2381:26 | 0 | | {EXTERNAL LOCATION} | i32 | | main.rs:2381:26:2381:26 | 0 | | {EXTERNAL LOCATION} | i64 | | main.rs:2383:23:2383:23 | a | | {EXTERNAL LOCATION} | i64 | | main.rs:2383:23:2383:28 | ... < ... | | {EXTERNAL LOCATION} | bool | +| main.rs:2383:27:2383:28 | 10 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | main.rs:2383:27:2383:28 | 10 | | {EXTERNAL LOCATION} | i32 | | main.rs:2383:27:2383:28 | 10 | | {EXTERNAL LOCATION} | i64 | | main.rs:2385:13:2385:13 | a | | {EXTERNAL LOCATION} | i64 | @@ -4943,49 +5009,49 @@ inferType | main.rs:2554:44:2554:44 | c | | main.rs:2541:5:2541:29 | MySqlConnection | | main.rs:2554:47:2554:67 | "SELECT * FROM users" | | file://:0:0:0:0 | & | | main.rs:2554:47:2554:67 | "SELECT * FROM users" | &T | {EXTERNAL LOCATION} | str | -| main.rs:2565:36:2567:9 | { ... } | | main.rs:2561:5:2562:5 | Path | -| main.rs:2566:13:2566:20 | Path {...} | | main.rs:2561:5:2562:5 | Path | -| main.rs:2569:29:2569:33 | SelfParam | | file://:0:0:0:0 | & | -| main.rs:2569:29:2569:33 | SelfParam | &T | main.rs:2561:5:2562:5 | Path | -| main.rs:2569:59:2571:9 | { ... } | | {EXTERNAL LOCATION} | Result | -| main.rs:2569:59:2571:9 | { ... } | E | file://:0:0:0:0 | () | -| main.rs:2569:59:2571:9 | { ... } | T | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2570:13:2570:30 | Ok(...) | | {EXTERNAL LOCATION} | Result | -| main.rs:2570:13:2570:30 | Ok(...) | E | file://:0:0:0:0 | () | -| main.rs:2570:13:2570:30 | Ok(...) | T | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2570:16:2570:29 | ...::new(...) | | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2578:39:2580:9 | { ... } | | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2579:13:2579:23 | PathBuf {...} | | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2588:18:2588:22 | SelfParam | | file://:0:0:0:0 | & | -| main.rs:2588:18:2588:22 | SelfParam | &T | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2588:34:2592:9 | { ... } | | file://:0:0:0:0 | & | -| main.rs:2588:34:2592:9 | { ... } | &T | main.rs:2561:5:2562:5 | Path | -| main.rs:2590:34:2590:44 | ...::new(...) | | main.rs:2561:5:2562:5 | Path | -| main.rs:2591:13:2591:17 | &path | | file://:0:0:0:0 | & | -| main.rs:2591:13:2591:17 | &path | &T | main.rs:2561:5:2562:5 | Path | -| main.rs:2591:14:2591:17 | path | | main.rs:2561:5:2562:5 | Path | -| main.rs:2596:13:2596:17 | path1 | | main.rs:2561:5:2562:5 | Path | -| main.rs:2596:21:2596:31 | ...::new(...) | | main.rs:2561:5:2562:5 | Path | -| main.rs:2597:13:2597:17 | path2 | | {EXTERNAL LOCATION} | Result | -| main.rs:2597:13:2597:17 | path2 | E | file://:0:0:0:0 | () | -| main.rs:2597:13:2597:17 | path2 | T | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2597:21:2597:25 | path1 | | main.rs:2561:5:2562:5 | Path | -| main.rs:2597:21:2597:40 | path1.canonicalize() | | {EXTERNAL LOCATION} | Result | -| main.rs:2597:21:2597:40 | path1.canonicalize() | E | file://:0:0:0:0 | () | -| main.rs:2597:21:2597:40 | path1.canonicalize() | T | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2598:13:2598:17 | path3 | | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2598:21:2598:25 | path2 | | {EXTERNAL LOCATION} | Result | -| main.rs:2598:21:2598:25 | path2 | E | file://:0:0:0:0 | () | -| main.rs:2598:21:2598:25 | path2 | T | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2598:21:2598:34 | path2.unwrap() | | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2600:13:2600:20 | pathbuf1 | | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2600:24:2600:37 | ...::new(...) | | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2601:24:2601:31 | pathbuf1 | | main.rs:2574:5:2575:5 | PathBuf | -| main.rs:2612:5:2612:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2613:5:2613:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2613:20:2613:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2613:41:2613:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2629:5:2629:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future | +| main.rs:2564:36:2566:9 | { ... } | | main.rs:2561:5:2561:22 | Path | +| main.rs:2565:13:2565:19 | Path {...} | | main.rs:2561:5:2561:22 | Path | +| main.rs:2568:29:2568:33 | SelfParam | | file://:0:0:0:0 | & | +| main.rs:2568:29:2568:33 | SelfParam | &T | main.rs:2561:5:2561:22 | Path | +| main.rs:2568:59:2570:9 | { ... } | | {EXTERNAL LOCATION} | Result | +| main.rs:2568:59:2570:9 | { ... } | E | file://:0:0:0:0 | () | +| main.rs:2568:59:2570:9 | { ... } | T | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2569:13:2569:30 | Ok(...) | | {EXTERNAL LOCATION} | Result | +| main.rs:2569:13:2569:30 | Ok(...) | E | file://:0:0:0:0 | () | +| main.rs:2569:13:2569:30 | Ok(...) | T | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2569:16:2569:29 | ...::new(...) | | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2576:39:2578:9 | { ... } | | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2577:13:2577:22 | PathBuf {...} | | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2586:18:2586:22 | SelfParam | | file://:0:0:0:0 | & | +| main.rs:2586:18:2586:22 | SelfParam | &T | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2586:34:2590:9 | { ... } | | file://:0:0:0:0 | & | +| main.rs:2586:34:2590:9 | { ... } | &T | main.rs:2561:5:2561:22 | Path | +| main.rs:2588:33:2588:43 | ...::new(...) | | main.rs:2561:5:2561:22 | Path | +| main.rs:2589:13:2589:17 | &path | | file://:0:0:0:0 | & | +| main.rs:2589:13:2589:17 | &path | &T | main.rs:2561:5:2561:22 | Path | +| main.rs:2589:14:2589:17 | path | | main.rs:2561:5:2561:22 | Path | +| main.rs:2594:13:2594:17 | path1 | | main.rs:2561:5:2561:22 | Path | +| main.rs:2594:21:2594:31 | ...::new(...) | | main.rs:2561:5:2561:22 | Path | +| main.rs:2595:13:2595:17 | path2 | | {EXTERNAL LOCATION} | Result | +| main.rs:2595:13:2595:17 | path2 | E | file://:0:0:0:0 | () | +| main.rs:2595:13:2595:17 | path2 | T | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2595:21:2595:25 | path1 | | main.rs:2561:5:2561:22 | Path | +| main.rs:2595:21:2595:40 | path1.canonicalize() | | {EXTERNAL LOCATION} | Result | +| main.rs:2595:21:2595:40 | path1.canonicalize() | E | file://:0:0:0:0 | () | +| main.rs:2595:21:2595:40 | path1.canonicalize() | T | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2596:13:2596:17 | path3 | | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2596:21:2596:25 | path2 | | {EXTERNAL LOCATION} | Result | +| main.rs:2596:21:2596:25 | path2 | E | file://:0:0:0:0 | () | +| main.rs:2596:21:2596:25 | path2 | T | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2596:21:2596:34 | path2.unwrap() | | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2598:13:2598:20 | pathbuf1 | | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2598:24:2598:37 | ...::new(...) | | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2599:24:2599:31 | pathbuf1 | | main.rs:2573:5:2573:25 | PathBuf | +| main.rs:2610:5:2610:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2611:5:2611:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2611:20:2611:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2611:41:2611:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2627:5:2627:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future | | pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option | | pattern_matching.rs:13:26:133:1 | { ... } | T | file://:0:0:0:0 | () | | pattern_matching.rs:14:9:14:13 | value | | {EXTERNAL LOCATION} | Option | @@ -5451,24 +5517,17 @@ inferType | pattern_matching.rs:270:11:270:26 | &mut ref_mut_val | &T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:270:16:270:26 | ref_mut_val | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:271:17:271:17 | x | | file://:0:0:0:0 | & | -| pattern_matching.rs:271:17:271:17 | x | &T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:271:17:271:17 | x | &T | file://:0:0:0:0 | & | | pattern_matching.rs:271:17:271:17 | x | &T.&T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:272:17:272:29 | ref_mut_bound | | file://:0:0:0:0 | & | -| pattern_matching.rs:272:17:272:29 | ref_mut_bound | &T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:272:17:272:29 | ref_mut_bound | &T | file://:0:0:0:0 | & | | pattern_matching.rs:272:17:272:29 | ref_mut_bound | &T.&T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:272:33:272:33 | x | | file://:0:0:0:0 | & | -| pattern_matching.rs:272:33:272:33 | x | &T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:272:33:272:33 | x | &T | file://:0:0:0:0 | & | | pattern_matching.rs:272:33:272:33 | x | &T.&T | {EXTERNAL LOCATION} | i32 | -| pattern_matching.rs:273:13:273:27 | * ... | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:273:13:273:32 | ... += ... | | file://:0:0:0:0 | () | | pattern_matching.rs:273:14:273:27 | * ... | | {EXTERNAL LOCATION} | i32 | -| pattern_matching.rs:273:14:273:27 | * ... | | file://:0:0:0:0 | & | -| pattern_matching.rs:273:14:273:27 | * ... | &T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:273:15:273:27 | ref_mut_bound | | file://:0:0:0:0 | & | -| pattern_matching.rs:273:15:273:27 | ref_mut_bound | &T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:273:15:273:27 | ref_mut_bound | &T | file://:0:0:0:0 | & | | pattern_matching.rs:273:15:273:27 | ref_mut_bound | &T.&T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:273:32:273:32 | 1 | | {EXTERNAL LOCATION} | i32 | @@ -6536,6 +6595,7 @@ inferType | pattern_matching.rs:805:9:805:9 | x | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:805:14:805:14 | x | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:805:14:805:18 | ... > ... | | {EXTERNAL LOCATION} | bool | +| pattern_matching.rs:805:18:805:18 | 0 | | {EXTERNAL LOCATION} | Self [trait PartialOrd] | | pattern_matching.rs:805:18:805:18 | 0 | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:806:17:806:23 | guard_x | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:806:27:806:27 | x | | {EXTERNAL LOCATION} | i32 | @@ -6548,3 +6608,28 @@ inferType | pattern_matching.rs:814:5:814:7 | f(...) | | {EXTERNAL LOCATION} | Option | | pattern_matching.rs:814:5:814:7 | f(...) | T | file://:0:0:0:0 | () | testFailures +| dyn_type.rs:104:16:104:29 | "".to_string() | Unexpected result: target=to_string | +| loop/main.rs:12:20:12:34 | //... | Missing result: target=foo | +| main.rs:1286:26:1286:56 | //... | Missing result: fieldof=MyInt | +| main.rs:1330:26:1330:44 | "Hello".to_string() | Unexpected result: target=to_string | +| main.rs:1429:27:1429:55 | //... | Missing result: type=n:bool | +| main.rs:1433:44:1433:62 | //... | Missing result: target=default | +| main.rs:1434:34:1434:49 | //... | Missing result: target=flip | +| main.rs:1435:33:1435:53 | //... | Missing result: type=flag:MyFlag | +| main.rs:1838:23:1838:30 | ... == ... | Unexpected result: target=eq | +| main.rs:1839:23:1839:30 | ... != ... | Unexpected result: target=ne | +| main.rs:1840:23:1840:29 | ... < ... | Unexpected result: target=lt | +| main.rs:1841:23:1841:30 | ... <= ... | Unexpected result: target=le | +| main.rs:1842:23:1842:29 | ... > ... | Unexpected result: target=gt | +| main.rs:1843:23:1843:30 | ... >= ... | Unexpected result: target=ge | +| main.rs:1902:30:1902:64 | ... == ... | Unexpected result: target=eq | +| main.rs:2075:37:2075:64 | //... | Missing result: type=vec:T.S | +| main.rs:2077:23:2077:57 | //... | Missing result: target=foo | +| main.rs:2360:37:2360:82 | //... | Missing result: type=vals7:T.u8 | +| main.rs:2362:27:2362:40 | //... | Missing result: type=u:u8 | +| main.rs:2371:58:2371:155 | //... | Missing result: type=map1:K.i32 | +| main.rs:2371:58:2371:155 | //... | Missing result: type=map1:V.Box | +| main.rs:2548:9:2548:20 | c.execute1() | Fixed missing result: target=execute1 | +| main.rs:2551:9:2551:41 | c.execute2(...) | Fixed missing result: target=execute2 | +| main.rs:2552:9:2552:49 | c.execute2(...) | Fixed missing result: target=execute2 | +| pattern_matching.rs:273:35:273:69 | //... | Missing result: target=add_assign | diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index 32615dc46cd6..99d9ad436698 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -494,6 +494,12 @@ module Make1 Input1> { module Make2 { private import Input2 + final private class FinalTypeMention = TypeMention; + + final class TypeMentionTypeTree extends FinalTypeMention { + Type getTypeAt(TypePath path) { result = this.resolveTypeAt(path) } + } + /** Gets the type at the empty path of `tm`. */ bindingset[tm] pragma[inline_late] @@ -502,7 +508,7 @@ module Make1 Input1> { } /** Provides the input to `IsInstantiationOf`. */ - signature module IsInstantiationOfInputSig { + signature module IsInstantiationOfInputSig { /** * Holds if `abs` is a type abstraction, `tm` occurs in the scope of * `abs`, and `app` is potentially an application/instantiation of `abs`. @@ -523,46 +529,45 @@ module Make1 Input1> { * accessing the `bar` method of `foo` potentially instantiates the `impl` * block with a type argument for `A`. */ - predicate potentialInstantiationOf(App app, TypeAbstraction abs, TypeMention tm); + predicate potentialInstantiationOf(App app, TypeAbstraction abs, Constraint tm); /** * Holds if `constraint` might occur as the third argument of * `potentialInstantiationOf`. Defaults to simply projecting the third * argument of `potentialInstantiationOf`. */ - default predicate relevantTypeMention(TypeMention tm) { potentialInstantiationOf(_, _, tm) } + default predicate relevantTypeMention(Constraint tm) { potentialInstantiationOf(_, _, tm) } } /** * Provides functionality for determining if a type is a possible * instantiation of a type mention containing type parameters. */ - module IsInstantiationOf Input> { + module IsInstantiationOf< + HasTypeTreeSig App, HasTypeTreeSig Constraint, + IsInstantiationOfInputSig Input> + { private import Input /** Gets the `i`th path in `tm` per some arbitrary order. */ pragma[nomagic] - private TypePath getNthPath(TypeMention tm, int i) { + private TypePath getNthPath(Constraint tm, int i) { result = - rank[i + 1](TypePath path | - exists(tm.resolveTypeAt(path)) and relevantTypeMention(tm) - | - path - ) + rank[i + 1](TypePath path | exists(tm.getTypeAt(path)) and relevantTypeMention(tm) | path) } pragma[nomagic] private Type resolveNthTypeAt( - App app, TypeAbstraction abs, TypeMention tm, int i, TypePath path + App app, TypeAbstraction abs, Constraint tm, int i, TypePath path ) { potentialInstantiationOf(app, abs, tm) and path = getNthPath(tm, i) and - result = tm.resolveTypeAt(path) + result = tm.getTypeAt(path) } pragma[nomagic] private predicate satisfiesConcreteTypesFromIndex( - App app, TypeAbstraction abs, TypeMention tm, int i + App app, TypeAbstraction abs, Constraint tm, int i ) { exists(Type t, TypePath path | t = resolveNthTypeAt(app, abs, tm, i, path) and @@ -574,7 +579,7 @@ module Make1 Input1> { /** Holds if all the concrete types in `tm` also occur in `app`. */ pragma[nomagic] - private predicate satisfiesConcreteTypes(App app, TypeAbstraction abs, TypeMention tm) { + private predicate satisfiesConcreteTypes(App app, TypeAbstraction abs, Constraint tm) { satisfiesConcreteTypesFromIndex(app, abs, tm, max(int i | exists(getNthPath(tm, i)))) } @@ -592,14 +597,14 @@ module Make1 Input1> { * arbitrary order, if any. */ pragma[nomagic] - private TypePath getNthTypeParameterPath(TypeMention tm, TypeParameter tp, int i) { + private TypePath getNthTypeParameterPath(Constraint tm, TypeParameter tp, int i) { result = - rank[i + 1](TypePath path | tp = tm.resolveTypeAt(path) and relevantTypeMention(tm) | path) + rank[i + 1](TypePath path | tp = tm.getTypeAt(path) and relevantTypeMention(tm) | path) } pragma[nomagic] private predicate typeParametersEqualFromIndexBase( - App app, TypeAbstraction abs, TypeMention tm, TypeParameter tp, TypePath path + App app, TypeAbstraction abs, Constraint tm, TypeParameter tp, TypePath path ) { path = getNthTypeParameterPath(tm, tp, 0) and satisfiesConcreteTypes(app, abs, tm) and @@ -609,7 +614,7 @@ module Make1 Input1> { pragma[nomagic] private predicate typeParametersEqualFromIndex( - App app, TypeAbstraction abs, TypeMention tm, TypeParameter tp, Type t, int i + App app, TypeAbstraction abs, Constraint tm, TypeParameter tp, Type t, int i ) { exists(TypePath path | t = app.getTypeAt(path) and @@ -623,7 +628,7 @@ module Make1 Input1> { } private predicate typeParametersEqual( - App app, TypeAbstraction abs, TypeMention tm, TypeParameter tp + App app, TypeAbstraction abs, Constraint tm, TypeParameter tp ) { satisfiesConcreteTypes(app, abs, tm) and tp = getNthTypeParameter(abs, _) and @@ -639,7 +644,7 @@ module Make1 Input1> { } private predicate typeParametersHaveEqualInstantiationFromIndex( - App app, TypeAbstraction abs, TypeMention tm, int i + App app, TypeAbstraction abs, Constraint tm, int i ) { exists(TypeParameter tp | tp = getNthTypeParameter(abs, i) | typeParametersEqual(app, abs, tm, tp) and @@ -662,7 +667,7 @@ module Make1 Input1> { * - `Pair` is _not_ an instantiation of `Pair` */ pragma[nomagic] - predicate isInstantiationOf(App app, TypeAbstraction abs, TypeMention tm) { + predicate isInstantiationOf(App app, TypeAbstraction abs, Constraint tm) { // We only need to check equality if the concrete types are satisfied. satisfiesConcreteTypes(app, abs, tm) and // Check if all the places where the same type parameter occurs in `tm` @@ -684,7 +689,7 @@ module Make1 Input1> { * Holds if `app` is _not_ a possible instantiation of `tm`. */ pragma[nomagic] - predicate isNotInstantiationOf(App app, TypeAbstraction abs, TypeMention tm) { + predicate isNotInstantiationOf(App app, TypeAbstraction abs, Constraint tm) { // `app` and `tm` differ on a concrete type exists(Type t, TypePath path | t = resolveNthTypeAt(app, abs, tm, _, path) and @@ -692,13 +697,35 @@ module Make1 Input1> { not path.isEmpty() and app.getTypeAt(path) != t ) - or - // `app` uses inconsistent type parameter instantiations - exists(TypeParameter tp | - potentialInstantiationOf(app, abs, tm) and - app.getTypeAt(getNthTypeParameterPath(tm, tp, _)) != - app.getTypeAt(getNthTypeParameterPath(tm, tp, _)) + // or + // // `app` uses inconsistent type parameter instantiations + // exists(TypeParameter tp, Type t1, Type t2 | + // potentialInstantiationOf(app, abs, tm) and + // t1 = app.getTypeAt(getNthTypeParameterPath(tm, tp, _)) and + // t2 = app.getTypeAt(getNthTypeParameterPath(tm, tp, _)) and + // t1 != t2 + // ) + } + + /** + * Holds if `app` is _not_ a possible instantiation of `tm`. + */ + pragma[nomagic] + predicate isNotInstantiationOfStrict(App app, TypeAbstraction abs, Constraint tm) { + // `app` and `tm` differ on a concrete type + exists(Type t, TypePath path | + t = resolveNthTypeAt(app, abs, tm, _, path) and + not t = abs.getATypeParameter() and + app.getTypeAt(path) != t ) + // or + // // `app` uses inconsistent type parameter instantiations + // exists(TypeParameter tp, Type t1, Type t2 | + // potentialInstantiationOf(app, abs, tm) and + // t1 = app.getTypeAt(getNthTypeParameterPath(tm, tp, _)) and + // t2 = app.getTypeAt(getNthTypeParameterPath(tm, tp, _)) and + // t1 != t2 + // ) } } @@ -721,14 +748,8 @@ module Make1 Input1> { ) } - final private class FinalTypeMention = TypeMention; - - final private class TypeMentionTypeTree extends FinalTypeMention { - Type getTypeAt(TypePath path) { result = this.resolveTypeAt(path) } - } - private module IsInstantiationOfInput implements - IsInstantiationOfInputSig + IsInstantiationOfInputSig { pragma[nomagic] private predicate typeCondition( @@ -745,7 +766,7 @@ module Make1 Input1> { } predicate potentialInstantiationOf( - TypeMentionTypeTree constraint, TypeAbstraction abs, TypeMention condition + TypeMentionTypeTree constraint, TypeAbstraction abs, TypeMentionTypeTree condition ) { exists(Type type | typeConstraint(type, constraint) and typeCondition(type, abs, condition) @@ -769,7 +790,7 @@ module Make1 Input1> { conditionSatisfiesConstraint(abs, condition, midConstraint) and // NOTE: `midAbs` describe the free type variables in `midCondition`, hence // we use that for instantiation check. - IsInstantiationOf::isInstantiationOf(midConstraint, + IsInstantiationOf::isInstantiationOf(midConstraint, midAbs, midCondition) | conditionSatisfiesConstraintTypeAt(midAbs, midCondition, constraint, path, t) and @@ -933,8 +954,12 @@ module Make1 Input1> { relevantConstraint(term, constraint) } - private module IsInstantiationOfInput implements IsInstantiationOfInputSig { - predicate potentialInstantiationOf(HasTypeTree tt, TypeAbstraction abs, TypeMention cond) { + private module IsInstantiationOfInput implements + IsInstantiationOfInputSig + { + predicate potentialInstantiationOf( + HasTypeTree tt, TypeAbstraction abs, TypeMentionTypeTree cond + ) { exists(Type constraint, Type type | hasTypeConstraint(tt, type, constraint) and rootTypesSatisfaction(type, constraint, abs, cond, _) and @@ -943,7 +968,7 @@ module Make1 Input1> { ) } - predicate relevantTypeMention(TypeMention constraint) { + predicate relevantTypeMention(TypeMentionTypeTree constraint) { rootTypesSatisfaction(_, _, _, constraint, _) } } @@ -969,8 +994,8 @@ module Make1 Input1> { // one where the type instantiates the precondition. if multipleConstraintImplementations(type, constraint) then - IsInstantiationOf::isInstantiationOf(tt, abs, - condition) + IsInstantiationOf::isInstantiationOf(tt, + abs, condition) else any() ) } @@ -1018,8 +1043,8 @@ module Make1 Input1> { } } - /** Provides the input to `Matching`. */ - signature module MatchingInputSig { + /** Provides the input to `MatchingWithState`. */ + signature module MatchingWithStateInputSig { /** * A position inside a declaration. For example, the integer position of a * parameter inside a method or the return type of a method. @@ -1064,6 +1089,12 @@ module Make1 Input1> { string toString(); } + bindingset[this] + class State { + bindingset[this] + string toString(); + } + /** An access that targets a declaration, for example a method call. */ class Access { /** Gets a textual representation of this access. */ @@ -1087,10 +1118,11 @@ module Make1 Input1> { * For example, if this access is the method call `M(42)`, then the inferred * type at argument position `0` is `int`. */ - Type getInferredType(AccessPosition apos, TypePath path); + bindingset[state] + Type getInferredType(State state, AccessPosition apos, TypePath path); /** Gets the declaration that this access targets. */ - Declaration getTarget(); + Declaration getTarget(State state); } /** Holds if `apos` and `dpos` match. */ @@ -1128,7 +1160,7 @@ module Make1 Input1> { * * Matching takes both base types and explicit type arguments into account. */ - module Matching { + module MatchingWithState { private import Input /** @@ -1137,11 +1169,11 @@ module Make1 Input1> { */ pragma[nomagic] private predicate adjustedAccessType( - Access a, AccessPosition apos, Declaration target, TypePath path, Type t + Access a, State state, AccessPosition apos, Declaration target, TypePath path, Type t ) { - target = a.getTarget() and + target = a.getTarget(state) and exists(TypePath path0, Type t0 | - t0 = a.getInferredType(apos, path0) and + t0 = a.getInferredType(state, apos, path0) and adjustAccessType(apos, target, path0, t0, path, t) ) } @@ -1170,13 +1202,13 @@ module Make1 Input1> { */ pragma[nomagic] private predicate directTypeMatch( - Access a, Declaration target, TypePath path, Type t, TypeParameter tp + Access a, State state, Declaration target, TypePath path, Type t, TypeParameter tp ) { not exists(getTypeArgument(a, target, tp, _)) and exists(AccessPosition apos, DeclarationPosition dpos, TypePath pathToTypeParam | tp = target.getDeclaredType(dpos, pathToTypeParam) and accessDeclarationPositionMatch(apos, dpos) and - adjustedAccessType(a, apos, target, pathToTypeParam.appendInverse(path), t) + adjustedAccessType(a, state, apos, target, pathToTypeParam.appendInverse(path), t) ) } @@ -1185,19 +1217,21 @@ module Make1 Input1> { * Holds if inferring types at `a` might depend on the type at `path` of * `apos` having `base` as a transitive base type. */ - private predicate relevantAccess(Access a, AccessPosition apos, Type base) { + private predicate relevantAccess(Access a, State state, AccessPosition apos, Type base) { exists(Declaration target, DeclarationPosition dpos | - adjustedAccessType(a, apos, target, _, _) and + adjustedAccessType(a, state, apos, target, _, _) and accessDeclarationPositionMatch(apos, dpos) and declarationBaseType(target, dpos, base, _, _) ) } pragma[nomagic] - private Type inferTypeAt(Access a, AccessPosition apos, TypeParameter tp, TypePath suffix) { - relevantAccess(a, apos, _) and + private Type inferTypeAt( + Access a, State state, AccessPosition apos, TypeParameter tp, TypePath suffix + ) { + relevantAccess(a, state, apos, _) and exists(TypePath path0 | - result = a.getInferredType(apos, path0) and + result = a.getInferredType(state, apos, path0) and path0.isCons(tp, suffix) ) } @@ -1234,15 +1268,15 @@ module Make1 Input1> { * `Base>` | `"T2.T1.T1"` | `int` */ predicate hasBaseTypeMention( - Access a, AccessPosition apos, TypeMention baseMention, TypePath path, Type t + Access a, State state, AccessPosition apos, TypeMention baseMention, TypePath path, Type t ) { - relevantAccess(a, apos, resolveTypeMentionRoot(baseMention)) and - exists(Type sub | sub = a.getInferredType(apos, TypePath::nil()) | + relevantAccess(a, state, apos, resolveTypeMentionRoot(baseMention)) and + exists(Type sub | sub = a.getInferredType(state, apos, TypePath::nil()) | baseTypeMentionHasNonTypeParameterAt(sub, baseMention, path, t) or exists(TypePath prefix, TypePath suffix, TypeParameter tp | baseTypeMentionHasTypeParameterAt(sub, baseMention, prefix, tp) and - t = inferTypeAt(a, apos, tp, suffix) and + t = inferTypeAt(a, state, apos, tp, suffix) and path = prefix.append(suffix) ) ) @@ -1251,15 +1285,18 @@ module Make1 Input1> { private module AccessConstraint { predicate relevantAccessConstraint( - Access a, Declaration target, AccessPosition apos, TypePath path, Type constraint + Access a, State state, Declaration target, AccessPosition apos, TypePath path, + Type constraint ) { - target = a.getTarget() and + target = a.getTarget(state) and typeParameterConstraintHasTypeParameter(target, apos, path, constraint, _, _) } private newtype TRelevantAccess = - MkRelevantAccess(Access a, Declaration target, AccessPosition apos, TypePath path) { - relevantAccessConstraint(a, target, apos, path, _) + MkRelevantAccess( + Access a, State state, Declaration target, AccessPosition apos, TypePath path + ) { + relevantAccessConstraint(a, state, target, apos, path, _) } /** @@ -1268,18 +1305,19 @@ module Make1 Input1> { */ private class RelevantAccess extends MkRelevantAccess { Access a; + State state; Declaration target; AccessPosition apos; TypePath path; - RelevantAccess() { this = MkRelevantAccess(a, target, apos, path) } + RelevantAccess() { this = MkRelevantAccess(a, state, target, apos, path) } Type getTypeAt(TypePath suffix) { - adjustedAccessType(a, apos, target, path.appendInverse(suffix), result) + adjustedAccessType(a, state, apos, target, path.appendInverse(suffix), result) } /** Holds if this relevant access should satisfy `constraint`. */ - Type getConstraint() { relevantAccessConstraint(a, target, apos, path, result) } + Type getConstraint() { relevantAccessConstraint(a, state, target, apos, path, result) } string toString() { result = a.toString() + ", " + apos.toString() + ", " + path.toString() @@ -1297,11 +1335,11 @@ module Make1 Input1> { } predicate satisfiesConstraintType( - Access a, Declaration target, AccessPosition apos, TypePath prefix, Type constraint, - TypePath path, Type t + Access a, State state, Declaration target, AccessPosition apos, TypePath prefix, + Type constraint, TypePath path, Type t ) { SatisfiesConstraint::satisfiesConstraintType(MkRelevantAccess(a, - target, apos, prefix), constraint, path, t) + state, target, apos, prefix), constraint, path, t) } } @@ -1311,10 +1349,10 @@ module Make1 Input1> { */ pragma[nomagic] private predicate accessBaseType( - Access a, AccessPosition apos, Type base, TypePath path, Type t + Access a, State state, AccessPosition apos, Type base, TypePath path, Type t ) { exists(TypeMention tm | - AccessBaseType::hasBaseTypeMention(a, apos, tm, path, t) and + AccessBaseType::hasBaseTypeMention(a, state, apos, tm, path, t) and base = resolveTypeMentionRoot(tm) ) } @@ -1365,12 +1403,12 @@ module Make1 Input1> { */ pragma[nomagic] private predicate baseTypeMatch( - Access a, Declaration target, TypePath path, Type t, TypeParameter tp + Access a, State state, Declaration target, TypePath path, Type t, TypeParameter tp ) { not exists(getTypeArgument(a, target, tp, _)) and - target = a.getTarget() and + target = a.getTarget(state) and exists(AccessPosition apos, DeclarationPosition dpos, Type base, TypePath pathToTypeParam | - accessBaseType(a, apos, base, pathToTypeParam.appendInverse(path), t) and + accessBaseType(a, state, apos, base, pathToTypeParam.appendInverse(path), t) and declarationBaseType(target, dpos, base, pathToTypeParam, tp) and accessDeclarationPositionMatch(apos, dpos) ) @@ -1383,9 +1421,9 @@ module Make1 Input1> { */ pragma[nomagic] private predicate explicitTypeMatch( - Access a, Declaration target, TypePath path, Type t, TypeParameter tp + Access a, State state, Declaration target, TypePath path, Type t, TypeParameter tp ) { - target = a.getTarget() and + target = a.getTarget(state) and t = getTypeArgument(a, target, tp, path) } @@ -1427,32 +1465,32 @@ module Make1 Input1> { pragma[nomagic] private predicate typeConstraintBaseTypeMatch( - Access a, Declaration target, TypePath path, Type t, TypeParameter tp + Access a, State state, Declaration target, TypePath path, Type t, TypeParameter tp ) { not exists(getTypeArgument(a, target, tp, _)) and exists(Type constraint, AccessPosition apos, TypePath pathToTp, TypePath pathToTp2 | typeParameterConstraintHasTypeParameter(target, apos, pathToTp2, constraint, pathToTp, tp) and - AccessConstraint::satisfiesConstraintType(a, target, apos, pathToTp2, constraint, + AccessConstraint::satisfiesConstraintType(a, state, target, apos, pathToTp2, constraint, pathToTp.appendInverse(path), t) ) } pragma[inline] private predicate typeMatch( - Access a, Declaration target, TypePath path, Type t, TypeParameter tp + Access a, State state, Declaration target, TypePath path, Type t, TypeParameter tp ) { // A type given at the access corresponds directly to the type parameter // at the target. - explicitTypeMatch(a, target, path, t, tp) + explicitTypeMatch(a, state, target, path, t, tp) or // We can infer the type of `tp` from one of the access positions - directTypeMatch(a, target, path, t, tp) + directTypeMatch(a, state, target, path, t, tp) or // We can infer the type of `tp` by going up the type hiearchy - baseTypeMatch(a, target, path, t, tp) + baseTypeMatch(a, state, target, path, t, tp) or // We can infer the type of `tp` by a type constraint - typeConstraintBaseTypeMatch(a, target, path, t, tp) + typeConstraintBaseTypeMatch(a, state, target, path, t, tp) } /** @@ -1494,25 +1532,168 @@ module Make1 Input1> { * `"T2.T1.T1"` | `int` */ pragma[nomagic] - Type inferAccessType(Access a, AccessPosition apos, TypePath path) { + Type inferAccessType(Access a, State state, AccessPosition apos, TypePath path) { exists(DeclarationPosition dpos | accessDeclarationPositionMatch(apos, dpos) | // A suffix of `path` leads to a type parameter in the target exists(Declaration target, TypePath prefix, TypeParameter tp, TypePath suffix | tp = target.getDeclaredType(dpos, prefix) and path = prefix.append(suffix) and - typeMatch(a, target, suffix, result, tp) + typeMatch(a, state, target, suffix, result, tp) ) or // `path` corresponds directly to a concrete type in the declaration exists(Declaration target | result = target.getDeclaredType(dpos, path) and - target = a.getTarget() and + target = a.getTarget(state) and not result instanceof TypeParameter ) ) } } + /** Provides the input to `Matching`. */ + signature module MatchingInputSig { + /** + * A position inside a declaration. For example, the integer position of a + * parameter inside a method or the return type of a method. + */ + bindingset[this] + class DeclarationPosition { + /** Gets a textual representation of this position. */ + bindingset[this] + string toString(); + } + + /** A declaration, for example a method. */ + class Declaration { + /** Gets a textual representation of this declaration. */ + string toString(); + + /** Gets the location of this declaration. */ + Location getLocation(); + + /** Gets the type parameter at position `tppos` of this declaration, if any. */ + TypeParameter getTypeParameter(TypeParameterPosition tppos); + + /** + * Gets the declared type of this declaration at `path` for position `dpos`. + * + * For example, if this declaration is the method `int M(bool b)`, + * then the declared type at parameter position `0` is `bool`, the + * declared type at the `this` position is the class type, and the + * declared return type is `int`. + */ + Type getDeclaredType(DeclarationPosition dpos, TypePath path); + } + + /** + * A position inside an access. For example, the integer position of an + * argument inside a method call. + */ + bindingset[this] + class AccessPosition { + /** Gets a textual representation of this position. */ + bindingset[this] + string toString(); + } + + /** An access that targets a declaration, for example a method call. */ + class Access { + /** Gets a textual representation of this access. */ + string toString(); + + /** Gets the location of this access. */ + Location getLocation(); + + /** + * Gets the type at `path` for the type argument at position `tapos` of + * this access, if any. + * + * For example, in a method call like `M()`, `int` is an explicit + * type argument at position `0`. + */ + Type getTypeArgument(TypeArgumentPosition tapos, TypePath path); + + /** + * Gets the inferred type at `path` for the position `apos` of this access. + * + * For example, if this access is the method call `M(42)`, then the inferred + * type at argument position `0` is `int`. + */ + Type getInferredType(AccessPosition apos, TypePath path); + + /** Gets the declaration that this access targets. */ + Declaration getTarget(); + } + + /** Holds if `apos` and `dpos` match. */ + bindingset[apos] + bindingset[dpos] + predicate accessDeclarationPositionMatch(AccessPosition apos, DeclarationPosition dpos); + + /** + * Holds if matching an inferred type `t` at `path` inside an access at `apos` + * against the declaration `target` means that the type should be adjusted to + * `tAdj` at `pathAdj`. + * + * For example, in + * + * ```csharp + * void M(int? i) {} + * M(42); + * ``` + * + * the inferred type of `42` is `int`, but it should be adjusted to `int?` + * when matching against `M`. + */ + bindingset[apos, target, path, t] + default predicate adjustAccessType( + AccessPosition apos, Declaration target, TypePath path, Type t, TypePath pathAdj, Type tAdj + ) { + pathAdj = path and + tAdj = t + } + } + + /** + * Provides logic for matching types at accesses against types at the + * declarations that the accesses target. + * + * Matching takes both base types and explicit type arguments into account. + */ + module Matching { + private module Inp implements MatchingWithStateInputSig { + private import codeql.util.Unit + import Input + + predicate adjustAccessType = Input::adjustAccessType/6; + + class State = Unit; + + final private class AccessFinal = Input::Access; + + class Access extends AccessFinal { + Type getInferredType(State state, AccessPosition apos, TypePath path) { + exists(state) and + result = super.getInferredType(apos, path) + } + + Declaration getTarget(State state) { + exists(state) and + result = super.getTarget() + } + } + } + + private module M = MatchingWithState; + + import M + + Type inferAccessType(Input::Access a, Input::AccessPosition apos, TypePath path) { + result = M::inferAccessType(a, _, apos, path) + } + } + /** Provides consistency checks. */ module Consistency { query predicate missingTypeParameterId(TypeParameter tp) {