Skip to content

Commit a95a619

Browse files
committed
wip3
1 parent 3629bb7 commit a95a619

2 files changed

Lines changed: 58 additions & 100 deletions

File tree

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

Lines changed: 44 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -352,15 +352,6 @@ private module Input3 implements InputSig3 {
352352
AstNode getExpr() { result = super.getExpr() }
353353
}
354354

355-
/** A ternary conditional expression. */
356-
class ConditionalExpr extends AstNode, IfExpr {
357-
AstNode getCondition() { result = super.getCondition() }
358-
359-
AstNode getThen() { result = super.getThen() }
360-
361-
AstNode getElse() { result = super.getElse() }
362-
}
363-
364355
predicate certainTypeEqualityInput(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
365356
n1 =
366357
any(IdentPat ip |
@@ -392,65 +383,10 @@ private module Input3 implements InputSig3 {
392383

393384
predicate inferCertainTypeInput = CertainTypeInferenceInput::inferCertainTypeInput/2;
394385

395-
/**
396-
* Holds if `child` is a child of `parent`, and the Rust compiler applies [least
397-
* upper bound (LUB) coercion][1] to infer the type of `parent` from the type of
398-
* `child`.
399-
*
400-
* In this case, we want type information to only flow from `child` to `parent`,
401-
* to avoid (a) either having to model LUB coercions, or (b) risk combinatorial
402-
* explosion in inferred types.
403-
*
404-
* [1]: https://doc.rust-lang.org/reference/type-coercions.html#r-coerce.least-upper-bound
405-
*/
406-
predicate lubCoercionInput(AstNode parent, AstNode child, TypePath prefix) {
407-
parent =
408-
any(MatchExpr me |
409-
child = me.getAnArm().getExpr() and
410-
me.getNumberOfArms() > 1
411-
) and
412-
prefix.isEmpty()
413-
or
414-
parent =
415-
any(ArrayListExpr ale |
416-
child = ale.getAnExpr() and
417-
ale.getNumberOfExprs() > 1
418-
) and
419-
prefix = TypePath::singleton(getArrayTypeParameter())
420-
or
421-
bodyReturns(parent, child) and
422-
strictcount(Expr e | bodyReturns(parent, e)) > 1 and
423-
prefix.isEmpty()
424-
or
425-
parent = any(ClosureExpr ce | not ce.hasRetType() and ce.getClosureBody() = child) and
426-
prefix = closureReturnPath()
427-
or
428-
exists(Struct s |
429-
child = [parent.(RangeExpr).getStart(), parent.(RangeExpr).getEnd()] and
430-
prefix = TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and
431-
s = getRangeType(parent)
432-
)
433-
}
434-
435-
predicate typeEqualityAsymmetricInput(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
436-
// When `n2` is `*n1` propagate type information from a raw pointer type
437-
// parameter at `n1`. The other direction is handled in
438-
// `inferDereferencedExprPtrType`.
439-
n1 = n2.(DerefExpr).getExpr() and
440-
prefix1 = TypePath::singleton(getPtrTypeParameter()) and
441-
prefix2.isEmpty()
442-
}
443-
444386
predicate typeEqualityInput(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
445387
prefix1.isEmpty() and
446388
prefix2.isEmpty() and
447389
(
448-
n2 =
449-
any(MatchExpr me |
450-
n1 = me.getAnArm().getExpr() and
451-
me.getNumberOfArms() = 1
452-
)
453-
or
454390
exists(MatchExpr me |
455391
n1 = me.getScrutinee() and
456392
n2 = me.getAnArm().getPat()
@@ -471,9 +407,6 @@ private module Input3 implements InputSig3 {
471407
not isPanicMacroCall(n2)
472408
or
473409
n1 = n2.(MacroPat).getMacroCall().getMacroCallExpansion()
474-
or
475-
bodyReturns(n1, n2) and
476-
strictcount(Expr e | bodyReturns(n1, e)) = 1
477410
)
478411
or
479412
n2 =
@@ -516,21 +449,56 @@ private module Input3 implements InputSig3 {
516449
)
517450
)
518451
or
519-
// an array list expression with only one element (such as `[1]`) has type from that element
520-
n1 =
521-
any(ArrayListExpr ale |
522-
ale.getAnExpr() = n2 and
523-
ale.getNumberOfExprs() = 1
524-
) and
525-
prefix1 = TypePath::singleton(getArrayTypeParameter()) and
526-
prefix2.isEmpty()
527-
or
528452
// an array repeat expression (`[1; 3]`) has the type of the repeat operand
529453
n1.(ArrayRepeatExpr).getRepeatOperand() = n2 and
530454
prefix1 = TypePath::singleton(getArrayTypeParameter()) and
531455
prefix2.isEmpty()
532456
}
533457

458+
predicate typeEqualityAsymmetricInput(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
459+
// When `n2` is `*n1` propagate type information from a raw pointer type
460+
// parameter at `n1`. The other direction is handled in
461+
// `inferDereferencedExprPtrType`.
462+
n1 = n2.(DerefExpr).getExpr() and
463+
prefix1 = TypePath::singleton(getPtrTypeParameter()) and
464+
prefix2.isEmpty()
465+
or
466+
n2 = any(ClosureExpr ce | not ce.hasRetType() and ce.getClosureBody() = n1) and
467+
prefix2 = closureReturnPath() and
468+
prefix1.isEmpty()
469+
}
470+
471+
/**
472+
* Holds if `child` is a child of `parent`, and the Rust compiler applies [least
473+
* upper bound (LUB) coercion][1] to infer the type of `parent` from the type of
474+
* `child`.
475+
*
476+
* In this case, we want type information to only flow from `child` to `parent`,
477+
* to avoid (a) either having to model LUB coercions, or (b) risk combinatorial
478+
* explosion in inferred types.
479+
*
480+
* [1]: https://doc.rust-lang.org/reference/type-coercions.html#r-coerce.least-upper-bound
481+
*/
482+
predicate parentChildType(AstNode parent, AstNode child, TypePath prefix) {
483+
child = parent.(IfExpr).getABranch() and
484+
prefix.isEmpty()
485+
or
486+
parent = any(MatchExpr me | child = me.getAnArm().getExpr()) and
487+
prefix.isEmpty()
488+
or
489+
parent = any(ArrayListExpr ale | child = ale.getAnExpr()) and
490+
prefix = TypePath::singleton(getArrayTypeParameter())
491+
or
492+
bodyReturns(parent, child) and
493+
prefix.isEmpty()
494+
or
495+
exists(Struct s |
496+
child = [parent.(RangeExpr).getStart(), parent.(RangeExpr).getEnd()] and
497+
prefix = TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and
498+
s = getRangeType(parent)
499+
)
500+
}
501+
534502
Type inferTypeInput(AstNode n, TypePath path) {
535503
result = inferAssignmentOperationType(n, path)
536504
or

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

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,18 +2199,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21992199
AstNode getExpr();
22002200
}
22012201

2202-
/** A ternary conditional expression. */
2203-
class ConditionalExpr extends AstNode {
2204-
/** Gets the condition of this expression. */
2205-
AstNode getCondition();
2206-
2207-
/** Gets the true branch of this expression. */
2208-
AstNode getThen();
2209-
2210-
/** Gets the false branch of this expression. */
2211-
AstNode getElse();
2212-
}
2213-
22142202
/**
22152203
* Holds if the types of `n1` at `path1` and `n2` at `path2` are certainly equal.
22162204
*/
@@ -2220,14 +2208,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22202208
Type inferCertainTypeInput(AstNode n, TypePath path);
22212209

22222210
/**
2223-
* Holds if `child` is a child of `parent`, and a least upper bound (LUB) coercion
2224-
* may be applied to infer the type of `parent` from the type of `child`.
2225-
*
2226-
* In this case, we want type information to only flow from `child` to `parent`,
2227-
* to avoid (a) either having to model LUB coercions, or (b) risk combinatorial
2228-
* explosion in inferred types.
2211+
* Holds if the types of `n1` at `path1` and `n2` at `path2` are possibly equal,
2212+
* and type information should be allowed to flow in both directions between them.
22292213
*/
2230-
predicate lubCoercionInput(AstNode parent, AstNode child, TypePath prefix);
2214+
predicate typeEqualityInput(AstNode n1, TypePath path1, AstNode n2, TypePath path2);
22312215

22322216
/**
22332217
* Holds if the type tree of `n1` at `path1` should be equal to the type tree
@@ -2237,9 +2221,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22372221
predicate typeEqualityAsymmetricInput(AstNode n1, TypePath path1, AstNode n2, TypePath path2);
22382222

22392223
/**
2240-
* Holds if the types of `n1` at `path1` and `n2` at `path2` are possibly equal.
2224+
* Holds if `child` is a child of `parent` and the type of `parent` at `prefix` can be
2225+
* inferred from the type of `child`.
2226+
*
2227+
* When `child` is unique, we also allow type information to flow from `parent` to `child`.
22412228
*/
2242-
predicate typeEqualityInput(AstNode n1, TypePath path1, AstNode n2, TypePath path2);
2229+
predicate parentChildType(AstNode parent, AstNode child, TypePath prefix);
22432230

22442231
/** Gets the inferred type of `n` at `path`. */
22452232
Type inferTypeInput(AstNode n, TypePath path);
@@ -2355,13 +2342,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23552342
)
23562343
or
23572344
typeEqualityInput(n1, path1, n2, path2)
2345+
or
2346+
n2 = unique(AstNode child | parentChildType(n1, child, path1) | child) and
2347+
path2.isEmpty()
23582348
}
23592349

23602350
private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) {
2361-
parent = any(ConditionalExpr ce | child = [ce.getThen(), ce.getElse()]) and
2362-
prefix.isEmpty()
2351+
parentChildType(parent, child, prefix) and
2352+
strictcount(AstNode child0 | parentChildType(parent, child0, prefix) | child0) > 1
23632353
or
2364-
lubCoercionInput(parent, child, prefix)
2354+
typeEqualityAsymmetricInput(child, TypePath::nil(), parent, prefix)
23652355
}
23662356

23672357
private predicate typeEqualityAsymmetric(

0 commit comments

Comments
 (0)