aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-25 14:25:15 +0100
committerGitHub <[email protected]>2021-05-25 14:25:15 +0100
commit33fdd512e318f86ccd66b84ce6128c03eb44cf77 (patch)
tree146d712f24c290963bb268e443f02b59dd79f26a
parentf3cfd8afb6db1ee0a8449655703172a0c8cf5411 (diff)
parent7c6f764ad6d7c6fc964be9fd2e96da717e2b2cc1 (diff)
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]>
-rw-r--r--crates/hir_def/src/path/lower.rs27
-rw-r--r--crates/hir_ty/src/display.rs6
-rw-r--r--crates/hir_ty/src/tests/traits.rs26
3 files changed, 43 insertions, 16 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/display.rs b/crates/hir_ty/src/display.rs
index 637bbc634..44f843bf3 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -778,8 +778,10 @@ fn write_bounds_like_dyn_trait(
778 } 778 }
779 WhereClause::AliasEq(alias_eq) if is_fn_trait => { 779 WhereClause::AliasEq(alias_eq) if is_fn_trait => {
780 is_fn_trait = false; 780 is_fn_trait = false;
781 write!(f, " -> ")?; 781 if !alias_eq.ty.is_unit() {
782 alias_eq.ty.hir_fmt(f)?; 782 write!(f, " -> ")?;
783 alias_eq.ty.hir_fmt(f)?;
784 }
783 } 785 }
784 WhereClause::AliasEq(AliasEq { ty, alias }) => { 786 WhereClause::AliasEq(AliasEq { ty, alias }) => {
785 // in types in actual Rust, these will always come 787 // in types in actual Rust, these will always come
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 71905baeb..6cd8786ea 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -3078,7 +3078,7 @@ fn infer_fn_trait_arg() {
3078 3078
3079#[test] 3079#[test]
3080fn infer_box_fn_arg() { 3080fn infer_box_fn_arg() {
3081 // The type mismatch is a bug 3081 // The type mismatch is because we don't define Unsize and CoerceUnsized
3082 check_infer_with_mismatches( 3082 check_infer_with_mismatches(
3083 r#" 3083 r#"
3084//- /lib.rs deps:std 3084//- /lib.rs deps:std
@@ -3138,7 +3138,7 @@ fn foo() {
3138 555..557 'ps': {unknown} 3138 555..557 'ps': {unknown}
3139 559..561 '{}': () 3139 559..561 '{}': ()
3140 568..569 'f': Box<dyn FnOnce(&Option<i32>)> 3140 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)': ()
3142 570..572 '&s': &Option<i32> 3142 570..572 '&s': &Option<i32>
3143 571..572 's': Option<i32> 3143 571..572 's': Option<i32>
3144 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()> 3144 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()>
@@ -3608,3 +3608,25 @@ fn main() {
3608 "#]], 3608 "#]],
3609 ) 3609 )
3610} 3610}
3611
3612#[test]
3613fn fn_returning_unit() {
3614 check_infer_with_mismatches(
3615 r#"
3616#[lang = "fn_once"]
3617trait FnOnce<Args> {
3618 type Output;
3619}
3620
3621fn 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}