1
Fork 0

Overhaul TyS and Ty.

Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
  means we can move a lot of methods away from `TyS`, leaving `TyS` as a
  barely-used type, which is appropriate given that it's not meant to
  be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
  E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
  than via `TyS`, which wasn't obvious at all.

Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs

Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
  `Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
  which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
  of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
  (pointer-based, for the `Equal` case) and partly on `TyS`
  (contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
  or `&`. They seem to be unavoidable.
This commit is contained in:
Nicholas Nethercote 2022-01-25 14:13:38 +11:00
parent 0c2ebbd412
commit e9a0c429c5
145 changed files with 519 additions and 531 deletions

View file

@ -2558,7 +2558,7 @@ impl<'tcx> ConstantKind<'tcx> {
pub fn ty(&self) -> Ty<'tcx> {
match self {
ConstantKind::Ty(c) => c.ty,
ConstantKind::Val(_, ty) => ty,
ConstantKind::Val(_, ty) => *ty,
}
}

View file

@ -17,7 +17,7 @@ use rustc_middle::mir::interpret::{
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::MirSource;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt, TyS, TypeFoldable, TypeVisitor};
use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitor};
use rustc_target::abi::Size;
use std::ops::ControlFlow;
@ -427,12 +427,12 @@ impl<'tcx> ExtraComments<'tcx> {
}
}
fn use_verbose<'tcx>(ty: &&TyS<'tcx>, fn_def: bool) -> bool {
match ty.kind() {
fn use_verbose<'tcx>(ty: Ty<'tcx>, fn_def: bool) -> bool {
match *ty.kind() {
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false,
// Unit type
ty::Tuple(g_args) if g_args.is_empty() => false,
ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty(), fn_def)),
ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(g_arg.expect_ty(), fn_def)),
ty::Array(ty, _) => use_verbose(ty, fn_def),
ty::FnDef(..) => fn_def,
_ => true,
@ -443,7 +443,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
self.super_constant(constant, location);
let Constant { span, user_ty, literal } = constant;
if use_verbose(&literal.ty(), true) {
if use_verbose(literal.ty(), true) {
self.push("mir::Constant");
self.push(&format!(
"+ span: {}",
@ -465,7 +465,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
self.super_const(constant);
let ty::Const { ty, val, .. } = constant;
if use_verbose(ty, false) {
if use_verbose(*ty, false) {
self.push("ty::Const");
self.push(&format!("+ ty: {:?}", ty));
let val = match val {

View file

@ -57,7 +57,7 @@ impl<'tcx> PlaceTy<'tcx> {
/// `PlaceElem`, where we can just use the `Ty` that is already
/// stored inline on field projection elems.
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty)
self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, &ty| ty)
}
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@ -93,11 +93,11 @@ impl<'tcx> PlaceTy<'tcx> {
ProjectionElem::Subslice { from, to, from_end } => {
PlaceTy::from_ty(match self.ty.kind() {
ty::Slice(..) => self.ty,
ty::Array(inner, _) if !from_end => tcx.mk_array(inner, (to - from) as u64),
ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64),
ty::Array(inner, size) if from_end => {
let size = size.eval_usize(tcx, param_env);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(inner, len)
tcx.mk_array(*inner, len)
}
_ => bug!("cannot subslice non-array type: `{:?}`", self),
})

View file

@ -430,7 +430,7 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn as_switch(&self) -> Option<(&Operand<'tcx>, Ty<'tcx>, &SwitchTargets)> {
match self {
TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
Some((discr, switch_ty, targets))
Some((discr, *switch_ty, targets))
}
_ => None,
}

View file

@ -242,7 +242,7 @@ macro_rules! make_mir_visitor {
) {
let span = body.span;
if let Some(gen) = &$($mutability)? body.generator {
if let Some(yield_ty) = &$($mutability)? gen.yield_ty {
if let Some(yield_ty) = $(& $mutability)? gen.yield_ty {
self.visit_ty(
yield_ty,
TyContext::YieldTy(SourceInfo::outermost(span))
@ -266,7 +266,7 @@ macro_rules! make_mir_visitor {
}
self.visit_ty(
&$($mutability)? body.return_ty(),
$(& $mutability)? body.return_ty(),
TyContext::ReturnTy(SourceInfo::outermost(body.span))
);
@ -355,7 +355,7 @@ macro_rules! make_mir_visitor {
ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
ty::InstanceDef::CloneShim(_def_id, ty) => {
// FIXME(eddyb) use a better `TyContext` here.
self.visit_ty(ty, TyContext::Location(location));
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
}
self.visit_substs(callee_substs, location);
@ -487,7 +487,7 @@ macro_rules! make_mir_visitor {
targets: _
} => {
self.visit_operand(discr, location);
self.visit_ty(switch_ty, TyContext::Location(location));
self.visit_ty($(& $mutability)? *switch_ty, TyContext::Location(location));
}
TerminatorKind::Drop {
@ -680,7 +680,7 @@ macro_rules! make_mir_visitor {
Rvalue::Cast(_cast_kind, operand, ty) => {
self.visit_operand(operand, location);
self.visit_ty(ty, TyContext::Location(location));
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
Rvalue::BinaryOp(_bin_op, box(lhs, rhs))
@ -702,14 +702,14 @@ macro_rules! make_mir_visitor {
}
Rvalue::NullaryOp(_op, ty) => {
self.visit_ty(ty, TyContext::Location(location));
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
Rvalue::Aggregate(kind, operands) => {
let kind = &$($mutability)? **kind;
match kind {
AggregateKind::Array(ty) => {
self.visit_ty(ty, TyContext::Location(location));
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
AggregateKind::Tuple => {
}
@ -744,7 +744,7 @@ macro_rules! make_mir_visitor {
Rvalue::ShallowInitBox(operand, ty) => {
self.visit_operand(operand, location);
self.visit_ty(ty, TyContext::Location(location));
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
}
}
@ -815,7 +815,7 @@ macro_rules! make_mir_visitor {
is_block_tail: _,
} = local_decl;
self.visit_ty(ty, TyContext::LocalDecl {
self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
local,
source_info: *source_info,
});
@ -865,7 +865,7 @@ macro_rules! make_mir_visitor {
drop(user_ty); // no visit method for this
match literal {
ConstantKind::Ty(ct) => self.visit_const(ct, location),
ConstantKind::Val(_, t) => self.visit_ty(t, TyContext::Location(location)),
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
}
}
@ -894,7 +894,7 @@ macro_rules! make_mir_visitor {
ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
) {
self.visit_span(& $($mutability)? ty.span);
self.visit_ty(& $($mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
}
fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {

View file

@ -1146,33 +1146,33 @@ rustc_queries! {
desc { "computing whether `{}` is `Copy`", env.value }
remap_env_constness
}
/// Query backing `TyS::is_sized`.
/// Query backing `Ty::is_sized`.
query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Sized`", env.value }
remap_env_constness
}
/// Query backing `TyS::is_freeze`.
/// Query backing `Ty::is_freeze`.
query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is freeze", env.value }
remap_env_constness
}
/// Query backing `TyS::is_unpin`.
/// Query backing `Ty::is_unpin`.
query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Unpin`", env.value }
remap_env_constness
}
/// Query backing `TyS::needs_drop`.
/// Query backing `Ty::needs_drop`.
query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` needs drop", env.value }
remap_env_constness
}
/// Query backing `TyS::has_significant_drop_raw`.
/// Query backing `Ty::has_significant_drop_raw`.
query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` has a significant drop", env.value }
remap_env_constness
}
/// Query backing `TyS::is_structural_eq_shallow`.
/// Query backing `Ty::is_structural_eq_shallow`.
///
/// This is only correct for ADTs. Call `is_structural_eq_shallow` to handle all types
/// correctly.

View file

@ -77,7 +77,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
) => Ok(a),
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
Err(TypeError::Sorts(relate::expected_found(self, &a, &b)))
Err(TypeError::Sorts(relate::expected_found(self, a, b)))
}
(&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(self.tcx().ty_error()),

View file

@ -116,7 +116,7 @@ impl<'tcx> ClosureKind {
}
/// Returns the representative scalar type for this closure kind.
/// See `TyS::to_opt_closure_kind` for more details.
/// See `Ty::to_opt_closure_kind` for more details.
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self {
ty::ClosureKind::Fn => tcx.types.i8,

View file

@ -26,6 +26,7 @@ use crate::ty::{
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
@ -151,19 +152,21 @@ impl<'tcx> CtxtInterners<'tcx> {
#[allow(rustc::usage_of_ty_tykind)]
#[inline(never)]
fn intern_ty(&self, kind: TyKind<'tcx>) -> Ty<'tcx> {
self.type_
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_kind(&kind);
Ty(Interned::new_unchecked(
self.type_
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_kind(&kind);
let ty_struct = TyS {
kind,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
};
let ty_struct = TyS {
kind,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
};
InternedInSet(self.arena.alloc(ty_struct))
})
.0
InternedInSet(self.arena.alloc(ty_struct))
})
.0,
))
}
#[inline(never)]
@ -1628,7 +1631,8 @@ pub trait Lift<'tcx>: fmt::Debug {
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>;
}
macro_rules! nop_lift {
// Deprecated: we are in the process of converting all uses to `nop_lift`.
macro_rules! nop_lift_old {
($set:ident; $ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for $ty {
type Lifted = $lifted;
@ -1643,6 +1647,21 @@ macro_rules! nop_lift {
};
}
macro_rules! nop_lift {
($set:ident; $ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for $ty {
type Lifted = $lifted;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if tcx.interners.$set.contains_pointer_to(&InternedInSet(self.0.0)) {
Some(unsafe { mem::transmute(self) })
} else {
None
}
}
}
};
}
macro_rules! nop_list_lift {
($set:ident; $ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
@ -1662,10 +1681,10 @@ macro_rules! nop_list_lift {
}
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
nop_lift! {region; Region<'a> => Region<'tcx>}
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
nop_lift! {const_allocation; &'a Allocation => &'tcx Allocation}
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
nop_lift_old! {region; Region<'a> => Region<'tcx>}
nop_lift_old! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
nop_lift_old! {const_allocation; &'a Allocation => &'tcx Allocation}
nop_lift_old! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>}
@ -1882,15 +1901,15 @@ macro_rules! sty_debug_print {
let shards = tcx.interners.type_.lock_shards();
let types = shards.iter().flat_map(|shard| shard.keys());
for &InternedInSet(t) in types {
let variant = match t.kind() {
let variant = match t.kind {
ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
ty::Float(..) | ty::Str | ty::Never => continue,
ty::Error(_) => /* unimportant */ continue,
$(ty::$variant(..) => &mut $variant,)*
};
let lt = t.flags().intersects(ty::TypeFlags::HAS_RE_INFER);
let ty = t.flags().intersects(ty::TypeFlags::HAS_TY_INFER);
let ct = t.flags().intersects(ty::TypeFlags::HAS_CT_INFER);
let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
variant.total += 1;
total.total += 1;
@ -2000,7 +2019,7 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, TyS<'tcx>> {
fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> {
&self.0.kind()
&self.0.kind
}
}
@ -2008,7 +2027,7 @@ impl<'tcx> PartialEq for InternedInSet<'tcx, TyS<'tcx>> {
fn eq(&self, other: &InternedInSet<'tcx, TyS<'tcx>>) -> bool {
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
// `x == y`.
self.0.kind() == other.0.kind()
self.0.kind == other.0.kind
}
}
@ -2017,7 +2036,7 @@ impl<'tcx> Eq for InternedInSet<'tcx, TyS<'tcx>> {}
impl<'tcx> Hash for InternedInSet<'tcx, TyS<'tcx>> {
fn hash<H: Hasher>(&self, s: &mut H) {
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
self.0.kind().hash(s)
self.0.kind.hash(s)
}
}

View file

@ -1,10 +1,10 @@
//! Diagnostics related methods for `TyS`.
//! Diagnostics related methods for `Ty`.
use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::TyKind::*;
use crate::ty::{
ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy,
ProjectionTy, Term, TyCtxt, TyS, TypeAndMut,
ProjectionTy, Term, Ty, TyCtxt, TypeAndMut,
};
use rustc_errors::{Applicability, DiagnosticBuilder};
@ -13,9 +13,9 @@ use rustc_hir::def_id::DefId;
use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
use rustc_span::Span;
impl<'tcx> TyS<'tcx> {
/// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive.
pub fn is_primitive_ty(&self) -> bool {
impl<'tcx> Ty<'tcx> {
/// Similar to `Ty::is_primitive`, but also considers inferred numeric values to be primitive.
pub fn is_primitive_ty(self) -> bool {
matches!(
self.kind(),
Bool | Char
@ -34,7 +34,7 @@ impl<'tcx> TyS<'tcx> {
/// Whether the type is succinctly representable as a type instead of just referred to with a
/// description in error messages. This is used in the main error message.
pub fn is_simple_ty(&self) -> bool {
pub fn is_simple_ty(self) -> bool {
match self.kind() {
Bool
| Char
@ -58,7 +58,7 @@ impl<'tcx> TyS<'tcx> {
/// description in error messages. This is used in the primary span label. Beyond what
/// `is_simple_ty` includes, it also accepts ADTs with no type arguments and references to
/// ADTs with no type arguments.
pub fn is_simple_text(&self) -> bool {
pub fn is_simple_text(self) -> bool {
match self.kind() {
Adt(_, substs) => substs.non_erasable_generics().next().is_none(),
Ref(_, ty, _) => ty.is_simple_text(),
@ -67,7 +67,7 @@ impl<'tcx> TyS<'tcx> {
}
/// Whether the type can be safely suggested during error recovery.
pub fn is_suggestable(&self) -> bool {
pub fn is_suggestable(self) -> bool {
fn generic_arg_is_suggestible(arg: GenericArg<'_>) -> bool {
match arg.unpack() {
GenericArgKind::Type(ty) => ty.is_suggestable(),

View file

@ -239,8 +239,8 @@ impl<'tcx> TypeError<'tcx> {
}
}
impl<'tcx> ty::TyS<'tcx> {
pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
impl<'tcx> Ty<'tcx> {
pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
match *self.kind() {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
format!("`{}`", self).into()
@ -306,7 +306,7 @@ impl<'tcx> ty::TyS<'tcx> {
}
}
pub fn prefix_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
pub fn prefix_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
match *self.kind() {
ty::Infer(_)
| ty::Error(_)

View file

@ -6,7 +6,7 @@ use std::slice;
pub struct FlagComputation {
pub flags: TypeFlags,
// see `TyS::outer_exclusive_binder` for details
// see `Ty::outer_exclusive_binder` for details
pub outer_exclusive_binder: ty::DebruijnIndex,
}
@ -270,7 +270,7 @@ impl FlagComputation {
fn add_ty(&mut self, ty: Ty<'_>) {
self.add_flags(ty.flags());
self.add_exclusive_binder(ty.outer_exclusive_binder);
self.add_exclusive_binder(ty.outer_exclusive_binder());
}
fn add_tys(&mut self, tys: &[Ty<'_>]) {

View file

@ -627,7 +627,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
if let Some(fld_t) = self.fld_t.as_mut() {
let ty = fld_t(bound_ty);
return ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32());
return ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32());
}
}
_ if t.has_vars_bound_at_or_above(self.current_index) => {
@ -926,7 +926,7 @@ impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if t.outer_exclusive_binder < self.binder_index
if t.outer_exclusive_binder() < self.binder_index
|| !self.visited.insert((self.binder_index, t))
{
return ControlFlow::BREAK;
@ -1146,7 +1146,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
// bound at `outer_index` or above (because
// `outer_exclusive_binder` is always 1 higher than the
// content in `t`). Therefore, `t` has some escaping vars.
if t.outer_exclusive_binder > self.outer_index {
if t.outer_exclusive_binder() > self.outer_index {
ControlFlow::Break(FoundEscapingVars)
} else {
ControlFlow::CONTINUE

View file

@ -3,7 +3,7 @@ pub use self::def_id_forest::DefIdForest;
use crate::ty;
use crate::ty::context::TyCtxt;
use crate::ty::TyKind::*;
use crate::ty::{AdtDef, FieldDef, Ty, TyS, VariantDef};
use crate::ty::{AdtDef, FieldDef, Ty, VariantDef};
use crate::ty::{AdtKind, Visibility};
use crate::ty::{DefId, SubstsRef};
@ -184,10 +184,10 @@ impl<'tcx> FieldDef {
}
}
impl<'tcx> TyS<'tcx> {
impl<'tcx> Ty<'tcx> {
/// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
fn uninhabited_from(
&'tcx self,
self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> DefIdForest<'tcx> {

View file

@ -101,7 +101,7 @@ impl<'tcx> Instance<'tcx> {
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id());
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty)
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty)
}
/// Finds a crate that contains a monomorphization of this instance that
@ -642,7 +642,7 @@ fn polymorphize<'tcx>(
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
debug!("fold_ty: ty={:?}", ty);
match ty.kind {
match *ty.kind() {
ty::Closure(def_id, substs) => {
let polymorphized_substs = polymorphize(
self.tcx,

View file

@ -29,6 +29,7 @@ use crate::ty::util::Discr;
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_hir as hir;
@ -42,7 +43,6 @@ use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{sym, Span};
use rustc_target::abi::Align;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::ops::ControlFlow;
use std::{fmt, ptr, str};
@ -380,21 +380,25 @@ pub struct CReaderCacheKey {
/// Represents a type.
///
/// IMPORTANT: Every `TyS` is *required* to have unique contents. The type's
/// correctness relies on this, *but it does not enforce it*. Therefore, any
/// code that creates a `TyS` must ensure uniqueness itself. In practice this
/// is achieved by interning.
/// IMPORTANT:
/// - This is a very "dumb" struct (with no derives and no `impls`).
/// - Values of this type are always interned and thus unique, and are stored
/// as an `Interned<TyS>`.
/// - `Ty` (which contains a reference to a `Interned<TyS>`) or `Interned<TyS>`
/// should be used everywhere instead of `TyS`. In particular, `Ty` has most
/// of the relevant methods.
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[allow(rustc::usage_of_ty_tykind)]
pub struct TyS<'tcx> {
crate struct TyS<'tcx> {
/// This field shouldn't be used directly and may be removed in the future.
/// Use `TyS::kind()` instead.
/// Use `Ty::kind()` instead.
kind: TyKind<'tcx>,
/// This field provides fast access to information that is also contained
/// in `kind`.
///
/// This field shouldn't be used directly and may be removed in the future.
/// Use `TyS::flags()` instead.
/// Use `Ty::flags()` instead.
flags: TypeFlags,
/// This field provides fast access to information that is also contained
@ -420,55 +424,27 @@ pub struct TyS<'tcx> {
outer_exclusive_binder: ty::DebruijnIndex,
}
impl<'tcx> TyS<'tcx> {
/// A constructor used only for internal testing.
#[allow(rustc::usage_of_ty_tykind)]
pub fn make_for_test(
kind: TyKind<'tcx>,
flags: TypeFlags,
outer_exclusive_binder: ty::DebruijnIndex,
) -> TyS<'tcx> {
TyS { kind, flags, outer_exclusive_binder }
}
}
// `TyS` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(TyS<'_>, 40);
impl<'tcx> Ord for TyS<'tcx> {
fn cmp(&self, other: &TyS<'tcx>) -> Ordering {
self.kind().cmp(other.kind())
}
}
/// Use this rather than `TyS`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[rustc_diagnostic_item = "Ty"]
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
impl<'tcx> PartialOrd for TyS<'tcx> {
fn partial_cmp(&self, other: &TyS<'tcx>) -> Option<Ordering> {
Some(self.kind().cmp(other.kind()))
}
}
// Statics only used for internal testing.
pub static BOOL_TY: Ty<'static> = Ty(Interned::new_unchecked(&BOOL_TYS));
static BOOL_TYS: TyS<'static> = TyS {
kind: ty::Bool,
flags: TypeFlags::empty(),
outer_exclusive_binder: DebruijnIndex::from_usize(0),
};
impl<'tcx> PartialEq for TyS<'tcx> {
#[inline]
fn eq(&self, other: &TyS<'tcx>) -> bool {
// Pointer equality implies equality (due to the unique contents
// assumption).
ptr::eq(self, other)
}
}
impl<'tcx> Eq for TyS<'tcx> {}
impl<'tcx> Hash for TyS<'tcx> {
fn hash<H: Hasher>(&self, s: &mut H) {
// Pointer hashing is sufficient (due to the unique contents
// assumption).
(self as *const TyS<'_>).hash(s)
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Ty<'tcx> {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let ty::TyS {
let TyS {
ref kind,
// The other fields just provide fast access to information that is
@ -476,16 +452,12 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
flags: _,
outer_exclusive_binder: _,
} = *self;
} = self.0.0;
kind.hash_stable(hcx, hasher);
}
}
#[rustc_diagnostic_item = "Ty"]
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
impl ty::EarlyBoundRegion {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
@ -864,7 +836,7 @@ impl<'tcx> From<&'tcx Const<'tcx>> for Term<'tcx> {
impl<'tcx> Term<'tcx> {
pub fn ty(&self) -> Option<Ty<'tcx>> {
if let Term::Ty(ty) = self { Some(ty) } else { None }
if let Term::Ty(ty) = self { Some(*ty) } else { None }
}
pub fn ct(&self) -> Option<&'tcx Const<'tcx>> {
if let Term::Const(c) = self { Some(c) } else { None }

View file

@ -346,7 +346,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
type Output = P::Type;
type Error = P::Error;
fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
cx.print_type(self)
cx.print_type(*self)
}
}

View file

@ -3,6 +3,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable};
use rustc_apfloat::ieee::{Double, Single};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::Interned;
use rustc_data_structures::sso::SsoHashSet;
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
@ -1232,16 +1233,20 @@ pub trait PrettyPrinter<'tcx>:
// Byte strings (&[u8; N])
ty::Ref(
_,
ty::TyS {
kind:
ty::Array(
ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. },
ty::Const {
val: ty::ConstKind::Value(ConstValue::Scalar(int)), ..
},
),
..
},
Ty(Interned(
ty::TyS {
kind:
ty::Array(
Ty(Interned(ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, _)),
ty::Const {
val: ty::ConstKind::Value(ConstValue::Scalar(int)),
..
},
),
..
},
_,
)),
_,
) => match self.tcx().get_global_alloc(alloc_id) {
Some(GlobalAlloc::Memory(alloc)) => {
@ -1399,7 +1404,7 @@ pub trait PrettyPrinter<'tcx>:
// Byte/string slices, printed as (byte) string literals.
(
ConstValue::Slice { data, start, end },
ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _),
ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Slice(t), .. }, _)), _),
) if *t == u8_type => {
// The `inspect` here is okay since we checked the bounds, and there are
// no relocations (we have an active slice reference here). We don't use
@ -1409,7 +1414,7 @@ pub trait PrettyPrinter<'tcx>:
}
(
ConstValue::Slice { data, start, end },
ty::Ref(_, ty::TyS { kind: ty::Str, .. }, _),
ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Str, .. }, _)), _),
) => {
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active `str` reference here). We don't use this

View file

@ -149,8 +149,8 @@ pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>(
Some((ty_def_id, variances)) => {
let variance = variances[i];
let variance_info = if variance == ty::Invariant {
let ty =
cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
let ty = *cached_ty
.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
} else {
ty::VarianceDiagInfo::default()

View file

@ -1078,7 +1078,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_ty(self)
visitor.visit_ty(*self)
}
}

View file

@ -9,7 +9,7 @@ use crate::ty::fold::ValidateBoundVars;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::InferTy::{self, *};
use crate::ty::{self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeFoldable};
use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
use crate::ty::{DelaySpanBugEmitted, List, ParamEnv};
use polonius_engine::Atom;
use rustc_data_structures::captures::Captures;
use rustc_hir as hir;
@ -196,7 +196,7 @@ pub enum TyKind<'tcx> {
Never,
/// A tuple type. For example, `(i32, bool)`.
/// Use `TyS::tuple_fields` to iterate over the field types.
/// Use `Ty::tuple_fields` to iterate over the field types.
Tuple(SubstsRef<'tcx>),
/// The projection of an associated type. For example,
@ -282,7 +282,7 @@ static_assert_size!(TyKind<'_>, 32);
/// in scope on the function that defined the closure,
/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This
/// is rather hackily encoded via a scalar type. See
/// `TyS::to_opt_closure_kind` for details.
/// `Ty::to_opt_closure_kind` for details.
/// - CS represents the *closure signature*, representing as a `fn()`
/// type. For example, `fn(u32, u32) -> u32` would mean that the closure
/// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait
@ -1756,19 +1756,19 @@ impl RegionKind {
}
/// Type utilities
impl<'tcx> TyS<'tcx> {
impl<'tcx> Ty<'tcx> {
#[inline(always)]
pub fn kind(&self) -> &TyKind<'tcx> {
&self.kind
pub fn kind(self) -> &'tcx TyKind<'tcx> {
&self.0.0.kind
}
#[inline(always)]
pub fn flags(&self) -> TypeFlags {
self.flags
pub fn flags(self) -> TypeFlags {
self.0.0.flags
}
#[inline]
pub fn is_unit(&self) -> bool {
pub fn is_unit(self) -> bool {
match self.kind() {
Tuple(ref tys) => tys.is_empty(),
_ => false,
@ -1776,32 +1776,32 @@ impl<'tcx> TyS<'tcx> {
}
#[inline]
pub fn is_never(&self) -> bool {
pub fn is_never(self) -> bool {
matches!(self.kind(), Never)
}
#[inline]
pub fn is_primitive(&self) -> bool {
pub fn is_primitive(self) -> bool {
self.kind().is_primitive()
}
#[inline]
pub fn is_adt(&self) -> bool {
pub fn is_adt(self) -> bool {
matches!(self.kind(), Adt(..))
}
#[inline]
pub fn is_ref(&self) -> bool {
pub fn is_ref(self) -> bool {
matches!(self.kind(), Ref(..))
}
#[inline]
pub fn is_ty_var(&self) -> bool {
pub fn is_ty_var(self) -> bool {
matches!(self.kind(), Infer(TyVar(_)))
}
#[inline]
pub fn ty_vid(&self) -> Option<ty::TyVid> {
pub fn ty_vid(self) -> Option<ty::TyVid> {
match self.kind() {
&Infer(TyVar(vid)) => Some(vid),
_ => None,
@ -1809,28 +1809,28 @@ impl<'tcx> TyS<'tcx> {
}
#[inline]
pub fn is_ty_infer(&self) -> bool {
pub fn is_ty_infer(self) -> bool {
matches!(self.kind(), Infer(_))
}
#[inline]
pub fn is_phantom_data(&self) -> bool {
pub fn is_phantom_data(self) -> bool {
if let Adt(def, _) = self.kind() { def.is_phantom_data() } else { false }
}
#[inline]
pub fn is_bool(&self) -> bool {
pub fn is_bool(self) -> bool {
*self.kind() == Bool
}
/// Returns `true` if this type is a `str`.
#[inline]
pub fn is_str(&self) -> bool {
pub fn is_str(self) -> bool {
*self.kind() == Str
}
#[inline]
pub fn is_param(&self, index: u32) -> bool {
pub fn is_param(self, index: u32) -> bool {
match self.kind() {
ty::Param(ref data) => data.index == index,
_ => false,
@ -1838,7 +1838,7 @@ impl<'tcx> TyS<'tcx> {
}
#[inline]
pub fn is_slice(&self) -> bool {
pub fn is_slice(self) -> bool {
match self.kind() {
RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_) | Str),
_ => false,
@ -1846,27 +1846,27 @@ impl<'tcx> TyS<'tcx> {
}
#[inline]
pub fn is_array(&self) -> bool {
pub fn is_array(self) -> bool {
matches!(self.kind(), Array(..))
}
#[inline]
pub fn is_simd(&self) -> bool {
pub fn is_simd(self) -> bool {
match self.kind() {
Adt(def, _) => def.repr.simd(),
_ => false,
}
}
pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self.kind() {
Array(ty, _) | Slice(ty) => ty,
Array(ty, _) | Slice(ty) => *ty,
Str => tcx.types.u8,
_ => bug!("`sequence_element_type` called on non-sequence value: {}", self),
}
}
pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
match self.kind() {
Adt(def, substs) => {
assert!(def.repr.simd(), "`simd_size_and_type` called on non-SIMD type");
@ -1881,7 +1881,7 @@ impl<'tcx> TyS<'tcx> {
// The way we evaluate the `N` in `[T; N]` here only works since we use
// `simd_size_and_type` post-monomorphization. It will probably start to ICE
// if we use it in generic code. See the `simd-array-trait` ui test.
(f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, f0_elem_ty)
(f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty)
}
// Otherwise, the fields of this Adt are the SIMD components (and we assume they
// all have the same type).
@ -1893,12 +1893,12 @@ impl<'tcx> TyS<'tcx> {
}
#[inline]
pub fn is_region_ptr(&self) -> bool {
pub fn is_region_ptr(self) -> bool {
matches!(self.kind(), Ref(..))
}
#[inline]
pub fn is_mutable_ptr(&self) -> bool {
pub fn is_mutable_ptr(self) -> bool {
matches!(
self.kind(),
RawPtr(TypeAndMut { mutbl: hir::Mutability::Mut, .. })
@ -1908,7 +1908,7 @@ impl<'tcx> TyS<'tcx> {
/// Get the mutability of the reference or `None` when not a reference
#[inline]
pub fn ref_mutability(&self) -> Option<hir::Mutability> {
pub fn ref_mutability(self) -> Option<hir::Mutability> {
match self.kind() {
Ref(_, _, mutability) => Some(*mutability),
_ => None,
@ -1916,18 +1916,18 @@ impl<'tcx> TyS<'tcx> {
}
#[inline]
pub fn is_unsafe_ptr(&self) -> bool {
pub fn is_unsafe_ptr(self) -> bool {
matches!(self.kind(), RawPtr(_))
}
/// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
#[inline]
pub fn is_any_ptr(&self) -> bool {
pub fn is_any_ptr(self) -> bool {
self.is_region_ptr() || self.is_unsafe_ptr() || self.is_fn_ptr()
}
#[inline]
pub fn is_box(&self) -> bool {
pub fn is_box(self) -> bool {
match self.kind() {
Adt(def, _) => def.is_box(),
_ => false,
@ -1935,7 +1935,7 @@ impl<'tcx> TyS<'tcx> {
}
/// Panics if called on any type other than `Box<T>`.
pub fn boxed_ty(&self) -> Ty<'tcx> {
pub fn boxed_ty(self) -> Ty<'tcx> {
match self.kind() {
Adt(def, substs) if def.is_box() => substs.type_at(0),
_ => bug!("`boxed_ty` is called on non-box type {:?}", self),
@ -1946,7 +1946,7 @@ impl<'tcx> TyS<'tcx> {
/// (A RawPtr is scalar because it represents a non-managed pointer, so its
/// contents are abstract to rustc.)
#[inline]
pub fn is_scalar(&self) -> bool {
pub fn is_scalar(self) -> bool {
matches!(
self.kind(),
Bool | Char
@ -1962,72 +1962,72 @@ impl<'tcx> TyS<'tcx> {
/// Returns `true` if this type is a floating point type.
#[inline]
pub fn is_floating_point(&self) -> bool {
pub fn is_floating_point(self) -> bool {
matches!(self.kind(), Float(_) | Infer(FloatVar(_)))
}
#[inline]
pub fn is_trait(&self) -> bool {
pub fn is_trait(self) -> bool {
matches!(self.kind(), Dynamic(..))
}
#[inline]
pub fn is_enum(&self) -> bool {
pub fn is_enum(self) -> bool {
matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum())
}
#[inline]
pub fn is_union(&self) -> bool {
pub fn is_union(self) -> bool {
matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union())
}
#[inline]
pub fn is_closure(&self) -> bool {
pub fn is_closure(self) -> bool {
matches!(self.kind(), Closure(..))
}
#[inline]
pub fn is_generator(&self) -> bool {
pub fn is_generator(self) -> bool {
matches!(self.kind(), Generator(..))
}
#[inline]
pub fn is_integral(&self) -> bool {
pub fn is_integral(self) -> bool {
matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_))
}
#[inline]
pub fn is_fresh_ty(&self) -> bool {
pub fn is_fresh_ty(self) -> bool {
matches!(self.kind(), Infer(FreshTy(_)))
}
#[inline]
pub fn is_fresh(&self) -> bool {
pub fn is_fresh(self) -> bool {
matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_)))
}
#[inline]
pub fn is_char(&self) -> bool {
pub fn is_char(self) -> bool {
matches!(self.kind(), Char)
}
#[inline]
pub fn is_numeric(&self) -> bool {
pub fn is_numeric(self) -> bool {
self.is_integral() || self.is_floating_point()
}
#[inline]
pub fn is_signed(&self) -> bool {
pub fn is_signed(self) -> bool {
matches!(self.kind(), Int(_))
}
#[inline]
pub fn is_ptr_sized_integral(&self) -> bool {
pub fn is_ptr_sized_integral(self) -> bool {
matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize))
}
#[inline]
pub fn has_concrete_skeleton(&self) -> bool {
pub fn has_concrete_skeleton(self) -> bool {
!matches!(self.kind(), Param(_) | Infer(_) | Error(_))
}
@ -2035,26 +2035,26 @@ impl<'tcx> TyS<'tcx> {
///
/// The parameter `explicit` indicates if this is an *explicit* dereference.
/// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
pub fn builtin_deref(self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
match self.kind() {
Adt(def, _) if def.is_box() => {
Some(TypeAndMut { ty: self.boxed_ty(), mutbl: hir::Mutability::Not })
}
Ref(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl: *mutbl }),
Ref(_, ty, mutbl) => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
RawPtr(mt) if explicit => Some(*mt),
_ => None,
}
}
/// Returns the type of `ty[i]`.
pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
pub fn builtin_index(self) -> Option<Ty<'tcx>> {
match self.kind() {
Array(ty, _) | Slice(ty) => Some(ty),
Array(ty, _) | Slice(ty) => Some(*ty),
_ => None,
}
}
pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
match self.kind() {
FnDef(def_id, substs) => tcx.fn_sig(*def_id).subst(tcx, substs),
FnPtr(f) => *f,
@ -2070,22 +2070,22 @@ impl<'tcx> TyS<'tcx> {
}
#[inline]
pub fn is_fn(&self) -> bool {
pub fn is_fn(self) -> bool {
matches!(self.kind(), FnDef(..) | FnPtr(_))
}
#[inline]
pub fn is_fn_ptr(&self) -> bool {
pub fn is_fn_ptr(self) -> bool {
matches!(self.kind(), FnPtr(_))
}
#[inline]
pub fn is_impl_trait(&self) -> bool {
pub fn is_impl_trait(self) -> bool {
matches!(self.kind(), Opaque(..))
}
#[inline]
pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
pub fn ty_adt_def(self) -> Option<&'tcx AdtDef> {
match self.kind() {
Adt(adt, _) => Some(adt),
_ => None,
@ -2094,7 +2094,7 @@ impl<'tcx> TyS<'tcx> {
/// Iterates over tuple fields.
/// Panics when called on anything but a tuple.
pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> {
pub fn tuple_fields(self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> {
match self.kind() {
Tuple(substs) => substs.iter().map(|field| field.expect_ty()),
_ => bug!("tuple_fields called on non-tuple"),
@ -2103,7 +2103,7 @@ impl<'tcx> TyS<'tcx> {
/// Get the `i`-th element of a tuple.
/// Panics when called on anything but a tuple.
pub fn tuple_element_ty(&self, i: usize) -> Option<Ty<'tcx>> {
pub fn tuple_element_ty(self, i: usize) -> Option<Ty<'tcx>> {
match self.kind() {
Tuple(substs) => substs.iter().nth(i).map(|field| field.expect_ty()),
_ => bug!("tuple_fields called on non-tuple"),
@ -2114,7 +2114,7 @@ impl<'tcx> TyS<'tcx> {
//
// FIXME: This requires the optimized MIR in the case of generators.
#[inline]
pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
match self.kind() {
TyKind::Adt(adt, _) => Some(adt.variant_range()),
TyKind::Generator(def_id, substs, _) => {
@ -2130,7 +2130,7 @@ impl<'tcx> TyS<'tcx> {
// FIXME: This requires the optimized MIR in the case of generators.
#[inline]
pub fn discriminant_for_variant(
&self,
self,
tcx: TyCtxt<'tcx>,
variant_index: VariantIdx,
) -> Option<Discr<'tcx>> {
@ -2151,7 +2151,7 @@ impl<'tcx> TyS<'tcx> {
}
/// Returns the type of the discriminant of this type.
pub fn discriminant_ty(&'tcx self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self.kind() {
ty::Adt(adt, _) if adt.is_enum() => adt.repr.discr_type().to_ty(tcx),
ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
@ -2195,7 +2195,7 @@ impl<'tcx> TyS<'tcx> {
/// Returns the type of metadata for (potentially fat) pointers to this type.
pub fn ptr_metadata_ty(
&'tcx self,
self,
tcx: TyCtxt<'tcx>,
normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
) -> Ty<'tcx> {
@ -2256,7 +2256,7 @@ impl<'tcx> TyS<'tcx> {
/// to represent the closure kind, because it has not yet been
/// inferred. Once upvar inference (in `rustc_typeck/src/check/upvar.rs`)
/// is complete, that type variable will be unified.
pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
pub fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
match self.kind() {
Int(int_ty) => match int_ty {
ty::IntTy::I8 => Some(ty::ClosureKind::Fn),
@ -2285,7 +2285,7 @@ impl<'tcx> TyS<'tcx> {
/// bound such as `[_]: Copy`. A function with such a bound obviously never
/// can be called, but that doesn't mean it shouldn't typecheck. This is why
/// this method doesn't return `Option<bool>`.
pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind() {
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Uint(_)

View file

@ -6,6 +6,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor}
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_serialize::{self, Decodable, Encodable};
@ -49,17 +50,17 @@ impl<'tcx> GenericArgKind<'tcx> {
GenericArgKind::Lifetime(lt) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(lt) & TAG_MASK, 0);
(REGION_TAG, lt as *const _ as usize)
(REGION_TAG, lt as *const ty::RegionKind as usize)
}
GenericArgKind::Type(ty) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0);
(TYPE_TAG, ty as *const _ as usize)
assert_eq!(mem::align_of_val(ty.0.0) & TAG_MASK, 0);
(TYPE_TAG, ty.0.0 as *const ty::TyS<'tcx> as usize)
}
GenericArgKind::Const(ct) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(ct) & TAG_MASK, 0);
(CONST_TAG, ct as *const _ as usize)
(CONST_TAG, ct as *const ty::Const<'tcx> as usize)
}
};
@ -111,11 +112,18 @@ impl<'tcx> GenericArg<'tcx> {
#[inline]
pub fn unpack(self) -> GenericArgKind<'tcx> {
let ptr = self.ptr.get();
// SAFETY: use of `Interned::new_unchecked` here is ok because these
// pointers were originally created from `Interned` types in `pack()`,
// and this is just going in the other direction.
unsafe {
match ptr & TAG_MASK {
REGION_TAG => GenericArgKind::Lifetime(&*((ptr & !TAG_MASK) as *const _)),
TYPE_TAG => GenericArgKind::Type(&*((ptr & !TAG_MASK) as *const _)),
CONST_TAG => GenericArgKind::Const(&*((ptr & !TAG_MASK) as *const _)),
REGION_TAG => {
GenericArgKind::Lifetime(&*((ptr & !TAG_MASK) as *const ty::RegionKind))
}
TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const ty::TyS<'tcx>),
))),
CONST_TAG => GenericArgKind::Const(&*((ptr & !TAG_MASK) as *const ty::Const<'tcx>)),
_ => intrinsics::unreachable(),
}
}

View file

@ -11,6 +11,7 @@ use rustc_apfloat::Float as _;
use rustc_ast as ast;
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorReported;
use rustc_hir as hir;
@ -392,9 +393,10 @@ impl<'tcx> TyCtxt<'tcx> {
GenericArgKind::Lifetime(&ty::RegionKind::ReEarlyBound(ref ebr)) => {
!impl_generics.region_param(ebr, self).pure_wrt_drop
}
GenericArgKind::Type(&ty::TyS { kind: ty::Param(ref pt), .. }) => {
!impl_generics.type_param(pt, self).pure_wrt_drop
}
GenericArgKind::Type(Ty(Interned(
ty::TyS { kind: ty::Param(ref pt), .. },
_,
))) => !impl_generics.type_param(pt, self).pure_wrt_drop,
GenericArgKind::Const(&ty::Const {
val: ty::ConstKind::Param(ref pc), ..
}) => !impl_generics.const_param(pc, self).pure_wrt_drop,
@ -577,7 +579,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
let substs = substs.fold_with(self);
if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
Some(expanded_ty) => expanded_ty,
Some(expanded_ty) => *expanded_ty,
None => {
let generic_ty = self.tcx.type_of(def_id);
let concrete_ty = generic_ty.subst(self.tcx, substs);
@ -606,7 +608,7 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Opaque(def_id, substs) = t.kind {
if let ty::Opaque(def_id, substs) = *t.kind() {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
} else if t.has_opaque_types() {
t.super_fold_with(self)
@ -616,10 +618,10 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
}
}
impl<'tcx> ty::TyS<'tcx> {
impl<'tcx> Ty<'tcx> {
/// Returns the maximum value for the given numeric type (including `char`s)
/// or returns `None` if the type is not numeric.
pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
let val = match self.kind() {
ty::Int(_) | ty::Uint(_) => {
let (size, signed) = int_size_and_signed(tcx, self);
@ -639,7 +641,7 @@ impl<'tcx> ty::TyS<'tcx> {
/// Returns the minimum value for the given numeric type (including `char`s)
/// or returns `None` if the type is not numeric.
pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> {
let val = match self.kind() {
ty::Int(_) | ty::Uint(_) => {
let (size, signed) = int_size_and_signed(tcx, self);
@ -664,7 +666,7 @@ impl<'tcx> ty::TyS<'tcx> {
/// full requirements for the `Copy` trait (cc #29149) -- this
/// winds up being reported as an error during NLL borrow check.
pub fn is_copy_modulo_regions(
&'tcx self,
self,
tcx_at: TyCtxtAt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
@ -677,7 +679,7 @@ impl<'tcx> ty::TyS<'tcx> {
/// over-approximation in generic contexts, where one can have
/// strange rules like `<T as Foo<'static>>::Bar: Sized` that
/// actually carry lifetime requirements.
pub fn is_sized(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
pub fn is_sized(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
self.is_trivially_sized(tcx_at.tcx) || tcx_at.is_sized_raw(param_env.and(self))
}
@ -688,7 +690,7 @@ impl<'tcx> ty::TyS<'tcx> {
/// optimization as well as the rules around static values. Note
/// that the `Freeze` trait is not exposed to end users and is
/// effectively an implementation detail.
pub fn is_freeze(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
pub fn is_freeze(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self))
}
@ -696,7 +698,7 @@ impl<'tcx> ty::TyS<'tcx> {
///
/// Returning true means the type is known to be `Freeze`. Returning
/// `false` means nothing -- could be `Freeze`, might not be.
fn is_trivially_freeze(&self) -> bool {
fn is_trivially_freeze(self) -> bool {
match self.kind() {
ty::Int(_)
| ty::Uint(_)
@ -710,7 +712,7 @@ impl<'tcx> ty::TyS<'tcx> {
| ty::FnDef(..)
| ty::Error(_)
| ty::FnPtr(_) => true,
ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_freeze),
ty::Tuple(_) => self.tuple_fields().all(|f| Self::is_trivially_freeze(f)),
ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(),
ty::Adt(..)
| ty::Bound(..)
@ -728,7 +730,7 @@ impl<'tcx> ty::TyS<'tcx> {
}
/// Checks whether values of this type `T` implement the `Unpin` trait.
pub fn is_unpin(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
pub fn is_unpin(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self))
}
@ -736,7 +738,7 @@ impl<'tcx> ty::TyS<'tcx> {
///
/// Returning true means the type is known to be `Unpin`. Returning
/// `false` means nothing -- could be `Unpin`, might not be.
fn is_trivially_unpin(&self) -> bool {
fn is_trivially_unpin(self) -> bool {
match self.kind() {
ty::Int(_)
| ty::Uint(_)
@ -750,7 +752,7 @@ impl<'tcx> ty::TyS<'tcx> {
| ty::FnDef(..)
| ty::Error(_)
| ty::FnPtr(_) => true,
ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_unpin),
ty::Tuple(_) => self.tuple_fields().all(|f| Self::is_trivially_unpin(f)),
ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(),
ty::Adt(..)
| ty::Bound(..)
@ -776,7 +778,7 @@ impl<'tcx> ty::TyS<'tcx> {
///
/// Note that this method is used to check eligible types in unions.
#[inline]
pub fn needs_drop(&'tcx self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
// Avoid querying in simple cases.
match needs_drop_components(self, &tcx.data_layout) {
Err(AlwaysRequiresDrop) => true,
@ -809,11 +811,7 @@ impl<'tcx> ty::TyS<'tcx> {
/// Note that this method is used to check for change in drop order for
/// 2229 drop reorder migration analysis.
#[inline]
pub fn has_significant_drop(
&'tcx self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
// Avoid querying in simple cases.
match needs_drop_components(self, &tcx.data_layout) {
Err(AlwaysRequiresDrop) => true,
@ -858,7 +856,7 @@ impl<'tcx> ty::TyS<'tcx> {
/// want to know whether a given call to `PartialEq::eq` will proceed structurally all the way
/// down, you will need to use a type visitor.
#[inline]
pub fn is_structural_eq_shallow(&'tcx self, tcx: TyCtxt<'tcx>) -> bool {
pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind() {
// Look for an impl of both `PartialStructuralEq` and `StructuralEq`.
Adt(..) => tcx.has_structural_eq_impls(self),
@ -903,16 +901,16 @@ impl<'tcx> ty::TyS<'tcx> {
/// - `&'a mut u8` -> `u8`
/// - `&'a &'b u8` -> `u8`
/// - `&'a *const &'b u8 -> *const &'b u8`
pub fn peel_refs(&'tcx self) -> Ty<'tcx> {
pub fn peel_refs(self) -> Ty<'tcx> {
let mut ty = self;
while let Ref(_, inner_ty, _) = ty.kind() {
ty = inner_ty;
ty = *inner_ty;
}
ty
}
pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex {
self.outer_exclusive_binder
pub fn outer_exclusive_binder(self) -> DebruijnIndex {
self.0.outer_exclusive_binder
}
}
@ -993,9 +991,9 @@ pub fn needs_drop_components<'tcx>(
ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop),
ty::Slice(ty) => needs_drop_components(ty, target_layout),
ty::Slice(ty) => needs_drop_components(*ty, target_layout),
ty::Array(elem_ty, size) => {
match needs_drop_components(elem_ty, target_layout) {
match needs_drop_components(*elem_ty, target_layout) {
Ok(v) if v.is_empty() => Ok(v),
res => match size.val.try_to_bits(target_layout.pointer_size) {
// Arrays of size zero don't need drop, even if their element

View file

@ -1,8 +1,8 @@
//! An iterator over the type substructure.
//! WARNING: this does not keep track of the region depth.
use crate::ty;
use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::{self, Ty};
use rustc_data_structures::sso::SsoHashSet;
use smallvec::{self, SmallVec};
@ -96,7 +96,7 @@ impl<'tcx> GenericArg<'tcx> {
}
}
impl<'tcx> super::TyS<'tcx> {
impl<'tcx> Ty<'tcx> {
/// Iterator that walks `self` and any types reachable from
/// `self`, in depth-first order. Note that just walks the types
/// that appear in `self`, it does not descend into the fields of
@ -107,7 +107,7 @@ impl<'tcx> super::TyS<'tcx> {
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
/// [isize] => { [isize], isize }
/// ```
pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
pub fn walk(self) -> TypeWalker<'tcx> {
TypeWalker::new(self.into())
}
}