diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 170 |
1 files changed, 160 insertions, 10 deletions
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index c2d7abd17..b80b67a7a 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -5,10 +5,13 @@ use log::debug; | |||
5 | 5 | ||
6 | use chalk_ir::{ | 6 | use chalk_ir::{ |
7 | cast::Cast, fold::shift::Shift, interner::HasInterner, GenericArg, Goal, GoalData, | 7 | cast::Cast, fold::shift::Shift, interner::HasInterner, GenericArg, Goal, GoalData, |
8 | PlaceholderIndex, TypeName, UniverseIndex, | 8 | PlaceholderIndex, Scalar, TypeName, UniverseIndex, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; | 11 | use hir_def::{ |
12 | type_ref::Mutability, AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, | ||
13 | TypeAliasId, | ||
14 | }; | ||
12 | use ra_db::{ | 15 | use ra_db::{ |
13 | salsa::{InternId, InternKey}, | 16 | salsa::{InternId, InternKey}, |
14 | CrateId, | 17 | CrateId, |
@@ -16,7 +19,11 @@ use ra_db::{ | |||
16 | 19 | ||
17 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 20 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
18 | use crate::{ | 21 | use crate::{ |
19 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, | 22 | db::HirDatabase, |
23 | display::HirDisplay, | ||
24 | method_resolution::TyFingerprint, | ||
25 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, | ||
26 | utils::generics, | ||
20 | ApplicationTy, DebruijnIndex, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 27 | ApplicationTy, DebruijnIndex, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
21 | }; | 28 | }; |
22 | 29 | ||
@@ -330,6 +337,9 @@ impl ToChalk for Ty { | |||
330 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { | 337 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { |
331 | match self { | 338 | match self { |
332 | Ty::Apply(apply_ty) => { | 339 | Ty::Apply(apply_ty) => { |
340 | if let TypeCtor::Ref(m) = apply_ty.ctor { | ||
341 | return ref_to_chalk(db, m, apply_ty.parameters); | ||
342 | } | ||
333 | let name = apply_ty.ctor.to_chalk(db); | 343 | let name = apply_ty.ctor.to_chalk(db); |
334 | let substitution = apply_ty.parameters.to_chalk(db); | 344 | let substitution = apply_ty.parameters.to_chalk(db); |
335 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | 345 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) |
@@ -373,6 +383,7 @@ impl ToChalk for Ty { | |||
373 | match chalk.data(&Interner).clone() { | 383 | match chalk.data(&Interner).clone() { |
374 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { | 384 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { |
375 | TypeName::Error => Ty::Unknown, | 385 | TypeName::Error => Ty::Unknown, |
386 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), | ||
376 | _ => { | 387 | _ => { |
377 | let ctor = from_chalk(db, apply_ty.name); | 388 | let ctor = from_chalk(db, apply_ty.name); |
378 | let parameters = from_chalk(db, apply_ty.substitution); | 389 | let parameters = from_chalk(db, apply_ty.substitution); |
@@ -409,6 +420,41 @@ impl ToChalk for Ty { | |||
409 | } | 420 | } |
410 | } | 421 | } |
411 | 422 | ||
423 | const LIFETIME_PLACEHOLDER: PlaceholderIndex = | ||
424 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; | ||
425 | |||
426 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a | ||
427 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. | ||
428 | fn ref_to_chalk( | ||
429 | db: &dyn HirDatabase, | ||
430 | mutability: Mutability, | ||
431 | subst: Substs, | ||
432 | ) -> chalk_ir::Ty<Interner> { | ||
433 | let arg = subst[0].clone().to_chalk(db); | ||
434 | let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); | ||
435 | chalk_ir::ApplicationTy { | ||
436 | name: TypeName::Ref(mutability.to_chalk(db)), | ||
437 | substitution: chalk_ir::Substitution::from( | ||
438 | &Interner, | ||
439 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], | ||
440 | ), | ||
441 | } | ||
442 | .intern(&Interner) | ||
443 | } | ||
444 | |||
445 | /// Here we remove the lifetime from the type we got from Chalk. | ||
446 | fn ref_from_chalk( | ||
447 | db: &dyn HirDatabase, | ||
448 | mutability: chalk_ir::Mutability, | ||
449 | subst: chalk_ir::Substitution<Interner>, | ||
450 | ) -> Ty { | ||
451 | let tys = subst | ||
452 | .iter(&Interner) | ||
453 | .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone()))) | ||
454 | .collect(); | ||
455 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) | ||
456 | } | ||
457 | |||
412 | impl ToChalk for Substs { | 458 | impl ToChalk for Substs { |
413 | type Chalk = chalk_ir::Substitution<Interner>; | 459 | type Chalk = chalk_ir::Substitution<Interner>; |
414 | 460 | ||
@@ -465,7 +511,31 @@ impl ToChalk for TypeCtor { | |||
465 | let type_id = type_alias.to_chalk(db); | 511 | let type_id = type_alias.to_chalk(db); |
466 | TypeName::AssociatedType(type_id) | 512 | TypeName::AssociatedType(type_id) |
467 | } | 513 | } |
468 | _ => { | 514 | |
515 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), | ||
516 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), | ||
517 | TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), | ||
518 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) => { | ||
519 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) | ||
520 | } | ||
521 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) => { | ||
522 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) | ||
523 | } | ||
524 | |||
525 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), | ||
526 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), | ||
527 | TypeCtor::Slice => TypeName::Slice, | ||
528 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), | ||
529 | TypeCtor::Str => TypeName::Str, | ||
530 | |||
531 | TypeCtor::Int(Uncertain::Unknown) | ||
532 | | TypeCtor::Float(Uncertain::Unknown) | ||
533 | | TypeCtor::Adt(_) | ||
534 | | TypeCtor::Array | ||
535 | | TypeCtor::FnDef(_) | ||
536 | | TypeCtor::FnPtr { .. } | ||
537 | | TypeCtor::Never | ||
538 | | TypeCtor::Closure { .. } => { | ||
469 | // other TypeCtors get interned and turned into a chalk StructId | 539 | // other TypeCtors get interned and turned into a chalk StructId |
470 | let struct_id = db.intern_type_ctor(self).into(); | 540 | let struct_id = db.intern_type_ctor(self).into(); |
471 | TypeName::Adt(struct_id) | 541 | TypeName::Adt(struct_id) |
@@ -479,12 +549,27 @@ impl ToChalk for TypeCtor { | |||
479 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | 549 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), |
480 | TypeName::OpaqueType(_) => unreachable!(), | 550 | TypeName::OpaqueType(_) => unreachable!(), |
481 | 551 | ||
482 | TypeName::Scalar(_) => unreachable!(), | 552 | TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, |
483 | TypeName::Tuple(_) => unreachable!(), | 553 | TypeName::Scalar(Scalar::Char) => TypeCtor::Char, |
484 | TypeName::Raw(_) => unreachable!(), | 554 | TypeName::Scalar(Scalar::Int(int_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { |
485 | TypeName::Slice => unreachable!(), | 555 | signedness: Signedness::Signed, |
486 | TypeName::Ref(_) => unreachable!(), | 556 | bitness: bitness_from_chalk_int(int_ty), |
487 | TypeName::Str => unreachable!(), | 557 | })), |
558 | TypeName::Scalar(Scalar::Uint(uint_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { | ||
559 | signedness: Signedness::Unsigned, | ||
560 | bitness: bitness_from_chalk_uint(uint_ty), | ||
561 | })), | ||
562 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => { | ||
563 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) | ||
564 | } | ||
565 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => { | ||
566 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) | ||
567 | } | ||
568 | TypeName::Tuple(cardinality) => TypeCtor::Tuple { cardinality: cardinality as u16 }, | ||
569 | TypeName::Raw(mutability) => TypeCtor::RawPtr(from_chalk(db, mutability)), | ||
570 | TypeName::Slice => TypeCtor::Slice, | ||
571 | TypeName::Ref(mutability) => TypeCtor::Ref(from_chalk(db, mutability)), | ||
572 | TypeName::Str => TypeCtor::Str, | ||
488 | 573 | ||
489 | TypeName::FnDef(_) => unreachable!(), | 574 | TypeName::FnDef(_) => unreachable!(), |
490 | 575 | ||
@@ -496,6 +581,71 @@ impl ToChalk for TypeCtor { | |||
496 | } | 581 | } |
497 | } | 582 | } |
498 | 583 | ||
584 | fn bitness_from_chalk_uint(uint_ty: chalk_ir::UintTy) -> IntBitness { | ||
585 | use chalk_ir::UintTy; | ||
586 | |||
587 | match uint_ty { | ||
588 | UintTy::Usize => IntBitness::Xsize, | ||
589 | UintTy::U8 => IntBitness::X8, | ||
590 | UintTy::U16 => IntBitness::X16, | ||
591 | UintTy::U32 => IntBitness::X32, | ||
592 | UintTy::U64 => IntBitness::X64, | ||
593 | UintTy::U128 => IntBitness::X128, | ||
594 | } | ||
595 | } | ||
596 | |||
597 | fn bitness_from_chalk_int(int_ty: chalk_ir::IntTy) -> IntBitness { | ||
598 | use chalk_ir::IntTy; | ||
599 | |||
600 | match int_ty { | ||
601 | IntTy::Isize => IntBitness::Xsize, | ||
602 | IntTy::I8 => IntBitness::X8, | ||
603 | IntTy::I16 => IntBitness::X16, | ||
604 | IntTy::I32 => IntBitness::X32, | ||
605 | IntTy::I64 => IntBitness::X64, | ||
606 | IntTy::I128 => IntBitness::X128, | ||
607 | } | ||
608 | } | ||
609 | |||
610 | fn int_ty_to_chalk(int_ty: IntTy) -> Scalar { | ||
611 | use chalk_ir::{IntTy, UintTy}; | ||
612 | |||
613 | match int_ty.signedness { | ||
614 | Signedness::Signed => Scalar::Int(match int_ty.bitness { | ||
615 | IntBitness::Xsize => IntTy::Isize, | ||
616 | IntBitness::X8 => IntTy::I8, | ||
617 | IntBitness::X16 => IntTy::I16, | ||
618 | IntBitness::X32 => IntTy::I32, | ||
619 | IntBitness::X64 => IntTy::I64, | ||
620 | IntBitness::X128 => IntTy::I128, | ||
621 | }), | ||
622 | Signedness::Unsigned => Scalar::Uint(match int_ty.bitness { | ||
623 | IntBitness::Xsize => UintTy::Usize, | ||
624 | IntBitness::X8 => UintTy::U8, | ||
625 | IntBitness::X16 => UintTy::U16, | ||
626 | IntBitness::X32 => UintTy::U32, | ||
627 | IntBitness::X64 => UintTy::U64, | ||
628 | IntBitness::X128 => UintTy::U128, | ||
629 | }), | ||
630 | } | ||
631 | } | ||
632 | |||
633 | impl ToChalk for Mutability { | ||
634 | type Chalk = chalk_ir::Mutability; | ||
635 | fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk { | ||
636 | match self { | ||
637 | Mutability::Shared => chalk_ir::Mutability::Not, | ||
638 | Mutability::Mut => chalk_ir::Mutability::Mut, | ||
639 | } | ||
640 | } | ||
641 | fn from_chalk(_db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
642 | match chalk { | ||
643 | chalk_ir::Mutability::Mut => Mutability::Mut, | ||
644 | chalk_ir::Mutability::Not => Mutability::Shared, | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | |||
499 | impl ToChalk for Impl { | 649 | impl ToChalk for Impl { |
500 | type Chalk = ImplId; | 650 | type Chalk = ImplId; |
501 | 651 | ||