Skip to content

Commit 41921a8

Browse files
committed
Rust: Make function trait syntax without return type default to unit
1 parent d452696 commit 41921a8

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

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

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,33 @@ class NonAliasPathTypeMention extends PathTypeMention {
222222
result = this.getPositionalTypeArgument(pragma[only_bind_into](i), path) and
223223
tp = this.resolveRootType().getPositionalTypeParameter(pragma[only_bind_into](i))
224224
)
225+
or
226+
// Handle the special syntactic sugar for function traits. The syntactic
227+
// form is detected by the presence of a parenthesized argument list which
228+
// is a mandatory part of the syntax [1].
229+
//
230+
// For now we only support `FnOnce` as we can't support the "inherited"
231+
// associated types of `Fn` and `FnMut` yet.
232+
//
233+
// [1]: https://doc.rust-lang.org/reference/paths.html#grammar-TypePathFn
234+
exists(FnOnceTrait t, PathSegment s |
235+
t = resolved and
236+
s = this.getSegment() and
237+
s.hasParenthesizedArgList()
238+
|
239+
tp = TTypeParamTypeParameter(t.getTypeParam()) and
240+
result = s.getParenthesizedArgList().(TypeMention).resolveTypeAt(path)
241+
or
242+
tp = TAssociatedTypeTypeParameter(t.getOutputType()) and
243+
(
244+
result = s.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path)
245+
or
246+
// When the `-> ...` return type is omitted, it defaults to `()`.
247+
not s.hasRetType() and
248+
result instanceof UnitType and
249+
path.isEmpty()
250+
)
251+
)
225252
}
226253

227254
pragma[nomagic]
@@ -256,17 +283,6 @@ class NonAliasPathTypeMention extends PathTypeMention {
256283
result = alias.getTypeRepr() and
257284
tp = TAssociatedTypeTypeParameter(this.getResolvedAlias(pragma[only_bind_into](name)))
258285
)
259-
or
260-
// Handle the special syntactic sugar for function traits. For now we only
261-
// support `FnOnce` as we can't support the "inherited" associated types of
262-
// `Fn` and `FnMut` yet.
263-
exists(FnOnceTrait t | t = resolved |
264-
tp = TTypeParamTypeParameter(t.getTypeParam()) and
265-
result = this.getSegment().getParenthesizedArgList()
266-
or
267-
tp = TAssociatedTypeTypeParameter(t.getOutputType()) and
268-
result = this.getSegment().getRetType().getTypeRepr()
269-
)
270286
}
271287

272288
pragma[nomagic]

rust/ql/test/library-tests/type-inference/closure.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ mod fn_once_trait {
3737
}
3838

3939
fn return_type_omitted<F: FnOnce(bool)>(f: F) {
40-
let _return = f(true); // $ MISSING: type=_return:()
40+
let _return = f(true); // $ type=_return:()
4141
}
4242

4343
fn argument_type<F: FnOnce(bool) -> i64>(f: F) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4982,7 +4982,9 @@ inferType
49824982
| closure.rs:36:25:36:28 | true | | {EXTERNAL LOCATION} | bool |
49834983
| closure.rs:39:45:39:45 | f | | closure.rs:39:28:39:42 | F |
49844984
| closure.rs:39:51:41:5 | { ... } | | {EXTERNAL LOCATION} | () |
4985+
| closure.rs:40:13:40:19 | _return | | {EXTERNAL LOCATION} | () |
49854986
| closure.rs:40:23:40:23 | f | | closure.rs:39:28:39:42 | F |
4987+
| closure.rs:40:23:40:29 | f(...) | | {EXTERNAL LOCATION} | () |
49864988
| closure.rs:40:25:40:28 | true | | {EXTERNAL LOCATION} | bool |
49874989
| closure.rs:43:46:43:46 | f | | closure.rs:43:22:43:43 | F |
49884990
| closure.rs:43:52:46:5 | { ... } | | {EXTERNAL LOCATION} | () |

0 commit comments

Comments
 (0)