Skip to content

Commit 35c948f

Browse files
committed
Fix lowering of FnOnce() without return type
This should result in an implicit `-> ()`, not leaving out the binding.
1 parent 835cf55 commit 35c948f

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

crates/hir_def/src/path/lower.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -205,26 +205,29 @@ fn lower_generic_args_from_fn_path(
205205
) -> Option<GenericArgs> {
206206
let mut args = Vec::new();
207207
let mut bindings = Vec::new();
208-
if let Some(params) = params {
209-
let mut param_types = Vec::new();
210-
for param in params.params() {
211-
let type_ref = TypeRef::from_ast_opt(&ctx, param.ty());
212-
param_types.push(type_ref);
213-
}
214-
let arg = GenericArg::Type(TypeRef::Tuple(param_types));
215-
args.push(arg);
208+
let params = params?;
209+
let mut param_types = Vec::new();
210+
for param in params.params() {
211+
let type_ref = TypeRef::from_ast_opt(&ctx, param.ty());
212+
param_types.push(type_ref);
216213
}
214+
let arg = GenericArg::Type(TypeRef::Tuple(param_types));
215+
args.push(arg);
217216
if let Some(ret_type) = ret_type {
218217
let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.ty());
219218
bindings.push(AssociatedTypeBinding {
220219
name: name![Output],
221220
type_ref: Some(type_ref),
222221
bounds: Vec::new(),
223222
});
224-
}
225-
if args.is_empty() && bindings.is_empty() {
226-
None
227223
} else {
228-
Some(GenericArgs { args, has_self_type: false, bindings })
224+
// -> ()
225+
let type_ref = TypeRef::Tuple(Vec::new());
226+
bindings.push(AssociatedTypeBinding {
227+
name: name![Output],
228+
type_ref: Some(type_ref),
229+
bounds: Vec::new(),
230+
});
229231
}
232+
Some(GenericArgs { args, has_self_type: false, bindings })
230233
}

crates/hir_ty/src/tests/traits.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,7 +3041,7 @@ fn infer_fn_trait_arg() {
30413041

30423042
#[test]
30433043
fn infer_box_fn_arg() {
3044-
// The type mismatch is a bug
3044+
// The type mismatch is because we don't define Unsize and CoerceUnsized
30453045
check_infer_with_mismatches(
30463046
r#"
30473047
//- /lib.rs deps:std
@@ -3095,16 +3095,16 @@ fn foo() {
30953095
478..576 '{ ...&s); }': ()
30963096
488..489 's': Option<i32>
30973097
492..504 'Option::None': Option<i32>
3098-
514..515 'f': Box<dyn FnOnce(&Option<i32>)>
3098+
514..515 'f': Box<dyn FnOnce(&Option<i32>) -> ()>
30993099
549..562 'box (|ps| {})': Box<|{unknown}| -> ()>
31003100
554..561 '|ps| {}': |{unknown}| -> ()
31013101
555..557 'ps': {unknown}
31023102
559..561 '{}': ()
3103-
568..569 'f': Box<dyn FnOnce(&Option<i32>)>
3104-
568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)>
3103+
568..569 'f': Box<dyn FnOnce(&Option<i32>) -> ()>
3104+
568..573 'f(&s)': ()
31053105
570..572 '&s': &Option<i32>
31063106
571..572 's': Option<i32>
3107-
549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()>
3107+
549..562: expected Box<dyn FnOnce(&Option<i32>) -> ()>, got Box<|{unknown}| -> ()>
31083108
"#]],
31093109
);
31103110
}
@@ -3571,3 +3571,25 @@ fn main() {
35713571
"#]],
35723572
)
35733573
}
3574+
3575+
#[test]
3576+
fn fn_returning_unit() {
3577+
check_infer_with_mismatches(
3578+
r#"
3579+
#[lang = "fn_once"]
3580+
trait FnOnce<Args> {
3581+
type Output;
3582+
}
3583+
3584+
fn test<F: FnOnce()>(f: F) {
3585+
let _: () = f();
3586+
}"#,
3587+
expect![[r#"
3588+
82..83 'f': F
3589+
88..112 '{ ...f(); }': ()
3590+
98..99 '_': ()
3591+
106..107 'f': F
3592+
106..109 'f()': ()
3593+
"#]],
3594+
);
3595+
}

0 commit comments

Comments
 (0)