aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/ty/infer.rs529
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs1
-rw-r--r--crates/ra_hir/src/ty/tests.rs329
-rw-r--r--crates/ra_hir/src/ty/tests/coercion.rs369
-rw-r--r--crates/ra_hir/src/ty/tests/never_type.rs246
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
16use std::borrow::Cow; 16use std::borrow::Cow;
17use std::iter::repeat; 17use std::iter::{repeat, repeat_with};
18use std::mem; 18use std::mem;
19use std::ops::Index; 19use std::ops::Index;
20use std::sync::Arc; 20use 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
200macro_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
193impl<'a, D: HirDatabase> InferenceContext<'a, D> { 209impl<'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
1405impl InferTy { 1778impl 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
1479fn is_never(ty: &Ty) -> bool {
1480 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) = ty {
1481 true
1482 } else {
1483 false
1484 }
1485}
1486
1487fn 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
23mod never_type;
24mod coercion;
25
23#[test] 26#[test]
24fn infer_await() { 27fn 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]
813fn infer_argument_autoderef() {
814 assert_snapshot!(
815 infer(r#"
816#[lang = "deref"]
817pub trait Deref {
818 type Target;
819 fn deref(&self) -> &Self::Target;
820}
821
822struct A<T>(T);
823
824impl<T> A<T> {
825 fn foo(&self) -> &T {
826 &self.0
827 }
828}
829
830struct B<T>(T);
831
832impl<T> Deref for B<T> {
833 type Target = T;
834 fn deref(&self) -> &Self::Target {
835 &self.0
836 }
837}
838
839fn 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]
873fn infer_method_argument_autoderef() {
874 assert_snapshot!(
875 infer(r#"
876#[lang = "deref"]
877pub trait Deref {
878 type Target;
879 fn deref(&self) -> &Self::Target;
880}
881
882struct A<T>(*mut T);
883
884impl<T> A<T> {
885 fn foo(&self, x: &A<T>) -> &T {
886 &*x.0
887 }
888}
889
890struct B<T>(T);
891
892impl<T> Deref for B<T> {
893 type Target = T;
894 fn deref(&self) -> &Self::Target {
895 &self.0
896 }
897}
898
899fn 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]
804fn bug_484() { 937fn 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
2028fn clone<T>(x: &T) -> T { 2148fn clone<T>(x: &T) -> T {
2029 x 2149 *x
2030} 2150}
2031 2151
2032fn test() { 2152fn 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
3284fn test(s: Arc<S>) { 3403fn 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
3358struct Arc<T>; 3477struct Arc<T>;
3359impl<T: ?Sized> Deref for Arc<T> { 3478impl<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
3368fn test(s: Arc<S>) { 3487fn 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
4410mod 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
4418fn 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
4437fn 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
4456fn 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
4476fn 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
4496fn 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
4514fn 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 @@
1use insta::assert_snapshot;
2use test_utils::covers;
3
4// Infer with some common definitions and impls.
5fn 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]
23fn infer_block_expr_type_mismatch() {
24 assert_snapshot!(
25 infer(r#"
26fn 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]
39fn coerce_places() {
40 assert_snapshot!(
41 infer(r#"
42struct S<T> { a: T }
43
44fn f<T>(_: &[T]) -> T { loop {} }
45fn g<T>(_: S<&[T]>) -> T { loop {} }
46
47fn gen<T>() -> *mut [T; 2] { loop {} }
48fn test1<U>() -> *mut [U] {
49 gen()
50}
51
52fn 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]
114fn infer_let_stmt_coerce() {
115 assert_snapshot!(
116 infer(r#"
117fn 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]
131fn infer_custom_coerce_unsized() {
132 assert_snapshot!(
133 infer(r#"
134struct A<T: ?Sized>(*const T);
135struct B<T: ?Sized>(*const T);
136struct C<T: ?Sized> { inner: *const T }
137
138impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
139impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
140
141fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
142fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
143fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
144
145fn 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]
182fn infer_if_coerce() {
183 assert_snapshot!(
184 infer(r#"
185fn foo<T>(x: &[T]) -> &[T] { loop {} }
186fn 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]
218fn infer_if_else_coerce() {
219 assert_snapshot!(
220 infer(r#"
221fn foo<T>(x: &[T]) -> &[T] { loop {} }
222fn 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]
254fn infer_match_first_coerce() {
255 assert_snapshot!(
256 infer(r#"
257fn foo<T>(x: &[T]) -> &[T] { loop {} }
258fn 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]
295fn infer_match_second_coerce() {
296 assert_snapshot!(
297 infer(r#"
298fn foo<T>(x: &[T]) -> &[T] { loop {} }
299fn 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]
336fn coerce_merge_one_by_one1() {
337 covers!(coerce_merge_fail_fallback);
338
339 assert_snapshot!(
340 infer(r#"
341fn 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 @@
1use super::type_at;
2
3#[test]
4fn infer_never1() {
5 let t = type_at(
6 r#"
7//- /main.rs
8fn test() {
9 let t = return;
10 t<|>;
11}
12"#,
13 );
14 assert_eq!(t, "!");
15}
16
17#[test]
18fn infer_never2() {
19 let t = type_at(
20 r#"
21//- /main.rs
22fn gen<T>() -> T { loop {} }
23
24fn test() {
25 let a = gen();
26 if false { a } else { loop {} };
27 a<|>;
28}
29"#,
30 );
31 assert_eq!(t, "!");
32}
33
34#[test]
35fn infer_never3() {
36 let t = type_at(
37 r#"
38//- /main.rs
39fn gen<T>() -> T { loop {} }
40
41fn test() {
42 let a = gen();
43 if false { loop {} } else { a };
44 a<|>;
45}
46"#,
47 );
48 assert_eq!(t, "!");
49}
50
51#[test]
52fn never_type_in_generic_args() {
53 let t = type_at(
54 r#"
55//- /main.rs
56enum Option<T> { None, Some(T) }
57
58fn 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]
68fn never_type_can_be_reinferred1() {
69 let t = type_at(
70 r#"
71//- /main.rs
72fn gen<T>() -> T { loop {} }
73
74fn 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]
86fn never_type_can_be_reinferred2() {
87 let t = type_at(
88 r#"
89//- /main.rs
90enum Option<T> { None, Some(T) }
91
92fn 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]
105fn never_type_can_be_reinferred3() {
106 let t = type_at(
107 r#"
108//- /main.rs
109enum Option<T> { None, Some(T) }
110
111fn 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]
125fn match_no_arm() {
126 let t = type_at(
127 r#"
128//- /main.rs
129enum Void {}
130
131fn test(a: Void) {
132 let t = match a {};
133 t<|>;
134}
135"#,
136 );
137 assert_eq!(t, "!");
138}
139
140#[test]
141fn if_never() {
142 let t = type_at(
143 r#"
144//- /main.rs
145fn 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]
159fn if_else_never() {
160 let t = type_at(
161 r#"
162//- /main.rs
163fn 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]
177fn match_first_arm_never() {
178 let t = type_at(
179 r#"
180//- /main.rs
181fn 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]
196fn match_second_arm_never() {
197 let t = type_at(
198 r#"
199//- /main.rs
200fn 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]
215fn match_all_arms_never() {
216 let t = type_at(
217 r#"
218//- /main.rs
219fn 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]
232fn match_no_never_arms() {
233 let t = type_at(
234 r#"
235//- /main.rs
236fn 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}