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

do not implement Relate for "boring" types #132044

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 0 additions & 3 deletions compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ impl<'tcx> TypeError<'tcx> {
TypeError::CyclicTy(_) => "cyclic type of infinite size".into(),
TypeError::CyclicConst(_) => "encountered a self-referencing constant".into(),
TypeError::Mismatch => "types differ".into(),
TypeError::ConstnessMismatch(values) => {
format!("expected {} bound, found {} bound", values.expected, values.found).into()
}
TypeError::PolarityMismatch(values) => {
format!("expected {} polarity, found {} polarity", values.expected, values.found)
.into()
Expand Down
22 changes: 0 additions & 22 deletions compiler/rustc_middle/src/ty/relate.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::iter;

use rustc_hir as hir;
use rustc_target::spec::abi;
pub use rustc_type_ir::relate::*;

use crate::ty::error::{ExpectedFound, TypeError};
Expand Down Expand Up @@ -121,26 +119,6 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
}
}

impl<'tcx> Relate<TyCtxt<'tcx>> for hir::Safety {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
_relation: &mut R,
a: hir::Safety,
b: hir::Safety,
) -> RelateResult<'tcx, hir::Safety> {
if a != b { Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a, b))) } else { Ok(a) }
}
}

impl<'tcx> Relate<TyCtxt<'tcx>> for abi::Abi {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
_relation: &mut R,
a: abi::Abi,
b: abi::Abi,
) -> RelateResult<'tcx, abi::Abi> {
if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(ExpectedFound::new(true, a, b))) }
}
}

impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
relation: &mut R,
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,6 @@ TrivialTypeTraversalImpls! {
// interners).
TrivialTypeTraversalAndLiftImpls! {
::rustc_hir::def_id::DefId,
::rustc_hir::Safety,
::rustc_target::spec::abi::Abi,
crate::ty::ClosureKind,
crate::ty::ParamConst,
crate::ty::ParamTy,
Expand All @@ -276,6 +274,11 @@ TrivialTypeTraversalAndLiftImpls! {
rustc_target::abi::Size,
}

TrivialLiftImpls! {
::rustc_hir::Safety,
::rustc_target::spec::abi::Abi,
}

///////////////////////////////////////////////////////////////////////////
// Lift implementations

Expand Down
13 changes: 6 additions & 7 deletions compiler/rustc_type_ir/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ impl<T> ExpectedFound<T> {
#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
pub enum TypeError<I: Interner> {
Mismatch,
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
SafetyMismatch(ExpectedFound<I::Safety>),
AbiMismatch(ExpectedFound<I::Abi>),
PolarityMismatch(#[type_visitable(ignore)] ExpectedFound<ty::PredicatePolarity>),
SafetyMismatch(#[type_visitable(ignore)] ExpectedFound<I::Safety>),
AbiMismatch(#[type_visitable(ignore)] ExpectedFound<I::Abi>),
Mutability,
ArgumentMutability(usize),
TupleSize(ExpectedFound<usize>),
Expand Down Expand Up @@ -73,9 +72,9 @@ impl<I: Interner> TypeError<I> {
pub fn must_include_note(self) -> bool {
use self::TypeError::*;
match self {
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_)
| PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
| ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | PolarityMismatch(_) | Mismatch
| AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_)
| VariadicMismatch(_) | TargetFeatureCast(_) => false,

Mutability
| ArgumentMutability(_)
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_type_ir/src/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,14 @@ pub trait Tys<I: Interner<Tys = Self>>:
fn output(self) -> I::Ty;
}

pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
fn rust() -> Self;

/// Whether this ABI is `extern "Rust"`.
fn is_rust(self) -> bool;
}

pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
fn safe() -> Self;

fn is_safe(self) -> bool;
Expand Down
54 changes: 17 additions & 37 deletions compiler/rustc_type_ir/src/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,17 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
ExpectedFound::new(true, a, b)
}));
}
let safety = relation.relate(a.safety, b.safety)?;
let abi = relation.relate(a.abi, b.abi)?;

if a.safety != b.safety {
return Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a.safety, b.safety)));
}

if a.abi != b.abi {
return Err(TypeError::AbiMismatch(ExpectedFound::new(true, a.abi, b.abi)));
};

let a_inputs = a.inputs();
let b_inputs = b.inputs();

if a_inputs.len() != b_inputs.len() {
return Err(TypeError::ArgCount);
}
Expand Down Expand Up @@ -212,26 +217,12 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
Ok(ty::FnSig {
inputs_and_output: cx.mk_type_list_from_iter(inputs_and_output)?,
c_variadic: a.c_variadic,
safety,
abi,
safety: a.safety,
abi: a.abi,
})
}
}

impl<I: Interner> Relate<I> for ty::BoundConstness {
fn relate<R: TypeRelation<I>>(
_relation: &mut R,
a: ty::BoundConstness,
b: ty::BoundConstness,
) -> RelateResult<I, ty::BoundConstness> {
if a != b {
Err(TypeError::ConstnessMismatch(ExpectedFound::new(true, a, b)))
} else {
Ok(a)
}
}
}

impl<I: Interner> Relate<I> for ty::AliasTy<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
Expand Down Expand Up @@ -659,29 +650,18 @@ impl<I: Interner, T: Relate<I>> Relate<I> for ty::Binder<I, T> {
}
}

