aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-05-25 13:24:08 +0100
committerFlorian Diebold <[email protected]>2021-05-25 13:29:53 +0100
commit35c948ff4a36b9c031bda96f79b8bf9e0d5bda26 (patch)
treee335ab0ab7271234b269974f92b591ea22174abd
parent835cf55887527bd1953cb7004259214f7c215095 (diff)
Fix lowering of FnOnce() without return type
This should result in an implicit `-> ()`, not leaving out the binding.
-rw-r--r--crates/hir_def/src/path/lower.rs27
-rw-r--r--crates/hir_ty/src/tests/traits.rs32
2 files changed, 42 insertions, 17 deletions
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index 5d5dd9c8f..54ede7393 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -205,15 +205,14 @@ fn lower_generic_args_from_fn_path(
205) -> Option<GenericArgs> { 205) -> Option<GenericArgs> {
206 let mut args = Vec::new(); 206 let mut args = Vec::new();
207 let mut bindings = Vec::new(); 207 let mut bindings = Vec::new();
208 if let Some(params) = params { 208 let params = params?;
209 let mut param_types = Vec::new(); 209 let mut param_types = Vec::new();
210 for param in params.params() { 210 for param in params.params() {
211 let type_ref = TypeRef::from_ast_opt(&ctx, param.ty()); 211 let type_ref = TypeRef::from_ast_opt(&ctx, param.ty());
212 param_types.push(type_ref); 212 param_types.push(type_ref);
213 }
214 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
215 args.push(arg);
216 } 213 }
214 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
215 args.push(arg);
217 if let Some(ret_type) = ret_type { 216 if let Some(ret_type) = ret_type {
218 let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.ty()); 217 let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.ty());
219 bindings.push(AssociatedTypeBinding { 218 bindings.push(AssociatedTypeBinding {
@@ -221,10 +220,14 @@ fn lower_generic_args_from_fn_path(
221 type_ref: Some(type_ref), 220 type_ref: Some(type_ref),
222 bounds: Vec::new(), 221 bounds: Vec::new(),
223 }); 222 });
224 }
225 if args.is_empty() && bindings.is_empty() {
226 None
227 } else { 223 } 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 });
229 } 231 }
232 Some(GenericArgs { args, has_self_type: false, bindings })
230} 233}
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index a5a2df54c..714f12937 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -3041,7 +3041,7 @@ fn infer_fn_trait_arg() {
3041 3041
3042#[test] 3042#[test]
3043fn infer_box_fn_arg() { 3043fn infer_box_fn_arg() {
3044 // The type mismatch is a bug 3044 // The type mismatch is because we don't define Unsize and CoerceUnsized
3045 check_infer_with_mismatches( 3045 check_infer_with_mismatches(
3046 r#" 3046 r#"
3047//- /lib.rs deps:std 3047//- /lib.rs deps:std
@@ -3095,16 +3095,16 @@ fn foo() {
3095 478..576 '{ ...&s); }': () 3095 478..576 '{ ...&s); }': ()
3096 488..489 's': Option<i32> 3096 488..489 's': Option<i32>
3097 492..504 'Option::None': Option<i32> 3097 492..504 'Option::None': Option<i32>
3098 514..515 'f': Box<dyn FnOnce(&Option<i32>)> 3098 514..515 'f': Box<dyn FnOnce(&Option<i32>) -> ()>
3099 549..562 'box (|ps| {})': Box<|{unknown}| -> ()> 3099 549..562 'box (|ps| {})': Box<|{unknown}| -> ()>
3100 554..561 '|ps| {}': |{unknown}| -> () 3100 554..561 '|ps| {}': |{unknown}| -> ()
3101 555..557 'ps': {unknown} 3101 555..557 'ps': {unknown}
3102 559..561 '{}': () 3102 559..561 '{}': ()
3103 568..569 'f': Box<dyn FnOnce(&Option<i32>)> 3103 568..569 'f': Box<dyn FnOnce(&Option<i32>) -> ()>
3104 568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)> 3104 568..573 'f(&s)': ()
3105 570..572 '&s': &Option<i32> 3105 570..572 '&s': &Option<i32>
3106 571..572 's': Option<i32> 3106 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}| -> ()>
3108 "#]], 3108 "#]],
3109 ); 3109 );
3110} 3110}
@@ -3571,3 +3571,25 @@ fn main() {
3571 "#]], 3571 "#]],
3572 ) 3572 )
3573} 3573}
3574
3575#[test]
3576fn fn_returning_unit() {
3577 check_infer_with_mismatches(
3578 r#"
3579#[lang = "fn_once"]
3580trait FnOnce<Args> {
3581 type Output;
3582}
3583
3584fn 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}