Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create rustc_type_ir #79169

Merged
merged 1 commit into from
Dec 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3918,6 +3918,7 @@ dependencies = [
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_type_ir",
"smallvec 1.4.2",
"tracing",
]
Expand Down Expand Up @@ -4251,6 +4252,16 @@ dependencies = [
"tracing",
]

[[package]]
name = "rustc_type_ir"
version = "0.0.0"
dependencies = [
"bitflags",
"rustc_data_structures",
"rustc_index",
"rustc_serialize",
]

[[package]]
name = "rustc_typeck"
version = "0.0.0"
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ chalk-ir = "0.36.0"
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
measureme = "9.0.0"
rustc_session = { path = "../rustc_session" }
rustc_type_ir = { path = "../rustc_type_ir" }
88 changes: 2 additions & 86 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub use self::sty::InferTy::*;
pub use self::sty::RegionKind;
pub use self::sty::RegionKind::*;
pub use self::sty::TyKind::*;
pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNERMOST};
pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar};
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::{CanonicalPolyFnSig, FnSig, GenSig, PolyFnSig, PolyGenSig};
pub use self::sty::{ClosureSubsts, GeneratorSubsts, TypeAndMut, UpvarSubsts};
Expand All @@ -67,6 +67,7 @@ pub use self::sty::{ExistentialProjection, PolyExistentialProjection};
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
pub use self::sty::{PolyTraitRef, TraitRef, TyKind};
pub use crate::ty::diagnostics::*;
pub use rustc_type_ir::{DebruijnIndex, TypeFlags, INNERMOST};

pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;
Expand Down Expand Up @@ -497,91 +498,6 @@ pub struct CReaderCacheKey {
pub pos: usize,
}

bitflags! {
/// Flags that we track on types. These flags are propagated upwards
/// through the type during type construction, so that we can quickly check
/// whether the type has various kinds of types in it without recursing
/// over the type itself.
pub struct TypeFlags: u32 {
// Does this have parameters? Used to determine whether substitution is
// required.
/// Does this have [Param]?
const HAS_TY_PARAM = 1 << 0;
/// Does this have [ReEarlyBound]?
const HAS_RE_PARAM = 1 << 1;
/// Does this have [ConstKind::Param]?
const HAS_CT_PARAM = 1 << 2;

const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits
| TypeFlags::HAS_RE_PARAM.bits
| TypeFlags::HAS_CT_PARAM.bits;

/// Does this have [Infer]?
const HAS_TY_INFER = 1 << 3;
/// Does this have [ReVar]?
const HAS_RE_INFER = 1 << 4;
/// Does this have [ConstKind::Infer]?
const HAS_CT_INFER = 1 << 5;

/// Does this have inference variables? Used to determine whether
/// inference is required.
const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits
| TypeFlags::HAS_RE_INFER.bits
| TypeFlags::HAS_CT_INFER.bits;

/// Does this have [Placeholder]?
const HAS_TY_PLACEHOLDER = 1 << 6;
/// Does this have [RePlaceholder]?
const HAS_RE_PLACEHOLDER = 1 << 7;
/// Does this have [ConstKind::Placeholder]?
const HAS_CT_PLACEHOLDER = 1 << 8;

/// `true` if there are "names" of regions and so forth
/// that are local to a particular fn/inferctxt
const HAS_FREE_LOCAL_REGIONS = 1 << 9;

/// `true` if there are "names" of types and regions and so forth
/// that are local to a particular fn
const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits
| TypeFlags::HAS_CT_PARAM.bits
| TypeFlags::HAS_TY_INFER.bits
| TypeFlags::HAS_CT_INFER.bits
| TypeFlags::HAS_TY_PLACEHOLDER.bits
| TypeFlags::HAS_CT_PLACEHOLDER.bits
| TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;

/// Does this have [Projection]?
const HAS_TY_PROJECTION = 1 << 10;
/// Does this have [Opaque]?
const HAS_TY_OPAQUE = 1 << 11;
/// Does this have [ConstKind::Unevaluated]?
const HAS_CT_PROJECTION = 1 << 12;

/// Could this type be normalized further?
const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits
| TypeFlags::HAS_TY_OPAQUE.bits
| TypeFlags::HAS_CT_PROJECTION.bits;

/// Is an error type/const reachable?
const HAS_ERROR = 1 << 13;

/// Does this have any region that "appears free" in the type?
/// Basically anything but [ReLateBound] and [ReErased].
const HAS_FREE_REGIONS = 1 << 14;

/// Does this have any [ReLateBound] regions? Used to check
/// if a global bound is safe to evaluate.
const HAS_RE_LATE_BOUND = 1 << 15;

/// Does this have any [ReErased] regions?
const HAS_RE_ERASED = 1 << 16;

/// Does this value have parameters/placeholders/inference variables which could be
/// replaced later, in a way that would change the results of `impl` specialization?
const STILL_FURTHER_SPECIALIZABLE = 1 << 17;
}
}

#[allow(rustc::usage_of_ty_tykind)]
pub struct TyS<'tcx> {
/// This field shouldn't be used directly and may be removed in the future.
Expand Down
110 changes: 2 additions & 108 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,53 +1289,6 @@ impl<'tcx> ParamConst {
}
}

