@@ -205,8 +205,18 @@ private module Input2 implements InputSig2 {
205205 // `DynTypeBoundListMention` for further details.
206206 exists(DynTraitTypeRepr object |
207207 abs = object and
208- condition = object.getTypeBoundList() and
208+ condition = object.getTypeBoundList()
209+ |
209210 constraint = object.getTrait()
211+ // or
212+ // TTrait(object.getTrait()) =
213+ // constraint
214+ // .(ImplTraitTypeRepr)
215+ // .getTypeBoundList()
216+ // .getABound()
217+ // .getTypeRepr()
218+ // .(TypeMention)
219+ // .resolveType()
210220 )
211221 )
212222 }
@@ -407,6 +417,14 @@ private predicate isPanicMacroCall(MacroExpr me) {
407417 me.getMacroCall().resolveMacro().(MacroRules).getName().getText() = "panic"
408418}
409419
420+ // Due to "binding modes" the type of the pattern is not necessarily the
421+ // same as the type of the initializer. The pattern being an identifier
422+ // pattern is sufficient to ensure that this is not the case.
423+ private predicate identLetStmt(LetStmt let, IdentPat lhs, Expr rhs) {
424+ let.getPat() = lhs and
425+ let.getInitializer() = rhs
426+ }
427+
410428/** Module for inferring certain type information. */
411429module CertainTypeInference {
412430 pragma[nomagic]
@@ -484,11 +502,7 @@ module CertainTypeInference {
484502 // is not a certain type equality.
485503 exists(LetStmt let |
486504 not let.hasTypeRepr() and
487- // Due to "binding modes" the type of the pattern is not necessarily the
488- // same as the type of the initializer. The pattern being an identifier
489- // pattern is sufficient to ensure that this is not the case.
490- let.getPat().(IdentPat) = n1 and
491- let.getInitializer() = n2
505+ identLetStmt(let, n1, n2)
492506 )
493507 or
494508 exists(LetExpr let |
@@ -512,6 +526,25 @@ module CertainTypeInference {
512526 )
513527 else prefix2.isEmpty()
514528 )
529+ or
530+ exists(CallExprImpl::DynamicCallExpr dce, TupleType tt, int i |
531+ n1 = dce.getArgList() and
532+ tt.getArity() = dce.getNumberOfSyntacticArguments() and
533+ n2 = dce.getSyntacticPositionalArgument(i) and
534+ prefix1 = TypePath::singleton(tt.getPositionalTypeParameter(i)) and
535+ prefix2.isEmpty()
536+ )
537+ or
538+ exists(ClosureExpr ce, int index |
539+ n1 = ce and
540+ n2 = ce.getParam(index).getPat() and
541+ prefix1 = closureParameterPath(ce.getNumberOfParams(), index) and
542+ prefix2.isEmpty()
543+ )
544+ or
545+ n1 = any(ClosureExpr ce | not ce.hasRetType() and ce.getClosureBody() = n2) and
546+ prefix1 = closureReturnPath() and
547+ prefix2.isEmpty()
515548 }
516549
517550 pragma[nomagic]
@@ -781,17 +814,6 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
781814 prefix2.isEmpty() and
782815 s = getRangeType(n1)
783816 )
784- or
785- exists(ClosureExpr ce, int index |
786- n1 = ce and
787- n2 = ce.getParam(index).getPat() and
788- prefix1 = closureParameterPath(ce.getNumberOfParams(), index) and
789- prefix2.isEmpty()
790- )
791- or
792- n1.(ClosureExpr).getClosureBody() = n2 and
793- prefix1 = closureReturnPath() and
794- prefix2.isEmpty()
795817}
796818
797819/**
@@ -828,6 +850,19 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) {
828850 prefix.isEmpty()
829851}
830852
853+ private Type inferUnknownTypeFromAnnotation(AstNode n, TypePath path) {
854+ inferType(n, path) = TUnknownType() and
855+ // Normally, these are coercion sites, but in case a type is unknown we
856+ // allow for type information to flow from the type annotation.
857+ exists(TypeMention tm | result = tm.resolveTypeAt(path) |
858+ tm = any(LetStmt let | identLetStmt(let, _, n)).getTypeRepr()
859+ or
860+ tm = any(ClosureExpr ce | n = ce.getBody()).getRetType().getTypeRepr()
861+ or
862+ tm = getReturnTypeMention(any(Function f | n = f.getBody()))
863+ )
864+ }
865+
831866/**
832867 * Holds if the type tree of `n1` at `prefix1` should be equal to the type tree
833868 * of `n2` at `prefix2`, but type information should only propagate from `n1` to
@@ -1509,6 +1544,8 @@ private module MethodResolution {
15091544 * or
15101545 * 4. `MethodCallOperation`: an operation expression, `x + y`, which is syntactic sugar
15111546 * for `Add::add(x, y)`.
1547+ * 5. `ClosureMethodCall`: a call to a closure, `c(x)`, which is syntactic sugar for
1548+ * `c.call_once(x)`, `c.call_mut(x)`, or `c.call(x)`.
15121549 *
15131550 * Note that only in case 1 and 2 is auto-dereferencing and borrowing allowed.
15141551 *
@@ -1520,7 +1557,7 @@ private module MethodResolution {
15201557 abstract class MethodCall extends Expr {
15211558 abstract predicate hasNameAndArity(string name, int arity);
15221559
1523- abstract Expr getArg(ArgumentPosition pos);
1560+ abstract AstNode getArg(ArgumentPosition pos);
15241561
15251562 abstract predicate supportsAutoDerefAndBorrow();
15261563
@@ -1888,6 +1925,16 @@ private module MethodResolution {
18881925 )
18891926 }
18901927
1928+ private Method testresolveCallTarget(
1929+ ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow
1930+ ) {
1931+ this = Debug::getRelevantLocatable() and
1932+ exists(MethodCallCand mcc |
1933+ mcc = MkMethodCallCand(this, derefChain, borrow) and
1934+ result = mcc.resolveCallTarget(i)
1935+ )
1936+ }
1937+
18911938 /**
18921939 * Holds if the argument `arg` of this call has been implicitly dereferenced
18931940 * and borrowed according to `derefChain` and `borrow`, in order to be able to
@@ -2050,6 +2097,26 @@ private module MethodResolution {
20502097 override Trait getTrait() { super.isOverloaded(result, _, _) }
20512098 }
20522099
2100+ private class ClosureMethodCall extends MethodCall instanceof CallExprImpl::DynamicCallExpr {
2101+ pragma[nomagic]
2102+ override predicate hasNameAndArity(string name, int arity) {
2103+ name = "call_once" and // todo: handle call_mut and call
2104+ arity = 1 // args are passed in a tuple
2105+ }
2106+
2107+ override AstNode getArg(ArgumentPosition pos) {
2108+ pos.isSelf() and
2109+ result = super.getFunction()
2110+ or
2111+ pos.asPosition() = 0 and
2112+ result = super.getArgList()
2113+ }
2114+
2115+ override predicate supportsAutoDerefAndBorrow() { any() }
2116+
2117+ override Trait getTrait() { result instanceof AnyFnTrait }
2118+ }
2119+
20532120 pragma[nomagic]
20542121 private Method getMethodSuccessor(ImplOrTraitItemNode i, string name, int arity) {
20552122 result = i.getASuccessor(name) and
@@ -2471,7 +2538,8 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
24712538 class Access extends MethodCallFinal, ContextTyping::ContextTypedCallCand {
24722539 Access() {
24732540 // handled in the `OperationMatchingInput` module
2474- not this instanceof Operation
2541+ not this instanceof Operation //and
2542+ // this = Debug::getRelevantLocatable()
24752543 }
24762544
24772545 pragma[nomagic]
@@ -2523,6 +2591,16 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
25232591 result = this.getInferredNonSelfType(apos, path)
25242592 }
25252593
2594+ private Type testgetInferredType(string derefChainBorrow, AccessPosition apos, TypePath path) {
2595+ this = Debug::getRelevantLocatable() and
2596+ (
2597+ result = this.getInferredSelfType(apos, derefChainBorrow, path)
2598+ or
2599+ result = this.getInferredNonSelfType(apos, path) and
2600+ derefChainBorrow = ""
2601+ )
2602+ }
2603+
25262604 Method getTarget(ImplOrTraitItemNode i, string derefChainBorrow) {
25272605 exists(DerefChain derefChain, BorrowKind borrow |
25282606 derefChainBorrow = encodeDerefChainBorrow(derefChain, borrow) and
@@ -2596,6 +2674,7 @@ pragma[nomagic]
25962674private Type inferMethodCallTypeSelf(
25972675 AstNode n, DerefChain derefChain, BorrowKind borrow, TypePath path
25982676) {
2677+ // n = Debug::getRelevantLocatable() and
25992678 exists(MethodCallMatchingInput::AccessPosition apos, string derefChainBorrow |
26002679 result = inferMethodCallType0(_, apos, n, derefChainBorrow, path) and
26012680 apos.isSelf() and
@@ -2639,6 +2718,11 @@ private Type inferMethodCallTypePreCheck(AstNode n, boolean isReturn, TypePath p
26392718 isReturn = false
26402719}
26412720
2721+ private Type testinferMethodCallTypePreCheck(AstNode n, boolean isReturn, TypePath path) {
2722+ result = inferMethodCallTypePreCheck(n, isReturn, path) and
2723+ n = Debug::getRelevantLocatable()
2724+ }
2725+
26422726/**
26432727 * Gets the type of `n` at `path`, where `n` is either a method call or an
26442728 * argument/receiver of a method call.
@@ -3137,6 +3221,7 @@ private module NonMethodCallMatchingInput implements MatchingInputSig {
31373221 }
31383222
31393223 class Access extends NonMethodResolution::NonMethodCall, ContextTyping::ContextTypedCallCand {
3224+ // Access() { this = Debug::getRelevantLocatable() }
31403225 pragma[nomagic]
31413226 override Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
31423227 result = getCallExprTypeArgument(this, apos, path)
@@ -3210,6 +3295,12 @@ private Type inferNonMethodCallType0(AstNode n, boolean isReturn, TypePath path)
32103295 )
32113296}
32123297
3298+ pragma[nomagic]
3299+ private Type inferNonMethodCallType1(AstNode n, boolean isReturn, TypePath path) {
3300+ result = inferNonMethodCallType0(n, isReturn, path) and
3301+ n = Debug::getRelevantLocatable()
3302+ }
3303+
32133304private predicate inferNonMethodCallType =
32143305 ContextTyping::CheckContextTyping<inferNonMethodCallType0/3>::check/2;
32153306
@@ -3892,73 +3983,39 @@ private TypePath closureParameterPath(int arity, int index) {
38923983 TypePath::singleton(getTupleTypeParameter(arity, index)))
38933984}
38943985
3895- /** Gets the path to the return type of the `FnOnce` trait. */
3896- private TypePath fnReturnPath() {
3897- result = TypePath::singleton(getAssociatedTypeTypeParameter(any(FnOnceTrait t).getOutputType()))
3898- }
3899-
3900- /**
3901- * Gets the path to the parameter type of the `FnOnce` trait with arity `arity`
3902- * and index `index`.
3903- */
3904- pragma[nomagic]
3905- private TypePath fnParameterPath(int arity, int index) {
3906- result =
3907- TypePath::cons(TTypeParamTypeParameter(any(FnOnceTrait t).getTypeParam()),
3908- TypePath::singleton(getTupleTypeParameter(arity, index)))
3909- }
3910-
39113986pragma[nomagic]
3912- private Type inferDynamicCallExprType(Expr n, TypePath path) {
3913- exists(InvokedClosureExpr ce |
3914- // Propagate the function's return type to the call expression
3915- exists(TypePath path0 | result = invokedClosureFnTypeAt(ce, path0) |
3916- n = ce.getCall() and
3917- path = path0.stripPrefix(fnReturnPath())
3987+ private Type inferClosureExprType(AstNode n, TypePath path) {
3988+ exists(ClosureExpr ce |
3989+ n = ce and
3990+ (
3991+ path.isEmpty() and
3992+ result = closureRootType()
3993+ or
3994+ path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and
3995+ result.(TupleType).getArity() = ce.getNumberOfParams()
39183996 or
3919- // Propagate the function's parameter type to the arguments
3920- exists(int index |
3921- n = ce.getCall().getSyntacticPositionalArgument(index) and
3922- path =
3923- path0.stripPrefix(fnParameterPath(ce.getCall().getArgList().getNumberOfArgs(), index))
3997+ exists(TypePath path0 |
3998+ result = ce.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path0) and
3999+ path = closureReturnPath().append(path0)
39244000 )
39254001 )
39264002 or
3927- // _If_ the invoked expression has the type of a closure, then we propagate
3928- // the surrounding types into the closure.
3929- exists(int arity, TypePath path0 | ce.getTypeAt(TypePath::nil()) = closureRootType() |
3930- // Propagate the type of arguments to the parameter types of closure
3931- exists(int index, ArgList args |
3932- n = ce and
3933- args = ce.getCall().getArgList() and
3934- arity = args.getNumberOfArgs() and
3935- result = inferType(args.getArg(index), path0) and
3936- path = closureParameterPath(arity, index).append(path0)
3937- )
3938- or
3939- // Propagate the type of the call expression to the return type of the closure
3940- n = ce and
3941- arity = ce.getCall().getArgList().getNumberOfArgs() and
3942- result = inferType(ce.getCall(), path0) and
3943- path = closureReturnPath().append(path0)
4003+ exists(Param p |
4004+ p = ce.getAParam() and
4005+ not p.hasTypeRepr() and
4006+ n = p.getPat() and
4007+ result = TUnknownType() and
4008+ path.isEmpty()
39444009 )
39454010 )
39464011}
39474012
39484013pragma[nomagic]
3949- private Type inferClosureExprType(AstNode n, TypePath path) {
3950- exists(ClosureExpr ce |
3951- n = ce and
3952- path.isEmpty() and
3953- result = closureRootType()
3954- or
3955- n = ce and
3956- path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and
3957- result.(TupleType).getArity() = ce.getNumberOfParams()
3958- or
3959- // Propagate return type annotation to body
3960- n = ce.getClosureBody() and
3961- result = ce.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path)
4014+ private TupleType inferArgList(ArgList args, TypePath path) {
4015+ exists(CallExprImpl::DynamicCallExpr dce |
4016+ args = dce.getArgList() and
4017+ result.getArity() = dce.getNumberOfSyntacticArguments() and
4018+ path.isEmpty()
39624019 )
39634020}
39644021
@@ -4005,7 +4062,9 @@ private module Cached {
40054062 or
40064063 i instanceof ImplItemNode and dispatch = false
40074064 |
4008- result = call.(MethodResolution::MethodCall).resolveCallTarget(i, _, _) or
4065+ result = call.(MethodResolution::MethodCall).resolveCallTarget(i, _, _) and
4066+ not call instanceof CallExprImpl::DynamicCallExpr
4067+ or
40094068 result = call.(NonMethodResolution::NonMethodCall).resolveCallTargetViaTypeInference(i)
40104069 )
40114070 }
@@ -4115,13 +4174,15 @@ private module Cached {
41154174 or
41164175 result = inferForLoopExprType(n, path)
41174176 or
4118- result = inferDynamicCallExprType(n, path)
4119- or
41204177 result = inferClosureExprType(n, path)
41214178 or
4179+ result = inferArgList(n, path)
4180+ or
41224181 result = inferStructPatType(n, path)
41234182 or
41244183 result = inferTupleStructPatType(n, path)
4184+ or
4185+ result = inferUnknownTypeFromAnnotation(n, path)
41254186 )
41264187 }
41274188}
@@ -4138,8 +4199,8 @@ private module Debug {
41384199 Locatable getRelevantLocatable() {
41394200 exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
41404201 result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
4141- filepath.matches("%/sqlx .rs") and
4142- startline = [56 .. 60 ]
4202+ filepath.matches("%/closure .rs") and
4203+ startline = [10 ]
41434204 )
41444205 }
41454206
0 commit comments