Skip to content

Commit f847160

Browse files
committed
Rust: Model async return types as dyn Future
1 parent bb9daa0 commit f847160

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
@@ -373,6 +373,9 @@ private module CertainTypeInference {
373373
or
374374
result = inferLiteralType(n, path, true)
375375
or
376+
result = inferAsyncBlockExprRootType(n) and
377+
path.isEmpty()
378+
or
376379
infersCertainTypeAt(n, path, result.getATypeParameter())
377380
}
378381

@@ -520,7 +523,7 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
520523
n2 = be.getStmtList().getTailExpr() and
521524
if be.isAsync()
522525
then
523-
prefix1 = TypePath::singleton(getFutureOutputTypeParameter()) and
526+
prefix1 = TypePath::singleton(getDynFutureOutputTypeParameter()) and
524527
prefix2.isEmpty()
525528
else (
526529
prefix1.isEmpty() and
@@ -940,7 +943,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
940943
or
941944
exists(TypePath suffix |
942945
result = this.resolveRetType(suffix) and
943-
path = TypePath::cons(getFutureOutputTypeParameter(), suffix)
946+
path = TypePath::cons(getDynFutureOutputTypeParameter(), suffix)
944947
)
945948
else result = this.resolveRetType(path)
946949
}
@@ -1426,16 +1429,22 @@ private Type inferLiteralType(LiteralExpr le, TypePath path, boolean certain) {
14261429
certain = true
14271430
}
14281431

1432+
// always exists because of the mention in `builtins/mentions.rs`
14291433
pragma[nomagic]
1430-
private TraitType getFutureTraitType() { result.getTrait() instanceof FutureTrait }
1434+
private DynTraitType getFutureTraitType() { result.getTrait() instanceof FutureTrait }
14311435

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

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

14501459
private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInputSig<AwaitTarget> {
1460+
pragma[nomagic]
14511461
predicate relevantConstraint(AwaitTarget term, Type constraint) {
14521462
exists(term) and
14531463
constraint.(TraitType).getTrait() instanceof FutureTrait
@@ -1773,7 +1783,7 @@ private Type inferClosureExprType(AstNode n, TypePath path) {
17731783
exists(ClosureExpr ce |
17741784
n = ce and
17751785
path.isEmpty() and
1776-
result = TDynTraitType(any(FnOnceTrait t))
1786+
result = TDynTraitType(any(FnOnceTrait t)) // always exists because of the mention in `builtins/mentions.rs`
17771787
or
17781788
n = ce and
17791789
path = TypePath::singleton(TDynTraitTypeParameter(any(FnOnceTrait t).getTypeParam())) and
@@ -2381,9 +2391,6 @@ private module Cached {
23812391
or
23822392
result = inferLiteralType(n, path, false)
23832393
or
2384-
result = inferAsyncBlockExprRootType(n) and
2385-
path.isEmpty()
2386-
or
23872394
result = inferAwaitExprType(n, path)
23882395
or
23892396
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] |
@@ -4954,7 +4953,7 @@ inferType
49544953
| main.rs:2565:5:2565:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo |
49554954
| main.rs:2565:20:2565:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
49564955
| main.rs:2565:41:2565:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
4957-
| main.rs:2581:5:2581:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
4956+
| main.rs:2581:5:2581:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future |
49584957
| pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option |
49594958
| pattern_matching.rs:13:26:133:1 | { ... } | T | file://:0:0:0:0 | () |
49604959
| 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)