@@ -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 { }
@@ -327,11 +328,121 @@ pub struct Ty<I: Interner> {
327328 interned : I :: InternedType ,
328329}
329330
331+ ///compute type flags for Lifetime
332+ fn compute_lifetime_flags < I : Interner > ( lifetime : & Lifetime < I > , interner : & I ) -> TypeFlags {
333+ match lifetime. data ( & interner) {
334+ LifetimeData :: InferenceVar ( _) => {
335+ TypeFlags :: HAS_RE_INFER | TypeFlags :: HAS_FREE_LOCAL_REGIONS | TypeFlags :: HAS_FREE_REGIONS
336+ } ,
337+ LifetimeData :: Placeholder ( _) => {
338+ TypeFlags :: HAS_RE_PLACEHOLDER | TypeFlags :: HAS_FREE_LOCAL_REGIONS | TypeFlags :: HAS_FREE_REGIONS
339+ } ,
340+ LifetimeData :: Static
341+ | LifetimeData :: Phantom ( _, _)
342+ | LifetimeData :: BoundVar ( _) => { TypeFlags :: empty ( ) } ,
343+ }
344+ }
345+
346+ /// Compute type flags for Substitution<I>
347+ fn compute_substitution_flags < I : Interner > ( substitution : & Substitution < I > , interner : & I ) -> TypeFlags {
348+ let mut flags = TypeFlags :: empty ( ) ;
349+ for generic_arg in substitution. iter ( & interner) {
350+ flags |= compute_generic_arg_flags ( generic_arg, & interner) ;
351+ }
352+ flags
353+ }
354+
355+ /// Compute type flags for GenericArg<I>
356+ fn compute_generic_arg_flags < I : Interner > ( generic_arg : & GenericArg < I > , interner : & I ) -> TypeFlags {
357+ match generic_arg. data ( & interner) {
358+ GenericArgData :: Ty ( ty) => ty. data ( interner) . flags ,
359+ GenericArgData :: Lifetime ( lifetime) => compute_lifetime_flags ( lifetime, interner) ,
360+ GenericArgData :: Const ( constant) => {
361+ let data = constant. data ( & interner) ;
362+ let flags = data. ty . data ( interner) . flags ;
363+ match data. value {
364+ ConstValue :: BoundVar ( _) => flags,
365+ ConstValue :: InferenceVar ( _) => flags | TypeFlags :: HAS_CT_INFER | TypeFlags :: STILL_FURTHER_SPECIALIZABLE ,
366+ ConstValue :: Placeholder ( _) => flags | TypeFlags :: HAS_CT_PLACEHOLDER | TypeFlags :: STILL_FURTHER_SPECIALIZABLE ,
367+ ConstValue :: Concrete ( _) => flags,
368+ }
369+ }
370+ }
371+ }
372+
373+ /// Compute type flags for aliases
374+ fn compute_alias_flags < I : Interner > ( alias_ty : & AliasTy < I > , interner : & I ) -> TypeFlags {
375+ match alias_ty {
376+ AliasTy :: Projection ( projection_ty) => TypeFlags :: HAS_TY_PROJECTION | compute_substitution_flags ( & ( projection_ty. substitution ) , interner) ,
377+ AliasTy :: Opaque ( opaque_ty) => TypeFlags :: HAS_TY_OPAQUE | compute_substitution_flags ( & ( opaque_ty. substitution ) , interner)
378+ }
379+ }
380+
381+ /// Compute type flags for a TyKind
382+ fn compute_flags < I : Interner > ( kind : & TyKind < I > , interner : & I ) -> TypeFlags {
383+ match kind {
384+ TyKind :: Adt ( _, substitution)
385+ | TyKind :: AssociatedType ( _, substitution)
386+ | TyKind :: Tuple ( _, substitution)
387+ | TyKind :: Closure ( _, substitution)
388+ | TyKind :: Generator ( _, substitution)
389+ | TyKind :: GeneratorWitness ( _, substitution)
390+ | TyKind :: FnDef ( _, substitution) => compute_substitution_flags ( substitution, interner) ,
391+ TyKind :: Scalar ( _)
392+ | TyKind :: Str
393+ | TyKind :: Never
394+ | TyKind :: Foreign ( _) => TypeFlags :: empty ( ) ,
395+ TyKind :: OpaqueType ( _, substitution) => TypeFlags :: HAS_TY_OPAQUE | compute_substitution_flags ( substitution, interner) ,
396+ TyKind :: Error => TypeFlags :: HAS_ERROR ,
397+ TyKind :: Slice ( ty)
398+ | TyKind :: Raw ( _, ty) => ty. data ( interner) . flags ,
399+ TyKind :: Ref ( _, lifetime, ty) => compute_lifetime_flags ( lifetime, interner) | ty. data ( interner) . flags ,
400+ TyKind :: Array ( ty, const_ty) => {
401+ let flags = ty. data ( interner) . flags ;
402+ let const_data = const_ty. data ( interner) ;
403+ flags | const_data. ty . data ( interner) . flags | match const_data. value {
404+ ConstValue :: BoundVar ( _)
405+ | ConstValue :: Concrete ( _) => TypeFlags :: empty ( ) ,
406+ ConstValue :: InferenceVar ( _) => TypeFlags :: HAS_CT_INFER | TypeFlags :: STILL_FURTHER_SPECIALIZABLE ,
407+ ConstValue :: Placeholder ( _) => TypeFlags :: HAS_CT_PLACEHOLDER | TypeFlags :: STILL_FURTHER_SPECIALIZABLE
408+ }
409+ } ,
410+ TyKind :: Placeholder ( _) => TypeFlags :: HAS_TY_PLACEHOLDER ,
411+ TyKind :: Dyn ( dyn_ty) => {
412+ let lifetime_flags = compute_lifetime_flags ( & ( dyn_ty. lifetime ) , & interner) ;
413+ let mut dyn_flags = TypeFlags :: empty ( ) ;
414+ for var_kind in dyn_ty. bounds . value . iter ( & interner) {
415+ match & ( var_kind. value ) {
416+ WhereClause :: Implemented ( trait_ref) => dyn_flags |= compute_substitution_flags ( & ( trait_ref. substitution ) , interner) ,
417+ WhereClause :: AliasEq ( alias_eq) => {
418+ dyn_flags |= compute_alias_flags ( & ( alias_eq. alias ) , & interner) ;
419+ dyn_flags |= alias_eq. ty . data ( & interner) . flags ;
420+ } ,
421+ WhereClause :: LifetimeOutlives ( lifetime_outlives) => {
422+ dyn_flags |= compute_lifetime_flags ( & ( lifetime_outlives. a ) , & interner) | compute_lifetime_flags ( & ( lifetime_outlives. b ) , & interner) ;
423+ } ,
424+ WhereClause :: TypeOutlives ( type_outlives) => {
425+ dyn_flags |= type_outlives. ty . data ( & interner) . flags ;
426+ dyn_flags |= compute_lifetime_flags ( & ( type_outlives. lifetime ) , & interner) ;
427+ }
428+ }
429+ } ;
430+ lifetime_flags | dyn_flags
431+ } ,
432+ TyKind :: Alias ( alias_ty) => compute_alias_flags ( & alias_ty, & interner) ,
433+ TyKind :: BoundVar ( _) => TypeFlags :: empty ( ) ,
434+ TyKind :: InferenceVar ( _, _) => TypeFlags :: HAS_TY_INFER ,
435+ TyKind :: Function ( fn_pointer) => compute_substitution_flags ( & ( fn_pointer. substitution ) , interner)
436+ }
437+ }
438+
330439impl < I : Interner > Ty < I > {
331440 /// Creates a type from `TyKind`.
332441 pub fn new ( interner : & I , data : impl CastTo < TyKind < I > > ) -> Self {
442+ let ty_kind = data. cast ( & interner) ;
333443 let data = TyData {
334- kind : data. cast ( interner) ,
444+ flags : compute_flags ( & ty_kind, & interner) ,
445+ kind : ty_kind,
335446 } ;
336447 Ty {
337448 interned : I :: intern_ty ( interner, data) ,
@@ -446,8 +557,57 @@ impl<I: Interner> Ty<I> {
446557pub struct TyData < I : Interner > {
447558 /// The kind
448559 pub kind : TyKind < I > ,
560+ /// Type flags
561+ pub flags : TypeFlags ,
562+ }
563+
564+ bitflags ! {
565+ /// Contains flags indicating various properties of a Ty
566+ pub struct TypeFlags : u16 {
567+ /// Does the type contain an InferenceVar
568+ const HAS_TY_INFER = 1 ;
569+ /// Does the type contain a lifetime with an InferenceVar
570+ const HAS_RE_INFER = 1 << 1 ;
571+ /// Does the type contain a ConstValue with an InferenceVar
572+ const HAS_CT_INFER = 1 << 2 ;
573+ /// Does the type contain a Placeholder TyKind
574+ const HAS_TY_PLACEHOLDER = 1 << 3 ;
575+ /// Does the type contain a lifetime with a Placeholder
576+ const HAS_RE_PLACEHOLDER = 1 << 4 ;
577+ /// Does the type contain a ConstValue Placeholder
578+ const HAS_CT_PLACEHOLDER = 1 << 5 ;
579+ /// True when the type has free lifetimes related to a local context
580+ const HAS_FREE_LOCAL_REGIONS = 1 << 6 ;
581+ /// Does the type contain a projection of an associated type
582+ const HAS_TY_PROJECTION = 1 << 7 ;
583+ /// Does the type contain an opaque type
584+ const HAS_TY_OPAQUE = 1 << 8 ;
585+ /// Does the type contain an unevaluated const projection
586+ const HAS_CT_PROJECTION = 1 << 9 ;
587+ /// Does the type contain an error
588+ const HAS_ERROR = 1 << 10 ;
589+ /// Does the type contain any free lifetimes
590+ const HAS_FREE_REGIONS = 1 << 11 ;
591+ /// True when the type contains lifetimes that will be substituted when function is called
592+ const HAS_RE_LATE_BOUND = 1 << 12 ;
593+ /// True when the type contains an erased lifetime
594+ const HAS_RE_ERASED = 1 << 13 ;
595+ /// Does the type contain placeholders or inference variables that could be replaced later
596+ const STILL_FURTHER_SPECIALIZABLE = 1 << 14 ;
597+
598+ /// True when the type contains free names local to a particular context
599+ const HAS_FREE_LOCAL_NAMES = TypeFlags :: HAS_TY_INFER . bits
600+ | TypeFlags :: HAS_CT_INFER . bits
601+ | TypeFlags :: HAS_TY_PLACEHOLDER . bits
602+ | TypeFlags :: HAS_CT_PLACEHOLDER . bits
603+ | TypeFlags :: HAS_FREE_LOCAL_REGIONS . bits;
604+
605+ /// Does the type contain any form of projection
606+ const HAS_PROJECTION = TypeFlags :: HAS_TY_PROJECTION . bits
607+ | TypeFlags :: HAS_TY_OPAQUE . bits
608+ | TypeFlags :: HAS_CT_PROJECTION . bits;
609+ }
449610}
450-
451611/// Type data, which holds the actual type information.
452612#[ derive( Clone , PartialEq , Eq , Hash , HasInterner ) ]
453613pub enum TyKind < I : Interner > {
0 commit comments