Skip to content

Commit ba8029f

Browse files
committed
wip5
1 parent 1ba70d6 commit ba8029f

2 files changed

Lines changed: 87 additions & 110 deletions

File tree

rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll

Lines changed: 53 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,6 @@ private module Input3 implements InputSig3 {
284284
(exists(resolveTupleFieldExpr(_, _)) implies any())
285285
}
286286

287-
predicate inferType = M3::inferType/2;
288-
289287
class BoolType extends DataType {
290288
BoolType() { this.getTypeItem() instanceof Builtins::Bool }
291289
}
@@ -480,22 +478,25 @@ private module Input3 implements InputSig3 {
480478
)
481479
or
482480
exists(CallExprImpl::DynamicCallExpr dce, TupleType tt, int i |
481+
n1 = dce.getSyntacticPositionalArgument(i) and
483482
n2 = dce.getArgList() and
484483
tt.getArity() = dce.getNumberOfSyntacticArguments() and
485-
n1 = dce.getSyntacticPositionalArgument(i) and
486-
path2 = TypePath::singleton(tt.getPositionalTypeParameter(i)) and
487-
path1.isEmpty()
484+
path1.isEmpty() and
485+
path2 = TypePath::singleton(tt.getPositionalTypeParameter(i))
488486
)
489487
or
490488
exists(ClosureExpr ce, int index |
491-
n2 = ce and
492489
n1 = ce.getParam(index).getPat() and
493-
path2 = closureParameterPath(ce.getNumberOfParams(), index) and
494-
path1.isEmpty()
490+
n2 = ce and
491+
path1.isEmpty() and
492+
path2 = closureParameterPath(ce.getNumberOfParams(), index)
495493
)
496494
}
497495

