@@ -5,20 +5,29 @@ use log::debug;
55
66use chalk_ir:: {
77 cast:: Cast , fold:: shift:: Shift , interner:: HasInterner , GenericArg , Goal , GoalData ,
8- PlaceholderIndex , TypeName , UniverseIndex ,
8+ PlaceholderIndex , Scalar , TypeName , UniverseIndex ,
99} ;
1010
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+ } ;
1216use ra_db:: {
1317 salsa:: { InternId , InternKey } ,
1418 CrateId ,
1519} ;
1620
1721use super :: { builtin, AssocTyValue , Canonical , ChalkContext , Impl , Obligation } ;
1822use 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,
2028 ApplicationTy , DebruijnIndex , GenericPredicate , ProjectionTy , Substs , TraitRef , Ty , TypeCtor ,
2129} ;
30+ use chalk_rust_ir:: WellKnownTrait ;
2231
2332pub ( super ) mod tls;
2433
@@ -330,6 +339,9 @@ impl ToChalk for Ty {
330339 fn to_chalk ( self , db : & dyn HirDatabase ) -> chalk_ir:: Ty < Interner > {
331340 match self {
332341 Ty :: Apply ( apply_ty) => {
342+ if let TypeCtor :: Ref ( m) = apply_ty. ctor {
343+ return ref_to_chalk ( db, m, apply_ty. parameters ) ;
344+ }
333345 let name = apply_ty. ctor . to_chalk ( db) ;
334346 let substitution = apply_ty. parameters . to_chalk ( db) ;
335347 chalk_ir:: ApplicationTy { name, substitution } . cast ( & Interner ) . intern ( & Interner )
@@ -373,6 +385,7 @@ impl ToChalk for Ty {
373385 match chalk. data ( & Interner ) . clone ( ) {
374386 chalk_ir:: TyData :: Apply ( apply_ty) => match apply_ty. name {
375387 TypeName :: Error => Ty :: Unknown ,
388+ TypeName :: Ref ( m) => ref_from_chalk ( db, m, apply_ty. substitution ) ,
376389 _ => {
377390 let ctor = from_chalk ( db, apply_ty. name ) ;
378391 let parameters = from_chalk ( db, apply_ty. substitution ) ;
@@ -409,6 +422,41 @@ impl ToChalk for Ty {
409422 }
410423}
411424
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+
412460impl ToChalk for Substs {
413461 type Chalk = chalk_ir:: Substitution < Interner > ;
414462
@@ -465,7 +513,31 @@ impl ToChalk for TypeCtor {
465513 let type_id = type_alias. to_chalk ( db) ;
466514 TypeName :: AssociatedType ( type_id)
467515 }
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 { .. } => {
469541 // other TypeCtors get interned and turned into a chalk StructId
470542 let struct_id = db. intern_type_ctor ( self ) . into ( ) ;
471543 TypeName :: Adt ( struct_id)
@@ -479,12 +551,27 @@ impl ToChalk for TypeCtor {
479551 TypeName :: AssociatedType ( type_id) => TypeCtor :: AssociatedType ( from_chalk ( db, type_id) ) ,
480552 TypeName :: OpaqueType ( _) => unreachable ! ( ) ,
481553
482- TypeName :: Scalar ( _) => unreachable ! ( ) ,
483- TypeName :: Tuple ( _) => unreachable ! ( ) ,
484- TypeName :: Raw ( _) => unreachable ! ( ) ,
485- TypeName :: Slice => unreachable ! ( ) ,
486- TypeName :: Ref ( _) => unreachable ! ( ) ,
487- TypeName :: Str => unreachable ! ( ) ,
554+ TypeName :: Scalar ( Scalar :: Bool ) => TypeCtor :: Bool ,
555+ TypeName :: Scalar ( Scalar :: Char ) => TypeCtor :: Char ,
556+ TypeName :: Scalar ( Scalar :: Int ( int_ty) ) => TypeCtor :: Int ( Uncertain :: Known ( IntTy {
557+ signedness : Signedness :: Signed ,
558+ bitness : bitness_from_chalk_int ( int_ty) ,
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 ,
488575
489576 TypeName :: FnDef ( _) => unreachable ! ( ) ,
490577
@@ -496,6 +583,71 @@ impl ToChalk for TypeCtor {
496583 }
497584}
498585
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+
499651impl ToChalk for Impl {
500652 type Chalk = ImplId ;
501653
@@ -907,10 +1059,15 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
9071059 }
9081060 fn well_known_trait_id (
9091061 & self ,
910- _well_known_trait : chalk_rust_ir:: WellKnownTrait ,
1062+ well_known_trait : chalk_rust_ir:: WellKnownTrait ,
9111063 ) -> Option < chalk_ir:: TraitId < Interner > > {
912- // FIXME tell Chalk about well-known traits (here and in trait_datum)
913- None
1064+ let lang_attr = lang_attr_from_well_known_trait ( well_known_trait) ;
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 ) )
9141071 }
9151072
9161073 fn program_clauses_for_env (
@@ -1012,7 +1169,8 @@ pub(crate) fn trait_datum_query(
10121169 let associated_ty_ids =
10131170 trait_data. associated_types ( ) . map ( |type_alias| type_alias. to_chalk ( db) ) . collect ( ) ;
10141171 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) ) ;
10161174 let trait_datum = TraitDatum {
10171175 id : trait_id,
10181176 binders : make_binders ( trait_datum_bound, bound_vars. len ( ) ) ,
@@ -1023,6 +1181,25 @@ pub(crate) fn trait_datum_query(
10231181 Arc :: new ( trait_datum)
10241182}
10251183
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+
10261203pub ( crate ) fn struct_datum_query (
10271204 db : & dyn HirDatabase ,
10281205 krate : CrateId ,
0 commit comments