diff options
Diffstat (limited to 'crates/hir_ty/src/traits/chalk')
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 94 |
1 files changed, 52 insertions, 42 deletions
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 65feb82e5..5b9c7e831 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 | |||
7 | use chalk_solve::rust_ir; | 7 | use chalk_solve::rust_ir; |
8 | 8 | ||
9 | use base_db::salsa::InternKey; | 9 | use base_db::salsa::InternKey; |
10 | use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, | 13 | db::HirDatabase, |
14 | from_assoc_type_id, | ||
15 | primitive::UintTy, | 14 | primitive::UintTy, |
16 | traits::{Canonical, DomainGoal}, | 15 | traits::{Canonical, DomainGoal}, |
17 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution, | 16 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, |
18 | TraitRef, Ty, WhereClause, | 17 | QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, |
19 | }; | 18 | }; |
20 | 19 | ||
21 | use super::interner::*; | 20 | use 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().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)), |
@@ -305,33 +308,22 @@ impl ToChalk for TypeAliasAsValue { | |||
305 | } | 308 | } |
306 | 309 | ||
307 | impl ToChalk for WhereClause { | 310 | impl 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 | WhereClause::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 | } |
317 | WhereClause::AliasEq(alias_eq) => make_binders( | 318 | WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)), |
318 | chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)), | ||
319 | 0, | ||
320 | ), | ||
321 | } | 319 | } |
322 | } | 320 | } |
323 | 321 | ||
324 | fn from_chalk( | 322 | fn from_chalk( |
325 | db: &dyn HirDatabase, | 323 | db: &dyn HirDatabase, |
326 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | 324 | where_clause: chalk_ir::WhereClause<Interner>, |
327 | ) -> WhereClause { | 325 | ) -> WhereClause { |
328 | // we don't produce any where clauses with binders and can't currently deal with them | 326 | match where_clause { |
329 | match where_clause | ||
330 | .skip_binders() | ||
331 | .clone() | ||
332 | .shifted_out(&Interner) | ||
333 | .expect("unexpected bound vars in where clause") | ||
334 | { | ||
335 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), | 327 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), |
336 | chalk_ir::WhereClause::AliasEq(alias_eq) => { | 328 | chalk_ir::WhereClause::AliasEq(alias_eq) => { |
337 | WhereClause::AliasEq(from_chalk(db, alias_eq)) | 329 | WhereClause::AliasEq(from_chalk(db, alias_eq)) |
@@ -500,6 +492,29 @@ where | |||
500 | } | 492 | } |
501 | } | 493 | } |
502 | 494 | ||
495 | impl<T: ToChalk> ToChalk for crate::Binders<T> | ||
496 | where | ||
497 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
498 | { | ||
499 | type Chalk = chalk_ir::Binders<T::Chalk>; | ||
500 | |||
501 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> { | ||
502 | chalk_ir::Binders::new( | ||
503 | chalk_ir::VariableKinds::from_iter( | ||
504 | &Interner, | ||
505 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)) | ||
506 | .take(self.num_binders), | ||
507 | ), | ||
508 | self.value.to_chalk(db), | ||
509 | ) | ||
510 | } | ||
511 | |||
512 | fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> { | ||
513 | let (v, b) = binders.into_value_and_skipped_binders(); | ||
514 | crate::Binders::new(b.len(&Interner), from_chalk(db, v)) | ||
515 | } | ||
516 | } | ||
517 | |||
503 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | 518 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> |
504 | where | 519 | where |
505 | T: HasInterner<Interner = Interner>, | 520 | T: HasInterner<Interner = Interner>, |
@@ -522,21 +537,22 @@ pub(super) fn convert_where_clauses( | |||
522 | let generic_predicates = db.generic_predicates(def); | 537 | let generic_predicates = db.generic_predicates(def); |
523 | let mut result = Vec::with_capacity(generic_predicates.len()); | 538 | let mut result = Vec::with_capacity(generic_predicates.len()); |
524 | for pred in generic_predicates.iter() { | 539 | for pred in generic_predicates.iter() { |
525 | result.push(pred.clone().subst(substs).to_chalk(db)); | 540 | result.push(crate::Binders::wrap_empty(pred.clone().subst(substs)).to_chalk(db)); |
526 | } | 541 | } |
527 | result | 542 | result |
528 | } | 543 | } |
529 | 544 | ||
530 | pub(super) fn generic_predicate_to_inline_bound( | 545 | pub(super) fn generic_predicate_to_inline_bound( |
531 | db: &dyn HirDatabase, | 546 | db: &dyn HirDatabase, |
532 | pred: &WhereClause, | 547 | pred: &QuantifiedWhereClause, |
533 | self_ty: &Ty, | 548 | self_ty: &Ty, |
534 | ) -> Option<rust_ir::InlineBound<Interner>> { | 549 | ) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> { |
535 | // An InlineBound is like a GenericPredicate, except the self type is left out. | 550 | // An InlineBound is like a GenericPredicate, except the self type is left out. |
536 | // We don't have a special type for this, but Chalk does. | 551 | // We don't have a special type for this, but Chalk does. |
537 | match pred { | 552 | let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE); |
553 | match &pred.value { | ||
538 | WhereClause::Implemented(trait_ref) => { | 554 | WhereClause::Implemented(trait_ref) => { |
539 | if &trait_ref.substitution[0] != self_ty { | 555 | if trait_ref.self_type_parameter() != &self_ty_shifted_in { |
540 | // we can only convert predicates back to type bounds if they | 556 | // we can only convert predicates back to type bounds if they |
541 | // have the expected self type | 557 | // have the expected self type |
542 | return None; | 558 | return None; |
@@ -546,19 +562,13 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
546 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 562 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
547 | .collect(); | 563 | .collect(); |
548 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; | 564 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; |
549 | Some(rust_ir::InlineBound::TraitBound(trait_bound)) | 565 | Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders)) |
550 | } | 566 | } |
551 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { | 567 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
552 | if &projection_ty.substitution[0] != self_ty { | 568 | if projection_ty.self_type_parameter() != &self_ty_shifted_in { |
553 | return None; | 569 | return None; |
554 | } | 570 | } |
555 | let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id) | 571 | let trait_ = projection_ty.trait_(db); |
556 | .lookup(db.upcast()) | ||
557 | .container | ||
558 | { | ||
559 | AssocContainerId::TraitId(t) => t, | ||
560 | _ => panic!("associated type not in trait"), | ||
561 | }; | ||
562 | let args_no_self = projection_ty.substitution[1..] | 572 | let args_no_self = projection_ty.substitution[1..] |
563 | .iter() | 573 | .iter() |
564 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 574 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
@@ -569,7 +579,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
569 | associated_ty_id: projection_ty.associated_ty_id, | 579 | associated_ty_id: projection_ty.associated_ty_id, |
570 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | 580 | parameters: Vec::new(), // FIXME we don't support generic associated types yet |
571 | }; | 581 | }; |
572 | Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | 582 | Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) |
573 | } | 583 | } |
574 | _ => None, | 584 | _ => None, |
575 | } | 585 | } |