diff options
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 5 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/coercion.rs | 101 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 37 |
4 files changed, 138 insertions, 7 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index db3c937ff..edb65622f 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -580,7 +580,10 @@ impl<'a> InferenceContext<'a> { | |||
580 | fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { | 580 | fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { |
581 | let path = path![core::ops::Try]; | 581 | let path = path![core::ops::Try]; |
582 | let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; | 582 | let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; |
583 | self.db.trait_data(trait_).associated_type_by_name(&name![Ok]) | 583 | let trait_data = self.db.trait_data(trait_); |
584 | trait_data | ||
585 | .associated_type_by_name(&name![Ok]) | ||
586 | .or_else(|| trait_data.associated_type_by_name(&name![Output])) | ||
584 | } | 587 | } |
585 | 588 | ||
586 | fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> { | 589 | fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> { |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index eab8fac91..79a732106 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -805,7 +805,7 @@ impl<'a> InferenceContext<'a> { | |||
805 | None => self.table.new_float_var(), | 805 | None => self.table.new_float_var(), |
806 | }, | 806 | }, |
807 | }, | 807 | }, |
808 | Expr::MacroStmts { tail } => self.infer_expr(*tail, expected), | 808 | Expr::MacroStmts { tail } => self.infer_expr_inner(*tail, expected), |
809 | }; | 809 | }; |
810 | // use a new type variable if we got unknown here | 810 | // use a new type variable if we got unknown here |
811 | let ty = self.insert_type_vars_shallow(ty); | 811 | let ty = self.insert_type_vars_shallow(ty); |
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs index bb568ea37..6dac7e103 100644 --- a/crates/hir_ty/src/tests/coercion.rs +++ b/crates/hir_ty/src/tests/coercion.rs | |||
@@ -832,11 +832,9 @@ fn coerce_unsize_super_trait_cycle() { | |||
832 | ); | 832 | ); |
833 | } | 833 | } |
834 | 834 | ||
835 | #[ignore] | ||
836 | #[test] | 835 | #[test] |
837 | fn coerce_unsize_generic() { | 836 | fn coerce_unsize_generic() { |
838 | // FIXME: Implement this | 837 | // FIXME: fix the type mismatches here |
839 | // https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions | ||
840 | check_infer_with_mismatches( | 838 | check_infer_with_mismatches( |
841 | r#" | 839 | r#" |
842 | #[lang = "unsize"] | 840 | #[lang = "unsize"] |
@@ -854,8 +852,58 @@ fn coerce_unsize_generic() { | |||
854 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); | 852 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); |
855 | } | 853 | } |
856 | "#, | 854 | "#, |
857 | expect![[r" | 855 | expect![[r#" |
858 | "]], | 856 | 209..317 '{ ... }); }': () |
857 | 219..220 '_': &Foo<[usize]> | ||
858 | 238..259 '&Foo {..., 3] }': &Foo<[usize]> | ||
859 | 239..259 'Foo { ..., 3] }': Foo<[usize]> | ||
860 | 248..257 '[1, 2, 3]': [usize; 3] | ||
861 | 249..250 '1': usize | ||
862 | 252..253 '2': usize | ||
863 | 255..256 '3': usize | ||
864 | 269..270 '_': &Bar<[usize]> | ||
865 | 288..314 '&Bar(F... 3] })': &Bar<[i32; 3]> | ||
866 | 289..292 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]> | ||
867 | 289..314 'Bar(Fo... 3] })': Bar<[i32; 3]> | ||
868 | 293..313 'Foo { ..., 3] }': Foo<[i32; 3]> | ||
869 | 302..311 '[1, 2, 3]': [i32; 3] | ||
870 | 303..304 '1': i32 | ||
871 | 306..307 '2': i32 | ||
872 | 309..310 '3': i32 | ||
873 | 248..257: expected [usize], got [usize; 3] | ||
874 | 288..314: expected &Bar<[usize]>, got &Bar<[i32; 3]> | ||
875 | "#]], | ||
876 | ); | ||
877 | } | ||
878 | |||
879 | #[test] | ||
880 | fn coerce_unsize_apit() { | ||
881 | // FIXME: #8984 | ||
882 | check_infer_with_mismatches( | ||
883 | r#" | ||
884 | #[lang = "sized"] | ||
885 | pub trait Sized {} | ||
886 | #[lang = "unsize"] | ||
887 | pub trait Unsize<T> {} | ||
888 | #[lang = "coerce_unsized"] | ||
889 | pub trait CoerceUnsized<T> {} | ||
890 | |||
891 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
892 | |||
893 | trait Foo {} | ||
894 | |||
895 | fn test(f: impl Foo) { | ||
896 | let _: &dyn Foo = &f; | ||
897 | } | ||
898 | "#, | ||
899 | expect![[r#" | ||
900 | 210..211 'f': impl Foo | ||
901 | 223..252 '{ ... &f; }': () | ||
902 | 233..234 '_': &dyn Foo | ||
903 | 247..249 '&f': &impl Foo | ||
904 | 248..249 'f': impl Foo | ||
905 | 247..249: expected &dyn Foo, got &impl Foo | ||
906 | "#]], | ||
859 | ); | 907 | ); |
860 | } | 908 | } |
861 | 909 | ||
@@ -912,3 +960,46 @@ fn test() -> i32 { | |||
912 | "#, | 960 | "#, |
913 | ) | 961 | ) |
914 | } | 962 | } |
963 | |||
964 | #[test] | ||
965 | fn panic_macro() { | ||
966 | check_infer_with_mismatches( | ||
967 | r#" | ||
968 | mod panic { | ||
969 | #[macro_export] | ||
970 | pub macro panic_2015 { | ||
971 | () => ( | ||
972 | $crate::panicking::panic() | ||
973 | ), | ||
974 | } | ||
975 | } | ||
976 | |||
977 | mod panicking { | ||
978 | pub fn panic() -> ! { loop {} } | ||
979 | } | ||
980 | |||
981 | #[rustc_builtin_macro = "core_panic"] | ||
982 | macro_rules! panic { | ||
983 | // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021` | ||
984 | // depending on the edition of the caller. | ||
985 | ($($arg:tt)*) => { | ||
986 | /* compiler built-in */ | ||
987 | }; | ||
988 | } | ||
989 | |||
990 | fn main() { | ||
991 | panic!() | ||
992 | } | ||
993 | "#, | ||
994 | expect![[r#" | ||
995 | 174..185 '{ loop {} }': ! | ||
996 | 176..183 'loop {}': ! | ||
997 | 181..183 '{}': () | ||
998 | !0..24 '$crate...:panic': fn panic() -> ! | ||
999 | !0..26 '$crate...anic()': ! | ||
1000 | !0..26 '$crate...anic()': ! | ||
1001 | !0..28 '$crate...015!()': ! | ||
1002 | 454..470 '{ ...c!() }': () | ||
1003 | "#]], | ||
1004 | ); | ||
1005 | } | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index a5a2df54c..71905baeb 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] |
164 | fn infer_tryv2() { | ||
165 | check_types( | ||
166 | r#" | ||
167 | //- /main.rs crate:main deps:core | ||
168 | fn 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::*; | ||
176 | mod ops { | ||
177 | trait Try { | ||
178 | type Output; | ||
179 | type Residual; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | #[prelude_import] use result::*; | ||
184 | mod 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] | ||
164 | fn infer_for_loop() { | 201 | fn infer_for_loop() { |
165 | check_types( | 202 | check_types( |
166 | r#" | 203 | r#" |