aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs13
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs15
-rw-r--r--crates/ra_hir_ty/src/lib.rs4
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs13
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs19
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs93
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs41
7 files changed, 168 insertions, 30 deletions
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index bf8ea192b..7a84e47f8 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -185,6 +185,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
185 self.write_pat_ty(pat, bound_ty); 185 self.write_pat_ty(pat, bound_ty);
186 return inner_ty; 186 return inner_ty;
187 } 187 }
188 Pat::Slice { prefix, slice: _slice, suffix } => {
189 let (container_ty, elem_ty) = match &expected {
190 ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()),
191 ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()),
192 _ => (TypeCtor::Slice, Ty::Unknown),
193 };
194
195 for pat_id in prefix.iter().chain(suffix) {
196 self.infer_pat(*pat_id, &elem_ty, default_bm);
197 }
198
199 Ty::apply_one(container_ty, elem_ty)
200 }
188 _ => Ty::Unknown, 201 _ => Ty::Unknown,
189 }; 202 };
190 // use a new type variable if we got Ty::Unknown here 203 // use a new type variable if we got Ty::Unknown here
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index aed527fe5..82b85d570 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -142,12 +142,21 @@ impl<T> Canonicalized<T> {
142 142
143pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> { 143pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
144 let mut table = InferenceTable::new(); 144 let mut table = InferenceTable::new();
145 let num_vars = ty1.num_vars.max(ty2.num_vars);
145 let vars = 146 let vars =
146 Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); 147 Substs::builder(num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
147 let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars); 148 let ty1_with_vars = ty1.value.clone().subst_bound_vars(&vars);
148 if !table.unify(&ty_with_vars, &ty2.value) { 149 let ty2_with_vars = ty2.value.clone().subst_bound_vars(&vars);
150 if !table.unify(&ty1_with_vars, &ty2_with_vars) {
149 return None; 151 return None;
150 } 152 }
153 // default any type vars that weren't unified back to their original bound vars
154 // (kind of hacky)
155 for (i, var) in vars.iter().enumerate() {
156 if &*table.resolve_ty_shallow(var) == var {
157 table.unify(var, &Ty::Bound(i as u32));
158 }
159 }
151 Some( 160 Some(
152 Substs::builder(ty1.num_vars) 161 Substs::builder(ty1.num_vars)
153 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) 162 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 0009c426c..ca194f806 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -355,6 +355,10 @@ impl Substs {
355 Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) 355 Substs(self.0[..std::cmp::min(self.0.len(), n)].into())
356 } 356 }
357 357
358 pub fn suffix(&self, n: usize) -> Substs {
359 Substs(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into())
360 }
361
358 pub fn as_single(&self) -> &Ty { 362 pub fn as_single(&self) -> &Ty {
359 if self.0.len() != 1 { 363 if self.0.len() != 1 {
360 panic!("expected substs of len 1, got {:?}", self); 364 panic!("expected substs of len 1, got {:?}", self);
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 74b908c2e..b7e8855fb 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -508,10 +508,17 @@ pub(crate) fn inherent_impl_substs(
508 impl_id: ImplId, 508 impl_id: ImplId,
509 self_ty: &Canonical<Ty>, 509 self_ty: &Canonical<Ty>,
510) -> Option<Substs> { 510) -> Option<Substs> {
511 let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); 511 // we create a var for each type parameter of the impl; we need to keep in
512 // mind here that `self_ty` might have vars of its own
513 let vars =
514 Substs::build_for_def(db, impl_id).fill_with_bound_vars(self_ty.num_vars as u32).build();
512 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 515 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
513 let self_ty_with_vars = Canonical { num_vars: vars.len(), value: self_ty_with_vars }; 516 let self_ty_with_vars =
514 super::infer::unify(&self_ty_with_vars, self_ty) 517 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars };
518 let substs = super::infer::unify(&self_ty_with_vars, self_ty);
519 // we only want the substs for the vars we added, not the ones from self_ty
520 let result = substs.map(|s| s.suffix(vars.len()));
521 result
515} 522}
516 523
517fn transform_receiver_ty( 524fn transform_receiver_ty(
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index f9b394f05..af3e5b12c 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -1049,6 +1049,25 @@ where
1049} 1049}
1050 1050
1051#[test] 1051#[test]
1052fn method_resolution_3373() {
1053 let t = type_at(
1054 r#"
1055//- /main.rs
1056struct A<T>(T);
1057
1058impl A<i32> {
1059 fn from(v: i32) -> A<i32> { A(v) }
1060}
1061
1062fn main() {
1063 A::from(3)<|>;
1064}
1065"#,
1066 );
1067 assert_eq!(t, "A<i32>");
1068}
1069
1070#[test]
1052fn method_resolution_slow() { 1071fn method_resolution_slow() {
1053 // this can get quite slow if we set the solver size limit too high 1072 // this can get quite slow if we set the solver size limit too high
1054 let t = type_at( 1073 let t = type_at(
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index 81d00c2af..76aa32024 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -53,8 +53,9 @@ fn test(x: &i32) {
53 [140; 141) 'g': {unknown} 53 [140; 141) 'g': {unknown}
54 [144; 145) 'e': {unknown} 54 [144; 145) 'e': {unknown}
55 [158; 205) 'if let... }': () 55 [158; 205) 'if let... }': ()
56 [165; 170) '[val]': {unknown} 56 [165; 170) '[val]': [{unknown}]
57 [173; 176) 'opt': {unknown} 57 [166; 169) 'val': {unknown}
58 [173; 176) 'opt': [{unknown}]
58 [177; 205) '{ ... }': () 59 [177; 205) '{ ... }': ()
59 [191; 192) 'h': {unknown} 60 [191; 192) 'h': {unknown}
60 [195; 198) 'val': {unknown} 61 [195; 198) 'val': {unknown}
@@ -137,6 +138,94 @@ fn test() {
137} 138}
138 139
139#[test] 140#[test]
141fn infer_pattern_match_slice() {
142 assert_snapshot!(
143 infer(r#"
144fn test() {
145 let slice: &[f64] = &[0.0];
146 match slice {
147 &[] => {},
148 &[a] => {
149 a;
150 },
151 &[b, c] => {
152 b;
153 c;
154 }
155 _ => {}
156 }
157}
158"#),
159 @r###"
160 [11; 210) '{ ... } }': ()
161 [21; 26) 'slice': &[f64]
162 [37; 43) '&[0.0]': &[f64; _]
163 [38; 43) '[0.0]': [f64; _]
164 [39; 42) '0.0': f64
165 [49; 208) 'match ... }': ()
166 [55; 60) 'slice': &[f64]
167 [71; 74) '&[]': &[f64]
168 [72; 74) '[]': [f64]
169 [78; 80) '{}': ()
170 [90; 94) '&[a]': &[f64]
171 [91; 94) '[a]': [f64]
172 [92; 93) 'a': f64
173 [98; 124) '{ ... }': ()
174 [112; 113) 'a': f64
175 [134; 141) '&[b, c]': &[f64]
176 [135; 141) '[b, c]': [f64]
177 [136; 137) 'b': f64
178 [139; 140) 'c': f64
179 [145; 186) '{ ... }': ()
180 [159; 160) 'b': f64
181 [174; 175) 'c': f64
182 [195; 196) '_': &[f64]
183 [200; 202) '{}': ()
184 "###
185 );
186}
187
188#[test]
189fn infer_pattern_match_arr() {
190 assert_snapshot!(
191 infer(r#"
192fn test() {
193 let arr: [f64; 2] = [0.0, 1.0];
194 match arr {
195 [1.0, a] => {
196 a;
197 },
198 [b, c] => {
199 b;
200 c;
201 }
202 }
203}
204"#),
205 @r###"
206 [11; 180) '{ ... } }': ()
207 [21; 24) 'arr': [f64; _]
208 [37; 47) '[0.0, 1.0]': [f64; _]
209 [38; 41) '0.0': f64
210 [43; 46) '1.0': f64
211 [53; 178) 'match ... }': ()
212 [59; 62) 'arr': [f64; _]
213 [73; 81) '[1.0, a]': [f64; _]
214 [74; 77) '1.0': f64
215 [79; 80) 'a': f64
216 [85; 111) '{ ... }': ()
217 [99; 100) 'a': f64
218 [121; 127) '[b, c]': [f64; _]
219 [122; 123) 'b': f64
220 [125; 126) 'c': f64
221 [131; 172) '{ ... }': ()
222 [145; 146) 'b': f64
223 [160; 161) 'c': f64
224 "###
225 );
226}
227
228#[test]
140fn infer_adt_pattern() { 229fn infer_adt_pattern() {
141 assert_snapshot!( 230 assert_snapshot!(
142 infer(r#" 231 infer(r#"
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 4001aa941..62509bc29 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -18,7 +18,7 @@ use crate::{
18}; 18};
19 19
20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
21pub struct Interner {} 21pub struct Interner;
22 22
23impl chalk_ir::interner::Interner for Interner { 23impl chalk_ir::interner::Interner for Interner {
24 type InternedType = Box<chalk_ir::TyData<Self>>; 24 type InternedType = Box<chalk_ir::TyData<Self>>;
@@ -27,6 +27,7 @@ impl chalk_ir::interner::Interner for Interner {
27 type InternedGoal = Arc<GoalData<Self>>; 27 type InternedGoal = Arc<GoalData<Self>>;
28 type InternedGoals = Vec<Goal<Self>>; 28 type InternedGoals = Vec<Goal<Self>>;
29 type InternedSubstitution = Vec<Parameter<Self>>; 29 type InternedSubstitution = Vec<Parameter<Self>>;
30 type Identifier = TypeAliasId;
30 type DefId = InternId; 31 type DefId = InternId;
31 32
32 // FIXME: implement these 33 // FIXME: implement these
@@ -58,7 +59,7 @@ impl chalk_ir::interner::Interner for Interner {
58 None 59 None
59 } 60 }
60 61
61 fn intern_ty(ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { 62 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
62 Box::new(ty) 63 Box::new(ty)
63 } 64 }
64 65
@@ -121,7 +122,7 @@ pub type StructId = chalk_ir::StructId<Interner>;
121pub type StructDatum = chalk_rust_ir::StructDatum<Interner>; 122pub type StructDatum = chalk_rust_ir::StructDatum<Interner>;
122pub type ImplId = chalk_ir::ImplId<Interner>; 123pub type ImplId = chalk_ir::ImplId<Interner>;
123pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>; 124pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>;
124pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; 125pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>;
125pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>; 126pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>;
126 127
127pub(super) trait ToChalk { 128pub(super) trait ToChalk {
@@ -144,12 +145,12 @@ impl ToChalk for Ty {
144 Ty::Apply(apply_ty) => { 145 Ty::Apply(apply_ty) => {
145 let name = apply_ty.ctor.to_chalk(db); 146 let name = apply_ty.ctor.to_chalk(db);
146 let substitution = apply_ty.parameters.to_chalk(db); 147 let substitution = apply_ty.parameters.to_chalk(db);
147 chalk_ir::ApplicationTy { name, substitution }.cast().intern() 148 chalk_ir::ApplicationTy { name, substitution }.cast().intern(&Interner)
148 } 149 }
149 Ty::Projection(proj_ty) => { 150 Ty::Projection(proj_ty) => {
150 let associated_ty_id = proj_ty.associated_ty.to_chalk(db); 151 let associated_ty_id = proj_ty.associated_ty.to_chalk(db);
151 let substitution = proj_ty.parameters.to_chalk(db); 152 let substitution = proj_ty.parameters.to_chalk(db);
152 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern() 153 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern(&Interner)
153 } 154 }
154 Ty::Placeholder(id) => { 155 Ty::Placeholder(id) => {
155 let interned_id = db.intern_type_param_id(id); 156 let interned_id = db.intern_type_param_id(id);
@@ -157,9 +158,9 @@ impl ToChalk for Ty {
157 ui: UniverseIndex::ROOT, 158 ui: UniverseIndex::ROOT,
158 idx: interned_id.as_intern_id().as_usize(), 159 idx: interned_id.as_intern_id().as_usize(),
159 } 160 }
160 .to_ty::<Interner>() 161 .to_ty::<Interner>(&Interner)
161 } 162 }
162 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), 163 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(&Interner),
163 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 164 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
164 Ty::Dyn(predicates) => { 165 Ty::Dyn(predicates) => {
165 let where_clauses = predicates 166 let where_clauses = predicates
@@ -169,12 +170,12 @@ impl ToChalk for Ty {
169 .map(|p| p.to_chalk(db)) 170 .map(|p| p.to_chalk(db))
170 .collect(); 171 .collect();
171 let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; 172 let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) };
172 chalk_ir::TyData::Dyn(bounded_ty).intern() 173 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
173 } 174 }
174 Ty::Opaque(_) | Ty::Unknown => { 175 Ty::Opaque(_) | Ty::Unknown => {
175 let substitution = chalk_ir::Substitution::empty(); 176 let substitution = chalk_ir::Substitution::empty();
176 let name = TypeName::Error; 177 let name = TypeName::Error;
177 chalk_ir::ApplicationTy { name, substitution }.cast().intern() 178 chalk_ir::ApplicationTy { name, substitution }.cast().intern(&Interner)
178 } 179 }
179 } 180 }
180 } 181 }
@@ -611,6 +612,9 @@ where
611 _ => None, 612 _ => None,
612 } 613 }
613 } 614 }
615 fn interner(&self) -> &Interner {
616 &Interner
617 }
614} 618}
615 619
616pub(crate) fn associated_ty_data_query( 620pub(crate) fn associated_ty_data_query(
@@ -632,7 +636,7 @@ pub(crate) fn associated_ty_data_query(
632 let datum = AssociatedTyDatum { 636 let datum = AssociatedTyDatum {
633 trait_id: trait_.to_chalk(db), 637 trait_id: trait_.to_chalk(db),
634 id, 638 id,
635 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()), 639 name: type_alias,
636 binders: make_binders(bound_data, generic_params.len()), 640 binders: make_binders(bound_data, generic_params.len()),
637 }; 641 };
638 Arc::new(datum) 642 Arc::new(datum)
@@ -822,13 +826,6 @@ fn type_alias_associated_ty_value(
822 Arc::new(value) 826 Arc::new(value)
823} 827}
824 828
825fn id_from_chalk<T: InternKey>(chalk_id: chalk_ir::RawId) -> T {
826 T::from_intern_id(InternId::from(chalk_id.index))
827}
828fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
829 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
830}
831
832impl From<StructId> for crate::TypeCtorId { 829impl From<StructId> for crate::TypeCtorId {
833 fn from(struct_id: StructId) -> Self { 830 fn from(struct_id: StructId) -> Self {
834 InternKey::from_intern_id(struct_id.0) 831 InternKey::from_intern_id(struct_id.0)
@@ -853,14 +850,14 @@ impl From<crate::traits::GlobalImplId> for ImplId {
853 } 850 }
854} 851}
855 852
856impl From<chalk_rust_ir::AssociatedTyValueId> for crate::traits::AssocTyValueId { 853impl From<chalk_rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId {
857 fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { 854 fn from(id: chalk_rust_ir::AssociatedTyValueId<Interner>) -> Self {
858 id_from_chalk(id.0) 855 Self::from_intern_id(id.0)
859 } 856 }
860} 857}
861 858
862impl From<crate::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { 859impl From<crate::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId<Interner> {
863 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self { 860 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self {
864 chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) 861 chalk_rust_ir::AssociatedTyValueId(assoc_ty_value_id.as_intern_id())
865 } 862 }
866} 863}