diff options
Diffstat (limited to 'crates/ra_hir_ty/src/traits')
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 205 |
1 files changed, 191 insertions, 14 deletions
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index c2d7abd17..7d3ad6eb4 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -5,10 +5,14 @@ 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 | lang_item::{lang_attr, LangItemTarget}, | ||
13 | type_ref::Mutability, | ||
14 | AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId, | ||
15 | }; | ||
12 | use ra_db::{ | 16 | use ra_db::{ |
13 | salsa::{InternId, InternKey}, | 17 | salsa::{InternId, InternKey}, |
14 | CrateId, | 18 | CrateId, |
@@ -16,9 +20,14 @@ use ra_db::{ | |||
16 | 20 | ||
17 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 21 | use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
18 | use crate::{ | 22 | use crate::{ |
19 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, | 23 | db::HirDatabase, |
24 | display::HirDisplay, | ||
25 | method_resolution::TyFingerprint, | ||
26 | primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, | ||
27 | utils::generics, | ||
20 | ApplicationTy, DebruijnIndex, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 28 | ApplicationTy, DebruijnIndex, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
21 | }; | 29 | }; |
30 | use chalk_rust_ir::WellKnownTrait; | ||
22 | 31 | ||
23 | pub(super) mod tls; | 32 | pub(super) mod tls; |
24 | 33 | ||
@@ -330,6 +339,9 @@ impl ToChalk for Ty { | |||
330 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { | 339 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { |
331 | match self { | 340 | match self { |
332 | Ty::Apply(apply_ty) => { | 341 | Ty::Apply(apply_ty) => { |
342 | if let TypeCtor::Ref(m) = apply_ty.ctor { | ||
343 | return ref_to_chalk(db, m, apply_ty.parameters); | ||
344 | } | ||
333 | let name = apply_ty.ctor.to_chalk(db); | 345 | let name = apply_ty.ctor.to_chalk(db); |
334 | let substitution = apply_ty.parameters.to_chalk(db); | 346 | let substitution = apply_ty.parameters.to_chalk(db); |
335 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) | 347 | chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) |
@@ -373,6 +385,7 @@ impl ToChalk for Ty { | |||
373 | match chalk.data(&Interner).clone() { | 385 | match chalk.data(&Interner).clone() { |
374 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { | 386 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { |
375 | TypeName::Error => Ty::Unknown, | 387 | TypeName::Error => Ty::Unknown, |
388 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), | ||
376 | _ => { | 389 | _ => { |
377 | let ctor = from_chalk(db, apply_ty.name); | 390 | let ctor = from_chalk(db, apply_ty.name); |
378 | let parameters = from_chalk(db, apply_ty.substitution); | 391 | let parameters = from_chalk(db, apply_ty.substitution); |
@@ -409,6 +422,41 @@ impl ToChalk for Ty { | |||
409 | } | 422 | } |
410 | } | 423 | } |
411 | 424 | ||
425 | const LIFETIME_PLACEHOLDER: PlaceholderIndex = | ||
426 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; | ||
427 | |||
428 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a | ||
429 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. | ||
430 | fn ref_to_chalk( | ||
431 | db: &dyn HirDatabase, | ||
432 | mutability: Mutability, | ||
433 | subst: Substs, | ||
434 | ) -> chalk_ir::Ty<Interner> { | ||
435 | let arg = subst[0].clone().to_chalk(db); | ||
436 | let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); | ||
437 | chalk_ir::ApplicationTy { | ||
438 | name: TypeName::Ref(mutability.to_chalk(db)), | ||
439 | substitution: chalk_ir::Substitution::from( | ||
440 | &Interner, | ||
441 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], | ||
442 | ), | ||
443 | } | ||
444 | .intern(&Interner) | ||
445 | } | ||
446 | |||
447 | /// Here we remove the lifetime from the type we got from Chalk. | ||
448 | fn ref_from_chalk( | ||
449 | db: &dyn HirDatabase, | ||
450 | mutability: chalk_ir::Mutability, | ||
451 | subst: chalk_ir::Substitution<Interner>, | ||
452 | ) -> Ty { | ||
453 | let tys = subst | ||
454 | .iter(&Interner) | ||
455 | .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone()))) | ||
456 | .collect(); | ||
457 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) | ||
458 | } | ||
459 | |||
412 | impl ToChalk for Substs { | 460 | impl ToChalk for Substs { |
413 | type Chalk = chalk_ir::Substitution<Interner>; | 461 | type Chalk = chalk_ir::Substitution<Interner>; |
414 | 462 | ||
@@ -465,7 +513,31 @@ impl ToChalk for TypeCtor { | |||
465 | let type_id = type_alias.to_chalk(db); | 513 | let type_id = type_alias.to_chalk(db); |
466 | TypeName::AssociatedType(type_id) | 514 | TypeName::AssociatedType(type_id) |
467 | } | 515 | } |
468 | _ => { | 516 | |
517 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), | ||
518 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), | ||
519 | TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), | ||
520 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) => { | ||
521 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) | ||
522 | } | ||
523 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) => { | ||
524 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) | ||
525 | } | ||
526 | |||
527 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), | ||
528 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), | ||
529 | TypeCtor::Slice => TypeName::Slice, | ||
530 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), | ||
531 | TypeCtor::Str => TypeName::Str, | ||
532 | |||
533 | TypeCtor::Int(Uncertain::Unknown) | ||
534 | | TypeCtor::Float(Uncertain::Unknown) | ||
535 | | TypeCtor::Adt(_) | ||
536 | | TypeCtor::Array | ||
537 | | TypeCtor::FnDef(_) | ||
538 | | TypeCtor::FnPtr { .. } | ||
539 | | TypeCtor::Never | ||
540 | | TypeCtor::Closure { .. } => { | ||
469 | // other TypeCtors get interned and turned into a chalk StructId | 541 | // other TypeCtors get interned and turned into a chalk StructId |
470 | let struct_id = db.intern_type_ctor(self).into(); | 542 | let struct_id = db.intern_type_ctor(self).into(); |
471 | TypeName::Adt(struct_id) | 543 | TypeName::Adt(struct_id) |
@@ -479,12 +551,27 @@ impl ToChalk for TypeCtor { | |||
479 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | 551 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), |
480 | TypeName::OpaqueType(_) => unreachable!(), | 552 | TypeName::OpaqueType(_) => unreachable!(), |
481 | 553 | ||
482 | TypeName::Scalar(_) => unreachable!(), | 554 | TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, |
483 | TypeName::Tuple(_) => unreachable!(), | 555 | TypeName::Scalar(Scalar::Char) => TypeCtor::Char, |
484 | TypeName::Raw(_) => unreachable!(), | 556 | TypeName::Scalar(Scalar::Int(int_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { |
485 | TypeName::Slice => unreachable!(), | 557 | signedness: Signedness::Signed, |
486 | TypeName::Ref(_) => unreachable!(), | 558 | bitness: bitness_from_chalk_int(int_ty), |
487 | TypeName::Str => unreachable!(), | 559 | })), |
560 | TypeName::Scalar(Scalar::Uint(uint_ty)) => TypeCtor::Int(Uncertain::Known(IntTy { | ||
561 | signedness: Signedness::Unsigned, | ||
562 | bitness: bitness_from_chalk_uint(uint_ty), | ||
563 | })), | ||
564 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F32)) => { | ||
565 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X32 })) | ||
566 | } | ||
567 | TypeName::Scalar(Scalar::Float(chalk_ir::FloatTy::F64)) => { | ||
568 | TypeCtor::Float(Uncertain::Known(FloatTy { bitness: FloatBitness::X64 })) | ||
569 | } | ||
570 | TypeName::Tuple(cardinality) => TypeCtor::Tuple { cardinality: cardinality as u16 }, | ||
571 | TypeName::Raw(mutability) => TypeCtor::RawPtr(from_chalk(db, mutability)), | ||
572 | TypeName::Slice => TypeCtor::Slice, | ||
573 | TypeName::Ref(mutability) => TypeCtor::Ref(from_chalk(db, mutability)), | ||
574 | TypeName::Str => TypeCtor::Str, | ||
488 | 575 | ||
489 | TypeName::FnDef(_) => unreachable!(), | 576 | TypeName::FnDef(_) => unreachable!(), |
490 | 577 | ||
@@ -496,6 +583,71 @@ impl ToChalk for TypeCtor { | |||
496 | } | 583 | } |
497 | } | 584 | } |
498 | 585 | ||
586 | fn bitness_from_chalk_uint(uint_ty: chalk_ir::UintTy) -> IntBitness { | ||
587 | use chalk_ir::UintTy; | ||
588 | |||
589 | match uint_ty { | ||
590 | UintTy::Usize => IntBitness::Xsize, | ||
591 | UintTy::U8 => IntBitness::X8, | ||
592 | UintTy::U16 => IntBitness::X16, | ||
593 | UintTy::U32 => IntBitness::X32, | ||
594 | UintTy::U64 => IntBitness::X64, | ||
595 | UintTy::U128 => IntBitness::X128, | ||
596 | } | ||
597 | } | ||
598 | |||
599 | fn bitness_from_chalk_int(int_ty: chalk_ir::IntTy) -> IntBitness { | ||
600 | use chalk_ir::IntTy; | ||
601 | |||
602 | match int_ty { | ||
603 | IntTy::Isize => IntBitness::Xsize, | ||
604 | IntTy::I8 => IntBitness::X8, | ||
605 | IntTy::I16 => IntBitness::X16, | ||
606 | IntTy::I32 => IntBitness::X32, | ||
607 | IntTy::I64 => IntBitness::X64, | ||
608 | IntTy::I128 => IntBitness::X128, | ||
609 | } | ||
610 | } | ||
611 | |||
612 | fn int_ty_to_chalk(int_ty: IntTy) -> Scalar { | ||
613 | use chalk_ir::{IntTy, UintTy}; | ||
614 | |||
615 | match int_ty.signedness { | ||
616 | Signedness::Signed => Scalar::Int(match int_ty.bitness { | ||
617 | IntBitness::Xsize => IntTy::Isize, | ||
618 | IntBitness::X8 => IntTy::I8, | ||
619 | IntBitness::X16 => IntTy::I16, | ||
620 | IntBitness::X32 => IntTy::I32, | ||
621 | IntBitness::X64 => IntTy::I64, | ||
622 | IntBitness::X128 => IntTy::I128, | ||
623 | }), | ||
624 | Signedness::Unsigned => Scalar::Uint(match int_ty.bitness { | ||
625 | IntBitness::Xsize => UintTy::Usize, | ||
626 | IntBitness::X8 => UintTy::U8, | ||
627 | IntBitness::X16 => UintTy::U16, | ||
628 | IntBitness::X32 => UintTy::U32, | ||
629 | IntBitness::X64 => UintTy::U64, | ||
630 | IntBitness::X128 => UintTy::U128, | ||
631 | }), | ||
632 | } | ||
633 | } | ||
634 | |||
635 | impl ToChalk for Mutability { | ||
636 | type Chalk = chalk_ir::Mutability; | ||
637 | fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk { | ||
638 | match self { | ||
639 | Mutability::Shared => chalk_ir::Mutability::Not, | ||
640 | Mutability::Mut => chalk_ir::Mutability::Mut, | ||
641 | } | ||
642 | } | ||
643 | fn from_chalk(_db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
644 | match chalk { | ||
645 | chalk_ir::Mutability::Mut => Mutability::Mut, | ||
646 | chalk_ir::Mutability::Not => Mutability::Shared, | ||
647 | } | ||
648 | } | ||
649 | } | ||
650 | |||
499 | impl ToChalk for Impl { | 651 | impl ToChalk for Impl { |
500 | type Chalk = ImplId; | 652 | type Chalk = ImplId; |
501 | 653 | ||
@@ -907,10 +1059,15 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
907 | } | 1059 | } |
908 | fn well_known_trait_id( | 1060 | fn well_known_trait_id( |
909 | &self, | 1061 | &self, |
910 | _well_known_trait: chalk_rust_ir::WellKnownTrait, | 1062 | well_known_trait: chalk_rust_ir::WellKnownTrait, |
911 | ) -> Option<chalk_ir::TraitId<Interner>> { | 1063 | ) -> Option<chalk_ir::TraitId<Interner>> { |
912 | // FIXME tell Chalk about well-known traits (here and in trait_datum) | 1064 | let lang_attr = lang_attr_from_well_known_trait(well_known_trait); |
913 | None | 1065 | let lang_items = self.db.crate_lang_items(self.krate); |
1066 | let trait_ = match lang_items.target(lang_attr) { | ||
1067 | Some(LangItemTarget::TraitId(trait_)) => trait_, | ||
1068 | _ => return None, | ||
1069 | }; | ||
1070 | Some(trait_.to_chalk(self.db)) | ||
914 | } | 1071 | } |
915 | 1072 | ||
916 | fn program_clauses_for_env( | 1073 | fn program_clauses_for_env( |
@@ -1012,7 +1169,8 @@ pub(crate) fn trait_datum_query( | |||
1012 | let associated_ty_ids = | 1169 | let associated_ty_ids = |
1013 | trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); | 1170 | trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); |
1014 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; | 1171 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; |
1015 | let well_known = None; // FIXME set this (depending on lang items) | 1172 | let well_known = |
1173 | lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); | ||
1016 | let trait_datum = TraitDatum { | 1174 | let trait_datum = TraitDatum { |
1017 | id: trait_id, | 1175 | id: trait_id, |
1018 | binders: make_binders(trait_datum_bound, bound_vars.len()), | 1176 | binders: make_binders(trait_datum_bound, bound_vars.len()), |
@@ -1023,6 +1181,25 @@ pub(crate) fn trait_datum_query( | |||
1023 | Arc::new(trait_datum) | 1181 | Arc::new(trait_datum) |
1024 | } | 1182 | } |
1025 | 1183 | ||
1184 | fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> { | ||
1185 | Some(match name { | ||
1186 | "sized" => WellKnownTrait::SizedTrait, | ||
1187 | "copy" => WellKnownTrait::CopyTrait, | ||
1188 | "clone" => WellKnownTrait::CloneTrait, | ||
1189 | "drop" => WellKnownTrait::DropTrait, | ||
1190 | _ => return None, | ||
1191 | }) | ||
1192 | } | ||
1193 | |||
1194 | fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str { | ||
1195 | match attr { | ||
1196 | WellKnownTrait::SizedTrait => "sized", | ||
1197 | WellKnownTrait::CopyTrait => "copy", | ||
1198 | WellKnownTrait::CloneTrait => "clone", | ||
1199 | WellKnownTrait::DropTrait => "drop", | ||
1200 | } | ||
1201 | } | ||
1202 | |||
1026 | pub(crate) fn struct_datum_query( | 1203 | pub(crate) fn struct_datum_query( |
1027 | db: &dyn HirDatabase, | 1204 | db: &dyn HirDatabase, |
1028 | krate: CrateId, | 1205 | krate: CrateId, |