Skip to content

Commit c9e6d42

Browse files
authored
Merge pull request #21139 from paldepind/rust/fn-syntax-return
Rust: Make function trait syntax without return type default to unit
2 parents 57ec850 + 41921a8 commit c9e6d42

File tree

3 files changed

+191
-161
lines changed

3 files changed

+191
-161
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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ mod fn_once_trait {
3636
let _return = f(true); // $ type=_return:i64
3737
}
3838

39+
fn return_type_omitted<F: FnOnce(bool)>(f: F) {
40+
let _return = f(true); // $ type=_return:()
41+
}
42+
3943
fn argument_type<F: FnOnce(bool) -> i64>(f: F) {
4044
let arg = Default::default(); // $ target=default type=arg:bool
4145
f(arg);

0 commit comments

Comments
 (0)