Skip to content

Commit bc53fee

Browse files
committed
Rust: Infer more () types
1 parent f395162 commit bc53fee

File tree

5 files changed

+995
-9
lines changed

5 files changed

+995
-9
lines changed

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ private TypeMention getTypeAnnotation(AstNode n) {
278278
)
279279
or
280280
exists(Function f |
281-
result = f.getRetType().getTypeRepr() and
281+
result = getReturnTypeMention(f) and
282282
n = f.getFunctionBody()
283283
)
284284
}
@@ -436,8 +436,7 @@ module CertainTypeInference {
436436
result = inferTupleRootType(n) and
437437
path.isEmpty()
438438
or
439-
result = inferAsyncBlockExprRootType(n) and
440-
path.isEmpty()
439+
result = inferBlockExprType(n, path)
441440
or
442441
result = inferArrayExprType(n) and
443442
path.isEmpty()
@@ -1854,7 +1853,7 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
18541853
}
18551854

18561855
private Type resolveRetType(TypePath path) {
1857-
result = this.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path)
1856+
result = getReturnTypeMention(this).resolveTypeAt(path)
18581857
}
18591858

18601859
pragma[nomagic]
@@ -2798,11 +2797,38 @@ private AssociatedTypeTypeParameter getFutureOutputTypeParameter() {
27982797
result.getTypeAlias() = any(FutureTrait ft).getOutputType()
27992798
}
28002799

2800+
private predicate isReturnExprCfgAncestor(AstNode n) {
2801+
n instanceof ReturnExpr
2802+
or
2803+
exists(AstNode mid |
2804+
isReturnExprCfgAncestor(mid) and
2805+
n = mid.getParentNode() and
2806+
n.getEnclosingCfgScope() = mid.getEnclosingCfgScope()
2807+
)
2808+
}
2809+
2810+
pragma[nomagic]
2811+
predicate isUnitBlockExpr(BlockExpr be) {
2812+
not be.getStmtList().hasTailExpr() and
2813+
not isReturnExprCfgAncestor(be)
2814+
}
2815+
28012816
pragma[nomagic]
2802-
private TraitType inferAsyncBlockExprRootType(AsyncBlockExpr abe) {
2817+
private Type inferBlockExprType(BlockExpr be, TypePath path) {
28032818
// `typeEquality` handles the non-root case
2804-
exists(abe) and
2805-
result = getFutureTraitType()
2819+
if be instanceof AsyncBlockExpr
2820+
then (
2821+
path.isEmpty() and
2822+
result = getFutureTraitType()
2823+
or
2824+
isUnitBlockExpr(be) and
2825+
path = TypePath::singleton(getFutureOutputTypeParameter()) and
2826+
result instanceof UnitType
2827+
) else (
2828+
isUnitBlockExpr(be) and
2829+
path.isEmpty() and
2830+
result instanceof UnitType
2831+
)
28062832
}
28072833

28082834
final private class AwaitTarget extends Expr {

‎rust/ql/lib/codeql/rust/internal/TypeMention.qll‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,30 @@ TypeMention getSelfParamTypeMention(SelfParam self) {
443443
result = self.getTypeRepr()
444444
}
445445

446+
/**
447+
* An element used to represent the implicit `()` return type of function.
448+
*/
449+
class ShorthandReturnTypeMention extends TypeMention instanceof Name {
450+
private Function f;
451+
452+
ShorthandReturnTypeMention() {
453+
this = f.getName() and
454+
not f.getRetType().hasTypeRepr()
455+
}
456+
457+
override Type resolveTypeAt(TypePath typePath) {
458+
typePath.isEmpty() and
459+
result instanceof UnitType
460+
}
461+
}
462+
463+
pragma[nomagic]
464+
TypeMention getReturnTypeMention(Function f) {
465+
result.(ShorthandReturnTypeMention) = f.getName()
466+
or
467+
result = f.getRetType().getTypeRepr()
468+
}
469+
446470
class DynTraitTypeReprMention extends TypeMention instanceof DynTraitTypeRepr {
447471
private DynTraitType dynType;
448472

‎rust/ql/test/library-tests/dataflow/sources/file/CONSISTENCY/PathResolutionConsistency.expected‎

Whitespace-only changes.

‎rust/ql/test/library-tests/dataflow/sources/web_frameworks/CONSISTENCY/PathResolutionConsistency.expected‎

Whitespace-only changes.

0 commit comments

Comments
 (0)