aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/display.rs6
-rw-r--r--crates/hir_ty/src/infer.rs7
-rw-r--r--crates/hir_ty/src/tests/traits.rs93
3 files changed, 101 insertions, 5 deletions
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/infer.rs b/crates/hir_ty/src/infer.rs
index 174b7471e..8cefd80f3 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -579,9 +579,14 @@ impl<'a> InferenceContext<'a> {
579 } 579 }
580 580
581 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { 581 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
582 // FIXME resolve via lang_item once try v2 is stable
582 let path = path![core::ops::Try]; 583 let path = path![core::ops::Try];
583 let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; 584 let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
584 self.db.trait_data(trait_).associated_type_by_name(&name![Ok]) 585 let trait_data = self.db.trait_data(trait_);
586 trait_data
587 // FIXME remove once try v2 is stable
588 .associated_type_by_name(&name![Ok])
589 .or_else(|| trait_data.associated_type_by_name(&name![Output]))
585 } 590 }
586 591
587 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> { 592 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index a5a2df54c..6ad96bfe3 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -161,6 +161,43 @@ mod result {
161} 161}
162 162
163#[test] 163#[test]
164fn infer_tryv2() {
165 check_types(
166 r#"
167//- /main.rs crate:main deps:core
168fn test() {
169 let r: Result<i32, u64> = Result::Ok(1);
170 let v = r?;
171 v;
172} //^ i32
173
174//- /core.rs crate:core
175#[prelude_import] use ops::*;
176mod ops {
177 trait Try {
178 type Output;
179 type Residual;
180 }
181}
182
183#[prelude_import] use result::*;
184mod result {
185 enum Infallible {}
186 enum Result<O, E> {
187 Ok(O),
188 Err(E)
189 }
190
191 impl<O, E> crate::ops::Try for Result<O, E> {
192 type Output = O;
193 type Error = Result<Infallible, E>;
194 }
195}
196"#,
197 );
198}
199
200#[test]
164fn infer_for_loop() { 201fn infer_for_loop() {
165 check_types( 202 check_types(
166 r#" 203 r#"
@@ -3041,7 +3078,7 @@ fn infer_fn_trait_arg() {
3041 3078
3042#[test] 3079#[test]
3043fn infer_box_fn_arg() { 3080fn infer_box_fn_arg() {
3044 // The type mismatch is a bug 3081 // The type mismatch is because we don't define Unsize and CoerceUnsized
3045 check_infer_with_mismatches( 3082 check_infer_with_mismatches(
3046 r#" 3083 r#"
3047//- /lib.rs deps:std 3084//- /lib.rs deps:std
@@ -3101,7 +3138,7 @@ fn foo() {
3101 555..557 'ps': {unknown} 3138 555..557 'ps': {unknown}
3102 559..561 '{}': () 3139 559..561 '{}': ()
3103 568..569 'f': Box<dyn FnOnce(&Option<i32>)> 3140 568..569 'f': Box<dyn FnOnce(&Option<i32>)>
3104 568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)> 3141 568..573 'f(&s)': ()
3105 570..572 '&s': &Option<i32> 3142 570..572 '&s': &Option<i32>
3106 571..572 's': Option<i32> 3143 571..572 's': Option<i32>
3107 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()> 3144 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()>
@@ -3571,3 +3608,55 @@ fn main() {
3571 "#]], 3608 "#]],
3572 ) 3609 )
3573} 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}
3633
3634#[test]
3635fn trait_in_scope_of_trait_impl() {
3636 check_infer(
3637 r#"
3638mod foo {
3639 pub trait Foo {
3640 fn foo(self);
3641 fn bar(self) -> usize { 0 }
3642 }
3643}
3644impl foo::Foo for u32 {
3645 fn foo(self) {
3646 let _x = self.bar();
3647 }
3648}
3649 "#,
3650 expect![[r#"
3651 45..49 'self': Self
3652 67..71 'self': Self
3653 82..87 '{ 0 }': usize
3654 84..85 '0': usize
3655 131..135 'self': u32
3656 137..173 '{ ... }': ()
3657 151..153 '_x': usize
3658 156..160 'self': u32
3659 156..166 'self.bar()': usize
3660 "#]],
3661 );
3662}