Skip to content

Commit 1c20541

Browse files
committed
wip2
1 parent a5dab5c commit 1c20541

1 file changed

Lines changed: 56 additions & 55 deletions

File tree

‎unified/ql/lib/codeql/unified/internal/typeinference/TypeInference.qll‎

Lines changed: 56 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ module Input3 implements InputSig3 {
138138
Expr() {
139139
isInAssignmentContext(this, _) or
140140
hasResultValue(this) or
141-
this = any(CallExpr ce).getCallee() or
142-
this = any(Expr e).(MemberAccessExpr).getBase()
141+
this = Construction::getConstructionReceiver(_)
143142
}
144143
}
145144

@@ -455,31 +454,31 @@ module Input3 implements InputSig3 {
455454

456455
Callable getEnclosingCallable(AstNode node) { result.asCallable() = node.getEnclosingCallable() }
457456

458-
private newtype CallKind =
459-
Invoke() or
460-
Constructor() or
461-
Ordinary()
462-
463457
class InvocationResolutionContext = Unit;
464458

465-
class Invocation extends Expr, CallExpr {
466-
TypeMention getReceiverTypeMention() {
467-
result = super.getCallee()
468-
or
469-
not super.getCallee() instanceof TypeMention and
470-
result = super.getCallee().(MemberAccessExpr).getBase()
471-
}
459+
private TypeMention getQualifierTypeMention(CallExpr ce) {
460+
result = ce.getCallee()
461+
or
462+
not ce.getCallee() instanceof TypeMention and
463+
result = ce.getCallee().(MemberAccessExpr).getBase()
464+
}
472465

473-
Type getTypeQualifier(TypePath path) { result = this.getReceiverTypeMention().getTypeAt(path) }
466+
class Invocation extends Expr, CallExpr {
467+
Type getTypeQualifier(TypePath path) { result = getQualifierTypeMention(this).getTypeAt(path) }
474468

475469
Type getTypeArgument(int i, TypePath path) { none() }
476470

477471
Expr getArgument(int i) {
478472
i = 0 and
479-
exists(CallKind kind | exists(this.getTargetImpl(kind)) |
480-
if kind = [Invoke().(CallKind), Constructor()]
481-
then result = CallExpr.super.getCallee()
482-
else result = CallExpr.super.getCallee().(MemberAccessExpr).getBase()
473+
(
474+
result = Construction::getConstructionReceiver(this)
475+
or
476+
not exists(Construction::getConstructionReceiver(this)) and
477+
exists(boolean isFunctionExprInvoke | exists(this.getTargetImpl(isFunctionExprInvoke)) |
478+
if isFunctionExprInvoke = true
479+
then result = CallExpr.super.getCallee()
480+
else result = CallExpr.super.getCallee().(MemberAccessExpr).getBase()
481+
)
483482
)
484483
or
485484
result = CallExpr.super.getArgument(i - 1).getValue()
@@ -492,41 +491,40 @@ module Input3 implements InputSig3 {
492491
result = getFunctionInvoke(t)
493492
}
494493

495-
Callable getTargetViaStaticNameBinding(CallKind kind) {
494+
Callable getTargetViaStaticNameBinding() {
496495
exists(NameBinding b | b = getStaticBindingTargetFromRef(this.getCallee()) |
497496
// object creation (including enum constructors): `String(42)`, `Optional.Some(42)`
498497
exists(ClassLikeDeclaration cls |
499498
cls.getNameNode() = b and
500499
result.isInstanceMemberOf(cls, _) and
501-
result.asCallable() instanceof ConstructorDeclaration and
502-
kind = Constructor()
500+
result.asCallable() instanceof ConstructorDeclaration
503501
)
504502
or
505503
// call without explicit receiver: `foo(42)`
506-
result.getNameNode() = b and
507-
kind = Ordinary()
504+
result.getNameNode() = b
508505
)
509506
}
510507

511-
Callable getTargetImpl(CallKind kind) {
508+
Callable getTargetImpl(boolean isFunctionExprInvoke) {
512509
// mutual recursion; call with explicit receiver: `obj.foo(42)`
513510
result = lookupInstanceMember(this.getCallee()) and
514-
kind = Ordinary()
511+
isFunctionExprInvoke = false
515512
or
516513
// mutual recursion; call to a function expression: `callback(42)`
517514
result.asCallable() = this.getInvokeTarget(_) and
518-
kind = Invoke()
515+
isFunctionExprInvoke = true
519516
or
520517
// no mutual recursion; can be resolved directly with static name binding
521-
result = this.getTargetViaStaticNameBinding(kind)
518+
result = this.getTargetViaStaticNameBinding() and
519+
isFunctionExprInvoke = false
522520
}
523521

524522
Callable getTarget(InvocationResolutionContext c) {
525523
result = this.getTargetImpl(_) and
526524
exists(c)
527525
}
528526

529-
Callable getATargetForTypeQualifierMatching() { result = this.getTargetViaStaticNameBinding(_) }
527+
Callable getATargetForTypeQualifierMatching() { result = this.getTargetViaStaticNameBinding() }
530528
}
531529

532530
Type inferInvocationArgumentType(
@@ -547,10 +545,8 @@ module Input3 implements InputSig3 {
547545
)
548546
or
549547
// A non-function-expression call
550-
exists(CallKind kind |
551-
exists(invocation.getTargetImpl(kind)) and
552-
kind != Invoke()
553-
|
548+
exists(invocation.getTargetImpl(false)) and
549+
(
554550
result = inferType(invocation.getArgument(i), path)
555551
or
556552
i = 0 and
@@ -620,7 +616,7 @@ module Input3 implements InputSig3 {
620616
}
621617

622618
/**
623-
* Provides logic for resolving the types of constructor invocations.
619+
* Provides logic for resolving types of constructor invocations.
624620
*
625621
* Constructors are treated as instance methods without return types, in order
626622
* to be able to handle inherited constructors similar to ordinary instance
@@ -650,11 +646,26 @@ module Input3 implements InputSig3 {
650646
* (3) The receiver has type `B<Int>`, and no further type inference is needed.
651647
*/
652648
private module Construction {
653-
private TypeMention getAReceiverTypeMention() {
654-
exists(Invocation invocation |
655-
invocation.getTargetViaStaticNameBinding(_).asCallable() instanceof ConstructorDeclaration and
656-
result = invocation.getReceiverTypeMention()
657-
)
649+
/**
650+
* Gets the AST node that is used to represent the receiver in a constructor
651+
* invocation.
652+
*/
653+
TypeMention getConstructionReceiver(Invocation invocation) {
654+
invocation.getTargetViaStaticNameBinding().asCallable() instanceof ConstructorDeclaration and
655+
result = getQualifierTypeMention(invocation)
656+
}
657+
658+
/**
659+
* Gets the inferred type at `path` of the object constructed at `i` using constructor
660+
* `cd`. Because of how we handle constructors as instance methods without return types,
661+
* this is simply the inferred type of the receiver.
662+
*
663+
* Note that this works for both calls without an actual receiver, `A.init(0)` or `A(0)`,
664+
* as well as calls with a receiver, `self.init(0)` or `super.init(0)`.
665+
*/
666+
private Type inferConstructionType(Invocation i, ConstructorDeclaration cd, TypePath path) {
667+
cd = i.getTargetImpl(_).asCallable() and
668+
result = inferType(i.getArgument(0), path)
658669
}
659670

660671
/**
@@ -687,16 +698,6 @@ module Input3 implements InputSig3 {
687698
private module ContextualConstructorReturnType =
688699
M3::ContextualTyping::ContextualReturnType<ContextualConstructorReturnTypeInput>;
689700

690-
/**
691-
* Gets the inferred type at `path` of the object constructed at `i` using constructor
692-
* `cd`. Because of how we handle constructors as instance methods without return types,
693-
* this is simply the inferred type of the receiver.
694-
*/
695-
private Type inferConstructionType(Invocation i, ConstructorDeclaration cd, TypePath path) {
696-
cd = i.getTargetImpl(_).asCallable() and
697-
result = inferType(i.getArgument(0), path)
698-
}
699-
700701
private predicate needsContextualTyping(Invocation i, TypePath path) {
701702
exists(ConstructorDeclaration cd, ClassLikeDeclaration declType, TypePath path0 |
702703
declType =
@@ -719,11 +720,11 @@ module Input3 implements InputSig3 {
719720
}
720721

721722
Type inferConstructionType(AstNode n, TypePath path) {
722-
exists(TypeMention tm |
723-
n = tm and
724-
tm = getAReceiverTypeMention() and
725-
result = tm.getTypeAt(path)
726-
)
723+
n =
724+
any(TypeMention tm |
725+
tm = getConstructionReceiver(_) and
726+
result = tm.getTypeAt(path)
727+
)
727728
or
728729
result = inferConstructionType(n, _, path)
729730
or
@@ -734,7 +735,7 @@ module Input3 implements InputSig3 {
734735
predicate allowFullContextualInference(TypeMention tm, TypePath path) {
735736
// For a construction such as `Optional.some(0)`, we need contextual inference
736737
// to infer the type of the wrapped object
737-
tm = getAReceiverTypeMention() and
738+
tm = getConstructionReceiver(_) and
738739
exists(TypePath prefix, Type t, TypeParameter tp |
739740
t = tm.getTypeAt(prefix) and
740741
not t instanceof UnknownType and

0 commit comments

Comments
 (0)