aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/traits
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/traits')
-rw-r--r--crates/hir_ty/src/traits/chalk.rs48
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs238
2 files changed, 145 insertions, 141 deletions
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index bef6e7e9c..4019fdf17 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -19,10 +19,10 @@ use crate::{
19 display::HirDisplay, 19 display::HirDisplay,
20 from_assoc_type_id, 20 from_assoc_type_id,
21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
22 to_assoc_type_id, 22 to_assoc_type_id, to_chalk_trait_id,
23 utils::generics, 23 utils::generics,
24 BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, GenericPredicate, 24 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, ProjectionTy,
25 ProjectionPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind, 25 Substitution, TraitRef, Ty, TyKind, WhereClause,
26}; 26};
27use mapping::{ 27use mapping::{
28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, 28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
@@ -187,13 +187,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
187 let data = &datas.value.impl_traits[idx as usize]; 187 let data = &datas.value.impl_traits[idx as usize];
188 let bound = OpaqueTyDatumBound { 188 let bound = OpaqueTyDatumBound {
189 bounds: make_binders( 189 bounds: make_binders(
190 data.bounds 190 data.bounds.value.iter().cloned().map(|b| b.to_chalk(self.db)).collect(),
191 .value
192 .iter()
193 .cloned()
194 .filter(|b| !b.is_error())
195 .map(|b| b.to_chalk(self.db))
196 .collect(),
197 1, 191 1,
198 ), 192 ),
199 where_clauses: make_binders(vec![], 0), 193 where_clauses: make_binders(vec![], 0),
@@ -218,10 +212,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
218 // |-------------OpaqueTyDatumBound--------------| 212 // |-------------OpaqueTyDatumBound--------------|
219 // for<T> <Self> [Future<Self>, Future::Output<Self> = T] 213 // for<T> <Self> [Future<Self>, Future::Output<Self> = T]
220 // ^1 ^0 ^0 ^0 ^1 214 // ^1 ^0 ^0 ^0 ^1
221 let impl_bound = GenericPredicate::Implemented(TraitRef { 215 let impl_bound = WhereClause::Implemented(TraitRef {
222 trait_: future_trait, 216 trait_id: to_chalk_trait_id(future_trait),
223 // Self type as the first parameter. 217 // Self type as the first parameter.
224 substs: Substitution::single( 218 substitution: Substitution::single(
225 TyKind::BoundVar(BoundVar { 219 TyKind::BoundVar(BoundVar {
226 debruijn: DebruijnIndex::INNERMOST, 220 debruijn: DebruijnIndex::INNERMOST,
227 index: 0, 221 index: 0,
@@ -229,22 +223,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
229 .intern(&Interner), 223 .intern(&Interner),
230 ), 224 ),
231 }); 225 });
232 let proj_bound = GenericPredicate::Projection(ProjectionPredicate { 226 let proj_bound = WhereClause::AliasEq(AliasEq {
233 // The parameter of the opaque type. 227 alias: AliasTy::Projection(ProjectionTy {
234 ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
235 .intern(&Interner),
236 projection_ty: ProjectionTy {
237 associated_ty_id: to_assoc_type_id(future_output), 228 associated_ty_id: to_assoc_type_id(future_output),
238 // Self type as the first parameter. 229 // Self type as the first parameter.
239 substitution: Substitution::single( 230 substitution: Substitution::single(
240 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 231 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
241 .intern(&Interner), 232 .intern(&Interner),
242 ), 233 ),
243 }, 234 }),
235 // The parameter of the opaque type.
236 ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
237 .intern(&Interner),
244 }); 238 });
245 let bound = OpaqueTyDatumBound { 239 let bound = OpaqueTyDatumBound {
246 bounds: make_binders( 240 bounds: make_binders(
247 vec![impl_bound.to_chalk(self.db), proj_bound.to_chalk(self.db)], 241 vec![
242 wrap_in_empty_binders(impl_bound).to_chalk(self.db),
243 wrap_in_empty_binders(proj_bound).to_chalk(self.db),
244 ],
248 1, 245 1,
249 ), 246 ),
250 where_clauses: make_binders(vec![], 0), 247 where_clauses: make_binders(vec![], 0),
@@ -401,9 +398,8 @@ pub(crate) fn associated_ty_data_query(
401 let bounds = type_alias_data 398 let bounds = type_alias_data
402 .bounds 399 .bounds
403 .iter() 400 .iter()
404 .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone())) 401 .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false))
405 .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) 402 .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
406 .map(|bound| make_binders(bound.shifted_in(&Interner), 0))
407 .collect(); 403 .collect();
408 404
409 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); 405 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
@@ -546,7 +542,7 @@ fn impl_def_datum(
546 542
547 let generic_params = generics(db.upcast(), impl_id.into()); 543 let generic_params = generics(db.upcast(), impl_id.into());
548 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 544 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
549 let trait_ = trait_ref.trait_; 545 let trait_ = trait_ref.hir_trait_id();
550 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { 546 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate {
551 rust_ir::ImplType::Local 547 rust_ir::ImplType::Local
552 } else { 548 } else {
@@ -614,7 +610,7 @@ fn type_alias_associated_ty_value(
614 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved 610 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved
615 611
616 let assoc_ty = db 612 let assoc_ty = db
617 .trait_data(trait_ref.trait_) 613 .trait_data(trait_ref.hir_trait_id())
618 .associated_type_by_name(&type_alias_data.name) 614 .associated_type_by_name(&type_alias_data.name)
619 .expect("assoc ty value should not exist"); // validated when building the impl data as well 615 .expect("assoc ty value should not exist"); // validated when building the impl data as well
620 let ty = db.ty(type_alias.into()); 616 let ty = db.ty(type_alias.into());
@@ -726,3 +722,7 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
726 chalk_ir::ClosureId(id.as_intern_id()) 722 chalk_ir::ClosureId(id.as_intern_id())
727 } 723 }
728} 724}
725
726fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> {
727 crate::Binders::wrap_empty(value)
728}
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index d969527dc..aef6b8a15 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -7,15 +7,14 @@ use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeDa
7use chalk_solve::rust_ir; 7use chalk_solve::rust_ir;
8 8
9use base_db::salsa::InternKey; 9use base_db::salsa::InternKey;
10use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use crate::{
13 db::HirDatabase, 13 db::HirDatabase,
14 from_assoc_type_id,
15 primitive::UintTy, 14 primitive::UintTy,
16 traits::{Canonical, Obligation}, 15 traits::{Canonical, DomainGoal},
17 AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, 16 AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy,
18 ProjectionPredicate, ProjectionTy, Scalar, Substitution, TraitRef, Ty, 17 QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause,
19}; 18};
20 19
21use super::interner::*; 20use super::interner::*;
@@ -95,10 +94,10 @@ impl ToChalk for Ty {
95 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), 94 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner),
96 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), 95 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
97 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), 96 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
98 TyKind::Dyn(predicates) => { 97 TyKind::Dyn(dyn_ty) => {
99 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( 98 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
100 &Interner, 99 &Interner,
101 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), 100 dyn_ty.bounds.value.interned().iter().cloned().map(|p| p.to_chalk(db)),
102 ); 101 );
103 let bounded_ty = chalk_ir::DynTy { 102 let bounded_ty = chalk_ir::DynTy {
104 bounds: make_binders(where_clauses, 1), 103 bounds: make_binders(where_clauses, 1),
@@ -144,13 +143,17 @@ impl ToChalk for Ty {
144 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, 143 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown,
145 chalk_ir::TyKind::Dyn(where_clauses) => { 144 chalk_ir::TyKind::Dyn(where_clauses) => {
146 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); 145 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
147 let predicates = where_clauses 146 let bounds = where_clauses
148 .bounds 147 .bounds
149 .skip_binders() 148 .skip_binders()
150 .iter(&Interner) 149 .iter(&Interner)
151 .map(|c| from_chalk(db, c.clone())) 150 .map(|c| from_chalk(db, c.clone()));
152 .collect(); 151 TyKind::Dyn(crate::DynTy {
153 TyKind::Dyn(predicates) 152 bounds: crate::Binders::new(
153 1,
154 crate::QuantifiedWhereClauses::from_iter(&Interner, bounds),
155 ),
156 })
154 } 157 }
155 158
156 chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), 159 chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)),
@@ -239,15 +242,15 @@ impl ToChalk for TraitRef {
239 type Chalk = chalk_ir::TraitRef<Interner>; 242 type Chalk = chalk_ir::TraitRef<Interner>;
240 243
241 fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> { 244 fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> {
242 let trait_id = self.trait_.to_chalk(db); 245 let trait_id = self.trait_id;
243 let substitution = self.substs.to_chalk(db); 246 let substitution = self.substitution.to_chalk(db);
244 chalk_ir::TraitRef { trait_id, substitution } 247 chalk_ir::TraitRef { trait_id, substitution }
245 } 248 }
246 249
247 fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self { 250 fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self {
248 let trait_ = from_chalk(db, trait_ref.trait_id); 251 let trait_id = trait_ref.trait_id;
249 let substs = from_chalk(db, trait_ref.substitution); 252 let substs = from_chalk(db, trait_ref.substitution);
250 TraitRef { trait_, substs } 253 TraitRef { trait_id, substitution: substs }
251 } 254 }
252} 255}
253 256
@@ -304,50 +307,26 @@ impl ToChalk for TypeAliasAsValue {
304 } 307 }
305} 308}
306 309
307impl ToChalk for GenericPredicate { 310impl ToChalk for WhereClause {
308 type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; 311 type Chalk = chalk_ir::WhereClause<Interner>;
309 312
310 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { 313 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> {
311 match self { 314 match self {
312 GenericPredicate::Implemented(trait_ref) => { 315 WhereClause::Implemented(trait_ref) => {
313 let chalk_trait_ref = trait_ref.to_chalk(db); 316 chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db))
314 let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner);
315 make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0)
316 }
317 GenericPredicate::Projection(projection_pred) => {
318 let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner);
319 let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner);
320 let alias = chalk_ir::AliasTy::Projection(projection);
321 make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0)
322 } 317 }
323 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), 318 WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)),
324 } 319 }
325 } 320 }
326 321
327 fn from_chalk( 322 fn from_chalk(
328 db: &dyn HirDatabase, 323 db: &dyn HirDatabase,
329 where_clause: chalk_ir::QuantifiedWhereClause<Interner>, 324 where_clause: chalk_ir::WhereClause<Interner>,
330 ) -> GenericPredicate { 325 ) -> WhereClause {
331 // we don't produce any where clauses with binders and can't currently deal with them 326 match where_clause {
332 match where_clause 327 chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)),
333 .skip_binders() 328 chalk_ir::WhereClause::AliasEq(alias_eq) => {
334 .clone() 329 WhereClause::AliasEq(from_chalk(db, alias_eq))
335 .shifted_out(&Interner)
336 .expect("unexpected bound vars in where clause")
337 {
338 chalk_ir::WhereClause::Implemented(tr) => {
339 GenericPredicate::Implemented(from_chalk(db, tr))
340 }
341 chalk_ir::WhereClause::AliasEq(projection_eq) => {
342 let projection_ty = from_chalk(
343 db,
344 match projection_eq.alias {
345 chalk_ir::AliasTy::Projection(p) => p,
346 _ => unimplemented!(),
347 },
348 );
349 let ty = from_chalk(db, projection_eq.ty);
350 GenericPredicate::Projection(ProjectionPredicate { projection_ty, ty })
351 } 330 }
352 331
353 chalk_ir::WhereClause::LifetimeOutlives(_) => { 332 chalk_ir::WhereClause::LifetimeOutlives(_) => {
@@ -383,29 +362,67 @@ impl ToChalk for ProjectionTy {
383 } 362 }
384 } 363 }
385} 364}
365impl ToChalk for OpaqueTy {
366 type Chalk = chalk_ir::OpaqueTy<Interner>;
367
368 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
369 chalk_ir::OpaqueTy {
370 opaque_ty_id: self.opaque_ty_id,
371 substitution: self.substitution.to_chalk(db),
372 }
373 }
374
375 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
376 OpaqueTy {
377 opaque_ty_id: chalk.opaque_ty_id,
378 substitution: from_chalk(db, chalk.substitution),
379 }
380 }
381}
382
383impl ToChalk for AliasTy {
384 type Chalk = chalk_ir::AliasTy<Interner>;
385
386 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
387 match self {
388 AliasTy::Projection(projection_ty) => {
389 chalk_ir::AliasTy::Projection(projection_ty.to_chalk(db))
390 }
391 AliasTy::Opaque(opaque_ty) => chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)),
392 }
393 }
394
395 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
396 match chalk {
397 chalk_ir::AliasTy::Projection(projection_ty) => {
398 AliasTy::Projection(from_chalk(db, projection_ty))
399 }
400 chalk_ir::AliasTy::Opaque(opaque_ty) => AliasTy::Opaque(from_chalk(db, opaque_ty)),
401 }
402 }
403}
386 404
387impl ToChalk for ProjectionPredicate { 405impl ToChalk for AliasEq {
388 type Chalk = chalk_ir::AliasEq<Interner>; 406 type Chalk = chalk_ir::AliasEq<Interner>;
389 407
390 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { 408 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> {
391 chalk_ir::AliasEq { 409 chalk_ir::AliasEq { alias: self.alias.to_chalk(db), ty: self.ty.to_chalk(db) }
392 alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)),
393 ty: self.ty.to_chalk(db),
394 }
395 } 410 }
396 411
397 fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { 412 fn from_chalk(db: &dyn HirDatabase, alias_eq: chalk_ir::AliasEq<Interner>) -> Self {
398 unimplemented!() 413 AliasEq { alias: from_chalk(db, alias_eq.alias), ty: from_chalk(db, alias_eq.ty) }
399 } 414 }
400} 415}
401 416
402impl ToChalk for Obligation { 417impl ToChalk for DomainGoal {
403 type Chalk = chalk_ir::DomainGoal<Interner>; 418 type Chalk = chalk_ir::DomainGoal<Interner>;
404 419
405 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { 420 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
406 match self { 421 match self {
407 Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), 422 DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner),
408 Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner), 423 DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => {
424 alias_eq.to_chalk(db).cast(&Interner)
425 }
409 } 426 }
410 } 427 }
411 428
@@ -422,35 +439,12 @@ where
422 type Chalk = chalk_ir::Canonical<T::Chalk>; 439 type Chalk = chalk_ir::Canonical<T::Chalk>;
423 440
424 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { 441 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
425 let kinds = self.kinds.iter().map(|&tk| {
426 chalk_ir::CanonicalVarKind::new(
427 chalk_ir::VariableKind::Ty(tk),
428 chalk_ir::UniverseIndex::ROOT,
429 )
430 });
431 let value = self.value.to_chalk(db); 442 let value = self.value.to_chalk(db);
432 chalk_ir::Canonical { 443 chalk_ir::Canonical { value, binders: self.binders }
433 value,
434 binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds),
435 }
436 } 444 }
437 445
438 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { 446 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
439 let kinds = canonical 447 Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) }
440 .binders
441 .iter(&Interner)
442 .map(|k| match k.kind {
443 chalk_ir::VariableKind::Ty(tk) => tk,
444 // HACK: Chalk can sometimes return new lifetime variables. We
445 // want to just skip them, but to not mess up the indices of
446 // other variables, we'll just create a new type variable in
447 // their place instead. This should not matter (we never see the
448 // actual *uses* of the lifetime variable).
449 chalk_ir::VariableKind::Lifetime => chalk_ir::TyVariableKind::General,
450 chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
451 })
452 .collect();
453 Canonical { kinds, value: from_chalk(db, canonical.value) }
454 } 448 }
455} 449}
456 450
@@ -461,10 +455,7 @@ where
461 type Chalk = chalk_ir::InEnvironment<T::Chalk>; 455 type Chalk = chalk_ir::InEnvironment<T::Chalk>;
462 456
463 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { 457 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
464 chalk_ir::InEnvironment { 458 chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) }
465 environment: self.environment.env.clone(),
466 goal: self.value.to_chalk(db),
467 }
468 } 459 }
469 460
470 fn from_chalk( 461 fn from_chalk(
@@ -475,6 +466,29 @@ where
475 } 466 }
476} 467}
477 468
469impl<T: ToChalk> ToChalk for crate::Binders<T>
470where
471 T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
472{
473 type Chalk = chalk_ir::Binders<T::Chalk>;
474
475 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> {
476 chalk_ir::Binders::new(
477 chalk_ir::VariableKinds::from_iter(
478 &Interner,
479 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
480 .take(self.num_binders),
481 ),
482 self.value.to_chalk(db),
483 )
484 }
485
486 fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> {
487 let (v, b) = binders.into_value_and_skipped_binders();
488 crate::Binders::new(b.len(&Interner), from_chalk(db, v))
489 }
490}
491
478pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> 492pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
479where 493where
480 T: HasInterner<Interner = Interner>, 494 T: HasInterner<Interner = Interner>,
@@ -497,10 +511,6 @@ pub(super) fn convert_where_clauses(
497 let generic_predicates = db.generic_predicates(def); 511 let generic_predicates = db.generic_predicates(def);
498 let mut result = Vec::with_capacity(generic_predicates.len()); 512 let mut result = Vec::with_capacity(generic_predicates.len());
499 for pred in generic_predicates.iter() { 513 for pred in generic_predicates.iter() {
500 if pred.value.is_error() {
501 // skip errored predicates completely
502 continue;
503 }
504 result.push(pred.clone().subst(substs).to_chalk(db)); 514 result.push(pred.clone().subst(substs).to_chalk(db));
505 } 515 }
506 result 516 result
@@ -508,49 +518,43 @@ pub(super) fn convert_where_clauses(
508 518
509pub(super) fn generic_predicate_to_inline_bound( 519pub(super) fn generic_predicate_to_inline_bound(
510 db: &dyn HirDatabase, 520 db: &dyn HirDatabase,
511 pred: &GenericPredicate, 521 pred: &QuantifiedWhereClause,
512 self_ty: &Ty, 522 self_ty: &Ty,
513) -> Option<rust_ir::InlineBound<Interner>> { 523) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
514 // An InlineBound is like a GenericPredicate, except the self type is left out. 524 // An InlineBound is like a GenericPredicate, except the self type is left out.
515 // We don't have a special type for this, but Chalk does. 525 // We don't have a special type for this, but Chalk does.
516 match pred { 526 let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE);
517 GenericPredicate::Implemented(trait_ref) => { 527 match &pred.value {
518 if &trait_ref.substs[0] != self_ty { 528 WhereClause::Implemented(trait_ref) => {
529 if trait_ref.self_type_parameter() != &self_ty_shifted_in {
519 // we can only convert predicates back to type bounds if they 530 // we can only convert predicates back to type bounds if they
520 // have the expected self type 531 // have the expected self type
521 return None; 532 return None;
522 } 533 }
523 let args_no_self = trait_ref.substs[1..] 534 let args_no_self = trait_ref.substitution[1..]
524 .iter() 535 .iter()
525 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 536 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
526 .collect(); 537 .collect();
527 let trait_bound = 538 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
528 rust_ir::TraitBound { trait_id: trait_ref.trait_.to_chalk(db), args_no_self }; 539 Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders))
529 Some(rust_ir::InlineBound::TraitBound(trait_bound))
530 } 540 }
531 GenericPredicate::Projection(proj) => { 541 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
532 if &proj.projection_ty.substitution[0] != self_ty { 542 if projection_ty.self_type_parameter() != &self_ty_shifted_in {
533 return None; 543 return None;
534 } 544 }
535 let trait_ = match from_assoc_type_id(proj.projection_ty.associated_ty_id) 545 let trait_ = projection_ty.trait_(db);
536 .lookup(db.upcast()) 546 let args_no_self = projection_ty.substitution[1..]
537 .container
538 {
539 AssocContainerId::TraitId(t) => t,
540 _ => panic!("associated type not in trait"),
541 };
542 let args_no_self = proj.projection_ty.substitution[1..]
543 .iter() 547 .iter()
544 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 548 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
545 .collect(); 549 .collect();
546 let alias_eq_bound = rust_ir::AliasEqBound { 550 let alias_eq_bound = rust_ir::AliasEqBound {
547 value: proj.ty.clone().to_chalk(db), 551 value: ty.clone().to_chalk(db),
548 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, 552 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self },
549 associated_ty_id: proj.projection_ty.associated_ty_id, 553 associated_ty_id: projection_ty.associated_ty_id,
550 parameters: Vec::new(), // FIXME we don't support generic associated types yet 554 parameters: Vec::new(), // FIXME we don't support generic associated types yet
551 }; 555 };
552 Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) 556 Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders))
553 } 557 }
554 GenericPredicate::Error => None, 558 _ => None,
555 } 559 }
556} 560}