diff options
author | Florian Diebold <[email protected]> | 2019-05-05 13:21:00 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-05-11 15:21:20 +0100 |
commit | 50bbf9eb09dc34781cc34e10bfba5f154e833123 (patch) | |
tree | 6ed1ff97c8923ddeea085c75d417d5185493ef11 /crates/ra_hir/src/ty/traits | |
parent | 940c538ecf42a53e5a0e0e9ebad7267c1fe843ca (diff) |
Handle where clauses in trait solving
Diffstat (limited to 'crates/ra_hir/src/ty/traits')
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 68 |
1 files changed, 55 insertions, 13 deletions
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 8b77d21b4..2772a0432 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -11,7 +11,7 @@ use ra_db::salsa::{InternId, InternKey}; | |||
11 | use crate::{ | 11 | use crate::{ |
12 | Trait, HasGenericParams, ImplBlock, | 12 | Trait, HasGenericParams, ImplBlock, |
13 | db::HirDatabase, | 13 | db::HirDatabase, |
14 | ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs}, | 14 | ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate}, generics::GenericDef, |
15 | }; | 15 | }; |
16 | use super::ChalkContext; | 16 | use super::ChalkContext; |
17 | 17 | ||
@@ -146,6 +146,27 @@ impl ToChalk for ImplBlock { | |||
146 | } | 146 | } |
147 | } | 147 | } |
148 | 148 | ||
149 | impl ToChalk for GenericPredicate { | ||
150 | type Chalk = chalk_ir::QuantifiedWhereClause; | ||
151 | |||
152 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { | ||
153 | match self { | ||
154 | GenericPredicate::Implemented(trait_ref) => { | ||
155 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) | ||
156 | } | ||
157 | GenericPredicate::Error => panic!("Trying to pass errored where clause to Chalk"), | ||
158 | } | ||
159 | } | ||
160 | |||
161 | fn from_chalk( | ||
162 | _db: &impl HirDatabase, | ||
163 | _where_clause: chalk_ir::QuantifiedWhereClause, | ||
164 | ) -> GenericPredicate { | ||
165 | // This should never need to be called | ||
166 | unimplemented!() | ||
167 | } | ||
168 | } | ||
169 | |||
149 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | 170 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { |
150 | chalk_ir::Binders { | 171 | chalk_ir::Binders { |
151 | value, | 172 | value, |
@@ -153,6 +174,25 @@ fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | |||
153 | } | 174 | } |
154 | } | 175 | } |
155 | 176 | ||
177 | fn convert_where_clauses( | ||
178 | db: &impl HirDatabase, | ||
179 | def: GenericDef, | ||
180 | substs: &Substs, | ||
181 | ) -> (Vec<chalk_ir::QuantifiedWhereClause>, bool) { | ||
182 | let generic_predicates = db.generic_predicates(def); | ||
183 | let mut result = Vec::with_capacity(generic_predicates.len()); | ||
184 | let mut has_error = false; | ||
185 | for pred in generic_predicates.iter() { | ||
186 | // FIXME: it would probably be nicer if we could just convert errored predicates to a where clause that is never true... | ||
187 | if pred.is_error() { | ||
188 | has_error = true; | ||
189 | } else { | ||
190 | result.push(pred.clone().subst(substs).to_chalk(db)); | ||
191 | } | ||
192 | } | ||
193 | (result, has_error) | ||
194 | } | ||
195 | |||
156 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> | 196 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> |
157 | where | 197 | where |
158 | DB: HirDatabase, | 198 | DB: HirDatabase, |
@@ -173,7 +213,7 @@ where | |||
173 | upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), | 213 | upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), |
174 | fundamental: false, | 214 | fundamental: false, |
175 | }; | 215 | }; |
176 | let where_clauses = Vec::new(); // FIXME add where clauses | 216 | let (where_clauses, _) = convert_where_clauses(self.db, trait_.into(), &bound_vars); |
177 | let associated_ty_ids = Vec::new(); // FIXME add associated tys | 217 | let associated_ty_ids = Vec::new(); // FIXME add associated tys |
178 | let trait_datum_bound = | 218 | let trait_datum_bound = |
179 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; | 219 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; |
@@ -185,21 +225,26 @@ where | |||
185 | let type_ctor = from_chalk(self.db, struct_id); | 225 | let type_ctor = from_chalk(self.db, struct_id); |
186 | // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor | 226 | // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor |
187 | // FIXME extract this to a method on Ty | 227 | // FIXME extract this to a method on Ty |
188 | let (num_params, upstream) = match type_ctor { | 228 | let (num_params, where_clauses, upstream) = match type_ctor { |
189 | TypeCtor::Bool | 229 | TypeCtor::Bool |
190 | | TypeCtor::Char | 230 | | TypeCtor::Char |
191 | | TypeCtor::Int(_) | 231 | | TypeCtor::Int(_) |
192 | | TypeCtor::Float(_) | 232 | | TypeCtor::Float(_) |
193 | | TypeCtor::Never | 233 | | TypeCtor::Never |
194 | | TypeCtor::Str => (0, true), | 234 | | TypeCtor::Str => (0, vec![], true), |
195 | TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => (1, true), | 235 | TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => { |
196 | TypeCtor::FnPtr { num_args } => (num_args as usize + 1, true), | 236 | (1, vec![], true) |
197 | TypeCtor::Tuple { cardinality } => (cardinality as usize, true), | 237 | } |
238 | TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true), | ||
239 | TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true), | ||
198 | TypeCtor::FnDef(_) => unimplemented!(), | 240 | TypeCtor::FnDef(_) => unimplemented!(), |
199 | TypeCtor::Adt(adt) => { | 241 | TypeCtor::Adt(adt) => { |
200 | let generic_params = adt.generic_params(self.db); | 242 | let generic_params = adt.generic_params(self.db); |
243 | let bound_vars = Substs::bound_vars(&generic_params); | ||
244 | let (where_clauses, _) = convert_where_clauses(self.db, adt.into(), &bound_vars); | ||
201 | ( | 245 | ( |
202 | generic_params.count_params_including_parent(), | 246 | generic_params.count_params_including_parent(), |
247 | where_clauses, | ||
203 | adt.krate(self.db) != Some(self.krate), | 248 | adt.krate(self.db) != Some(self.krate), |
204 | ) | 249 | ) |
205 | } | 250 | } |
@@ -209,7 +254,6 @@ where | |||
209 | // FIXME set fundamental flag correctly | 254 | // FIXME set fundamental flag correctly |
210 | fundamental: false, | 255 | fundamental: false, |
211 | }; | 256 | }; |
212 | let where_clauses = Vec::new(); // FIXME add where clauses | ||
213 | let self_ty = chalk_ir::ApplicationTy { | 257 | let self_ty = chalk_ir::ApplicationTy { |
214 | name: TypeName::TypeKindId(type_ctor.to_chalk(self.db).into()), | 258 | name: TypeName::TypeKindId(type_ctor.to_chalk(self.db).into()), |
215 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), | 259 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), |
@@ -237,10 +281,12 @@ where | |||
237 | } else { | 281 | } else { |
238 | chalk_rust_ir::ImplType::External | 282 | chalk_rust_ir::ImplType::External |
239 | }; | 283 | }; |
284 | let (where_clauses, where_clause_error) = | ||
285 | convert_where_clauses(self.db, impl_block.into(), &bound_vars); | ||
240 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | 286 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { |
241 | // FIXME handle negative impls (impl !Sync for Foo) | 287 | // FIXME handle negative impls (impl !Sync for Foo) |
242 | trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(self.db)), | 288 | trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(self.db)), |
243 | where_clauses: Vec::new(), // FIXME add where clauses | 289 | where_clauses, |
244 | associated_ty_values: Vec::new(), // FIXME add associated type values | 290 | associated_ty_values: Vec::new(), // FIXME add associated type values |
245 | impl_type, | 291 | impl_type, |
246 | }; | 292 | }; |
@@ -253,10 +299,6 @@ where | |||
253 | self.db | 299 | self.db |
254 | .impls_for_trait(self.krate, trait_) | 300 | .impls_for_trait(self.krate, trait_) |
255 | .iter() | 301 | .iter() |
256 | // FIXME temporary hack -- as long as we're not lowering where clauses | ||
257 | // correctly, ignore impls with them completely so as to not treat | ||
258 | // impl<T> Trait for T where T: ... as a blanket impl on all types | ||
259 | .filter(|impl_block| impl_block.generic_params(self.db).where_predicates.is_empty()) | ||
260 | .map(|impl_block| impl_block.to_chalk(self.db)) | 302 | .map(|impl_block| impl_block.to_chalk(self.db)) |
261 | .collect() | 303 | .collect() |
262 | } | 304 | } |