Skip to content

Commit 33fdd51

Browse files
Merge #8987
8987: Fix lowering of FnOnce() without return type r=flodiebold a=flodiebold This should result in an implicit `-> ()`, not leaving out the binding. Co-authored-by: Florian Diebold <[email protected]>
2 parents f3cfd8a + 7c6f764 commit 33fdd51

File tree

3 files changed

+43
-16
lines changed

3 files changed

+43
-16
lines changed

crates/hir_def/src/path/lower.rs

+15-12
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/display.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,10 @@ fn write_bounds_like_dyn_trait(
778778
}
779779
WhereClause::AliasEq(alias_eq) if is_fn_trait => {
780780
is_fn_trait = false;
781-
write!(f, " -> ")?;
782-
alias_eq.ty.hir_fmt(f)?;
781+
if !alias_eq.ty.is_unit() {
782+
write!(f, " -> ")?;
783+
alias_eq.ty.hir_fmt(f)?;
784+
}
783785
}
784786
WhereClause::AliasEq(AliasEq { ty, alias }) => {
785787
// in types in actual Rust, these will always come

crates/hir_ty/src/tests/traits.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -3078,7 +3078,7 @@ fn infer_fn_trait_arg() {
30783078

30793079
#[test]
30803080
fn infer_box_fn_arg() {
3081-
// The type mismatch is a bug
3081+
// The type mismatch is because we don't define Unsize and CoerceUnsized
30823082
check_infer_with_mismatches(
30833083
r#"
30843084
//- /lib.rs deps:std
@@ -3138,7 +3138,7 @@ fn foo() {
31383138
555..557 'ps': {unknown}
31393139
559..561 '{}': ()
31403140
568..569 'f': Box<dyn FnOnce(&Option<i32>)>
3141-
568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)>
3141+
568..573 'f(&s)': ()
31423142
570..572 '&s': &Option<i32>
31433143
571..572 's': Option<i32>
31443144
549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()>
@@ -3608,3 +3608,25 @@ fn main() {
36083608
"#]],
36093609
)
36103610
}
3611+
3612+
#[test]
3613+
fn fn_returning_unit() {
3614+
check_infer_with_mismatches(
3615+
r#"
3616+
#[lang = "fn_once"]
3617+
trait FnOnce<Args> {
3618+
type Output;
3619+
}
3620+
3621+
fn test<F: FnOnce()>(f: F) {
3622+
let _: () = f();
3623+
}"#,
3624+
expect![[r#"
3625+
82..83 'f': F
3626+
88..112 '{ ...f(); }': ()
3627+
98..99 '_': ()
3628+
106..107 'f': F
3629+
106..109 'f()': ()
3630+
"#]],
3631+
);
3632+
}

0 commit comments

Comments
 (0)