diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-26 09:19:18 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-26 09:19:18 +0100 |
commit | 79376abb43e3e1e607b5307e85dd43251ad6c5e3 (patch) | |
tree | 03ab755672e9b973bbcbb9fd86f9d2fdf4f0e1ba | |
parent | 6c1878009db50b81fd70b7eb93a76d57a366c7ba (diff) | |
parent | 29e56b8ee480828b81011cfa16c055fa0c9c89fe (diff) |
Merge #1823
1823: Support type coercion r=flodiebold a=uHOOCCOOHu
Co-authored-by: uHOOCCOOHu <[email protected]>
-rw-r--r-- | crates/ra_hir/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 529 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/unify.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 329 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/coercion.rs | 369 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/never_type.rs | 246 |
6 files changed, 1218 insertions, 257 deletions
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs index fe119b97c..b2111be05 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs | |||
@@ -13,4 +13,5 @@ test_utils::marks!( | |||
13 | infer_while_let | 13 | infer_while_let |
14 | macro_rules_from_other_crates_are_visible_with_macro_use | 14 | macro_rules_from_other_crates_are_visible_with_macro_use |
15 | prelude_is_macro_use | 15 | prelude_is_macro_use |
16 | coerce_merge_fail_fallback | ||
16 | ); | 17 | ); |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 76b4b6faa..db3377357 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -14,7 +14,7 @@ | |||
14 | //! the `ena` crate, which is extracted from rustc. | 14 | //! the `ena` crate, which is extracted from rustc. |
15 | 15 | ||
16 | use std::borrow::Cow; | 16 | use std::borrow::Cow; |
17 | use std::iter::repeat; | 17 | use std::iter::{repeat, repeat_with}; |
18 | use std::mem; | 18 | use std::mem; |
19 | use std::ops::Index; | 19 | use std::ops::Index; |
20 | use std::sync::Arc; | 20 | use std::sync::Arc; |
@@ -42,6 +42,7 @@ use crate::{ | |||
42 | RecordFieldPat, Statement, UnaryOp, | 42 | RecordFieldPat, Statement, UnaryOp, |
43 | }, | 43 | }, |
44 | generics::{GenericParams, HasGenericParams}, | 44 | generics::{GenericParams, HasGenericParams}, |
45 | lang_item::LangItemTarget, | ||
45 | name, | 46 | name, |
46 | nameres::Namespace, | 47 | nameres::Namespace, |
47 | path::{known, GenericArg, GenericArgs}, | 48 | path::{known, GenericArg, GenericArgs}, |
@@ -188,6 +189,21 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
188 | result: InferenceResult, | 189 | result: InferenceResult, |
189 | /// The return type of the function being inferred. | 190 | /// The return type of the function being inferred. |
190 | return_ty: Ty, | 191 | return_ty: Ty, |
192 | |||
193 | /// Impls of `CoerceUnsized` used in coercion. | ||
194 | /// (from_ty_ctor, to_ty_ctor) => coerce_generic_index | ||
195 | // FIXME: Use trait solver for this. | ||
196 | // Chalk seems unable to work well with builtin impl of `Unsize` now. | ||
197 | coerce_unsized_map: FxHashMap<(TypeCtor, TypeCtor), usize>, | ||
198 | } | ||
199 | |||
200 | macro_rules! ty_app { | ||
201 | ($ctor:pat, $param:pat) => { | ||
202 | Ty::Apply(ApplicationTy { ctor: $ctor, parameters: $param }) | ||
203 | }; | ||
204 | ($ctor:pat) => { | ||
205 | ty_app!($ctor, _) | ||
206 | }; | ||
191 | } | 207 | } |
192 | 208 | ||
193 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 209 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
@@ -198,12 +214,52 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
198 | obligations: Vec::default(), | 214 | obligations: Vec::default(), |
199 | return_ty: Ty::Unknown, // set in collect_fn_signature | 215 | return_ty: Ty::Unknown, // set in collect_fn_signature |
200 | trait_env: lower::trait_env(db, &resolver), | 216 | trait_env: lower::trait_env(db, &resolver), |
217 | coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), | ||
201 | db, | 218 | db, |
202 | body, | 219 | body, |
203 | resolver, | 220 | resolver, |
204 | } | 221 | } |
205 | } | 222 | } |
206 | 223 | ||
224 | fn init_coerce_unsized_map( | ||
225 | db: &'a D, | ||
226 | resolver: &Resolver, | ||
227 | ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { | ||
228 | let krate = resolver.krate().unwrap(); | ||
229 | let impls = match db.lang_item(krate, "coerce_unsized".into()) { | ||
230 | Some(LangItemTarget::Trait(trait_)) => db.impls_for_trait(krate, trait_), | ||
231 | _ => return FxHashMap::default(), | ||
232 | }; | ||
233 | |||
234 | impls | ||
235 | .iter() | ||
236 | .filter_map(|impl_block| { | ||
237 | // `CoerseUnsized` has one generic parameter for the target type. | ||
238 | let trait_ref = impl_block.target_trait_ref(db)?; | ||
239 | let cur_from_ty = trait_ref.substs.0.get(0)?; | ||
240 | let cur_to_ty = trait_ref.substs.0.get(1)?; | ||
241 | |||
242 | match (&cur_from_ty, cur_to_ty) { | ||
243 | (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => { | ||
244 | // FIXME: We return the first non-equal bound as the type parameter to coerce to unsized type. | ||
245 | // This works for smart-pointer-like coercion, which covers all impls from std. | ||
246 | st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| { | ||
247 | match (ty1, ty2) { | ||
248 | (Ty::Param { idx: p1, .. }, Ty::Param { idx: p2, .. }) | ||
249 | if p1 != p2 => | ||
250 | { | ||
251 | Some(((*ctor1, *ctor2), i)) | ||
252 | } | ||
253 | _ => None, | ||
254 | } | ||
255 | }) | ||
256 | } | ||
257 | _ => None, | ||
258 | } | ||
259 | }) | ||
260 | .collect() | ||
261 | } | ||
262 | |||
207 | fn resolve_all(mut self) -> InferenceResult { | 263 | fn resolve_all(mut self) -> InferenceResult { |
208 | // FIXME resolve obligations as well (use Guidance if necessary) | 264 | // FIXME resolve obligations as well (use Guidance if necessary) |
209 | let mut result = mem::replace(&mut self.result, InferenceResult::default()); | 265 | let mut result = mem::replace(&mut self.result, InferenceResult::default()); |
@@ -278,27 +334,45 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
278 | let ty1 = self.resolve_ty_shallow(ty1); | 334 | let ty1 = self.resolve_ty_shallow(ty1); |
279 | let ty2 = self.resolve_ty_shallow(ty2); | 335 | let ty2 = self.resolve_ty_shallow(ty2); |
280 | match (&*ty1, &*ty2) { | 336 | match (&*ty1, &*ty2) { |
281 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, | ||
282 | (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { | 337 | (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { |
283 | self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) | 338 | self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) |
284 | } | 339 | } |
340 | _ => self.unify_inner_trivial(&ty1, &ty2), | ||
341 | } | ||
342 | } | ||
343 | |||
344 | fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | ||
345 | match (ty1, ty2) { | ||
346 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, | ||
347 | |||
285 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | 348 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) |
286 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | 349 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) |
287 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { | 350 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) |
351 | | ( | ||
352 | Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)), | ||
353 | Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)), | ||
354 | ) => { | ||
288 | // both type vars are unknown since we tried to resolve them | 355 | // both type vars are unknown since we tried to resolve them |
289 | self.var_unification_table.union(*tv1, *tv2); | 356 | self.var_unification_table.union(*tv1, *tv2); |
290 | true | 357 | true |
291 | } | 358 | } |
359 | |||
360 | // The order of MaybeNeverTypeVar matters here. | ||
361 | // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. | ||
362 | // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. | ||
292 | (Ty::Infer(InferTy::TypeVar(tv)), other) | 363 | (Ty::Infer(InferTy::TypeVar(tv)), other) |
293 | | (other, Ty::Infer(InferTy::TypeVar(tv))) | 364 | | (other, Ty::Infer(InferTy::TypeVar(tv))) |
294 | | (Ty::Infer(InferTy::IntVar(tv)), other) | 365 | | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other) |
295 | | (other, Ty::Infer(InferTy::IntVar(tv))) | 366 | | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv))) |
296 | | (Ty::Infer(InferTy::FloatVar(tv)), other) | 367 | | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_))) |
297 | | (other, Ty::Infer(InferTy::FloatVar(tv))) => { | 368 | | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv))) |
369 | | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_))) | ||
370 | | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => { | ||
298 | // the type var is unknown since we tried to resolve it | 371 | // the type var is unknown since we tried to resolve it |
299 | self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); | 372 | self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); |
300 | true | 373 | true |
301 | } | 374 | } |
375 | |||
302 | _ => false, | 376 | _ => false, |
303 | } | 377 | } |
304 | } | 378 | } |
@@ -315,6 +389,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
315 | Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) | 389 | Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) |
316 | } | 390 | } |
317 | 391 | ||
392 | fn new_maybe_never_type_var(&mut self) -> Ty { | ||
393 | Ty::Infer(InferTy::MaybeNeverTypeVar( | ||
394 | self.var_unification_table.new_key(TypeVarValue::Unknown), | ||
395 | )) | ||
396 | } | ||
397 | |||
318 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 398 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
319 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 399 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
320 | match ty { | 400 | match ty { |
@@ -795,17 +875,304 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
795 | ret_ty | 875 | ret_ty |
796 | } | 876 | } |
797 | 877 | ||
798 | /// This is similar to unify, but it makes the first type coerce to the | 878 | /// Infer type of expression with possibly implicit coerce to the expected type. |
799 | /// second one. | 879 | /// Return the type after possible coercion. |
800 | fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { | 880 | fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { |
801 | if is_never(from_ty) { | 881 | let ty = self.infer_expr_inner(expr, &expected); |
802 | // ! coerces to any type | 882 | let ty = if !self.coerce(&ty, &expected.ty) { |
803 | true | 883 | self.result |
884 | .type_mismatches | ||
885 | .insert(expr, TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }); | ||
886 | // Return actual type when type mismatch. | ||
887 | // This is needed for diagnostic when return type mismatch. | ||
888 | ty | ||
889 | } else if expected.ty == Ty::Unknown { | ||
890 | ty | ||
804 | } else { | 891 | } else { |
805 | self.unify(from_ty, to_ty) | 892 | expected.ty.clone() |
893 | }; | ||
894 | |||
895 | self.resolve_ty_as_possible(&mut vec![], ty) | ||
896 | } | ||
897 | |||
898 | /// Merge two types from different branches, with possible implicit coerce. | ||
899 | /// | ||
900 | /// Note that it is only possible that one type are coerced to another. | ||
901 | /// Coercing both types to another least upper bound type is not possible in rustc, | ||
902 | /// which will simply result in "incompatible types" error. | ||
903 | fn coerce_merge_branch<'t>(&mut self, ty1: &Ty, ty2: &Ty) -> Ty { | ||
904 | if self.coerce(ty1, ty2) { | ||
905 | ty2.clone() | ||
906 | } else if self.coerce(ty2, ty1) { | ||
907 | ty1.clone() | ||
908 | } else { | ||
909 | tested_by!(coerce_merge_fail_fallback); | ||
910 | // For incompatible types, we use the latter one as result | ||
911 | // to be better recovery for `if` without `else`. | ||
912 | ty2.clone() | ||
913 | } | ||
914 | } | ||
915 | |||
916 | /// Unify two types, but may coerce the first one to the second one | ||
917 | /// using "implicit coercion rules" if needed. | ||
918 | /// | ||
919 | /// See: https://doc.rust-lang.org/nomicon/coercions.html | ||
920 | fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { | ||
921 | let from_ty = self.resolve_ty_shallow(from_ty).into_owned(); | ||
922 | let to_ty = self.resolve_ty_shallow(to_ty); | ||
923 | self.coerce_inner(from_ty, &to_ty) | ||
924 | } | ||
925 | |||
926 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { | ||
927 | match (&from_ty, to_ty) { | ||
928 | // Never type will make type variable to fallback to Never Type instead of Unknown. | ||
929 | (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { | ||
930 | let var = self.new_maybe_never_type_var(); | ||
931 | self.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); | ||
932 | return true; | ||
933 | } | ||
934 | (ty_app!(TypeCtor::Never), _) => return true, | ||
935 | |||
936 | // Trivial cases, this should go after `never` check to | ||
937 | // avoid infer result type to be never | ||
938 | _ => { | ||
939 | if self.unify_inner_trivial(&from_ty, &to_ty) { | ||
940 | return true; | ||
941 | } | ||
942 | } | ||
943 | } | ||
944 | |||
945 | // Pointer weakening and function to pointer | ||
946 | match (&mut from_ty, to_ty) { | ||
947 | // `*mut T`, `&mut T, `&T`` -> `*const T` | ||
948 | // `&mut T` -> `&T` | ||
949 | // `&mut T` -> `*mut T` | ||
950 | (ty_app!(c1@TypeCtor::RawPtr(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) | ||
951 | | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) | ||
952 | | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::Ref(Mutability::Shared))) | ||
953 | | (ty_app!(c1@TypeCtor::Ref(Mutability::Mut)), ty_app!(c2@TypeCtor::RawPtr(_))) => { | ||
954 | *c1 = *c2; | ||
955 | } | ||
956 | |||
957 | // Illegal mutablity conversion | ||
958 | ( | ||
959 | ty_app!(TypeCtor::RawPtr(Mutability::Shared)), | ||
960 | ty_app!(TypeCtor::RawPtr(Mutability::Mut)), | ||
961 | ) | ||
962 | | ( | ||
963 | ty_app!(TypeCtor::Ref(Mutability::Shared)), | ||
964 | ty_app!(TypeCtor::Ref(Mutability::Mut)), | ||
965 | ) => return false, | ||
966 | |||
967 | // `{function_type}` -> `fn()` | ||
968 | (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnPtr { .. })) => { | ||
969 | match from_ty.callable_sig(self.db) { | ||
970 | None => return false, | ||
971 | Some(sig) => { | ||
972 | let num_args = sig.params_and_return.len() as u16 - 1; | ||
973 | from_ty = | ||
974 | Ty::apply(TypeCtor::FnPtr { num_args }, Substs(sig.params_and_return)); | ||
975 | } | ||
976 | } | ||
977 | } | ||
978 | |||
979 | _ => {} | ||
980 | } | ||
981 | |||
982 | if let Some(ret) = self.try_coerce_unsized(&from_ty, &to_ty) { | ||
983 | return ret; | ||
984 | } | ||
985 | |||
986 | // Auto Deref if cannot coerce | ||
987 | match (&from_ty, to_ty) { | ||
988 | // FIXME: DerefMut | ||
989 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) => { | ||
990 | self.unify_autoderef_behind_ref(&st1[0], &st2[0]) | ||
991 | } | ||
992 | |||
993 | // Otherwise, normal unify | ||
994 | _ => self.unify(&from_ty, to_ty), | ||
995 | } | ||
996 | } | ||
997 | |||
998 | /// Coerce a type using `from_ty: CoerceUnsized<ty_ty>` | ||
999 | /// | ||
1000 | /// See: https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html | ||
1001 | fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> Option<bool> { | ||
1002 | let (ctor1, st1, ctor2, st2) = match (from_ty, to_ty) { | ||
1003 | (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => (ctor1, st1, ctor2, st2), | ||
1004 | _ => return None, | ||
1005 | }; | ||
1006 | |||
1007 | let coerce_generic_index = *self.coerce_unsized_map.get(&(*ctor1, *ctor2))?; | ||
1008 | |||
1009 | // Check `Unsize` first | ||
1010 | match self.check_unsize_and_coerce( | ||
1011 | st1.0.get(coerce_generic_index)?, | ||
1012 | st2.0.get(coerce_generic_index)?, | ||
1013 | 0, | ||
1014 | ) { | ||
1015 | Some(true) => {} | ||
1016 | ret => return ret, | ||
1017 | } | ||
1018 | |||
1019 | let ret = st1 | ||
1020 | .iter() | ||
1021 | .zip(st2.iter()) | ||
1022 | .enumerate() | ||
1023 | .filter(|&(idx, _)| idx != coerce_generic_index) | ||
1024 | .all(|(_, (ty1, ty2))| self.unify(ty1, ty2)); | ||
1025 | |||
1026 | Some(ret) | ||
1027 | } | ||
1028 | |||
1029 | /// Check if `from_ty: Unsize<to_ty>`, and coerce to `to_ty` if it holds. | ||
1030 | /// | ||
1031 | /// It should not be directly called. It is only used by `try_coerce_unsized`. | ||
1032 | /// | ||
1033 | /// See: https://doc.rust-lang.org/nightly/std/marker/trait.Unsize.html | ||
1034 | fn check_unsize_and_coerce(&mut self, from_ty: &Ty, to_ty: &Ty, depth: usize) -> Option<bool> { | ||
1035 | if depth > 1000 { | ||
1036 | panic!("Infinite recursion in coercion"); | ||
1037 | } | ||
1038 | |||
1039 | match (&from_ty, &to_ty) { | ||
1040 | // `[T; N]` -> `[T]` | ||
1041 | (ty_app!(TypeCtor::Array, st1), ty_app!(TypeCtor::Slice, st2)) => { | ||
1042 | Some(self.unify(&st1[0], &st2[0])) | ||
1043 | } | ||
1044 | |||
1045 | // `T` -> `dyn Trait` when `T: Trait` | ||
1046 | (_, Ty::Dyn(_)) => { | ||
1047 | // FIXME: Check predicates | ||
1048 | Some(true) | ||
1049 | } | ||
1050 | |||
1051 | // `(..., T)` -> `(..., U)` when `T: Unsize<U>` | ||
1052 | ( | ||
1053 | ty_app!(TypeCtor::Tuple { cardinality: len1 }, st1), | ||
1054 | ty_app!(TypeCtor::Tuple { cardinality: len2 }, st2), | ||
1055 | ) => { | ||
1056 | if len1 != len2 || *len1 == 0 { | ||
1057 | return None; | ||
1058 | } | ||
1059 | |||
1060 | match self.check_unsize_and_coerce( | ||
1061 | st1.last().unwrap(), | ||
1062 | st2.last().unwrap(), | ||
1063 | depth + 1, | ||
1064 | ) { | ||
1065 | Some(true) => {} | ||
1066 | ret => return ret, | ||
1067 | } | ||
1068 | |||
1069 | let ret = st1[..st1.len() - 1] | ||
1070 | .iter() | ||
1071 | .zip(&st2[..st2.len() - 1]) | ||
1072 | .all(|(ty1, ty2)| self.unify(ty1, ty2)); | ||
1073 | |||
1074 | Some(ret) | ||
1075 | } | ||
1076 | |||
1077 | // Foo<..., T, ...> is Unsize<Foo<..., U, ...>> if: | ||
1078 | // - T: Unsize<U> | ||
1079 | // - Foo is a struct | ||
1080 | // - Only the last field of Foo has a type involving T | ||
1081 | // - T is not part of the type of any other fields | ||
1082 | // - Bar<T>: Unsize<Bar<U>>, if the last field of Foo has type Bar<T> | ||
1083 | ( | ||
1084 | ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), | ||
1085 | ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), | ||
1086 | ) if struct1 == struct2 => { | ||
1087 | let fields = struct1.fields(self.db); | ||
1088 | let (last_field, prev_fields) = fields.split_last()?; | ||
1089 | |||
1090 | // Get the generic parameter involved in the last field. | ||
1091 | let unsize_generic_index = { | ||
1092 | let mut index = None; | ||
1093 | let mut multiple_param = false; | ||
1094 | last_field.ty(self.db).walk(&mut |ty| match ty { | ||
1095 | &Ty::Param { idx, .. } => { | ||
1096 | if index.is_none() { | ||
1097 | index = Some(idx); | ||
1098 | } else if Some(idx) != index { | ||
1099 | multiple_param = true; | ||
1100 | } | ||
1101 | } | ||
1102 | _ => {} | ||
1103 | }); | ||
1104 | |||
1105 | if multiple_param { | ||
1106 | return None; | ||
1107 | } | ||
1108 | index? | ||
1109 | }; | ||
1110 | |||
1111 | // Check other fields do not involve it. | ||
1112 | let mut multiple_used = false; | ||
1113 | prev_fields.iter().for_each(|field| { | ||
1114 | field.ty(self.db).walk(&mut |ty| match ty { | ||
1115 | &Ty::Param { idx, .. } if idx == unsize_generic_index => { | ||
1116 | multiple_used = true | ||
1117 | } | ||
1118 | _ => {} | ||
1119 | }) | ||
1120 | }); | ||
1121 | if multiple_used { | ||
1122 | return None; | ||
1123 | } | ||
1124 | |||
1125 | let unsize_generic_index = unsize_generic_index as usize; | ||
1126 | |||
1127 | // Check `Unsize` first | ||
1128 | match self.check_unsize_and_coerce( | ||
1129 | st1.get(unsize_generic_index)?, | ||
1130 | st2.get(unsize_generic_index)?, | ||
1131 | depth + 1, | ||
1132 | ) { | ||
1133 | Some(true) => {} | ||
1134 | ret => return ret, | ||
1135 | } | ||
1136 | |||
1137 | // Then unify other parameters | ||
1138 | let ret = st1 | ||
1139 | .iter() | ||
1140 | .zip(st2.iter()) | ||
1141 | .enumerate() | ||
1142 | .filter(|&(idx, _)| idx != unsize_generic_index) | ||
1143 | .all(|(_, (ty1, ty2))| self.unify(ty1, ty2)); | ||
1144 | |||
1145 | Some(ret) | ||
1146 | } | ||
1147 | |||
1148 | _ => None, | ||
806 | } | 1149 | } |
807 | } | 1150 | } |
808 | 1151 | ||
1152 | /// Unify `from_ty` to `to_ty` with optional auto Deref | ||
1153 | /// | ||
1154 | /// Note that the parameters are already stripped the outer reference. | ||
1155 | fn unify_autoderef_behind_ref(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { | ||
1156 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); | ||
1157 | let to_ty = self.resolve_ty_shallow(&to_ty); | ||
1158 | // FIXME: Auto DerefMut | ||
1159 | for derefed_ty in | ||
1160 | autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) | ||
1161 | { | ||
1162 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | ||
1163 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { | ||
1164 | // Stop when constructor matches. | ||
1165 | (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { | ||
1166 | // It will not recurse to `coerce`. | ||
1167 | return self.unify_substs(st1, st2, 0); | ||
1168 | } | ||
1169 | _ => {} | ||
1170 | } | ||
1171 | } | ||
1172 | |||
1173 | false | ||
1174 | } | ||
1175 | |||
809 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 1176 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
810 | let ty = self.infer_expr_inner(tgt_expr, expected); | 1177 | let ty = self.infer_expr_inner(tgt_expr, expected); |
811 | let could_unify = self.unify(&ty, &expected.ty); | 1178 | let could_unify = self.unify(&ty, &expected.ty); |
@@ -828,15 +1195,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
828 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 1195 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
829 | 1196 | ||
830 | let then_ty = self.infer_expr_inner(*then_branch, &expected); | 1197 | let then_ty = self.infer_expr_inner(*then_branch, &expected); |
831 | self.coerce(&then_ty, &expected.ty); | ||
832 | |||
833 | let else_ty = match else_branch { | 1198 | let else_ty = match else_branch { |
834 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), | 1199 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), |
835 | None => Ty::unit(), | 1200 | None => Ty::unit(), |
836 | }; | 1201 | }; |
837 | self.coerce(&else_ty, &expected.ty); | ||
838 | 1202 | ||
839 | expected.ty.clone() | 1203 | self.coerce_merge_branch(&then_ty, &else_ty) |
840 | } | 1204 | } |
841 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), | 1205 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), |
842 | Expr::TryBlock { body } => { | 1206 | Expr::TryBlock { body } => { |
@@ -932,13 +1296,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
932 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), | 1296 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), |
933 | Expr::Match { expr, arms } => { | 1297 | Expr::Match { expr, arms } => { |
934 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | 1298 | let input_ty = self.infer_expr(*expr, &Expectation::none()); |
935 | let expected = if expected.ty == Ty::Unknown { | ||
936 | Expectation::has_type(self.new_type_var()) | ||
937 | } else { | ||
938 | expected.clone() | ||
939 | }; | ||
940 | 1299 | ||
941 | let mut arm_tys = Vec::with_capacity(arms.len()); | 1300 | let mut result_ty = self.new_maybe_never_type_var(); |
942 | 1301 | ||
943 | for arm in arms { | 1302 | for arm in arms { |
944 | for &pat in &arm.pats { | 1303 | for &pat in &arm.pats { |
@@ -950,16 +1309,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
950 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), | 1309 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), |
951 | ); | 1310 | ); |
952 | } | 1311 | } |
953 | arm_tys.push(self.infer_expr_inner(arm.expr, &expected)); | ||
954 | } | ||
955 | |||
956 | let lub_ty = calculate_least_upper_bound(expected.ty, &arm_tys); | ||
957 | 1312 | ||
958 | for arm_ty in &arm_tys { | 1313 | let arm_ty = self.infer_expr_inner(arm.expr, &expected); |
959 | self.coerce(arm_ty, &lub_ty); | 1314 | result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); |
960 | } | 1315 | } |
961 | 1316 | ||
962 | lub_ty | 1317 | result_ty |
963 | } | 1318 | } |
964 | Expr::Path(p) => { | 1319 | Expr::Path(p) => { |
965 | // FIXME this could be more efficient... | 1320 | // FIXME this could be more efficient... |
@@ -986,6 +1341,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
986 | self.write_variant_resolution(tgt_expr.into(), variant); | 1341 | self.write_variant_resolution(tgt_expr.into(), variant); |
987 | } | 1342 | } |
988 | 1343 | ||
1344 | self.unify(&ty, &expected.ty); | ||
1345 | |||
989 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 1346 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
990 | for (field_idx, field) in fields.iter().enumerate() { | 1347 | for (field_idx, field) in fields.iter().enumerate() { |
991 | let field_ty = def_id | 1348 | let field_ty = def_id |
@@ -1001,7 +1358,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1001 | }) | 1358 | }) |
1002 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 1359 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
1003 | .subst(&substs); | 1360 | .subst(&substs); |
1004 | self.infer_expr(field.expr, &Expectation::has_type(field_ty)); | 1361 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); |
1005 | } | 1362 | } |
1006 | if let Some(expr) = spread { | 1363 | if let Some(expr) = spread { |
1007 | self.infer_expr(*expr, &Expectation::has_type(ty.clone())); | 1364 | self.infer_expr(*expr, &Expectation::has_type(ty.clone())); |
@@ -1171,35 +1528,41 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1171 | Ty::Unknown | 1528 | Ty::Unknown |
1172 | } | 1529 | } |
1173 | Expr::Tuple { exprs } => { | 1530 | Expr::Tuple { exprs } => { |
1174 | let mut ty_vec = Vec::with_capacity(exprs.len()); | 1531 | let mut tys = match &expected.ty { |
1175 | for arg in exprs.iter() { | 1532 | ty_app!(TypeCtor::Tuple { .. }, st) => st |
1176 | ty_vec.push(self.infer_expr(*arg, &Expectation::none())); | 1533 | .iter() |
1534 | .cloned() | ||
1535 | .chain(repeat_with(|| self.new_type_var())) | ||
1536 | .take(exprs.len()) | ||
1537 | .collect::<Vec<_>>(), | ||
1538 | _ => (0..exprs.len()).map(|_| self.new_type_var()).collect(), | ||
1539 | }; | ||
1540 | |||
1541 | for (expr, ty) in exprs.iter().zip(tys.iter_mut()) { | ||
1542 | self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); | ||
1177 | } | 1543 | } |
1178 | 1544 | ||
1179 | Ty::apply( | 1545 | Ty::apply(TypeCtor::Tuple { cardinality: tys.len() as u16 }, Substs(tys.into())) |
1180 | TypeCtor::Tuple { cardinality: ty_vec.len() as u16 }, | ||
1181 | Substs(ty_vec.into()), | ||
1182 | ) | ||
1183 | } | 1546 | } |
1184 | Expr::Array(array) => { | 1547 | Expr::Array(array) => { |
1185 | let elem_ty = match &expected.ty { | 1548 | let elem_ty = match &expected.ty { |
1186 | Ty::Apply(a_ty) => match a_ty.ctor { | 1549 | ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => { |
1187 | TypeCtor::Slice | TypeCtor::Array => { | 1550 | st.as_single().clone() |
1188 | Ty::clone(&a_ty.parameters.as_single()) | 1551 | } |
1189 | } | ||
1190 | _ => self.new_type_var(), | ||
1191 | }, | ||
1192 | _ => self.new_type_var(), | 1552 | _ => self.new_type_var(), |
1193 | }; | 1553 | }; |
1194 | 1554 | ||
1195 | match array { | 1555 | match array { |
1196 | Array::ElementList(items) => { | 1556 | Array::ElementList(items) => { |
1197 | for expr in items.iter() { | 1557 | for expr in items.iter() { |
1198 | self.infer_expr(*expr, &Expectation::has_type(elem_ty.clone())); | 1558 | self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone())); |
1199 | } | 1559 | } |
1200 | } | 1560 | } |
1201 | Array::Repeat { initializer, repeat } => { | 1561 | Array::Repeat { initializer, repeat } => { |
1202 | self.infer_expr(*initializer, &Expectation::has_type(elem_ty.clone())); | 1562 | self.infer_expr_coerce( |
1563 | *initializer, | ||
1564 | &Expectation::has_type(elem_ty.clone()), | ||
1565 | ); | ||
1203 | self.infer_expr( | 1566 | self.infer_expr( |
1204 | *repeat, | 1567 | *repeat, |
1205 | &Expectation::has_type(Ty::simple(TypeCtor::Int( | 1568 | &Expectation::has_type(Ty::simple(TypeCtor::Int( |
@@ -1246,14 +1609,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1246 | Statement::Let { pat, type_ref, initializer } => { | 1609 | Statement::Let { pat, type_ref, initializer } => { |
1247 | let decl_ty = | 1610 | let decl_ty = |
1248 | type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); | 1611 | type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); |
1249 | let decl_ty = self.insert_type_vars(decl_ty); | ||
1250 | let ty = if let Some(expr) = initializer { | ||
1251 | let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); | ||
1252 | expr_ty | ||
1253 | } else { | ||
1254 | decl_ty | ||
1255 | }; | ||
1256 | 1612 | ||
1613 | // Always use the declared type when specified | ||
1614 | let mut ty = decl_ty.clone(); | ||
1615 | |||
1616 | if let Some(expr) = initializer { | ||
1617 | let actual_ty = | ||
1618 | self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone())); | ||
1619 | if decl_ty == Ty::Unknown { | ||
1620 | ty = actual_ty; | ||
1621 | } | ||
1622 | } | ||
1623 | |||
1624 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); | ||
1257 | self.infer_pat(*pat, &ty, BindingMode::default()); | 1625 | self.infer_pat(*pat, &ty, BindingMode::default()); |
1258 | } | 1626 | } |
1259 | Statement::Expr(expr) => { | 1627 | Statement::Expr(expr) => { |
@@ -1261,9 +1629,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1261 | } | 1629 | } |
1262 | } | 1630 | } |
1263 | } | 1631 | } |
1264 | let ty = | 1632 | |
1265 | if let Some(expr) = tail { self.infer_expr_inner(expr, expected) } else { Ty::unit() }; | 1633 | if let Some(expr) = tail { |
1266 | ty | 1634 | self.infer_expr_coerce(expr, expected) |
1635 | } else { | ||
1636 | self.coerce(&Ty::unit(), &expected.ty); | ||
1637 | Ty::unit() | ||
1638 | } | ||
1267 | } | 1639 | } |
1268 | 1640 | ||
1269 | fn check_call_arguments(&mut self, args: &[ExprId], param_tys: &[Ty]) { | 1641 | fn check_call_arguments(&mut self, args: &[ExprId], param_tys: &[Ty]) { |
@@ -1285,7 +1657,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1285 | } | 1657 | } |
1286 | 1658 | ||
1287 | let param_ty = self.normalize_associated_types_in(param_ty); | 1659 | let param_ty = self.normalize_associated_types_in(param_ty); |
1288 | self.infer_expr(arg, &Expectation::has_type(param_ty)); | 1660 | self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); |
1289 | } | 1661 | } |
1290 | } | 1662 | } |
1291 | } | 1663 | } |
@@ -1400,12 +1772,16 @@ pub enum InferTy { | |||
1400 | TypeVar(TypeVarId), | 1772 | TypeVar(TypeVarId), |
1401 | IntVar(TypeVarId), | 1773 | IntVar(TypeVarId), |
1402 | FloatVar(TypeVarId), | 1774 | FloatVar(TypeVarId), |
1775 | MaybeNeverTypeVar(TypeVarId), | ||
1403 | } | 1776 | } |
1404 | 1777 | ||
1405 | impl InferTy { | 1778 | impl InferTy { |
1406 | fn to_inner(self) -> TypeVarId { | 1779 | fn to_inner(self) -> TypeVarId { |
1407 | match self { | 1780 | match self { |
1408 | InferTy::TypeVar(ty) | InferTy::IntVar(ty) | InferTy::FloatVar(ty) => ty, | 1781 | InferTy::TypeVar(ty) |
1782 | | InferTy::IntVar(ty) | ||
1783 | | InferTy::FloatVar(ty) | ||
1784 | | InferTy::MaybeNeverTypeVar(ty) => ty, | ||
1409 | } | 1785 | } |
1410 | } | 1786 | } |
1411 | 1787 | ||
@@ -1418,6 +1794,7 @@ impl InferTy { | |||
1418 | InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float( | 1794 | InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float( |
1419 | primitive::UncertainFloatTy::Known(primitive::FloatTy::f64()), | 1795 | primitive::UncertainFloatTy::Known(primitive::FloatTy::f64()), |
1420 | )), | 1796 | )), |
1797 | InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never), | ||
1421 | } | 1798 | } |
1422 | } | 1799 | } |
1423 | } | 1800 | } |
@@ -1475,37 +1852,3 @@ mod diagnostics { | |||
1475 | } | 1852 | } |
1476 | } | 1853 | } |
1477 | } | 1854 | } |
1478 | |||
1479 | fn is_never(ty: &Ty) -> bool { | ||
1480 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) = ty { | ||
1481 | true | ||
1482 | } else { | ||
1483 | false | ||
1484 | } | ||
1485 | } | ||
1486 | |||
1487 | fn calculate_least_upper_bound(expected_ty: Ty, actual_tys: &[Ty]) -> Ty { | ||
1488 | let mut all_never = true; | ||
1489 | let mut last_never_ty = None; | ||
1490 | let mut least_upper_bound = expected_ty; | ||
1491 | |||
1492 | for actual_ty in actual_tys { | ||
1493 | if is_never(actual_ty) { | ||
1494 | last_never_ty = Some(actual_ty.clone()); | ||
1495 | } else { | ||
1496 | all_never = false; | ||
1497 | least_upper_bound = match (actual_ty, &least_upper_bound) { | ||
1498 | (_, Ty::Unknown) | ||
1499 | | (Ty::Infer(_), Ty::Infer(InferTy::TypeVar(_))) | ||
1500 | | (Ty::Apply(_), _) => actual_ty.clone(), | ||
1501 | _ => least_upper_bound, | ||
1502 | } | ||
1503 | } | ||
1504 | } | ||
1505 | |||
1506 | if all_never && last_never_ty.is_some() { | ||
1507 | last_never_ty.unwrap() | ||
1508 | } else { | ||
1509 | least_upper_bound | ||
1510 | } | ||
1511 | } | ||
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index 9a0d2d8f9..b6ebee3b1 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs | |||
@@ -63,6 +63,7 @@ where | |||
63 | InferTy::TypeVar(_) => InferTy::TypeVar(root), | 63 | InferTy::TypeVar(_) => InferTy::TypeVar(root), |
64 | InferTy::IntVar(_) => InferTy::IntVar(root), | 64 | InferTy::IntVar(_) => InferTy::IntVar(root), |
65 | InferTy::FloatVar(_) => InferTy::FloatVar(root), | 65 | InferTy::FloatVar(_) => InferTy::FloatVar(root), |
66 | InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root), | ||
66 | }; | 67 | }; |
67 | let position = self.add(free_var); | 68 | let position = self.add(free_var); |
68 | Ty::Bound(position as u32) | 69 | Ty::Bound(position as u32) |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index f4f63ca93..4362bb27a 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -20,6 +20,9 @@ use crate::{ | |||
20 | // against snapshots of the expected results using insta. Use cargo-insta to | 20 | // against snapshots of the expected results using insta. Use cargo-insta to |
21 | // update the snapshots. | 21 | // update the snapshots. |
22 | 22 | ||
23 | mod never_type; | ||
24 | mod coercion; | ||
25 | |||
23 | #[test] | 26 | #[test] |
24 | fn infer_await() { | 27 | fn infer_await() { |
25 | let (mut db, pos) = MockDatabase::with_position( | 28 | let (mut db, pos) = MockDatabase::with_position( |
@@ -236,17 +239,23 @@ fn test() { | |||
236 | let a = 1isize; | 239 | let a = 1isize; |
237 | let b: usize = 1; | 240 | let b: usize = 1; |
238 | let c = b; | 241 | let c = b; |
242 | let d: u32; | ||
243 | let e; | ||
244 | let f: i32 = e; | ||
239 | } | 245 | } |
240 | "#), | 246 | "#), |
241 | @r###" | 247 | @r###" |
242 | 248 | [11; 118) '{ ...= e; }': () | |
243 | [11; 71) '{ ...= b; }': () | ||
244 | [21; 22) 'a': isize | 249 | [21; 22) 'a': isize |
245 | [25; 31) '1isize': isize | 250 | [25; 31) '1isize': isize |
246 | [41; 42) 'b': usize | 251 | [41; 42) 'b': usize |
247 | [52; 53) '1': usize | 252 | [52; 53) '1': usize |
248 | [63; 64) 'c': usize | 253 | [63; 64) 'c': usize |
249 | [67; 68) 'b': usize | 254 | [67; 68) 'b': usize |
255 | [78; 79) 'd': u32 | ||
256 | [94; 95) 'e': i32 | ||
257 | [105; 106) 'f': i32 | ||
258 | [114; 115) 'e': i32 | ||
250 | "### | 259 | "### |
251 | ); | 260 | ); |
252 | } | 261 | } |
@@ -328,14 +337,14 @@ fn test() { | |||
328 | "#), | 337 | "#), |
329 | @r###" | 338 | @r###" |
330 | [45; 49) 'self': &[T] | 339 | [45; 49) 'self': &[T] |
331 | [56; 79) '{ ... }': ! | 340 | [56; 79) '{ ... }': T |
332 | [66; 73) 'loop {}': ! | 341 | [66; 73) 'loop {}': ! |
333 | [71; 73) '{}': () | 342 | [71; 73) '{}': () |
334 | [133; 160) '{ ...o"); }': () | 343 | [133; 160) '{ ...o"); }': () |
335 | [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T | 344 | [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T |
336 | [139; 157) '<[_]>:..."foo")': u8 | 345 | [139; 157) '<[_]>:..."foo")': u8 |
337 | [150; 156) 'b"foo"': &[u8] | 346 | [150; 156) 'b"foo"': &[u8] |
338 | "### | 347 | "### |
339 | ); | 348 | ); |
340 | } | 349 | } |
341 | 350 | ||
@@ -801,6 +810,130 @@ fn test2(a1: *const A, a2: *mut A) { | |||
801 | } | 810 | } |
802 | 811 | ||
803 | #[test] | 812 | #[test] |
813 | fn infer_argument_autoderef() { | ||
814 | assert_snapshot!( | ||
815 | infer(r#" | ||
816 | #[lang = "deref"] | ||
817 | pub trait Deref { | ||
818 | type Target; | ||
819 | fn deref(&self) -> &Self::Target; | ||
820 | } | ||
821 | |||
822 | struct A<T>(T); | ||
823 | |||
824 | impl<T> A<T> { | ||
825 | fn foo(&self) -> &T { | ||
826 | &self.0 | ||
827 | } | ||
828 | } | ||
829 | |||
830 | struct B<T>(T); | ||
831 | |||
832 | impl<T> Deref for B<T> { | ||
833 | type Target = T; | ||
834 | fn deref(&self) -> &Self::Target { | ||
835 | &self.0 | ||
836 | } | ||
837 | } | ||
838 | |||
839 | fn test() { | ||
840 | let t = A::foo(&&B(B(A(42)))); | ||
841 | } | ||
842 | "#), | ||
843 | @r###" | ||
844 | [68; 72) 'self': &Self | ||
845 | [139; 143) 'self': &A<T> | ||
846 | [151; 174) '{ ... }': &T | ||
847 | [161; 168) '&self.0': &T | ||
848 | [162; 166) 'self': &A<T> | ||
849 | [162; 168) 'self.0': T | ||
850 | [255; 259) 'self': &B<T> | ||
851 | [278; 301) '{ ... }': &T | ||
852 | [288; 295) '&self.0': &T | ||
853 | [289; 293) 'self': &B<T> | ||
854 | [289; 295) 'self.0': T | ||
855 | [315; 353) '{ ...))); }': () | ||
856 | [325; 326) 't': &i32 | ||
857 | [329; 335) 'A::foo': fn foo<i32>(&A<T>) -> &T | ||
858 | [329; 350) 'A::foo...42))))': &i32 | ||
859 | [336; 349) '&&B(B(A(42)))': &&B<B<A<i32>>> | ||
860 | [337; 349) '&B(B(A(42)))': &B<B<A<i32>>> | ||
861 | [338; 339) 'B': B<B<A<i32>>>(T) -> B<T> | ||
862 | [338; 349) 'B(B(A(42)))': B<B<A<i32>>> | ||
863 | [340; 341) 'B': B<A<i32>>(T) -> B<T> | ||
864 | [340; 348) 'B(A(42))': B<A<i32>> | ||
865 | [342; 343) 'A': A<i32>(T) -> A<T> | ||
866 | [342; 347) 'A(42)': A<i32> | ||
867 | [344; 346) '42': i32 | ||
868 | "### | ||
869 | ); | ||
870 | } | ||
871 | |||
872 | #[test] | ||
873 | fn infer_method_argument_autoderef() { | ||
874 | assert_snapshot!( | ||
875 | infer(r#" | ||
876 | #[lang = "deref"] | ||
877 | pub trait Deref { | ||
878 | type Target; | ||
879 | fn deref(&self) -> &Self::Target; | ||
880 | } | ||
881 | |||
882 | struct A<T>(*mut T); | ||
883 | |||
884 | impl<T> A<T> { | ||
885 | fn foo(&self, x: &A<T>) -> &T { | ||
886 | &*x.0 | ||
887 | } | ||
888 | } | ||
889 | |||
890 | struct B<T>(T); | ||
891 | |||
892 | impl<T> Deref for B<T> { | ||
893 | type Target = T; | ||
894 | fn deref(&self) -> &Self::Target { | ||
895 | &self.0 | ||
896 | } | ||
897 | } | ||
898 | |||
899 | fn test(a: A<i32>) { | ||
900 | let t = A(0 as *mut _).foo(&&B(B(a))); | ||
901 | } | ||
902 | "#), | ||
903 | @r###" | ||
904 | [68; 72) 'self': &Self | ||
905 | [144; 148) 'self': &A<T> | ||
906 | [150; 151) 'x': &A<T> | ||
907 | [166; 187) '{ ... }': &T | ||
908 | [176; 181) '&*x.0': &T | ||
909 | [177; 181) '*x.0': T | ||
910 | [178; 179) 'x': &A<T> | ||
911 | [178; 181) 'x.0': *mut T | ||
912 | [268; 272) 'self': &B<T> | ||
913 | [291; 314) '{ ... }': &T | ||
914 | [301; 308) '&self.0': &T | ||
915 | [302; 306) 'self': &B<T> | ||
916 | [302; 308) 'self.0': T | ||
917 | [326; 327) 'a': A<i32> | ||
918 | [337; 383) '{ ...))); }': () | ||
919 | [347; 348) 't': &i32 | ||
920 | [351; 352) 'A': A<i32>(*mut T) -> A<T> | ||
921 | [351; 365) 'A(0 as *mut _)': A<i32> | ||
922 | [351; 380) 'A(0 as...B(a)))': &i32 | ||
923 | [353; 354) '0': i32 | ||
924 | [353; 364) '0 as *mut _': *mut i32 | ||
925 | [370; 379) '&&B(B(a))': &&B<B<A<i32>>> | ||
926 | [371; 379) '&B(B(a))': &B<B<A<i32>>> | ||
927 | [372; 373) 'B': B<B<A<i32>>>(T) -> B<T> | ||
928 | [372; 379) 'B(B(a))': B<B<A<i32>>> | ||
929 | [374; 375) 'B': B<A<i32>>(T) -> B<T> | ||
930 | [374; 378) 'B(a)': B<A<i32>> | ||
931 | [376; 377) 'a': A<i32> | ||
932 | "### | ||
933 | ); | ||
934 | } | ||
935 | |||
936 | #[test] | ||
804 | fn bug_484() { | 937 | fn bug_484() { |
805 | assert_snapshot!( | 938 | assert_snapshot!( |
806 | infer(r#" | 939 | infer(r#" |
@@ -983,14 +1116,12 @@ fn test(x: &str, y: isize) { | |||
983 | 1116 | ||
984 | let b = [a, ["b"]]; | 1117 | let b = [a, ["b"]]; |
985 | let x: [u8; 0] = []; | 1118 | let x: [u8; 0] = []; |
986 | let z: &[u8] = &[1, 2, 3]; | ||
987 | } | 1119 | } |
988 | "#), | 1120 | "#), |
989 | @r###" | 1121 | @r###" |
990 | |||
991 | [9; 10) 'x': &str | 1122 | [9; 10) 'x': &str |
992 | [18; 19) 'y': isize | 1123 | [18; 19) 'y': isize |
993 | [28; 324) '{ ... 3]; }': () | 1124 | [28; 293) '{ ... []; }': () |
994 | [38; 39) 'a': [&str;_] | 1125 | [38; 39) 'a': [&str;_] |
995 | [42; 45) '[x]': [&str;_] | 1126 | [42; 45) '[x]': [&str;_] |
996 | [43; 44) 'x': &str | 1127 | [43; 44) 'x': &str |
@@ -1040,12 +1171,6 @@ fn test(x: &str, y: isize) { | |||
1040 | [260; 263) '"b"': &str | 1171 | [260; 263) '"b"': &str |
1041 | [275; 276) 'x': [u8;_] | 1172 | [275; 276) 'x': [u8;_] |
1042 | [288; 290) '[]': [u8;_] | 1173 | [288; 290) '[]': [u8;_] |
1043 | [300; 301) 'z': &[u8;_] | ||
1044 | [311; 321) '&[1, 2, 3]': &[u8;_] | ||
1045 | [312; 321) '[1, 2, 3]': [u8;_] | ||
1046 | [313; 314) '1': u8 | ||
1047 | [316; 317) '2': u8 | ||
1048 | [319; 320) '3': u8 | ||
1049 | "### | 1174 | "### |
1050 | ); | 1175 | ); |
1051 | } | 1176 | } |
@@ -1767,8 +1892,7 @@ fn test() { | |||
1767 | } | 1892 | } |
1768 | "#), | 1893 | "#), |
1769 | @r###" | 1894 | @r###" |
1770 | 1895 | [80; 104) '{ ... }': Gen<T> | |
1771 | [80; 104) '{ ... }': ! | ||
1772 | [90; 98) 'loop { }': ! | 1896 | [90; 98) 'loop { }': ! |
1773 | [95; 98) '{ }': () | 1897 | [95; 98) '{ }': () |
1774 | [118; 146) '{ ...e(); }': () | 1898 | [118; 146) '{ ...e(); }': () |
@@ -1798,8 +1922,7 @@ fn test() { | |||
1798 | } | 1922 | } |
1799 | "#), | 1923 | "#), |
1800 | @r###" | 1924 | @r###" |
1801 | 1925 | [76; 100) '{ ... }': Gen<T> | |
1802 | [76; 100) '{ ... }': ! | ||
1803 | [86; 94) 'loop { }': ! | 1926 | [86; 94) 'loop { }': ! |
1804 | [91; 94) '{ }': () | 1927 | [91; 94) '{ }': () |
1805 | [114; 149) '{ ...e(); }': () | 1928 | [114; 149) '{ ...e(); }': () |
@@ -1830,8 +1953,7 @@ fn test() { | |||
1830 | } | 1953 | } |
1831 | "#), | 1954 | "#), |
1832 | @r###" | 1955 | @r###" |
1833 | 1956 | [102; 126) '{ ... }': Gen<u32, T> | |
1834 | [102; 126) '{ ... }': ! | ||
1835 | [112; 120) 'loop { }': ! | 1957 | [112; 120) 'loop { }': ! |
1836 | [117; 120) '{ }': () | 1958 | [117; 120) '{ }': () |
1837 | [140; 180) '{ ...e(); }': () | 1959 | [140; 180) '{ ...e(); }': () |
@@ -1973,7 +2095,6 @@ fn test() { | |||
1973 | } | 2095 | } |
1974 | "#), | 2096 | "#), |
1975 | @r###" | 2097 | @r###" |
1976 | |||
1977 | [11; 48) '{ ...&y]; }': () | 2098 | [11; 48) '{ ...&y]; }': () |
1978 | [21; 22) 'y': &{unknown} | 2099 | [21; 22) 'y': &{unknown} |
1979 | [25; 32) 'unknown': &{unknown} | 2100 | [25; 32) 'unknown': &{unknown} |
@@ -1998,14 +2119,13 @@ fn test() { | |||
1998 | } | 2119 | } |
1999 | "#), | 2120 | "#), |
2000 | @r###" | 2121 | @r###" |
2001 | |||
2002 | [11; 80) '{ ...x)]; }': () | 2122 | [11; 80) '{ ...x)]; }': () |
2003 | [21; 22) 'x': &&{unknown} | 2123 | [21; 22) 'x': &&{unknown} |
2004 | [25; 32) 'unknown': &&{unknown} | 2124 | [25; 32) 'unknown': &&{unknown} |
2005 | [42; 43) 'y': &&{unknown} | 2125 | [42; 43) 'y': &&{unknown} |
2006 | [46; 53) 'unknown': &&{unknown} | 2126 | [46; 53) 'unknown': &&{unknown} |
2007 | [59; 77) '[(x, y..., &x)]': [(&&{unknown}, &&{unknown});_] | 2127 | [59; 77) '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown});_] |
2008 | [60; 66) '(x, y)': (&&{unknown}, &&{unknown}) | 2128 | [60; 66) '(x, y)': (&&&{unknown}, &&&{unknown}) |
2009 | [61; 62) 'x': &&{unknown} | 2129 | [61; 62) 'x': &&{unknown} |
2010 | [64; 65) 'y': &&{unknown} | 2130 | [64; 65) 'y': &&{unknown} |
2011 | [68; 76) '(&y, &x)': (&&&{unknown}, &&&{unknown}) | 2131 | [68; 76) '(&y, &x)': (&&&{unknown}, &&&{unknown}) |
@@ -2026,7 +2146,7 @@ fn id<T>(x: T) -> T { | |||
2026 | } | 2146 | } |
2027 | 2147 | ||
2028 | fn clone<T>(x: &T) -> T { | 2148 | fn clone<T>(x: &T) -> T { |
2029 | x | 2149 | *x |
2030 | } | 2150 | } |
2031 | 2151 | ||
2032 | fn test() { | 2152 | fn test() { |
@@ -2037,26 +2157,26 @@ fn test() { | |||
2037 | } | 2157 | } |
2038 | "#), | 2158 | "#), |
2039 | @r###" | 2159 | @r###" |
2040 | |||
2041 | [10; 11) 'x': T | 2160 | [10; 11) 'x': T |
2042 | [21; 30) '{ x }': T | 2161 | [21; 30) '{ x }': T |
2043 | [27; 28) 'x': T | 2162 | [27; 28) 'x': T |
2044 | [44; 45) 'x': &T | 2163 | [44; 45) 'x': &T |
2045 | [56; 65) '{ x }': &T | 2164 | [56; 66) '{ *x }': T |
2046 | [62; 63) 'x': &T | 2165 | [62; 64) '*x': T |
2047 | [77; 157) '{ ...(1); }': () | 2166 | [63; 64) 'x': &T |
2048 | [87; 88) 'y': u32 | 2167 | [78; 158) '{ ...(1); }': () |
2049 | [91; 96) '10u32': u32 | 2168 | [88; 89) 'y': u32 |
2050 | [102; 104) 'id': fn id<u32>(T) -> T | 2169 | [92; 97) '10u32': u32 |
2051 | [102; 107) 'id(y)': u32 | 2170 | [103; 105) 'id': fn id<u32>(T) -> T |
2052 | [105; 106) 'y': u32 | 2171 | [103; 108) 'id(y)': u32 |
2053 | [117; 118) 'x': bool | 2172 | [106; 107) 'y': u32 |
2054 | [127; 132) 'clone': fn clone<bool>(&T) -> T | 2173 | [118; 119) 'x': bool |
2055 | [127; 135) 'clone(z)': bool | 2174 | [128; 133) 'clone': fn clone<bool>(&T) -> T |
2056 | [133; 134) 'z': &bool | 2175 | [128; 136) 'clone(z)': bool |
2057 | [141; 151) 'id::<i128>': fn id<i128>(T) -> T | 2176 | [134; 135) 'z': &bool |
2058 | [141; 154) 'id::<i128>(1)': i128 | 2177 | [142; 152) 'id::<i128>': fn id<i128>(T) -> T |
2059 | [152; 153) '1': i128 | 2178 | [142; 155) 'id::<i128>(1)': i128 |
2179 | [153; 154) '1': i128 | ||
2060 | "### | 2180 | "### |
2061 | ); | 2181 | ); |
2062 | } | 2182 | } |
@@ -2181,7 +2301,6 @@ fn extra_compiler_flags() { | |||
2181 | } | 2301 | } |
2182 | "#), | 2302 | "#), |
2183 | @r###" | 2303 | @r###" |
2184 | |||
2185 | [27; 323) '{ ... } }': () | 2304 | [27; 323) '{ ... } }': () |
2186 | [33; 321) 'for co... }': () | 2305 | [33; 321) 'for co... }': () |
2187 | [37; 44) 'content': &{unknown} | 2306 | [37; 44) 'content': &{unknown} |
@@ -2195,8 +2314,8 @@ fn extra_compiler_flags() { | |||
2195 | [135; 167) '{ ... }': &&{unknown} | 2314 | [135; 167) '{ ... }': &&{unknown} |
2196 | [149; 157) '&content': &&{unknown} | 2315 | [149; 157) '&content': &&{unknown} |
2197 | [150; 157) 'content': &{unknown} | 2316 | [150; 157) 'content': &{unknown} |
2198 | [182; 189) 'content': &&{unknown} | 2317 | [182; 189) 'content': &{unknown} |
2199 | [192; 314) 'if ICE... }': &&{unknown} | 2318 | [192; 314) 'if ICE... }': &{unknown} |
2200 | [195; 232) 'ICE_RE..._VALUE': {unknown} | 2319 | [195; 232) 'ICE_RE..._VALUE': {unknown} |
2201 | [195; 248) 'ICE_RE...&name)': bool | 2320 | [195; 248) 'ICE_RE...&name)': bool |
2202 | [242; 247) '&name': &&&{unknown} | 2321 | [242; 247) '&name': &&&{unknown} |
@@ -3282,7 +3401,7 @@ impl S { | |||
3282 | } | 3401 | } |
3283 | 3402 | ||
3284 | fn test(s: Arc<S>) { | 3403 | fn test(s: Arc<S>) { |
3285 | (*s, s.foo())<|> | 3404 | (*s, s.foo())<|>; |
3286 | } | 3405 | } |
3287 | "#, | 3406 | "#, |
3288 | ); | 3407 | ); |
@@ -3356,7 +3475,7 @@ trait Deref { | |||
3356 | } | 3475 | } |
3357 | 3476 | ||
3358 | struct Arc<T>; | 3477 | struct Arc<T>; |
3359 | impl<T: ?Sized> Deref for Arc<T> { | 3478 | impl<T> Deref for Arc<T> { |
3360 | type Target = T; | 3479 | type Target = T; |
3361 | } | 3480 | } |
3362 | 3481 | ||
@@ -3366,7 +3485,7 @@ impl S { | |||
3366 | } | 3485 | } |
3367 | 3486 | ||
3368 | fn test(s: Arc<S>) { | 3487 | fn test(s: Arc<S>) { |
3369 | (*s, s.foo())<|> | 3488 | (*s, s.foo())<|>; |
3370 | } | 3489 | } |
3371 | "#, | 3490 | "#, |
3372 | ); | 3491 | ); |
@@ -4406,121 +4525,3 @@ fn no_such_field_diagnostics() { | |||
4406 | "### | 4525 | "### |
4407 | ); | 4526 | ); |
4408 | } | 4527 | } |
4409 | |||
4410 | mod branching_with_never_tests { | ||
4411 | use super::type_at; | ||
4412 | |||
4413 | #[test] | ||
4414 | fn if_never() { | ||
4415 | let t = type_at( | ||
4416 | r#" | ||
4417 | //- /main.rs | ||
4418 | fn test() { | ||
4419 | let i = if true { | ||
4420 | loop {} | ||
4421 | } else { | ||
4422 | 3.0 | ||
4423 | }; | ||
4424 | i<|> | ||
4425 | () | ||
4426 | } | ||
4427 | "#, | ||
4428 | ); | ||
4429 | assert_eq!(t, "f64"); | ||
4430 | } | ||
4431 | |||
4432 | #[test] | ||
4433 | fn if_else_never() { | ||
4434 | let t = type_at( | ||
4435 | r#" | ||
4436 | //- /main.rs | ||
4437 | fn test(input: bool) { | ||
4438 | let i = if input { | ||
4439 | 2.0 | ||
4440 | } else { | ||
4441 | return | ||
4442 | }; | ||
4443 | i<|> | ||
4444 | () | ||
4445 | } | ||
4446 | "#, | ||
4447 | ); | ||
4448 | assert_eq!(t, "f64"); | ||
4449 | } | ||
4450 | |||
4451 | #[test] | ||
4452 | fn match_first_arm_never() { | ||
4453 | let t = type_at( | ||
4454 | r#" | ||
4455 | //- /main.rs | ||
4456 | fn test(a: i32) { | ||
4457 | let i = match a { | ||
4458 | 1 => return, | ||
4459 | 2 => 2.0, | ||
4460 | 3 => loop {}, | ||
4461 | _ => 3.0, | ||
4462 | }; | ||
4463 | i<|> | ||
4464 | () | ||
4465 | } | ||
4466 | "#, | ||
4467 | ); | ||
4468 | assert_eq!(t, "f64"); | ||
4469 | } | ||
4470 | |||
4471 | #[test] | ||
4472 | fn match_second_arm_never() { | ||
4473 | let t = type_at( | ||
4474 | r#" | ||
4475 | //- /main.rs | ||
4476 | fn test(a: i32) { | ||
4477 | let i = match a { | ||
4478 | 1 => 3.0, | ||
4479 | 2 => loop {}, | ||
4480 | 3 => 3.0, | ||
4481 | _ => return, | ||
4482 | }; | ||
4483 | i<|> | ||
4484 | () | ||
4485 | } | ||
4486 | "#, | ||
4487 | ); | ||
4488 | assert_eq!(t, "f64"); | ||
4489 | } | ||
4490 | |||
4491 | #[test] | ||
4492 | fn match_all_arms_never() { | ||
4493 | let t = type_at( | ||
4494 | r#" | ||
4495 | //- /main.rs | ||
4496 | fn test(a: i32) { | ||
4497 | let i = match a { | ||
4498 | 2 => return, | ||
4499 | _ => loop {}, | ||
4500 | }; | ||
4501 | i<|> | ||
4502 | () | ||
4503 | } | ||
4504 | "#, | ||
4505 | ); | ||
4506 | assert_eq!(t, "!"); | ||
4507 | } | ||
4508 | |||
4509 | #[test] | ||
4510 | fn match_no_never_arms() { | ||
4511 | let t = type_at( | ||
4512 | r#" | ||
4513 | //- /main.rs | ||
4514 | fn test(a: i32) { | ||
4515 | let i = match a { | ||
4516 | 2 => 2.0, | ||
4517 | _ => 3.0, | ||
4518 | }; | ||
4519 | i<|> | ||
4520 | () | ||
4521 | } | ||
4522 | "#, | ||
4523 | ); | ||
4524 | assert_eq!(t, "f64"); | ||
4525 | } | ||
4526 | } | ||
diff --git a/crates/ra_hir/src/ty/tests/coercion.rs b/crates/ra_hir/src/ty/tests/coercion.rs new file mode 100644 index 000000000..1530fcc63 --- /dev/null +++ b/crates/ra_hir/src/ty/tests/coercion.rs | |||
@@ -0,0 +1,369 @@ | |||
1 | use insta::assert_snapshot; | ||
2 | use test_utils::covers; | ||
3 | |||
4 | // Infer with some common definitions and impls. | ||
5 | fn infer(source: &str) -> String { | ||
6 | let defs = r#" | ||
7 | #[lang = "sized"] | ||
8 | pub trait Sized {} | ||
9 | #[lang = "unsize"] | ||
10 | pub trait Unsize<T: ?Sized> {} | ||
11 | #[lang = "coerce_unsized"] | ||
12 | pub trait CoerceUnsized<T> {} | ||
13 | |||
14 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
15 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
16 | "#; | ||
17 | |||
18 | // Append to the end to keep positions unchanged. | ||
19 | super::infer(&format!("{}{}", source, defs)) | ||
20 | } | ||
21 | |||
22 | #[test] | ||
23 | fn infer_block_expr_type_mismatch() { | ||
24 | assert_snapshot!( | ||
25 | infer(r#" | ||
26 | fn test() { | ||
27 | let a: i32 = { 1i64 }; | ||
28 | } | ||
29 | "#), | ||
30 | @r###" | ||
31 | [11; 41) '{ ...4 }; }': () | ||
32 | [21; 22) 'a': i32 | ||
33 | [30; 38) '{ 1i64 }': i64 | ||
34 | [32; 36) '1i64': i64 | ||
35 | "###); | ||
36 | } | ||
37 | |||
38 | #[test] | ||
39 | fn coerce_places() { | ||
40 | assert_snapshot!( | ||
41 | infer(r#" | ||
42 | struct S<T> { a: T } | ||
43 | |||
44 | fn f<T>(_: &[T]) -> T { loop {} } | ||
45 | fn g<T>(_: S<&[T]>) -> T { loop {} } | ||
46 | |||
47 | fn gen<T>() -> *mut [T; 2] { loop {} } | ||
48 | fn test1<U>() -> *mut [U] { | ||
49 | gen() | ||
50 | } | ||
51 | |||
52 | fn test2() { | ||
53 | let arr: &[u8; 1] = &[1]; | ||
54 | |||
55 | let a: &[_] = arr; | ||
56 | let b = f(arr); | ||
57 | let c: &[_] = { arr }; | ||
58 | let d = g(S { a: arr }); | ||
59 | let e: [&[_]; 1] = [arr]; | ||
60 | let f: [&[_]; 2] = [arr; 2]; | ||
61 | let g: (&[_], &[_]) = (arr, arr); | ||
62 | } | ||
63 | "#), | ||
64 | @r###" | ||
65 | [31; 32) '_': &[T] | ||
66 | [45; 56) '{ loop {} }': T | ||
67 | [47; 54) 'loop {}': ! | ||
68 | [52; 54) '{}': () | ||
69 | [65; 66) '_': S<&[T]> | ||
70 | [82; 93) '{ loop {} }': T | ||
71 | [84; 91) 'loop {}': ! | ||
72 | [89; 91) '{}': () | ||
73 | [122; 133) '{ loop {} }': *mut [T;_] | ||
74 | [124; 131) 'loop {}': ! | ||
75 | [129; 131) '{}': () | ||
76 | [160; 173) '{ gen() }': *mut [U] | ||
77 | [166; 169) 'gen': fn gen<U>() -> *mut [T;_] | ||
78 | [166; 171) 'gen()': *mut [U;_] | ||
79 | [186; 420) '{ ...rr); }': () | ||
80 | [196; 199) 'arr': &[u8;_] | ||
81 | [212; 216) '&[1]': &[u8;_] | ||
82 | [213; 216) '[1]': [u8;_] | ||
83 | [214; 215) '1': u8 | ||
84 | [227; 228) 'a': &[u8] | ||
85 | [237; 240) 'arr': &[u8;_] | ||
86 | [250; 251) 'b': u8 | ||
87 | [254; 255) 'f': fn f<u8>(&[T]) -> T | ||
88 | [254; 260) 'f(arr)': u8 | ||
89 | [256; 259) 'arr': &[u8;_] | ||
90 | [270; 271) 'c': &[u8] | ||
91 | [280; 287) '{ arr }': &[u8] | ||
92 | [282; 285) 'arr': &[u8;_] | ||
93 | [297; 298) 'd': u8 | ||
94 | [301; 302) 'g': fn g<u8>(S<&[T]>) -> T | ||
95 | [301; 316) 'g(S { a: arr })': u8 | ||
96 | [303; 315) 'S { a: arr }': S<&[u8]> | ||
97 | [310; 313) 'arr': &[u8;_] | ||
98 | [326; 327) 'e': [&[u8];_] | ||
99 | [341; 346) '[arr]': [&[u8];_] | ||
100 | [342; 345) 'arr': &[u8;_] | ||
101 | [356; 357) 'f': [&[u8];_] | ||
102 | [371; 379) '[arr; 2]': [&[u8];_] | ||
103 | [372; 375) 'arr': &[u8;_] | ||
104 | [377; 378) '2': usize | ||
105 | [389; 390) 'g': (&[u8], &[u8]) | ||
106 | [407; 417) '(arr, arr)': (&[u8], &[u8]) | ||
107 | [408; 411) 'arr': &[u8;_] | ||
108 | [413; 416) 'arr': &[u8;_] | ||
109 | "### | ||
110 | ); | ||
111 | } | ||
112 | |||
113 | #[test] | ||
114 | fn infer_let_stmt_coerce() { | ||
115 | assert_snapshot!( | ||
116 | infer(r#" | ||
117 | fn test() { | ||
118 | let x: &[i32] = &[1]; | ||
119 | } | ||
120 | "#), | ||
121 | @r###" | ||
122 | [11; 40) '{ ...[1]; }': () | ||
123 | [21; 22) 'x': &[i32] | ||
124 | [33; 37) '&[1]': &[i32;_] | ||
125 | [34; 37) '[1]': [i32;_] | ||
126 | [35; 36) '1': i32 | ||
127 | "###); | ||
128 | } | ||
129 | |||
130 | #[test] | ||
131 | fn infer_custom_coerce_unsized() { | ||
132 | assert_snapshot!( | ||
133 | infer(r#" | ||
134 | struct A<T: ?Sized>(*const T); | ||
135 | struct B<T: ?Sized>(*const T); | ||
136 | struct C<T: ?Sized> { inner: *const T } | ||
137 | |||
138 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} | ||
139 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {} | ||
140 | |||
141 | fn foo1<T>(x: A<[T]>) -> A<[T]> { x } | ||
142 | fn foo2<T>(x: B<[T]>) -> B<[T]> { x } | ||
143 | fn foo3<T>(x: C<[T]>) -> C<[T]> { x } | ||
144 | |||
145 | fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | ||
146 | let d = foo1(a); | ||
147 | let e = foo2(b); | ||
148 | let f = foo3(c); | ||
149 | } | ||
150 | "#), | ||
151 | @r###" | ||
152 | [258; 259) 'x': A<[T]> | ||
153 | [279; 284) '{ x }': A<[T]> | ||
154 | [281; 282) 'x': A<[T]> | ||
155 | [296; 297) 'x': B<[T]> | ||
156 | [317; 322) '{ x }': B<[T]> | ||
157 | [319; 320) 'x': B<[T]> | ||
158 | [334; 335) 'x': C<[T]> | ||
159 | [355; 360) '{ x }': C<[T]> | ||
160 | [357; 358) 'x': C<[T]> | ||
161 | [370; 371) 'a': A<[u8;_]> | ||
162 | [385; 386) 'b': B<[u8;_]> | ||
163 | [400; 401) 'c': C<[u8;_]> | ||
164 | [415; 481) '{ ...(c); }': () | ||
165 | [425; 426) 'd': A<[{unknown}]> | ||
166 | [429; 433) 'foo1': fn foo1<{unknown}>(A<[T]>) -> A<[T]> | ||
167 | [429; 436) 'foo1(a)': A<[{unknown}]> | ||
168 | [434; 435) 'a': A<[u8;_]> | ||
169 | [446; 447) 'e': B<[u8]> | ||
170 | [450; 454) 'foo2': fn foo2<u8>(B<[T]>) -> B<[T]> | ||
171 | [450; 457) 'foo2(b)': B<[u8]> | ||
172 | [455; 456) 'b': B<[u8;_]> | ||
173 | [467; 468) 'f': C<[u8]> | ||
174 | [471; 475) 'foo3': fn foo3<u8>(C<[T]>) -> C<[T]> | ||
175 | [471; 478) 'foo3(c)': C<[u8]> | ||
176 | [476; 477) 'c': C<[u8;_]> | ||
177 | "### | ||
178 | ); | ||
179 | } | ||
180 | |||
181 | #[test] | ||
182 | fn infer_if_coerce() { | ||
183 | assert_snapshot!( | ||
184 | infer(r#" | ||
185 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
186 | fn test() { | ||
187 | let x = if true { | ||
188 | foo(&[1]) | ||
189 | } else { | ||
190 | &[1] | ||
191 | }; | ||
192 | } | ||
193 | "#), | ||
194 | @r###" | ||
195 | [11; 12) 'x': &[T] | ||
196 | [28; 39) '{ loop {} }': &[T] | ||
197 | [30; 37) 'loop {}': ! | ||
198 | [35; 37) '{}': () | ||
199 | [50; 126) '{ ... }; }': () | ||
200 | [60; 61) 'x': &[i32] | ||
201 | [64; 123) 'if tru... }': &[i32] | ||
202 | [67; 71) 'true': bool | ||
203 | [72; 97) '{ ... }': &[i32] | ||
204 | [82; 85) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
205 | [82; 91) 'foo(&[1])': &[i32] | ||
206 | [86; 90) '&[1]': &[i32;_] | ||
207 | [87; 90) '[1]': [i32;_] | ||
208 | [88; 89) '1': i32 | ||
209 | [103; 123) '{ ... }': &[i32;_] | ||
210 | [113; 117) '&[1]': &[i32;_] | ||
211 | [114; 117) '[1]': [i32;_] | ||
212 | [115; 116) '1': i32 | ||
213 | "### | ||
214 | ); | ||
215 | } | ||
216 | |||
217 | #[test] | ||
218 | fn infer_if_else_coerce() { | ||
219 | assert_snapshot!( | ||
220 | infer(r#" | ||
221 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
222 | fn test() { | ||
223 | let x = if true { | ||
224 | &[1] | ||
225 | } else { | ||
226 | foo(&[1]) | ||
227 | }; | ||
228 | } | ||
229 | "#), | ||
230 | @r###" | ||
231 | [11; 12) 'x': &[T] | ||
232 | [28; 39) '{ loop {} }': &[T] | ||
233 | [30; 37) 'loop {}': ! | ||
234 | [35; 37) '{}': () | ||
235 | [50; 126) '{ ... }; }': () | ||
236 | [60; 61) 'x': &[i32] | ||
237 | [64; 123) 'if tru... }': &[i32] | ||
238 | [67; 71) 'true': bool | ||
239 | [72; 92) '{ ... }': &[i32;_] | ||
240 | [82; 86) '&[1]': &[i32;_] | ||
241 | [83; 86) '[1]': [i32;_] | ||
242 | [84; 85) '1': i32 | ||
243 | [98; 123) '{ ... }': &[i32] | ||
244 | [108; 111) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
245 | [108; 117) 'foo(&[1])': &[i32] | ||
246 | [112; 116) '&[1]': &[i32;_] | ||
247 | [113; 116) '[1]': [i32;_] | ||
248 | [114; 115) '1': i32 | ||
249 | "### | ||
250 | ); | ||
251 | } | ||
252 | |||
253 | #[test] | ||
254 | fn infer_match_first_coerce() { | ||
255 | assert_snapshot!( | ||
256 | infer(r#" | ||
257 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
258 | fn test(i: i32) { | ||
259 | let x = match i { | ||
260 | 2 => foo(&[2]), | ||
261 | 1 => &[1], | ||
262 | _ => &[3], | ||
263 | }; | ||
264 | } | ||
265 | "#), | ||
266 | @r###" | ||
267 | [11; 12) 'x': &[T] | ||
268 | [28; 39) '{ loop {} }': &[T] | ||
269 | [30; 37) 'loop {}': ! | ||
270 | [35; 37) '{}': () | ||
271 | [48; 49) 'i': i32 | ||
272 | [56; 150) '{ ... }; }': () | ||
273 | [66; 67) 'x': &[i32] | ||
274 | [70; 147) 'match ... }': &[i32] | ||
275 | [76; 77) 'i': i32 | ||
276 | [88; 89) '2': i32 | ||
277 | [93; 96) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
278 | [93; 102) 'foo(&[2])': &[i32] | ||
279 | [97; 101) '&[2]': &[i32;_] | ||
280 | [98; 101) '[2]': [i32;_] | ||
281 | [99; 100) '2': i32 | ||
282 | [112; 113) '1': i32 | ||
283 | [117; 121) '&[1]': &[i32;_] | ||
284 | [118; 121) '[1]': [i32;_] | ||
285 | [119; 120) '1': i32 | ||
286 | [131; 132) '_': i32 | ||
287 | [136; 140) '&[3]': &[i32;_] | ||
288 | [137; 140) '[3]': [i32;_] | ||
289 | [138; 139) '3': i32 | ||
290 | "### | ||
291 | ); | ||
292 | } | ||
293 | |||
294 | #[test] | ||
295 | fn infer_match_second_coerce() { | ||
296 | assert_snapshot!( | ||
297 | infer(r#" | ||
298 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
299 | fn test(i: i32) { | ||
300 | let x = match i { | ||
301 | 1 => &[1], | ||
302 | 2 => foo(&[2]), | ||
303 | _ => &[3], | ||
304 | }; | ||
305 | } | ||
306 | "#), | ||
307 | @r###" | ||
308 | [11; 12) 'x': &[T] | ||
309 | [28; 39) '{ loop {} }': &[T] | ||
310 | [30; 37) 'loop {}': ! | ||
311 | [35; 37) '{}': () | ||
312 | [48; 49) 'i': i32 | ||
313 | [56; 150) '{ ... }; }': () | ||
314 | [66; 67) 'x': &[i32] | ||
315 | [70; 147) 'match ... }': &[i32] | ||
316 | [76; 77) 'i': i32 | ||
317 | [88; 89) '1': i32 | ||
318 | [93; 97) '&[1]': &[i32;_] | ||
319 | [94; 97) '[1]': [i32;_] | ||
320 | [95; 96) '1': i32 | ||
321 | [107; 108) '2': i32 | ||
322 | [112; 115) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
323 | [112; 121) 'foo(&[2])': &[i32] | ||
324 | [116; 120) '&[2]': &[i32;_] | ||
325 | [117; 120) '[2]': [i32;_] | ||
326 | [118; 119) '2': i32 | ||
327 | [131; 132) '_': i32 | ||
328 | [136; 140) '&[3]': &[i32;_] | ||
329 | [137; 140) '[3]': [i32;_] | ||
330 | [138; 139) '3': i32 | ||
331 | "### | ||
332 | ); | ||
333 | } | ||
334 | |||
335 | #[test] | ||
336 | fn coerce_merge_one_by_one1() { | ||
337 | covers!(coerce_merge_fail_fallback); | ||
338 | |||
339 | assert_snapshot!( | ||
340 | infer(r#" | ||
341 | fn test() { | ||
342 | let t = &mut 1; | ||
343 | let x = match 1 { | ||
344 | 1 => t as *mut i32, | ||
345 | 2 => t as &i32, | ||
346 | _ => t as *const i32, | ||
347 | }; | ||
348 | } | ||
349 | "#), | ||
350 | @r###" | ||
351 | [11; 145) '{ ... }; }': () | ||
352 | [21; 22) 't': &mut i32 | ||
353 | [25; 31) '&mut 1': &mut i32 | ||
354 | [30; 31) '1': i32 | ||
355 | [41; 42) 'x': *const i32 | ||
356 | [45; 142) 'match ... }': *const i32 | ||
357 | [51; 52) '1': i32 | ||
358 | [63; 64) '1': i32 | ||
359 | [68; 69) 't': &mut i32 | ||
360 | [68; 81) 't as *mut i32': *mut i32 | ||
361 | [91; 92) '2': i32 | ||
362 | [96; 97) 't': &mut i32 | ||
363 | [96; 105) 't as &i32': &i32 | ||
364 | [115; 116) '_': i32 | ||
365 | [120; 121) 't': &mut i32 | ||
366 | [120; 135) 't as *const i32': *const i32 | ||
367 | "### | ||
368 | ); | ||
369 | } | ||
diff --git a/crates/ra_hir/src/ty/tests/never_type.rs b/crates/ra_hir/src/ty/tests/never_type.rs new file mode 100644 index 000000000..c202f545a --- /dev/null +++ b/crates/ra_hir/src/ty/tests/never_type.rs | |||
@@ -0,0 +1,246 @@ | |||
1 | use super::type_at; | ||
2 | |||
3 | #[test] | ||
4 | fn infer_never1() { | ||
5 | let t = type_at( | ||
6 | r#" | ||
7 | //- /main.rs | ||
8 | fn test() { | ||
9 | let t = return; | ||
10 | t<|>; | ||
11 | } | ||
12 | "#, | ||
13 | ); | ||
14 | assert_eq!(t, "!"); | ||
15 | } | ||
16 | |||
17 | #[test] | ||
18 | fn infer_never2() { | ||
19 | let t = type_at( | ||
20 | r#" | ||
21 | //- /main.rs | ||
22 | fn gen<T>() -> T { loop {} } | ||
23 | |||
24 | fn test() { | ||
25 | let a = gen(); | ||
26 | if false { a } else { loop {} }; | ||
27 | a<|>; | ||
28 | } | ||
29 | "#, | ||
30 | ); | ||
31 | assert_eq!(t, "!"); | ||
32 | } | ||
33 | |||
34 | #[test] | ||
35 | fn infer_never3() { | ||
36 | let t = type_at( | ||
37 | r#" | ||
38 | //- /main.rs | ||
39 | fn gen<T>() -> T { loop {} } | ||
40 | |||
41 | fn test() { | ||
42 | let a = gen(); | ||
43 | if false { loop {} } else { a }; | ||
44 | a<|>; | ||
45 | } | ||
46 | "#, | ||
47 | ); | ||
48 | assert_eq!(t, "!"); | ||
49 | } | ||
50 | |||
51 | #[test] | ||
52 | fn never_type_in_generic_args() { | ||
53 | let t = type_at( | ||
54 | r#" | ||
55 | //- /main.rs | ||
56 | enum Option<T> { None, Some(T) } | ||
57 | |||
58 | fn test() { | ||
59 | let a = if true { Option::None } else { Option::Some(return) }; | ||
60 | a<|>; | ||
61 | } | ||
62 | "#, | ||
63 | ); | ||
64 | assert_eq!(t, "Option<!>"); | ||
65 | } | ||
66 | |||
67 | #[test] | ||
68 | fn never_type_can_be_reinferred1() { | ||
69 | let t = type_at( | ||
70 | r#" | ||
71 | //- /main.rs | ||
72 | fn gen<T>() -> T { loop {} } | ||
73 | |||
74 | fn test() { | ||
75 | let a = gen(); | ||
76 | if false { loop {} } else { a }; | ||
77 | a<|>; | ||
78 | if false { a }; | ||
79 | } | ||
80 | "#, | ||
81 | ); | ||
82 | assert_eq!(t, "()"); | ||
83 | } | ||
84 | |||
85 | #[test] | ||
86 | fn never_type_can_be_reinferred2() { | ||
87 | let t = type_at( | ||
88 | r#" | ||
89 | //- /main.rs | ||
90 | enum Option<T> { None, Some(T) } | ||
91 | |||
92 | fn test() { | ||
93 | let a = if true { Option::None } else { Option::Some(return) }; | ||
94 | a<|>; | ||
95 | match 42 { | ||
96 | 42 => a, | ||
97 | _ => Option::Some(42), | ||
98 | }; | ||
99 | } | ||
100 | "#, | ||
101 | ); | ||
102 | assert_eq!(t, "Option<i32>"); | ||
103 | } | ||
104 | #[test] | ||
105 | fn never_type_can_be_reinferred3() { | ||
106 | let t = type_at( | ||
107 | r#" | ||
108 | //- /main.rs | ||
109 | enum Option<T> { None, Some(T) } | ||
110 | |||
111 | fn test() { | ||
112 | let a = if true { Option::None } else { Option::Some(return) }; | ||
113 | a<|>; | ||
114 | match 42 { | ||
115 | 42 => a, | ||
116 | _ => Option::Some("str"), | ||
117 | }; | ||
118 | } | ||
119 | "#, | ||
120 | ); | ||
121 | assert_eq!(t, "Option<&str>"); | ||
122 | } | ||
123 | |||
124 | #[test] | ||
125 | fn match_no_arm() { | ||
126 | let t = type_at( | ||
127 | r#" | ||
128 | //- /main.rs | ||
129 | enum Void {} | ||
130 | |||
131 | fn test(a: Void) { | ||
132 | let t = match a {}; | ||
133 | t<|>; | ||
134 | } | ||
135 | "#, | ||
136 | ); | ||
137 | assert_eq!(t, "!"); | ||
138 | } | ||
139 | |||
140 | #[test] | ||
141 | fn if_never() { | ||
142 | let t = type_at( | ||
143 | r#" | ||
144 | //- /main.rs | ||
145 | fn test() { | ||
146 | let i = if true { | ||
147 | loop {} | ||
148 | } else { | ||
149 | 3.0 | ||
150 | }; | ||
151 | i<|>; | ||
152 | } | ||
153 | "#, | ||
154 | ); | ||
155 | assert_eq!(t, "f64"); | ||
156 | } | ||
157 | |||
158 | #[test] | ||
159 | fn if_else_never() { | ||
160 | let t = type_at( | ||
161 | r#" | ||
162 | //- /main.rs | ||
163 | fn test(input: bool) { | ||
164 | let i = if input { | ||
165 | 2.0 | ||
166 | } else { | ||
167 | return | ||
168 | }; | ||
169 | i<|>; | ||
170 | } | ||
171 | "#, | ||
172 | ); | ||
173 | assert_eq!(t, "f64"); | ||
174 | } | ||
175 | |||
176 | #[test] | ||
177 | fn match_first_arm_never() { | ||
178 | let t = type_at( | ||
179 | r#" | ||
180 | //- /main.rs | ||
181 | fn test(a: i32) { | ||
182 | let i = match a { | ||
183 | 1 => return, | ||
184 | 2 => 2.0, | ||
185 | 3 => loop {}, | ||
186 | _ => 3.0, | ||
187 | }; | ||
188 | i<|>; | ||
189 | } | ||
190 | "#, | ||
191 | ); | ||
192 | assert_eq!(t, "f64"); | ||
193 | } | ||
194 | |||
195 | #[test] | ||
196 | fn match_second_arm_never() { | ||
197 | let t = type_at( | ||
198 | r#" | ||
199 | //- /main.rs | ||
200 | fn test(a: i32) { | ||
201 | let i = match a { | ||
202 | 1 => 3.0, | ||
203 | 2 => loop {}, | ||
204 | 3 => 3.0, | ||
205 | _ => return, | ||
206 | }; | ||
207 | i<|>; | ||
208 | } | ||
209 | "#, | ||
210 | ); | ||
211 | assert_eq!(t, "f64"); | ||
212 | } | ||
213 | |||
214 | #[test] | ||
215 | fn match_all_arms_never() { | ||
216 | let t = type_at( | ||
217 | r#" | ||
218 | //- /main.rs | ||
219 | fn test(a: i32) { | ||
220 | let i = match a { | ||
221 | 2 => return, | ||
222 | _ => loop {}, | ||
223 | }; | ||
224 | i<|>; | ||
225 | } | ||
226 | "#, | ||
227 | ); | ||
228 | assert_eq!(t, "!"); | ||
229 | } | ||
230 | |||
231 | #[test] | ||
232 | fn match_no_never_arms() { | ||
233 | let t = type_at( | ||
234 | r#" | ||
235 | //- /main.rs | ||
236 | fn test(a: i32) { | ||
237 | let i = match a { | ||
238 | 2 => 2.0, | ||
239 | _ => 3.0, | ||
240 | }; | ||
241 | i<|>; | ||
242 | } | ||
243 | "#, | ||
244 | ); | ||
245 | assert_eq!(t, "f64"); | ||
246 | } | ||