rustc_index::newtype_index! {
/// A [De Bruijn index][dbi] is a standard means of representing
/// regions (and perhaps later types) in a higher-ranked setting. In
/// particular, imagine a type like this:
///
/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
/// ^ ^ | | |
/// | | | | |
/// | +------------+ 0 | |
/// | | |
/// +----------------------------------+ 1 |
/// | |
/// +----------------------------------------------+ 0
///
/// In this type, there are two binders (the outer fn and the inner
/// fn). We need to be able to determine, for any given region, which
/// fn type it is bound by, the inner or the outer one. There are
/// various ways you can do this, but a De Bruijn index is one of the
/// more convenient and has some nice properties. The basic idea is to
/// count the number of binders, inside out. Some examples should help
/// clarify what I mean.
///
/// Let's start with the reference type `&'b isize` that is the first
/// argument to the inner function. This region `'b` is assigned a De
/// Bruijn index of 0, meaning "the innermost binder" (in this case, a
/// fn). The region `'a` that appears in the second argument type (`&'a
/// isize`) would then be assigned a De Bruijn index of 1, meaning "the
/// second-innermost binder". (These indices are written on the arrays
LeSeulArtichaut marked this conversation as resolved.
Show resolved Hide resolved
/// in the diagram).
///
/// What is interesting is that De Bruijn index attached to a particular
/// variable will vary depending on where it appears. For example,
/// the final type `&'a char` also refers to the region `'a` declared on
/// the outermost fn. But this time, this reference is not nested within
/// any other binders (i.e., it is not an argument to the inner fn, but
/// rather the outer one). Therefore, in this case, it is assigned a
/// De Bruijn index of 0, because the innermost binder in that location
/// is the outer fn.
///
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
#[derive(HashStable)]
pub struct DebruijnIndex {
DEBUG_FORMAT = "DebruijnIndex({})",
const INNERMOST = 0,
}
}

pub type Region<'tcx> = &'tcx RegionKind;

/// Representation of regions. Note that the NLL checker uses a distinct
Expand Down Expand Up @@ -1450,7 +1403,7 @@ pub enum RegionKind {

/// Region bound in a function scope, which will be substituted when the
/// function is called.
ReLateBound(DebruijnIndex, BoundRegion),
ReLateBound(ty::DebruijnIndex, BoundRegion),

/// When checking a function body, the types of all arguments and so forth
/// that refer to bound region parameters are modified to refer to free
Expand Down Expand Up @@ -1614,65 +1567,6 @@ impl<'tcx> PolyExistentialProjection<'tcx> {
}
}

impl DebruijnIndex {
/// Returns the resulting index when this value is moved into
/// `amount` number of new binders. So, e.g., if you had
///
/// for<'a> fn(&'a x)
///
/// and you wanted to change it to
///
/// for<'a> fn(for<'b> fn(&'a x))
///
/// you would need to shift the index for `'a` into a new binder.
#[must_use]
pub fn shifted_in(self, amount: u32) -> DebruijnIndex {
DebruijnIndex::from_u32(self.as_u32() + amount)
}

/// Update this index in place by shifting it "in" through
/// `amount` number of binders.
pub fn shift_in(&mut self, amount: u32) {
*self = self.shifted_in(amount);
}

/// Returns the resulting index when this value is moved out from
/// `amount` number of new binders.
#[must_use]
pub fn shifted_out(self, amount: u32) -> DebruijnIndex {
DebruijnIndex::from_u32(self.as_u32() - amount)
}

/// Update in place by shifting out from `amount` binders.
pub fn shift_out(&mut self, amount: u32) {
*self = self.shifted_out(amount);
}

/// Adjusts any De Bruijn indices so as to make `to_binder` the
/// innermost binder. That is, if we have something bound at `to_binder`,
/// it will now be bound at INNERMOST. This is an appropriate thing to do
/// when moving a region out from inside binders:
///
/// ```
/// for<'a> fn(for<'b> for<'c> fn(&'a u32), _)
/// // Binder: D3 D2 D1 ^^
/// ```
///
/// Here, the region `'a` would have the De Bruijn index D3,
/// because it is the bound 3 binders out. However, if we wanted
/// to refer to that region `'a` in the second argument (the `_`),
/// those two binders would not be in scope. In that case, we
/// might invoke `shift_out_to_binder(D3)`. This would adjust the
/// De Bruijn index of `'a` to D1 (the innermost binder).
///
/// If we invoke `shift_out_to_binder` and the region is in fact
/// bound by one of the binders we are shifting out of, that is an
/// error (and should fail an assertion failure).
pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self {
self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32())
}
}

/// Region utilities
impl RegionKind {
/// Is this region named by the user?
Expand Down Expand Up @@ -1703,7 +1597,7 @@ impl RegionKind {
}
}

pub fn bound_at_or_above_binder(&self, index: DebruijnIndex) -> bool {
pub fn bound_at_or_above_binder(&self, index: ty::DebruijnIndex) -> bool {
match *self {
ty::ReLateBound(debruijn, _) => debruijn >= index,
_ => false,
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_type_ir/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "rustc_type_ir"
version = "0.0.0"
authors = ["The Rust Project Developers"]
edition = "2018"

[lib]
doctest = false

[dependencies]
bitflags = "1.2.1"
rustc_index = { path = "../rustc_index" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_data_structures = { path = "../rustc_data_structures" }
Loading