impl<I: Interner> Relate<I> for ty::PredicatePolarity {
fn relate<R: TypeRelation<I>>(
_relation: &mut R,
a: ty::PredicatePolarity,
b: ty::PredicatePolarity,
) -> RelateResult<I, ty::PredicatePolarity> {
if a != b {
Err(TypeError::PolarityMismatch(ExpectedFound::new(true, a, b)))
} else {
Ok(a)
}
}
}

impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
fn relate<R: TypeRelation<I>>(
relation: &mut R,
a: ty::TraitPredicate<I>,
b: ty::TraitPredicate<I>,
) -> RelateResult<I, ty::TraitPredicate<I>> {
Ok(ty::TraitPredicate {
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
polarity: relation.relate(a.polarity, b.polarity)?,
})
let trait_ref = relation.relate(a.trait_ref, b.trait_ref)?;
if a.polarity != b.polarity {
return Err(TypeError::PolarityMismatch(ExpectedFound::new(
true, a.polarity, b.polarity,
)));
}
Ok(ty::TraitPredicate { trait_ref, polarity: a.polarity })
}
}
4 changes: 4 additions & 0 deletions compiler/rustc_type_ir/src/ty_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,11 @@ pub struct TypeAndMut<I: Interner> {
pub struct FnSig<I: Interner> {
pub inputs_and_output: I::Tys,
pub c_variadic: bool,
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub safety: I::Safety,
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub abi: I::Abi,
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_type_ir/src/ty_kind/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,12 @@ pub struct CoroutineClosureSignature<I: Interner> {
/// Always false
pub c_variadic: bool,
/// Always `Normal` (safe)
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub safety: I::Safety,
/// Always `RustCall`
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub abi: I::Abi,
}

Expand Down
114 changes: 72 additions & 42 deletions compiler/rustc_type_ir_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,73 @@
use quote::quote;
use syn::parse_quote;
use quote::{ToTokens, quote};
use syn::visit_mut::VisitMut;
use syn::{Attribute, parse_quote};
use synstructure::decl_derive;

decl_derive!(
[TypeFoldable_Generic] => type_foldable_derive
[TypeVisitable_Generic, attributes(type_visitable)] => type_visitable_derive
);
decl_derive!(
[TypeVisitable_Generic] => type_visitable_derive
[TypeFoldable_Generic, attributes(type_foldable)] => type_foldable_derive
);
decl_derive!(
[Lift_Generic] => lift_derive
);

fn has_ignore_attr(attrs: &[Attribute], name: &'static str, meta: &'static str) -> bool {
let mut ignored = false;
attrs.iter().for_each(|attr| {
if !attr.path().is_ident(name) {
return;
}
let _ = attr.parse_nested_meta(|nested| {
if nested.path.is_ident(meta) {
ignored = true;
}
Ok(())
});
});

ignored
}

fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
panic!("cannot derive on union")
}

if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
s.add_impl_generic(parse_quote! { I });
}

s.filter(|bi| !has_ignore_attr(&bi.ast().attrs, "type_visitable", "ignore"));

s.add_where_predicate(parse_quote! { I: Interner });
s.add_bounds(synstructure::AddBounds::Fields);
let body_visit = s.each(|bind| {
quote! {
match ::rustc_ast_ir::visit::VisitorResult::branch(
::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
) {
::core::ops::ControlFlow::Continue(()) => {},
::core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
},
}
}
});
s.bind_with(|_| synstructure::BindStyle::Move);

s.bound_impl(quote!(::rustc_type_ir::visit::TypeVisitable<I>), quote! {
fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor<I>>(
&self,
__visitor: &mut __V
) -> __V::Result {
match *self { #body_visit }
<__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
}
})
}

fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
panic!("cannot derive on union")
Expand All @@ -29,12 +84,23 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke
let bindings = vi.bindings();
vi.construct(|_, index| {
let bind = &bindings[index];
quote! {
::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)?

// retain value of fields with #[type_foldable(identity)]
if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") {
bind.to_token_stream()
} else {
quote! {
::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)?
}
}
})
});

// We filter fields which get ignored and don't require them to implement
// `TypeFoldable`. We do so after generating `body_fold` as we still need
// to generate code for them.
s.filter(|bi| !has_ignore_attr(&bi.ast().attrs, "type_foldable", "identity"));
s.add_bounds(synstructure::AddBounds::Fields);
s.bound_impl(quote!(::rustc_type_ir::fold::TypeFoldable<I>), quote! {
fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder<I>>(
self,
Expand Down Expand Up @@ -113,39 +179,3 @@ fn lift(mut ty: syn::Type) -> syn::Type {

ty
}

fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
panic!("cannot derive on union")
}

if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
s.add_impl_generic(parse_quote! { I });
}

s.add_where_predicate(parse_quote! { I: Interner });
s.add_bounds(synstructure::AddBounds::Fields);
let body_visit = s.each(|bind| {
quote! {
match ::rustc_ast_ir::visit::VisitorResult::branch(
::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
) {
::core::ops::ControlFlow::Continue(()) => {},
::core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
},
}
}
});
s.bind_with(|_| synstructure::BindStyle::Move);

s.bound_impl(quote!(::rustc_type_ir::visit::TypeVisitable<I>), quote! {
fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor<I>>(
&self,
__visitor: &mut __V
) -> __V::Result {
match *self { #body_visit }
<__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
}
})
}
Loading