@@ -5,20 +5,29 @@ use log::debug;
5
5
6
6
use chalk_ir:: {
7
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
16
use ra_db:: {
13
17
salsa:: { InternId , InternKey } ,
14
18
CrateId ,
15
19
} ;
16
20
17
21
use super :: { builtin, AssocTyValue , Canonical , ChalkContext , Impl , Obligation } ;
18
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
28
ApplicationTy , DebruijnIndex , GenericPredicate , ProjectionTy , Substs , TraitRef , Ty , TypeCtor ,
21
29
} ;
30
+ use chalk_rust_ir:: WellKnownTrait ;
22
31
23
32
pub ( super ) mod tls;
24
33
@@ -330,6 +339,9 @@ impl ToChalk for Ty {
330
339
fn to_chalk ( self , db : & dyn HirDatabase ) -> chalk_ir:: Ty < Interner > {
331
340
match self {
332
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
345
let name = apply_ty. ctor . to_chalk ( db) ;
334
346
let substitution = apply_ty. parameters . to_chalk ( db) ;
335
347
chalk_ir:: ApplicationTy { name, substitution } . cast ( & Interner ) . intern ( & Interner )
@@ -373,6 +385,7 @@ impl ToChalk for Ty {
373
385
match chalk. data ( & Interner ) . clone ( ) {
374
386
chalk_ir:: TyData :: Apply ( apply_ty) => match apply_ty. name {
375
387
TypeName :: Error => Ty :: Unknown ,
388
+ TypeName :: Ref ( m) => ref_from_chalk ( db, m, apply_ty. substitution ) ,
376
389
_ => {
377
390
let ctor = from_chalk ( db, apply_ty. name ) ;
378
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
460
impl ToChalk for Substs {
413
461
type Chalk = chalk_ir:: Substitution < Interner > ;
414
462
@@ -465,7 +513,31 @@ impl ToChalk for TypeCtor {
465
513
let type_id = type_alias. to_chalk ( db) ;
466
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
541
// other TypeCtors get interned and turned into a chalk StructId
470
542
let struct_id = db. intern_type_ctor ( self ) . into ( ) ;
471
543
TypeName :: Adt ( struct_id)
@@ -479,12 +551,27 @@ impl ToChalk for TypeCtor {
479
551
TypeName :: AssociatedType ( type_id) => TypeCtor :: AssociatedType ( from_chalk ( db, type_id) ) ,
480
552
TypeName :: OpaqueType ( _) => unreachable ! ( ) ,
481
553
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 ,
488
575
489
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
651
impl ToChalk for Impl {
500
652
type Chalk = ImplId ;
501
653
@@ -907,10 +1059,15 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
907
1059
}
908
1060
fn well_known_trait_id (
909
1061
& self ,
910
- _well_known_trait : chalk_rust_ir:: WellKnownTrait ,
1062
+ well_known_trait : chalk_rust_ir:: WellKnownTrait ,
911
1063
) -> 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 ) )
914
1071
}
915
1072
916
1073
fn program_clauses_for_env (
@@ -1012,7 +1169,8 @@ pub(crate) fn trait_datum_query(
1012
1169
let associated_ty_ids =
1013
1170
trait_data. associated_types ( ) . map ( |type_alias| type_alias. to_chalk ( db) ) . collect ( ) ;
1014
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
1174
let trait_datum = TraitDatum {
1017
1175
id : trait_id,
1018
1176
binders : make_binders ( trait_datum_bound, bound_vars. len ( ) ) ,
@@ -1023,6 +1181,25 @@ pub(crate) fn trait_datum_query(
1023
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
1203
pub ( crate ) fn struct_datum_query (
1027
1204
db : & dyn HirDatabase ,
1028
1205
krate : CrateId ,
0 commit comments