introduce macros for type-foldable, convert stuff to use them

This commit is contained in:
Niko Matsakis 2017-11-11 13:04:36 -05:00
parent 247d98ec37
commit 27d5872025

View File

@ -8,6 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module contains implements of the `Lift` and `TypeFoldable`
//! traits for various types in the Rust compiler. Most are written by
//! hand, though we've recently added some macros (e.g.,
//! `BraceStructLiftImpl!`) to help with the tedium.
use infer::type_variable;
use middle::const_val::{self, ConstVal, ConstAggregate, ConstEvalErr};
use ty::{self, Lift, Ty, TyCtxt};
@ -16,9 +21,158 @@
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use std::rc::Rc;
use syntax::abi;
use hir;
///////////////////////////////////////////////////////////////////////////
// Atomic structs
//
// For things that don't carry any arena-allocated data (and are
// copy...), just add them to this list.
macro_rules! CopyImpls {
($($ty:ty,)+) => {
$(
impl<'tcx> Lift<'tcx> for $ty {
type Lifted = Self;
fn lift_to_tcx<'a, 'gcx>(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self> {
Some(*self)
}
}
impl<'tcx> TypeFoldable<'tcx> for $ty {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> $ty {
*self
}
fn super_visit_with<F: TypeVisitor<'tcx>>(&self, _: &mut F) -> bool {
false
}
}
)+
}
}
CopyImpls! {
(),
::hir::Unsafety,
::syntax::abi::Abi,
::hir::def_id::DefId,
::mir::Local,
::traits::Reveal,
::syntax_pos::Span,
}
///////////////////////////////////////////////////////////////////////////
// Macros
//
// When possible, use one of these (relatively) convenient macros to write
// the impls for you.
#[macro_export]
macro_rules! BraceStructLiftImpl {
(impl<$($p:tt),*> Lift<$tcx:tt> for $s:path {
type Lifted = $lifted:ty;
$($field:ident),* $(,)*
} $(where $($wc:tt)*)*) => {
impl<$($p),*> $crate::ty::Lift<$tcx> for $s
$(where $($wc)*)*
{
type Lifted = $lifted;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> {
$(let $field = tcx.lift(&self.$field)?;)*
Some(Self::Lifted { $($field),* })
}
}
};
}
#[macro_export]
macro_rules! EnumLiftImpl {
(impl<$($p:tt),*> Lift<$tcx:tt> for $s:path {
type Lifted = $lifted:ty;
$(
($variant:path) ( $( $variant_arg:ident),* )
),*
$(,)*
} $(where $($wc:tt)*)*) => {
impl<$($p),*> $crate::ty::Lift<$tcx> for $s
$(where $($wc)*)*
{
type Lifted = $lifted;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> {
match self {
$($variant ( $($variant_arg),* ) => {
Some($variant ( $(tcx.lift($variant_arg)?),* ))
})*
}
}
}
};
}
#[macro_export]
macro_rules! BraceStructTypeFoldableImpl {
(impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
$($field:ident),* $(,)*
} $(where $($wc:tt)*)*) => {
impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
$(where $($wc)*)*
{
fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
&self,
folder: &mut V,
) -> Self {
let $s { $($field,)* } = self;
$s { $($field: $field.fold_with(folder),)* }
}
fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
&self,
visitor: &mut V,
) -> bool {
let $s { $($field,)* } = self;
false $(|| $field.visit_with(visitor))*
}
}
};
}
#[macro_export]
macro_rules! EnumTypeFoldableImpl {
(impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
$(
($variant:path) ( $( $variant_arg:ident),* )
),*
$(,)*
} $(where $($wc:tt)*)*) => {
impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
$(where $($wc)*)*
{
fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>(
&self,
folder: &mut V,
) -> Self {
match self {
$($variant ( $($variant_arg),* ) => {
$variant ( $($variant_arg.fold_with(folder)),* )
})*
}
}
fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
&self,
visitor: &mut V,
) -> bool {
match self {
$($variant ( $($variant_arg),* ) => {
false $(|| $variant_arg.visit_with(visitor))*
})*
}
}
}
};
}
///////////////////////////////////////////////////////////////////////////
// Lift implementations
@ -90,6 +244,15 @@ fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lif
}
}
impl<'tcx, I: Idx, T: Lift<'tcx>> Lift<'tcx> for IndexVec<I, T> {
type Lifted = IndexVec<I, T::Lifted>;
fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
self.iter()
.map(|e| tcx.lift(e))
.collect()
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> {
type Lifted = ty::TraitRef<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@ -384,16 +547,10 @@ fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lif
}
}
impl<'a, 'tcx> Lift<'tcx> for type_variable::Default<'a> {
type Lifted = type_variable::Default<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
tcx.lift(&self.ty).map(|ty| {
type_variable::Default {
ty,
origin_span: self.origin_span,
def_id: self.def_id
}
})
BraceStructLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for type_variable::Default<'a> {
type Lifted = type_variable::Default<'tcx>;
ty, origin_span, def_id
}
}
@ -506,31 +663,6 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
// can easily refactor the folding into the TypeFolder trait as
// needed.
macro_rules! CopyImpls {
($($ty:ty),+) => {
$(
impl<'tcx> Lift<'tcx> for $ty {
type Lifted = Self;
fn lift_to_tcx<'a, 'gcx>(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self> {
Some(*self)
}
}
impl<'tcx> TypeFoldable<'tcx> for $ty {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> $ty {
*self
}
fn super_visit_with<F: TypeVisitor<'tcx>>(&self, _: &mut F) -> bool {
false
}
}
)+
}
}
CopyImpls! { (), hir::Unsafety, abi::Abi, hir::def_id::DefId, ::mir::Local }
impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) {
(self.0.fold_with(folder), self.1.fold_with(folder))
@ -600,18 +732,8 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ParamEnv {
reveal: self.reveal,
caller_bounds: self.caller_bounds.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
let &ty::ParamEnv { reveal: _, ref caller_bounds } = self;
caller_bounds.super_visit_with(visitor)
}
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> { reveal, caller_bounds }
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
@ -733,17 +855,9 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::GenSig<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::GenSig {
yield_ty: self.yield_ty.fold_with(folder),
return_ty: self.return_ty.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.yield_ty.visit_with(visitor) ||
self.return_ty.visit_with(visitor)
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::GenSig<'tcx> {
yield_ty, return_ty
}
}
@ -764,46 +878,20 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TraitRef {
def_id: self.def_id,
substs: self.substs.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.substs.visit_with(visitor)
}
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> { def_id, substs }
}
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ExistentialTraitRef {
def_id: self.def_id,
substs: self.substs.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.substs.visit_with(visitor)
}
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> { def_id, substs }
}
impl<'tcx> TypeFoldable<'tcx> for ty::ImplHeader<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ImplHeader {
impl_def_id: self.impl_def_id,
self_ty: self.self_ty.fold_with(folder),
trait_ref: self.trait_ref.map(|t| t.fold_with(folder)),
predicates: self.predicates.iter().map(|p| p.fold_with(folder)).collect(),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.self_ty.visit_with(visitor) ||
self.trait_ref.map(|r| r.visit_with(visitor)).unwrap_or(false) ||
self.predicates.iter().any(|p| p.visit_with(visitor))
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::ImplHeader<'tcx> {
impl_def_id,
self_ty,
trait_ref,
predicates,
}
}
@ -847,17 +935,10 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjustment<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::adjustment::Adjustment {
kind: self.kind.fold_with(folder),
target: self.target.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.kind.visit_with(visitor) ||
self.target.visit_with(visitor)
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjustment<'tcx> {
kind,
target,
}
}
@ -928,16 +1009,10 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::GenericPredicates {
parent: self.parent,
predicates: self.predicates.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.predicates.visit_with(visitor)
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
parent, predicates
}
}
@ -995,55 +1070,27 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ProjectionPredicate {
projection_ty: self.projection_ty.fold_with(folder),
ty: self.ty.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.projection_ty.visit_with(visitor) || self.ty.visit_with(visitor)
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
projection_ty, ty
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ExistentialProjection {
ty: self.ty.fold_with(folder),
substs: self.substs.fold_with(folder),
item_def_id: self.item_def_id,
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.substs.visit_with(visitor) || self.ty.visit_with(visitor)
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> {
ty, substs, item_def_id
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ProjectionTy {
substs: self.substs.fold_with(folder),
item_def_id: self.item_def_id,
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.substs.visit_with(visitor)
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
substs, item_def_id
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::InstantiatedPredicates {
predicates: self.predicates.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.predicates.visit_with(visitor)
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
predicates
}
}