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