Skip to content

Commit 30be9c4

Browse files
committed
wip3
1 parent ff96c2b commit 30be9c4

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
@@ -2172,18 +2172,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21722172
AstNode getExpr();
21732173
}
21742174

2175-
/** A ternary conditional expression. */
2176-
class ConditionalExpr extends AstNode {
2177-
/** Gets the condition of this expression. */
2178-
AstNode getCondition();
2179-
2180-
/** Gets the true branch of this expression. */
2181-
AstNode getThen();
2182-
2183-
/** Gets the false branch of this expression. */
2184-
AstNode getElse();
2185-
}
2186-
21872175
/**
21882176
* Holds if the types of `n1` at `path1` and `n2` at `path2` are certainly equal.
21892177
*/
@@ -2193,14 +2181,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21932181
Type inferCertainTypeInput(AstNode n, TypePath path);
21942182

21952183
/**
2196-
* Holds if `child` is a child of `parent`, and a least upper bound (LUB) coercion
2197-
* may be applied to infer the type of `parent` from the type of `child`.
2198-
*
2199-
* In this case, we want type information to only flow from `child` to `parent`,
2200-
* to avoid (a) either having to model LUB coercions, or (b) risk combinatorial
2201-
* explosion in inferred types.
2184+
* Holds if the types of `n1` at `path1` and `n2` at `path2` are possibly equal,
2185+
* and type information should be allowed to flow in both directions between them.
22022186
*/
2203-
predicate lubCoercionInput(AstNode parent, AstNode child, TypePath prefix);
2187+
predicate typeEqualityInput(AstNode n1, TypePath path1, AstNode n2, TypePath path2);
22042188

22052189
/**
22062190
* Holds if the type tree of `n1` at `path1` should be equal to the type tree
@@ -2210,9 +2194,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22102194
predicate typeEqualityAsymmetricInput(AstNode n1, TypePath path1, AstNode n2, TypePath path2);
22112195

22122196
/**
2213-
* Holds if the types of `n1` at `path1` and `n2` at `path2` are possibly equal.
2197+
* Holds if `child` is a child of `parent` and the type of `parent` at `prefix` can be
2198+
* inferred from the type of `child`.
2199+
*
2200+
* When `child` is unique, we also allow type information to flow from `parent` to `child`.
22142201
*/
2215-
predicate typeEqualityInput(AstNode n1, TypePath path1, AstNode n2, TypePath path2);
2202+
predicate parentChildType(AstNode parent, AstNode child, TypePath prefix);
22162203

22172204
/** Gets the inferred type of `n` at `path`. */
22182205
Type inferTypeInput(AstNode n, TypePath path);
@@ -2328,13 +2315,16 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
23282315
)
23292316
or
23302317
typeEqualityInput(n1, path1, n2, path2)
2318+
or
2319+
n2 = unique(AstNode child | parentChildType(n1, child, path1) | child) and
2320+
path2.isEmpty()
23312321
}
23322322

23332323
private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) {
2334-
parent = any(ConditionalExpr ce | child = [ce.getThen(), ce.getElse()]) and
2335-
prefix.isEmpty()
2324+
parentChildType(parent, child, prefix) and
2325+
strictcount(AstNode child0 | parentChildType(parent, child0, prefix) | child0) > 1
23362326
or
2337-
lubCoercionInput(parent, child, prefix)
2327+
typeEqualityAsymmetricInput(child, TypePath::nil(), parent, prefix)
23382328
}
23392329

23402330
private predicate typeEqualityAsymmetric(

0 commit comments

Comments
 (0)