Skip to content

Commit 31aaa6a

Browse files
chfontjackh726
authored andcommitted
Add TypeFlags for TyKind in chalk-ir
1 parent 40c4789 commit 31aaa6a

File tree

6 files changed

+355
-3
lines changed

6 files changed

+355
-3
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chalk-integration/src/test_macros.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,13 @@ macro_rules! lifetime {
119119
lifetime!($($b)*)
120120
};
121121
}
122+
123+
#[macro_export]
124+
macro_rules! empty_substitution {
125+
() => {
126+
chalk_ir::Substitution::from_iter(
127+
&chalk_integration::interner::ChalkIr,
128+
Vec::<chalk_ir::GenericArg<chalk_integration::interner::ChalkIr>>::new(),
129+
);
130+
};
131+
}

chalk-ir/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ edition = "2018"
1111

1212
[dependencies]
1313
lazy_static = "1.4.0"
14+
bitflags = "1.2.1"
1415
chalk-derive = { version = "0.44.0-dev.0", path = "../chalk-derive" }

chalk-ir/src/lib.rs

Lines changed: 190 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use chalk_derive::{Fold, HasInterner, SuperVisit, Visit, Zip};
1414
use std::marker::PhantomData;
1515

1616
pub 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)]
2021
pub 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+
414550
impl<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> {
530668
pub 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)]
537724
pub enum TyKind<I: Interner> {

tests/test/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ mod slices;
348348
mod string;
349349
mod subtype;
350350
mod tuples;
351+
mod type_flags;
351352
mod unify;
352353
mod unpin;
353354
mod unsize;

0 commit comments

Comments
 (0)