diff options
| author | Florian Diebold <flodiebold@gmail.com> | 2021-05-25 14:24:08 +0200 |
|---|---|---|
| committer | Florian Diebold <flodiebold@gmail.com> | 2021-05-25 14:29:53 +0200 |
| commit | 35c948ff4a36b9c031bda96f79b8bf9e0d5bda26 (patch) | |
| tree | e335ab0ab7271234b269974f92b591ea22174abd | |
| parent | 835cf55887527bd1953cb7004259214f7c215095 (diff) | |
| download | rust-35c948ff4a36b9c031bda96f79b8bf9e0d5bda26.tar.gz rust-35c948ff4a36b9c031bda96f79b8bf9e0d5bda26.zip | |
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.rs | 27 | ||||
| -rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 32 |
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 5d5dd9c8f8a..54ede739394 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( ) -> Option<GenericArgs> { let mut args = Vec::new(); let mut bindings = Vec::new(); - if let Some(params) = params { - let mut param_types = Vec::new(); - for param in params.params() { - let type_ref = TypeRef::from_ast_opt(&ctx, param.ty()); - param_types.push(type_ref); - } - let arg = GenericArg::Type(TypeRef::Tuple(param_types)); - args.push(arg); + let params = params?; + let mut param_types = Vec::new(); + for param in params.params() { + let type_ref = TypeRef::from_ast_opt(&ctx, param.ty()); + param_types.push(type_ref); } + let arg = GenericArg::Type(TypeRef::Tuple(param_types)); + args.push(arg); if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.ty()); bindings.push(AssociatedTypeBinding { @@ -221,10 +220,14 @@ fn lower_generic_args_from_fn_path( type_ref: Some(type_ref), bounds: Vec::new(), }); - } - if args.is_empty() && bindings.is_empty() { - None } else { - Some(GenericArgs { args, has_self_type: false, bindings }) + // -> () + let type_ref = TypeRef::Tuple(Vec::new()); + bindings.push(AssociatedTypeBinding { + name: name![Output], + type_ref: Some(type_ref), + bounds: Vec::new(), + }); } + Some(GenericArgs { args, has_self_type: false, bindings }) } diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index a5a2df54cb6..714f1293782 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() { #[test] fn infer_box_fn_arg() { - // The type mismatch is a bug + // The type mismatch is because we don't define Unsize and CoerceUnsized check_infer_with_mismatches( r#" //- /lib.rs deps:std @@ -3095,16 +3095,16 @@ fn foo() { 478..576 '{ ...&s); }': () 488..489 's': Option<i32> 492..504 'Option::None': Option<i32> - 514..515 'f': Box<dyn FnOnce(&Option<i32>)> + 514..515 'f': Box<dyn FnOnce(&Option<i32>) -> ()> 549..562 'box (|ps| {})': Box<|{unknown}| -> ()> 554..561 '|ps| {}': |{unknown}| -> () 555..557 'ps': {unknown} 559..561 '{}': () - 568..569 'f': Box<dyn FnOnce(&Option<i32>)> - 568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)> + 568..569 'f': Box<dyn FnOnce(&Option<i32>) -> ()> + 568..573 'f(&s)': () 570..572 '&s': &Option<i32> 571..572 's': Option<i32> - 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()> + 549..562: expected Box<dyn FnOnce(&Option<i32>) -> ()>, got Box<|{unknown}| -> ()> "#]], ); } @@ -3571,3 +3571,25 @@ fn main() { "#]], ) } + +#[test] +fn fn_returning_unit() { + check_infer_with_mismatches( + r#" +#[lang = "fn_once"] +trait FnOnce<Args> { + type Output; +} + +fn test<F: FnOnce()>(f: F) { + let _: () = f(); +}"#, + expect![[r#" + 82..83 'f': F + 88..112 '{ ...f(); }': () + 98..99 '_': () + 106..107 'f': F + 106..109 'f()': () + "#]], + ); +} |
