@@ -14,7 +14,8 @@ use chalk_derive::{Fold, HasInterner, SuperVisit, Visit, Zip};
1414use std:: marker:: PhantomData ;
1515
1616pub use crate :: debug:: SeparatorTraitRef ;
17-
17+ #[ macro_use( bitflags) ]
18+ extern crate bitflags;
1819/// Uninhabited (empty) type, used in combination with `PhantomData`.
1920#[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
2021pub enum Void { }
@@ -411,11 +412,147 @@ pub struct Ty<I: Interner> {
411412 interned : I :: InternedType ,
412413}
413414
415+ ///compute type flags for Lifetime
416+ fn compute_lifetime_flags < I : Interner > ( lifetime : & Lifetime < I > , interner : & I ) -> TypeFlags {
417+ match lifetime. data ( & interner) {
418+ LifetimeData :: InferenceVar ( _) => {
419+ TypeFlags :: HAS_RE_INFER
420+ | TypeFlags :: HAS_FREE_LOCAL_REGIONS
421+ | TypeFlags :: HAS_FREE_REGIONS
422+ }
423+ LifetimeData :: Placeholder ( _) => {
424+ TypeFlags :: HAS_RE_PLACEHOLDER
425+ | TypeFlags :: HAS_FREE_LOCAL_REGIONS
426+ | TypeFlags :: HAS_FREE_REGIONS
427+ }
428+ LifetimeData :: Static | LifetimeData :: Empty ( _) => TypeFlags :: HAS_FREE_REGIONS ,
429+ LifetimeData :: Phantom ( _, _) => TypeFlags :: empty ( ) ,
430+ LifetimeData :: BoundVar ( _) => TypeFlags :: HAS_RE_LATE_BOUND ,
431+ LifetimeData :: Erased => TypeFlags :: HAS_RE_ERASED ,
432+ }
433+ }
434+
435+ /// Compute type flags for Substitution<I>
436+ fn compute_substitution_flags < I : Interner > (
437+ substitution : & Substitution < I > ,
438+ interner : & I ,
439+ ) -> TypeFlags {
440+ let mut flags = TypeFlags :: empty ( ) ;
441+ for generic_arg in substitution. iter ( & interner) {
442+ flags |= compute_generic_arg_flags ( generic_arg, & interner) ;
443+ }
444+ flags
445+ }
446+
447+ /// Compute type flags for GenericArg<I>
448+ fn compute_generic_arg_flags < I : Interner > ( generic_arg : & GenericArg < I > , interner : & I ) -> TypeFlags {
449+ match generic_arg. data ( & interner) {
450+ GenericArgData :: Ty ( ty) => ty. data ( interner) . flags ,
451+ GenericArgData :: Lifetime ( lifetime) => compute_lifetime_flags ( lifetime, interner) ,
452+ GenericArgData :: Const ( constant) => {
453+ let data = constant. data ( & interner) ;
454+ let flags = data. ty . data ( interner) . flags ;
455+ match data. value {
456+ ConstValue :: BoundVar ( _) => flags,
457+ ConstValue :: InferenceVar ( _) => {
458+ flags | TypeFlags :: HAS_CT_INFER | TypeFlags :: STILL_FURTHER_SPECIALIZABLE
459+ }
460+ ConstValue :: Placeholder ( _) => {
461+ flags | TypeFlags :: HAS_CT_PLACEHOLDER | TypeFlags :: STILL_FURTHER_SPECIALIZABLE
462+ }
463+ ConstValue :: Concrete ( _) => flags,
464+ }
465+ }
466+ }
467+ }
468+
469+ /// Compute type flags for aliases
470+ fn compute_alias_flags < I : Interner > ( alias_ty : & AliasTy < I > , interner : & I ) -> TypeFlags {
471+ match alias_ty {
472+ AliasTy :: Projection ( projection_ty) => {
473+ TypeFlags :: HAS_TY_PROJECTION
474+ | compute_substitution_flags ( & ( projection_ty. substitution ) , interner)
475+ }
476+ AliasTy :: Opaque ( opaque_ty) => {
477+ TypeFlags :: HAS_TY_OPAQUE
478+ | compute_substitution_flags ( & ( opaque_ty. substitution ) , interner)
479+ }
480+ }
481+ }
482+
483+ /// Compute type flags for a TyKind
484+ fn compute_flags < I : Interner > ( kind : & TyKind < I > , interner : & I ) -> TypeFlags {
485+ match kind {
486+ TyKind :: Adt ( _, substitution)
487+ | TyKind :: AssociatedType ( _, substitution)
488+ | TyKind :: Tuple ( _, substitution)
489+ | TyKind :: Closure ( _, substitution)
490+ | TyKind :: Generator ( _, substitution)
491+ | TyKind :: GeneratorWitness ( _, substitution)
492+ | TyKind :: FnDef ( _, substitution)
493+ | TyKind :: OpaqueType ( _, substitution) => compute_substitution_flags ( substitution, interner) ,
494+ TyKind :: Scalar ( _) | TyKind :: Str | TyKind :: Never | TyKind :: Foreign ( _) => TypeFlags :: empty ( ) ,
495+ TyKind :: Error => TypeFlags :: HAS_ERROR ,
496+ TyKind :: Slice ( ty) | TyKind :: Raw ( _, ty) => ty. data ( interner) . flags ,
497+ TyKind :: Ref ( _, lifetime, ty) => {
498+ compute_lifetime_flags ( lifetime, interner) | ty. data ( interner) . flags
499+ }
500+ TyKind :: Array ( ty, const_ty) => {
501+ let flags = ty. data ( interner) . flags ;
502+ let const_data = const_ty. data ( interner) ;
503+ flags
504+ | const_data. ty . data ( interner) . flags
505+ | match const_data. value {
506+ ConstValue :: BoundVar ( _) | ConstValue :: Concrete ( _) => TypeFlags :: empty ( ) ,
507+ ConstValue :: InferenceVar ( _) => {
508+ TypeFlags :: HAS_CT_INFER | TypeFlags :: STILL_FURTHER_SPECIALIZABLE
509+ }
510+ ConstValue :: Placeholder ( _) => {
511+ TypeFlags :: HAS_CT_PLACEHOLDER | TypeFlags :: STILL_FURTHER_SPECIALIZABLE
512+ }
513+ }
514+ }
515+ TyKind :: Placeholder ( _) => TypeFlags :: HAS_TY_PLACEHOLDER ,
516+ TyKind :: Dyn ( dyn_ty) => {
517+ let lifetime_flags = compute_lifetime_flags ( & ( dyn_ty. lifetime ) , & interner) ;
518+ let mut dyn_flags = TypeFlags :: empty ( ) ;
519+ for var_kind in dyn_ty. bounds . value . iter ( & interner) {
520+ match & ( var_kind. value ) {
521+ WhereClause :: Implemented ( trait_ref) => {
522+ dyn_flags |= compute_substitution_flags ( & ( trait_ref. substitution ) , interner)
523+ }
524+ WhereClause :: AliasEq ( alias_eq) => {
525+ dyn_flags |= compute_alias_flags ( & ( alias_eq. alias ) , & interner) ;
526+ dyn_flags |= alias_eq. ty . data ( & interner) . flags ;
527+ }
528+ WhereClause :: LifetimeOutlives ( lifetime_outlives) => {
529+ dyn_flags |= compute_lifetime_flags ( & ( lifetime_outlives. a ) , & interner)
530+ | compute_lifetime_flags ( & ( lifetime_outlives. b ) , & interner) ;
531+ }
532+ WhereClause :: TypeOutlives ( type_outlives) => {
533+ dyn_flags |= type_outlives. ty . data ( & interner) . flags ;
534+ dyn_flags |= compute_lifetime_flags ( & ( type_outlives. lifetime ) , & interner) ;
535+ }
536+ }
537+ }
538+ lifetime_flags | dyn_flags
539+ }
540+ TyKind :: Alias ( alias_ty) => compute_alias_flags ( & alias_ty, & interner) ,
541+ TyKind :: BoundVar ( _) => TypeFlags :: empty ( ) ,
542+ TyKind :: InferenceVar ( _, _) => TypeFlags :: HAS_TY_INFER ,
543+ TyKind :: Function ( fn_pointer) => {
544+ compute_substitution_flags ( & fn_pointer. substitution . 0 , interner)
545+ }
546+ }
547+ }
548+
414549impl < I : Interner > Ty < I > {
415550 /// Creates a type from `TyKind`.
416551 pub fn new ( interner : & I , data : impl CastTo < TyKind < I > > ) -> Self {
552+ let ty_kind = data. cast ( & interner) ;
417553 let data = TyData {
418- kind : data. cast ( interner) ,
554+ flags : compute_flags ( & ty_kind, & interner) ,
555+ kind : ty_kind,
419556 } ;
420557 Ty {
421558 interned : I :: intern_ty ( interner, data) ,
@@ -530,8 +667,57 @@ impl<I: Interner> Ty<I> {
530667pub struct TyData < I : Interner > {
531668 /// The kind
532669 pub kind : TyKind < I > ,
670+ /// Type flags
671+ pub flags : TypeFlags ,
672+ }
673+
674+ bitflags ! {
675+ /// Contains flags indicating various properties of a Ty
676+ pub struct TypeFlags : u16 {
677+ /// Does the type contain an InferenceVar
678+ const HAS_TY_INFER = 1 ;
679+ /// Does the type contain a lifetime with an InferenceVar
680+ const HAS_RE_INFER = 1 << 1 ;
681+ /// Does the type contain a ConstValue with an InferenceVar
682+ const HAS_CT_INFER = 1 << 2 ;
683+ /// Does the type contain a Placeholder TyKind
684+ const HAS_TY_PLACEHOLDER = 1 << 3 ;
685+ /// Does the type contain a lifetime with a Placeholder
686+ const HAS_RE_PLACEHOLDER = 1 << 4 ;
687+ /// Does the type contain a ConstValue Placeholder
688+ const HAS_CT_PLACEHOLDER = 1 << 5 ;
689+ /// True when the type has free lifetimes related to a local context
690+ const HAS_FREE_LOCAL_REGIONS = 1 << 6 ;
691+ /// Does the type contain a projection of an associated type
692+ const HAS_TY_PROJECTION = 1 << 7 ;
693+ /// Does the type contain an opaque type
694+ const HAS_TY_OPAQUE = 1 << 8 ;
695+ /// Does the type contain an unevaluated const projection
696+ const HAS_CT_PROJECTION = 1 << 9 ;
697+ /// Does the type contain an error
698+ const HAS_ERROR = 1 << 10 ;
699+ /// Does the type contain any free lifetimes
700+ const HAS_FREE_REGIONS = 1 << 11 ;
701+ /// True when the type contains lifetimes that will be substituted when function is called
702+ const HAS_RE_LATE_BOUND = 1 << 12 ;
703+ /// True when the type contains an erased lifetime
704+ const HAS_RE_ERASED = 1 << 13 ;
705+ /// Does the type contain placeholders or inference variables that could be replaced later
706+ const STILL_FURTHER_SPECIALIZABLE = 1 << 14 ;
707+
708+ /// True when the type contains free names local to a particular context
709+ const HAS_FREE_LOCAL_NAMES = TypeFlags :: HAS_TY_INFER . bits
710+ | TypeFlags :: HAS_CT_INFER . bits
711+ | TypeFlags :: HAS_TY_PLACEHOLDER . bits
712+ | TypeFlags :: HAS_CT_PLACEHOLDER . bits
713+ | TypeFlags :: HAS_FREE_LOCAL_REGIONS . bits;
714+
715+ /// Does the type contain any form of projection
716+ const HAS_PROJECTION = TypeFlags :: HAS_TY_PROJECTION . bits
717+ | TypeFlags :: HAS_TY_OPAQUE . bits
718+ | TypeFlags :: HAS_CT_PROJECTION . bits;
719+ }
533720}
534-
535721/// Type data, which holds the actual type information.
536722#[ derive( Clone , PartialEq , Eq , Hash , HasInterner ) ]
537723pub enum TyKind < I : Interner > {
0 commit comments