diff options
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 27 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 26 |
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] |
3080 | fn infer_box_fn_arg() { | 3080 | 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 |
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] | ||
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 | } | ||