498-
Type inferTypeCertainSpecific(AstNode n, TypePath path) {
496+
pragma[inline]
497+
Type inferTypeCertain(AstNode n, TypePath path) {
498+
result = M3::inferTypeCertain(n, path)
499+
or
499500
result = inferLiteralType(n, path, true)
500501
or
501502
result = inferRefPatType(n) and
@@ -539,55 +540,64 @@ private module Input3 implements InputSig3 {
539540
path2.isEmpty()
540541
or
541542
n2 = any(ClosureExpr ce | not ce.hasRetType() and ce.getClosureBody() = n1) and
542-
path2 = closureReturnPath() and
543-
path1.isEmpty()
543+
path1.isEmpty() and
544+
path2 = closureReturnPath()
544545
or
545546
path1.isEmpty() and
546547
(
547548
n1 = n2.(ArrayListExpr).getAnExpr() and
548549
path2 = TypePath::singleton(getArrayTypeParameter())
549550
or
550-
exists(ReturnExpr re, Rust::Callable c |
551-
n1 = re.getExpr() and
552-
c = re.getEnclosingCallable() and
553-
n2 = c.getBody() and
554-
path2.isEmpty()
555-
)
556-
or
557551
exists(Struct s |
558552
n1 = [n2.(RangeExpr).getStart(), n2.(RangeExpr).getEnd()] and
559553
path2 =
560554
TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and
561555
s = getRangeType(n2)
562556
)
563-
)
564-
or
565-
path1.isEmpty() and
566-
path2.isEmpty() and
567-
(
568-
n2 = n1.(OrPat).getAPat()
569-
or
570-
n2 = n1.(ParenPat).getPat()
571557
or
572-
n2 = n1.(LiteralPat).getLiteral()
558+
n2 =
559+
any(RefExpr re |
560+
n1 = re.getExpr() and
561+
path2 = TypePath::singleton(inferRefExprType(re).getPositionalTypeParameter(0))
562+
)
573563
or
574-
exists(BreakExpr break |
575-
break.getExpr() = n1 and
576-
break.getTarget() = n2.(LoopExpr)
564+
exists(BlockExpr be |
565+
n2 = be and
566+
n1 = be.getStmtList().getTailExpr() and
567+
if be.isAsync()
568+
then path2 = TypePath::singleton(getDynFutureOutputTypeParameter())
569+
else path2.isEmpty()
577570
)
578571
or
579-
n1 = n2.(MacroExpr).getMacroCall().getMacroCallExpansion() and
580-
not isPanicMacroCall(n2)
572+
// an array repeat expression (`[1; 3]`) has the type of the repeat operand
573+
n2.(ArrayRepeatExpr).getRepeatOperand() = n1 and
574+
path2 = TypePath::singleton(getArrayTypeParameter())
581575
or
582-
n1 = n2.(MacroPat).getMacroCall().getMacroCallExpansion()
583-
)
584-
or
585-
n2 =
586-
any(RefExpr re |
587-
n1 = re.getExpr() and
588-
path1.isEmpty() and
589-
path2 = TypePath::singleton(inferRefExprType(re).getPositionalTypeParameter(0))
576+
path2.isEmpty() and
577+
(
578+
exists(ReturnExpr re, Rust::Callable c |
579+
n1 = re.getExpr() and
580+
c = re.getEnclosingCallable() and
581+
n2 = c.getBody()
582+
)
583+
or
584+
n2 = n1.(OrPat).getAPat()
585+
or
586+
n2 = n1.(ParenPat).getPat()
587+
or
588+
n2 = n1.(LiteralPat).getLiteral()
589+
or
590+
exists(BreakExpr break |
591+
break.getExpr() = n1 and
592+
break.getTarget() = n2.(LoopExpr)
593+
)
594+
or
595+
n1 = n2.(MacroExpr).getMacroCall().getMacroCallExpansion() and
596+
not isPanicMacroCall(n2)
597+
or
598+
n1 = n2.(MacroPat).getMacroCall().getMacroCallExpansion()
590599
)
600+
)
591601
or
592602
n1 =
593603
any(RefPat rp |
@@ -611,24 +621,6 @@ private module Input3 implements InputSig3 {
611621
path2.isEmpty() and
612622
path1 = path
613623
)
614-
or
615-
exists(BlockExpr be |
616-
n2 = be and
617-
n1 = be.getStmtList().getTailExpr() and
618-
if be.isAsync()
619-
then
620-
path2 = TypePath::singleton(getDynFutureOutputTypeParameter()) and
621-
path1.isEmpty()
622-
else (
623-
path1.isEmpty() and
624-
path2.isEmpty()
625-
)
626-
)
627-
or
628-
// an array repeat expression (`[1; 3]`) has the type of the repeat operand
629-
n2.(ArrayRepeatExpr).getRepeatOperand() = n1 and
630-
path2 = TypePath::singleton(getArrayTypeParameter()) and
631-
path1.isEmpty()
632624
}
633625

634626
Type inferTypeTopDown(AstNode n, TypePath path) {
@@ -645,9 +637,9 @@ private module Input3 implements InputSig3 {
645637
result = inferFieldExprType(n, path, true)
646638
}
647639

648-
Type inferTypeSpecific(AstNode n, TypePath path) {
649-
// result = inferTypeCertainSpecific0(n, path)
650-
// or
640+
Type inferType(AstNode n, TypePath path) {
641+
result = M3::inferType(n, path)
642+
or
651643
isPanicMacroCall(n) and
652644
path.isEmpty() and
653645
result instanceof UnknownType
@@ -684,7 +676,6 @@ private module Input3 implements InputSig3 {
684676

685677
private module M3 = Make3<Input3>;
686678

687-
// import M3
688679
predicate inferType = M3::inferType/1;
689680

690681
predicate inferType = M3::inferType/2;
@@ -693,23 +684,6 @@ predicate inferTypeCertain = M3::inferTypeCertain/2;
693684

694685
module Consistency = M3::Consistency;
695686

696-
// {
697-
// import M2::Consistency
698-
// private Type inferTypeCertainAdj(AstNode n, TypePath path) {
699-
// result = inferTypeCertain(n, path) and
700-
// not result = TUnknownType()
701-
// }
702-
// predicate nonUniqueCertainType(AstNode n, TypePath path, Type t) {
703-
// strictcount(inferTypeCertainAdj(n, path)) > 1 and
704-
// t = inferTypeCertainAdj(n, path) and
705-
// // Suppress the inconsistency if `n` is a self parameter and the type
706-
// // mention for the self type has multiple types for a path.
707-
// not exists(ImplItemNode impl, TypePath selfTypePath |
708-
// n = impl.getAnAssocItem().(Function).getSelfParam() and
709-
// strictcount(impl.(Impl).getSelfTy().(TypeMention).getTypeAt(selfTypePath)) > 1
710-
// )
711-
// }
712-
// }
713687
/** A function without a `self` parameter. */
714688
private class NonMethodFunction extends Function {
715689
NonMethodFunction() { not this.hasSelfParam() }

shared/typeinference/codeql/typeinference/internal/TypeInference.qll

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,14 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
13611361
module MatchingWithEnvironment<MatchingWithEnvironmentInputSig Input> {
13621362
private import Input
13631363

1364+
pragma[nomagic]
1365+
private TypeParameter getDeclTypeParameter(Declaration decl, TypeArgumentPosition tapos) {
1366+
exists(TypeParameterPosition tppos |
1367+
result = decl.getTypeParameter(tppos) and
1368+
typeArgumentParameterPositionMatch(tapos, tppos)
1369+
)
1370+
}
1371+
13641372
/**
13651373
* Gets the type of the type argument at `path` in `a` that corresponds to
13661374
* the type parameter `tp` in `target`, if any.
@@ -1372,10 +1380,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
13721380
bindingset[a, target]
13731381
pragma[inline_late]
13741382
private Type getTypeArgument(Access a, Declaration target, TypeParameter tp, TypePath path) {
1375-
exists(TypeArgumentPosition tapos, TypeParameterPosition tppos |
1383+
exists(TypeArgumentPosition tapos |
13761384
result = a.getTypeArgument(tapos, path) and
1377-
tp = target.getTypeParameter(tppos) and
1378-
typeArgumentParameterPositionMatch(tapos, tppos) and
1385+
tp = getDeclTypeParameter(target, tapos) and
13791386
not result instanceof UnknownType //and path.isEmpty())
13801387
)
13811388
}
@@ -2036,13 +2043,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
20362043
*/
20372044
default predicate cacheRevRef() { none() }
20382045

2039-
/**
2040-
* Point this predicate to the `inferType` predicate from the output of this module.
2041-
*
2042-
* Needed to be able to refer to `inferType` in default signature implementations.
2043-
*/
2044-
Type inferType(AstNode n, TypePath path);
2045-
20462046
/** A boolean type. */
20472047
class BoolType extends Type;
20482048

@@ -2293,9 +2293,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22932293
/**
22942294
* Gets the inferred certain type of `n` at `path`.
22952295
*
2296-
* This predicate will be included directly in the exposed `inferTypeCertain` predicate.
2296+
* This predicate should include the `inferTypeCertain` predicate from the
2297+
* output of this module, as well as any language-specific additions.
22972298
*/
2298-
default Type inferTypeCertainSpecific(AstNode n, TypePath path) { none() }
2299+
Type inferTypeCertain(AstNode n, TypePath path);
22992300

23002301
/**
23012302
* Holds if `n1` having type `t` at `path1` implies that `n2` has type `t` at `path2`,
@@ -2304,19 +2305,20 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23042305
predicate inferStep(AstNode n1, TypePath path1, AstNode n2, TypePath path2);
23052306

23062307
/**
2307-
* Gets the top-down inferred type of `n` at `path`.
2308+
* Gets the inferred certain type of `n` at `path`.
23082309
*
2309-
* Type information is only propagated into nodes with an explicitly unknown
2310-
* type.
2310+
* This predicate should include the `inferType` predicate from the output of this module,
2311+
* as well as any language-specific additions.
23112312
*/
2312-
default Type inferTypeTopDown(AstNode n, TypePath path) { none() }
2313+
Type inferType(AstNode n, TypePath path);
23132314

23142315
/**
2315-
* Gets the inferred type of `n` at `path`.
2316+
* Gets the top-down inferred type of `n` at `path`.
23162317
*
2317-
* This predicate will be included directly in the exposed `inferType` predicate.
2318+
* Type information is only propagated into nodes with an explicitly unknown
2319+
* type.
23182320
*/
2319-
Type inferTypeSpecific(AstNode n, TypePath path);
2321+
default Type inferTypeTopDown(AstNode n, TypePath path) { none() }
23202322
}
23212323

23222324
module Make3<InputSig3 Input3> {
@@ -2371,12 +2373,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23712373
Type inferTypeCertain(AstNode n, TypePath path) {
23722374
(
23732375
CachedStage::ref() and
2376+
result = Input3::inferTypeCertain(n, path)
2377+
or
23742378
result = inferAnnotatedType(n, path)
23752379
or
23762380
result = inferTypeFromStepCertain(n, path)
23772381
or
2378-
result = inferTypeCertainSpecific(n, path)
2379-
or
23802382
result = inferLogicalOperationType(n, path)
23812383
or
23822384
infersCertainTypeAt(n, path, result.getATypeParameter())
@@ -2403,6 +2405,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
24032405
private predicate infersCertainTypeAt(AstNode n, TypePath prefix, TypeParameter tp) {
24042406
exists(TypePath path |
24052407
hasInferredCertainType(n, path) and
2408+
not path.isEmpty() and // implied by `isSnoc` below, but improves performance slightly
24062409
path.isSnoc(prefix, tp)
24072410
)
24082411
}
@@ -2481,6 +2484,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
24812484
}
24822485

24832486
private Type inferType0(AstNode n, TypePath path) {
2487+
result = Input3::inferType(n, path)
2488+
or
24842489
result = inferAnnotatedType(n, path)
24852490
or
24862491
exists(LocalVariableDeclaration decl |
@@ -2499,8 +2504,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
24992504
result = TopDownTyping<inferCallArgumentTypeTopDown/2>::inferType(n, path)
25002505
or
25012506
result = TopDownTyping<inferTypeTopDown/2>::inferType(n, path)
2502-
or
2503-
result = inferTypeSpecific(n, path)
25042507
}
25052508

25062509
/**
@@ -2521,26 +2524,26 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
25212524
not Certain::certainTypeConflict(n, prefix, path, result)
25222525
)
25232526
or
2524-
hasUnknownCertainTypeAt(n, path) and
2525-
result instanceof UnknownType
2526-
or
2527-
infersTypeAt(n, path, result.getATypeParameter())
2528-
}
2529-
2530-
private predicate hasUnknownCertainTypeAt(AstNode n, TypePath path) {
2527+
// If `n` has an explicitly unknown type at `prefix` and at the same time a certain
2528+
// type at `prefix.suffix`, then extend the unknown type information to any path
2529+
// extending `prefix.suffix` where there is no certain type information
25312530
exists(TypePath prefix, TypePath suffix, Type certain, TypeParameter tp |
25322531
inferType0(n, prefix) instanceof UnknownType and
25332532
certain = inferTypeCertain(n, prefix.appendInverse(suffix)) and
25342533
tp = certain.getATypeParameter() and
25352534
path = prefix.append(suffix).append(TypePath::singleton(tp)) and
2536-
not exists(inferTypeCertain(n, path))
2535+
not exists(inferTypeCertain(n, path)) and
2536+
result instanceof UnknownType
25372537
)
2538+
or
2539+
infersTypeAt(n, path, result.getATypeParameter())
25382540
}
25392541

25402542
pragma[nomagic]
25412543
private predicate infersTypeAt(AstNode n, TypePath prefix, TypeParameter tp) {
25422544
exists(TypePath path |
25432545
exists(inferType(n, path)) and
2546+
not path.isEmpty() and // implied by `isSnoc` below, but improves performance slightly
25442547
path.isSnoc(prefix, tp)
25452548
)
25462549
}

0 commit comments

Comments
 (0)