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

@@ -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