diff options
Diffstat (limited to 'crates/hir_ty/src/traits')
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 124 |
2 files changed, 62 insertions, 72 deletions
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 944145603..4019fdf17 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -238,7 +238,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
238 | }); | 238 | }); |
239 | let bound = OpaqueTyDatumBound { | 239 | let bound = OpaqueTyDatumBound { |
240 | bounds: make_binders( | 240 | bounds: make_binders( |
241 | 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 | ], | ||
242 | 1, | 245 | 1, |
243 | ), | 246 | ), |
244 | where_clauses: make_binders(vec![], 0), | 247 | where_clauses: make_binders(vec![], 0), |
@@ -397,7 +400,6 @@ pub(crate) fn associated_ty_data_query( | |||
397 | .iter() | 400 | .iter() |
398 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) | 401 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) |
399 | .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)) |
400 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) | ||
401 | .collect(); | 403 | .collect(); |
402 | 404 | ||
403 | 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); |
@@ -720,3 +722,7 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { | |||
720 | chalk_ir::ClosureId(id.as_intern_id()) | 722 | chalk_ir::ClosureId(id.as_intern_id()) |
721 | } | 723 | } |
722 | } | 724 | } |
725 | |||
726 | fn 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 65feb82e5..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 | |||
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)) |
@@ -447,35 +439,12 @@ where | |||
447 | type Chalk = chalk_ir::Canonical<T::Chalk>; | 439 | type Chalk = chalk_ir::Canonical<T::Chalk>; |
448 | 440 | ||
449 | 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> { |
450 | let kinds = self.kinds.iter().map(|&tk| { | ||
451 | chalk_ir::CanonicalVarKind::new( | ||
452 | chalk_ir::VariableKind::Ty(tk), | ||
453 | chalk_ir::UniverseIndex::ROOT, | ||
454 | ) | ||
455 | }); | ||
456 | let value = self.value.to_chalk(db); | 442 | let value = self.value.to_chalk(db); |
457 | chalk_ir::Canonical { | 443 | chalk_ir::Canonical { value, binders: self.binders } |
458 | value, | ||
459 | binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds), | ||
460 | } | ||
461 | } | 444 | } |
462 | 445 | ||
463 | 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> { |
464 | let kinds = canonical | 447 | Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) } |
465 | .binders | ||
466 | .iter(&Interner) | ||
467 | .map(|k| match k.kind { | ||
468 | chalk_ir::VariableKind::Ty(tk) => tk, | ||
469 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
470 | // want to just skip them, but to not mess up the indices of | ||
471 | // other variables, we'll just create a new type variable in | ||
472 | // their place instead. This should not matter (we never see the | ||
473 | // actual *uses* of the lifetime variable). | ||
474 | chalk_ir::VariableKind::Lifetime => chalk_ir::TyVariableKind::General, | ||
475 | chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), | ||
476 | }) | ||
477 | .collect(); | ||
478 | Canonical { kinds, value: from_chalk(db, canonical.value) } | ||
479 | } | 448 | } |
480 | } | 449 | } |
481 | 450 | ||
@@ -486,10 +455,7 @@ where | |||
486 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | 455 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; |
487 | 456 | ||
488 | 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> { |
489 | chalk_ir::InEnvironment { | 458 | chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) } |
490 | environment: self.environment.env.clone(), | ||
491 | goal: self.value.to_chalk(db), | ||
492 | } | ||
493 | } | 459 | } |
494 | 460 | ||
495 | fn from_chalk( | 461 | fn from_chalk( |
@@ -500,6 +466,29 @@ where | |||
500 | } | 466 | } |
501 | } | 467 | } |
502 | 468 | ||
469 | impl<T: ToChalk> ToChalk for crate::Binders<T> | ||
470 | where | ||
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 | |||
503 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | 492 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> |
504 | where | 493 | where |
505 | T: HasInterner<Interner = Interner>, | 494 | T: HasInterner<Interner = Interner>, |
@@ -529,14 +518,15 @@ pub(super) fn convert_where_clauses( | |||
529 | 518 | ||
530 | pub(super) fn generic_predicate_to_inline_bound( | 519 | pub(super) fn generic_predicate_to_inline_bound( |
531 | db: &dyn HirDatabase, | 520 | db: &dyn HirDatabase, |
532 | pred: &WhereClause, | 521 | pred: &QuantifiedWhereClause, |
533 | self_ty: &Ty, | 522 | self_ty: &Ty, |
534 | ) -> Option<rust_ir::InlineBound<Interner>> { | 523 | ) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> { |
535 | // 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. |
536 | // 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. |
537 | match pred { | 526 | let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE); |
527 | match &pred.value { | ||
538 | WhereClause::Implemented(trait_ref) => { | 528 | WhereClause::Implemented(trait_ref) => { |
539 | if &trait_ref.substitution[0] != self_ty { | 529 | if trait_ref.self_type_parameter() != &self_ty_shifted_in { |
540 | // we can only convert predicates back to type bounds if they | 530 | // we can only convert predicates back to type bounds if they |
541 | // have the expected self type | 531 | // have the expected self type |
542 | return None; | 532 | return None; |
@@ -546,19 +536,13 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
546 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 536 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
547 | .collect(); | 537 | .collect(); |
548 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; | 538 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; |
549 | Some(rust_ir::InlineBound::TraitBound(trait_bound)) | 539 | Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders)) |
550 | } | 540 | } |
551 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { | 541 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
552 | if &projection_ty.substitution[0] != self_ty { | 542 | if projection_ty.self_type_parameter() != &self_ty_shifted_in { |
553 | return None; | 543 | return None; |
554 | } | 544 | } |
555 | let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id) | 545 | 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..] | 546 | let args_no_self = projection_ty.substitution[1..] |
563 | .iter() | 547 | .iter() |
564 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 548 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
@@ -569,7 +553,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
569 | associated_ty_id: projection_ty.associated_ty_id, | 553 | associated_ty_id: projection_ty.associated_ty_id, |
570 | 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 |
571 | }; | 555 | }; |
572 | Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | 556 | Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) |
573 | } | 557 | } |
574 | _ => None, | 558 | _ => None, |
575 | } | 559 | } |