diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-26 23:11:13 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-26 23:11:13 +0000 |
commit | 7f9a6521efc6939bb395238d249ee3a397fa4446 (patch) | |
tree | 7a90002872ed3a2ea6d6df369519053e277d1a1f /crates/ra_hir/src/ty.rs | |
parent | e40d8d40321b191ee82b8b07910f8a0898c8914c (diff) | |
parent | 94bbb2418aa5201ddf2d5faf01f349896303cb82 (diff) |
Merge #686
686: Handle cycles in type vars r=matklad a=flodiebold
This might be the cause of #587.
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 179ebddee..31ea45706 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -29,6 +29,8 @@ use ra_arena::map::ArenaMap; | |||
29 | use join_to_string::join; | 29 | use join_to_string::join; |
30 | use rustc_hash::FxHashMap; | 30 | use rustc_hash::FxHashMap; |
31 | 31 | ||
32 | use test_utils::tested_by; | ||
33 | |||
32 | use crate::{ | 34 | use crate::{ |
33 | Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, | 35 | Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, |
34 | FnSignature, FnScopes, ModuleDef, AdtDef, | 36 | FnSignature, FnScopes, ModuleDef, AdtDef, |
@@ -862,14 +864,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
862 | } | 864 | } |
863 | 865 | ||
864 | fn resolve_all(mut self) -> InferenceResult { | 866 | fn resolve_all(mut self) -> InferenceResult { |
867 | let mut tv_stack = Vec::new(); | ||
865 | let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default()); | 868 | let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default()); |
866 | for ty in expr_types.values_mut() { | 869 | for ty in expr_types.values_mut() { |
867 | let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); | 870 | let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown)); |
868 | *ty = resolved; | 871 | *ty = resolved; |
869 | } | 872 | } |
870 | let mut pat_types = mem::replace(&mut self.type_of_pat, ArenaMap::default()); | 873 | let mut pat_types = mem::replace(&mut self.type_of_pat, ArenaMap::default()); |
871 | for ty in pat_types.values_mut() { | 874 | for ty in pat_types.values_mut() { |
872 | let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); | 875 | let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown)); |
873 | *ty = resolved; | 876 | *ty = resolved; |
874 | } | 877 | } |
875 | InferenceResult { | 878 | InferenceResult { |
@@ -1014,13 +1017,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1014 | /// by their known types. All types returned by the infer_* functions should | 1017 | /// by their known types. All types returned by the infer_* functions should |
1015 | /// be resolved as far as possible, i.e. contain no type variables with | 1018 | /// be resolved as far as possible, i.e. contain no type variables with |
1016 | /// known type. | 1019 | /// known type. |
1017 | fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { | 1020 | fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
1018 | ty.fold(&mut |ty| match ty { | 1021 | ty.fold(&mut |ty| match ty { |
1019 | Ty::Infer(tv) => { | 1022 | Ty::Infer(tv) => { |
1020 | let inner = tv.to_inner(); | 1023 | let inner = tv.to_inner(); |
1024 | if tv_stack.contains(&inner) { | ||
1025 | tested_by!(type_var_cycles_resolve_as_possible); | ||
1026 | // recursive type | ||
1027 | return tv.fallback_value(); | ||
1028 | } | ||
1021 | if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() { | 1029 | if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() { |
1022 | // known_ty may contain other variables that are known by now | 1030 | // known_ty may contain other variables that are known by now |
1023 | self.resolve_ty_as_possible(known_ty.clone()) | 1031 | tv_stack.push(inner); |
1032 | let result = self.resolve_ty_as_possible(tv_stack, known_ty.clone()); | ||
1033 | tv_stack.pop(); | ||
1034 | result | ||
1024 | } else { | 1035 | } else { |
1025 | ty | 1036 | ty |
1026 | } | 1037 | } |
@@ -1049,13 +1060,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1049 | 1060 | ||
1050 | /// Resolves the type completely; type variables without known type are | 1061 | /// Resolves the type completely; type variables without known type are |
1051 | /// replaced by Ty::Unknown. | 1062 | /// replaced by Ty::Unknown. |
1052 | fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { | 1063 | fn resolve_ty_completely(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
1053 | ty.fold(&mut |ty| match ty { | 1064 | ty.fold(&mut |ty| match ty { |
1054 | Ty::Infer(tv) => { | 1065 | Ty::Infer(tv) => { |
1055 | let inner = tv.to_inner(); | 1066 | let inner = tv.to_inner(); |
1067 | if tv_stack.contains(&inner) { | ||
1068 | tested_by!(type_var_cycles_resolve_completely); | ||
1069 | // recursive type | ||
1070 | return tv.fallback_value(); | ||
1071 | } | ||
1056 | if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() { | 1072 | if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() { |
1057 | // known_ty may contain other variables that are known by now | 1073 | // known_ty may contain other variables that are known by now |
1058 | self.resolve_ty_completely(known_ty.clone()) | 1074 | tv_stack.push(inner); |
1075 | let result = self.resolve_ty_completely(tv_stack, known_ty.clone()); | ||
1076 | tv_stack.pop(); | ||
1077 | result | ||
1059 | } else { | 1078 | } else { |
1060 | tv.fallback_value() | 1079 | tv.fallback_value() |
1061 | } | 1080 | } |
@@ -1070,7 +1089,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1070 | let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); | 1089 | let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); |
1071 | if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { | 1090 | if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { |
1072 | let ty = self.type_of_pat.get(scope_entry.pat())?; | 1091 | let ty = self.type_of_pat.get(scope_entry.pat())?; |
1073 | let ty = self.resolve_ty_as_possible(ty.clone()); | 1092 | let ty = self.resolve_ty_as_possible(&mut vec![], ty.clone()); |
1074 | return Some(ty); | 1093 | return Some(ty); |
1075 | }; | 1094 | }; |
1076 | }; | 1095 | }; |
@@ -1239,7 +1258,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1239 | // use a new type variable if we got Ty::Unknown here | 1258 | // use a new type variable if we got Ty::Unknown here |
1240 | let ty = self.insert_type_vars_shallow(ty); | 1259 | let ty = self.insert_type_vars_shallow(ty); |
1241 | self.unify(&ty, expected); | 1260 | self.unify(&ty, expected); |
1242 | let ty = self.resolve_ty_as_possible(ty); | 1261 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); |
1243 | self.write_pat_ty(pat, ty.clone()); | 1262 | self.write_pat_ty(pat, ty.clone()); |
1244 | ty | 1263 | ty |
1245 | } | 1264 | } |
@@ -1538,7 +1557,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1538 | // use a new type variable if we got Ty::Unknown here | 1557 | // use a new type variable if we got Ty::Unknown here |
1539 | let ty = self.insert_type_vars_shallow(ty); | 1558 | let ty = self.insert_type_vars_shallow(ty); |
1540 | self.unify(&ty, &expected.ty); | 1559 | self.unify(&ty, &expected.ty); |
1541 | let ty = self.resolve_ty_as_possible(ty); | 1560 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); |
1542 | self.write_expr_ty(tgt_expr, ty.clone()); | 1561 | self.write_expr_ty(tgt_expr, ty.clone()); |
1543 | ty | 1562 | ty |
1544 | } | 1563 | } |