Skip to content

Commit f7f08f6

Browse files
committed
Rust: Model async return types as dyn Future
1 parent 4684ac1 commit f7f08f6

File tree

6 files changed

+75
-39
lines changed

6 files changed

+75
-39
lines changed

rust/ql/lib/codeql/rust/internal/Type.qll

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,22 @@ abstract class Type extends TType {
8282
pragma[nomagic]
8383
abstract TupleField getTupleField(int i);
8484

85-
/** Gets the `i`th type parameter of this type, if any. */
86-
abstract TypeParameter getTypeParameter(int i);
85+
/**
86+
* Gets the `i`th positional type parameter of this type, if any.
87+
*
88+
* This excludes for example associated type parameters.
89+
*/
90+
abstract TypeParameter getPositionalTypeParameter(int i);
8791

8892
/** Gets the default type for the `i`th type parameter, if any. */
8993
TypeMention getTypeParameterDefault(int i) { none() }
9094

91-
/** Gets a type parameter of this type. */
92-
final TypeParameter getATypeParameter() { result = this.getTypeParameter(_) }
95+
/**
96+
* Gets a type parameter of this type.
97+
*
98+
* This includes both positional and other type parameters, such as associated types.
99+
*/
100+
TypeParameter getATypeParameter() { result = this.getPositionalTypeParameter(_) }
93101

94102
/** Gets a textual representation of this type. */
95103
abstract string toString();
@@ -108,7 +116,9 @@ class TupleType extends Type, TTuple {
108116

109117
override TupleField getTupleField(int i) { none() }
110118

111-
override TypeParameter getTypeParameter(int i) { result = TTupleTypeParameter(arity, i) }
119+
override TypeParameter getPositionalTypeParameter(int i) {
120+
result = TTupleTypeParameter(arity, i)
121+
}
112122

113123
/** Gets the arity of this tuple type. */
114124
int getArity() { result = arity }
@@ -141,7 +151,7 @@ class StructType extends StructOrEnumType, TStruct {
141151

142152
override TupleField getTupleField(int i) { result = struct.getTupleField(i) }
143153

144-
override TypeParameter getTypeParameter(int i) {
154+
override TypeParameter getPositionalTypeParameter(int i) {
145155
result = TTypeParamTypeParameter(struct.getGenericParamList().getTypeParam(i))
146156
}
147157

@@ -166,7 +176,7 @@ class EnumType extends StructOrEnumType, TEnum {
166176

167177
override TupleField getTupleField(int i) { none() }
168178

169-
override TypeParameter getTypeParameter(int i) {
179+
override TypeParameter getPositionalTypeParameter(int i) {
170180
result = TTypeParamTypeParameter(enum.getGenericParamList().getTypeParam(i))
171181
}
172182

@@ -192,10 +202,18 @@ class TraitType extends Type, TTrait {
192202

193203
override TupleField getTupleField(int i) { none() }
194204

195-
override TypeParameter getTypeParameter(int i) {
205+
override TypeParameter getPositionalTypeParameter(int i) {
196206
result = TTypeParamTypeParameter(trait.getGenericParamList().getTypeParam(i))
197207
}
198208

209+
override TypeParameter getATypeParameter() {
210+
result = super.getATypeParameter()
211+
or
212+
result.(AssociatedTypeTypeParameter).getTrait() = trait
213+
or
214+
result.(SelfTypeParameter).getTrait() = trait
215+
}
216+
199217
override TypeMention getTypeParameterDefault(int i) {
200218
result = trait.getGenericParamList().getTypeParam(i).getDefaultType()
201219
}
@@ -218,7 +236,7 @@ class ArrayType extends Type, TArrayType {
218236

219237
override TupleField getTupleField(int i) { none() }
220238

221-
override TypeParameter getTypeParameter(int i) {
239+
override TypeParameter getPositionalTypeParameter(int i) {
222240
result = TArrayTypeParameter() and
223241
i = 0
224242
}
@@ -241,7 +259,7 @@ class RefType extends Type, TRefType {
241259

242260
override TupleField getTupleField(int i) { none() }
243261

244-
override TypeParameter getTypeParameter(int i) {
262+
override TypeParameter getPositionalTypeParameter(int i) {
245263
result = TRefTypeParameter() and
246264
i = 0
247265
}
@@ -274,7 +292,7 @@ class ImplTraitType extends Type, TImplTraitType {
274292

275293
override TupleField getTupleField(int i) { none() }
276294

277-
override TypeParameter getTypeParameter(int i) {
295+
override TypeParameter getPositionalTypeParameter(int i) {
278296
exists(TypeParam tp |
279297
implTraitTypeParam(impl, i, tp) and
280298
result = TImplTraitTypeParameter(impl, tp)
@@ -295,10 +313,19 @@ class DynTraitType extends Type, TDynTraitType {
295313

296314
override TupleField getTupleField(int i) { none() }
297315

298-
override DynTraitTypeParameter getTypeParameter(int i) {
316+
override DynTraitTypeParameter getPositionalTypeParameter(int i) {
299317
result = TDynTraitTypeParameter(trait.getGenericParamList().getTypeParam(i))
300318
}
301319

320+
override TypeParameter getATypeParameter() {
321+
result = super.getATypeParameter()
322+
or
323+
exists(AstNode n |
324+
dynTraitTypeParameter(trait, n) and
325+
result = TDynTraitTypeParameter(n)
326+
)
327+
}
328+
302329
Trait getTrait() { result = trait }
303330

304331
override string toString() { result = "dyn " + trait.getName().toString() }
@@ -336,7 +363,7 @@ class SliceType extends Type, TSliceType {
336363

337364
override TupleField getTupleField(int i) { none() }
338365

339-
override TypeParameter getTypeParameter(int i) {
366+
override TypeParameter getPositionalTypeParameter(int i) {
340367
result = TSliceTypeParameter() and
341368
i = 0
342369
}
@@ -352,7 +379,7 @@ abstract class TypeParameter extends Type {
352379

353380
override TupleField getTupleField(int i) { none() }
354381

355-
override TypeParameter getTypeParameter(int i) { none() }
382+
override TypeParameter getPositionalTypeParameter(int i) { none() }
356383
}
357384

358385
private class RawTypeParameter = @type_param or @trait or @type_alias or @impl_trait_type_repr;
@@ -548,7 +575,7 @@ class ImplTraitTypeTypeParameter extends ImplTraitType, TypeParameter {
548575

549576
override TupleField getTupleField(int i) { none() }
550577

551-
override TypeParameter getTypeParameter(int i) { none() }
578+
override TypeParameter getPositionalTypeParameter(int i) { none() }
552579
}
553580

554581
/**

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,9 @@ private module CertainTypeInference {
374374
or
375375
result = inferLiteralType(n, path, true)
376376
or
377+
result = inferAsyncBlockExprRootType(n) and
378+
path.isEmpty()
379+
or
377380
infersCertainTypeAt(n, path, result.getATypeParameter())
378381
}
379382

@@ -521,7 +524,7 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
521524
n2 = be.getStmtList().getTailExpr() and
522525
if be.isAsync()
523526
then
524-
prefix1 = TypePath::singleton(getFutureOutputTypeParameter()) and
527+
prefix1 = TypePath::singleton(getDynFutureOutputTypeParameter()) and
525528
prefix2.isEmpty()
526529
else (
527530
prefix1.isEmpty() and
@@ -941,7 +944,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
941944
or
942945
exists(TypePath suffix |
943946
result = this.resolveRetType(suffix) and
944-
path = TypePath::cons(getFutureOutputTypeParameter(), suffix)
947+
path = TypePath::cons(getDynFutureOutputTypeParameter(), suffix)
945948
)
946949
else result = this.resolveRetType(path)
947950
}
@@ -1427,16 +1430,22 @@ private Type inferLiteralType(LiteralExpr le, TypePath path, boolean certain) {
14271430
certain = true
14281431
}
14291432

1433+
// always exists because of the mention in `builtins/mentions.rs`
14301434
pragma[nomagic]
1431-
private TraitType getFutureTraitType() { result.getTrait() instanceof FutureTrait }
1435+
private DynTraitType getFutureTraitType() { result.getTrait() instanceof FutureTrait }
14321436

14331437
pragma[nomagic]
14341438
private AssociatedTypeTypeParameter getFutureOutputTypeParameter() {
14351439
result.getTypeAlias() = any(FutureTrait ft).getOutputType()
14361440
}
14371441

14381442
pragma[nomagic]
1439-
private TraitType inferAsyncBlockExprRootType(AsyncBlockExpr abe) {
1443+
private DynTraitTypeParameter getDynFutureOutputTypeParameter() {
1444+
result = TDynTraitTypeParameter(any(FutureTrait ft).getOutputType())
1445+
}
1446+
1447+
pragma[nomagic]
1448+
private DynTraitType inferAsyncBlockExprRootType(AsyncBlockExpr abe) {
14401449
// `typeEquality` handles the non-root case
14411450
exists(abe) and
14421451
result = getFutureTraitType()
@@ -1449,6 +1458,7 @@ final private class AwaitTarget extends Expr {
14491458
}
14501459

14511460
private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInputSig<AwaitTarget> {
1461+
pragma[nomagic]
14521462
predicate relevantConstraint(AwaitTarget term, Type constraint) {
14531463
exists(term) and
14541464
constraint.(TraitType).getTrait() instanceof FutureTrait
@@ -1774,7 +1784,7 @@ private Type inferClosureExprType(AstNode n, TypePath path) {
17741784
exists(ClosureExpr ce |
17751785
n = ce and
17761786
path.isEmpty() and
1777-
result = TDynTraitType(any(FnOnceTrait t))
1787+
result = TDynTraitType(any(FnOnceTrait t)) // always exists because of the mention in `builtins/mentions.rs`
17781788
or
17791789
n = ce and
17801790
path = TypePath::singleton(TDynTraitTypeParameter(any(FnOnceTrait t).getTypeParam())) and
@@ -2382,9 +2392,6 @@ private module Cached {
23822392
or
23832393
result = inferLiteralType(n, path, false)
23842394
or
2385-
result = inferAsyncBlockExprRootType(n) and
2386-
path.isEmpty()
2387-
or
23882395
result = inferAwaitExprType(n, path)
23892396
or
23902397
result = inferArrayExprType(n) and

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ class NonAliasPathTypeMention extends PathTypeMention {
182182
private TypeMention getTypeMentionForTypeParameter(TypeParameter tp) {
183183
exists(int i |
184184
result = this.getPositionalTypeArgument(pragma[only_bind_into](i)) and
185-
tp = this.resolveRootType().getTypeParameter(pragma[only_bind_into](i))
185+
tp = this.resolveRootType().getPositionalTypeParameter(pragma[only_bind_into](i))
186186
)
187187
or
188188
exists(TypeAlias alias |

rust/ql/test/library-tests/type-inference/type-inference.expected

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3728,9 +3728,8 @@ inferType
37283728
| main.rs:1915:25:1917:5 | { ... } | | main.rs:1909:5:1909:14 | S1 |
37293729
| main.rs:1916:9:1916:10 | S1 | | main.rs:1909:5:1909:14 | S1 |
37303730
| main.rs:1919:41:1921:5 | { ... } | | main.rs:1919:16:1919:39 | ImplTraitTypeRepr |
3731-
| main.rs:1920:9:1920:20 | { ... } | | {EXTERNAL LOCATION} | trait Future |
3732-
| main.rs:1920:9:1920:20 | { ... } | | main.rs:1919:16:1919:39 | ImplTraitTypeRepr |
3733-
| main.rs:1920:9:1920:20 | { ... } | Output | main.rs:1909:5:1909:14 | S1 |
3731+
| main.rs:1920:9:1920:20 | { ... } | | {EXTERNAL LOCATION} | dyn Future |
3732+
| main.rs:1920:9:1920:20 | { ... } | dyn(Output) | main.rs:1909:5:1909:14 | S1 |
37343733
| main.rs:1920:17:1920:18 | S1 | | main.rs:1909:5:1909:14 | S1 |
37353734
| main.rs:1929:13:1929:42 | SelfParam | | {EXTERNAL LOCATION} | Pin |
37363735
| main.rs:1929:13:1929:42 | SelfParam | Ptr | file://:0:0:0:0 | & |
@@ -3745,22 +3744,22 @@ inferType
37453744
| main.rs:1936:41:1938:5 | { ... } | | main.rs:1936:16:1936:39 | ImplTraitTypeRepr |
37463745
| main.rs:1937:9:1937:10 | S2 | | main.rs:1923:5:1923:14 | S2 |
37473746
| main.rs:1937:9:1937:10 | S2 | | main.rs:1936:16:1936:39 | ImplTraitTypeRepr |
3748-
| main.rs:1941:9:1941:12 | f1(...) | | {EXTERNAL LOCATION} | trait Future |
3749-
| main.rs:1941:9:1941:12 | f1(...) | Output | main.rs:1909:5:1909:14 | S1 |
3747+
| main.rs:1941:9:1941:12 | f1(...) | | {EXTERNAL LOCATION} | dyn Future |
3748+
| main.rs:1941:9:1941:12 | f1(...) | dyn(Output) | main.rs:1909:5:1909:14 | S1 |
37503749
| main.rs:1941:9:1941:18 | await ... | | main.rs:1909:5:1909:14 | S1 |
37513750
| main.rs:1942:9:1942:12 | f2(...) | | main.rs:1919:16:1919:39 | ImplTraitTypeRepr |
37523751
| main.rs:1942:9:1942:18 | await ... | | main.rs:1909:5:1909:14 | S1 |
37533752
| main.rs:1943:9:1943:12 | f3(...) | | main.rs:1936:16:1936:39 | ImplTraitTypeRepr |
37543753
| main.rs:1943:9:1943:18 | await ... | | main.rs:1909:5:1909:14 | S1 |
37553754
| main.rs:1944:9:1944:10 | S2 | | main.rs:1923:5:1923:14 | S2 |
37563755
| main.rs:1944:9:1944:16 | await S2 | | main.rs:1909:5:1909:14 | S1 |
3757-
| main.rs:1945:13:1945:13 | b | | {EXTERNAL LOCATION} | trait Future |
3758-
| main.rs:1945:13:1945:13 | b | Output | main.rs:1909:5:1909:14 | S1 |
3759-
| main.rs:1945:17:1945:28 | { ... } | | {EXTERNAL LOCATION} | trait Future |
3760-
| main.rs:1945:17:1945:28 | { ... } | Output | main.rs:1909:5:1909:14 | S1 |
3756+
| main.rs:1945:13:1945:13 | b | | {EXTERNAL LOCATION} | dyn Future |
3757+
| main.rs:1945:13:1945:13 | b | dyn(Output) | main.rs:1909:5:1909:14 | S1 |
3758+
| main.rs:1945:17:1945:28 | { ... } | | {EXTERNAL LOCATION} | dyn Future |
3759+
| main.rs:1945:17:1945:28 | { ... } | dyn(Output) | main.rs:1909:5:1909:14 | S1 |
37613760
| main.rs:1945:25:1945:26 | S1 | | main.rs:1909:5:1909:14 | S1 |
3762-
| main.rs:1946:9:1946:9 | b | | {EXTERNAL LOCATION} | trait Future |
3763-
| main.rs:1946:9:1946:9 | b | Output | main.rs:1909:5:1909:14 | S1 |
3761+
| main.rs:1946:9:1946:9 | b | | {EXTERNAL LOCATION} | dyn Future |
3762+
| main.rs:1946:9:1946:9 | b | dyn(Output) | main.rs:1909:5:1909:14 | S1 |
37643763
| main.rs:1946:9:1946:15 | await b | | main.rs:1909:5:1909:14 | S1 |
37653764
| main.rs:1957:15:1957:19 | SelfParam | | file://:0:0:0:0 | & |
37663765
| main.rs:1957:15:1957:19 | SelfParam | &T | main.rs:1956:5:1958:5 | Self [trait Trait1] |
@@ -4992,7 +4991,7 @@ inferType
49924991
| main.rs:2613:5:2613:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo |
49934992
| main.rs:2613:20:2613:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
49944993
| main.rs:2613:41:2613:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
4995-
| main.rs:2629:5:2629:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
4994+
| main.rs:2629:5:2629:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future |
49964995
| pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option |
49974996
| pattern_matching.rs:13:26:133:1 | { ... } | T | file://:0:0:0:0 | () |
49984997
| pattern_matching.rs:14:9:14:13 | value | | {EXTERNAL LOCATION} | Option |

rust/tools/builtins/mentions.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Type mentions required by type inference
2+
3+
use std::future::Future;
4+
fn mention_dyn_future<T>(f: &dyn Future<Output = T>) {}
5+
6+
fn mention_dyn_fn_once<F>(f: &dyn FnOnce() -> F) {}

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,9 +1007,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
10071007
tt.getTypeAt(pathToTypeParamInSub.appendInverse(suffix)) = t and
10081008
path = prefix0.append(suffix)
10091009
)
1010-
or
1011-
hasTypeConstraint(tt, constraint, constraint) and
1012-
t = tt.getTypeAt(path)
10131010
}
10141011
}
10151012

0 commit comments

Comments
 (0)