do not relate Abi
and Safety
and update some macros while we're at it
This commit is contained in:
parent
86d69c705a
commit
196fdf144f
@ -1,7 +1,5 @@
|
|||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_target::spec::abi;
|
|
||||||
pub use rustc_type_ir::relate::*;
|
pub use rustc_type_ir::relate::*;
|
||||||
|
|
||||||
use crate::ty::error::{ExpectedFound, TypeError};
|
use crate::ty::error::{ExpectedFound, TypeError};
|
||||||
@ -121,26 +119,6 @@ fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
|
||||||
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
|
||||||
relation: &mut R,
|
relation: &mut R,
|
||||||
|
@ -264,8 +264,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
// interners).
|
// interners).
|
||||||
TrivialTypeTraversalAndLiftImpls! {
|
TrivialTypeTraversalAndLiftImpls! {
|
||||||
::rustc_hir::def_id::DefId,
|
::rustc_hir::def_id::DefId,
|
||||||
::rustc_hir::Safety,
|
|
||||||
::rustc_target::spec::abi::Abi,
|
|
||||||
crate::ty::ClosureKind,
|
crate::ty::ClosureKind,
|
||||||
crate::ty::ParamConst,
|
crate::ty::ParamConst,
|
||||||
crate::ty::ParamTy,
|
crate::ty::ParamTy,
|
||||||
@ -276,6 +274,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
rustc_target::abi::Size,
|
rustc_target::abi::Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TrivialLiftImpls! {
|
||||||
|
::rustc_hir::Safety,
|
||||||
|
::rustc_target::spec::abi::Abi,
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Lift implementations
|
// Lift implementations
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ pub enum TypeError<I: Interner> {
|
|||||||
Mismatch,
|
Mismatch,
|
||||||
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
|
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
|
||||||
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
|
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
|
||||||
SafetyMismatch(ExpectedFound<I::Safety>),
|
SafetyMismatch(#[type_visitable(ignore)] ExpectedFound<I::Safety>),
|
||||||
AbiMismatch(ExpectedFound<I::Abi>),
|
AbiMismatch(#[type_visitable(ignore)] ExpectedFound<I::Abi>),
|
||||||
Mutability,
|
Mutability,
|
||||||
ArgumentMutability(usize),
|
ArgumentMutability(usize),
|
||||||
TupleSize(ExpectedFound<usize>),
|
TupleSize(ExpectedFound<usize>),
|
||||||
|
@ -208,14 +208,14 @@ pub trait Tys<I: Interner<Tys = Self>>:
|
|||||||
fn output(self) -> I::Ty;
|
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;
|
fn rust() -> Self;
|
||||||
|
|
||||||
/// Whether this ABI is `extern "Rust"`.
|
/// Whether this ABI is `extern "Rust"`.
|
||||||
fn is_rust(self) -> bool;
|
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 safe() -> Self;
|
||||||
|
|
||||||
fn is_safe(self) -> bool;
|
fn is_safe(self) -> bool;
|
||||||
|
@ -174,12 +174,17 @@ fn relate<R: TypeRelation<I>>(
|
|||||||
ExpectedFound::new(true, a, b)
|
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 a_inputs = a.inputs();
|
||||||
let b_inputs = b.inputs();
|
let b_inputs = b.inputs();
|
||||||
|
|
||||||
if a_inputs.len() != b_inputs.len() {
|
if a_inputs.len() != b_inputs.len() {
|
||||||
return Err(TypeError::ArgCount);
|
return Err(TypeError::ArgCount);
|
||||||
}
|
}
|
||||||
@ -212,8 +217,8 @@ fn relate<R: TypeRelation<I>>(
|
|||||||
Ok(ty::FnSig {
|
Ok(ty::FnSig {
|
||||||
inputs_and_output: cx.mk_type_list_from_iter(inputs_and_output)?,
|
inputs_and_output: cx.mk_type_list_from_iter(inputs_and_output)?,
|
||||||
c_variadic: a.c_variadic,
|
c_variadic: a.c_variadic,
|
||||||
safety,
|
safety: a.safety,
|
||||||
abi,
|
abi: a.abi,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -861,7 +861,11 @@ pub struct TypeAndMut<I: Interner> {
|
|||||||
pub struct FnSig<I: Interner> {
|
pub struct FnSig<I: Interner> {
|
||||||
pub inputs_and_output: I::Tys,
|
pub inputs_and_output: I::Tys,
|
||||||
pub c_variadic: bool,
|
pub c_variadic: bool,
|
||||||
|
#[type_visitable(ignore)]
|
||||||
|
#[type_foldable(identity)]
|
||||||
pub safety: I::Safety,
|
pub safety: I::Safety,
|
||||||
|
#[type_visitable(ignore)]
|
||||||
|
#[type_foldable(identity)]
|
||||||
pub abi: I::Abi,
|
pub abi: I::Abi,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,8 +372,12 @@ pub struct CoroutineClosureSignature<I: Interner> {
|
|||||||
/// Always false
|
/// Always false
|
||||||
pub c_variadic: bool,
|
pub c_variadic: bool,
|
||||||
/// Always `Normal` (safe)
|
/// Always `Normal` (safe)
|
||||||
|
#[type_visitable(ignore)]
|
||||||
|
#[type_foldable(identity)]
|
||||||
pub safety: I::Safety,
|
pub safety: I::Safety,
|
||||||
/// Always `RustCall`
|
/// Always `RustCall`
|
||||||
|
#[type_visitable(ignore)]
|
||||||
|
#[type_foldable(identity)]
|
||||||
pub abi: I::Abi,
|
pub abi: I::Abi,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,73 @@
|
|||||||
use quote::quote;
|
use quote::{ToTokens, quote};
|
||||||
use syn::parse_quote;
|
|
||||||
use syn::visit_mut::VisitMut;
|
use syn::visit_mut::VisitMut;
|
||||||
|
use syn::{Attribute, parse_quote};
|
||||||
use synstructure::decl_derive;
|
use synstructure::decl_derive;
|
||||||
|
|
||||||
decl_derive!(
|
decl_derive!(
|
||||||
[TypeFoldable_Generic] => type_foldable_derive
|
[TypeVisitable_Generic, attributes(type_visitable)] => type_visitable_derive
|
||||||
);
|
);
|
||||||
decl_derive!(
|
decl_derive!(
|
||||||
[TypeVisitable_Generic] => type_visitable_derive
|
[TypeFoldable_Generic, attributes(type_foldable)] => type_foldable_derive
|
||||||
);
|
);
|
||||||
decl_derive!(
|
decl_derive!(
|
||||||
[Lift_Generic] => lift_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 {
|
fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||||
if let syn::Data::Union(_) = s.ast().data {
|
if let syn::Data::Union(_) = s.ast().data {
|
||||||
panic!("cannot derive on union")
|
panic!("cannot derive on union")
|
||||||
@ -29,12 +84,23 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke
|
|||||||
let bindings = vi.bindings();
|
let bindings = vi.bindings();
|
||||||
vi.construct(|_, index| {
|
vi.construct(|_, index| {
|
||||||
let bind = &bindings[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! {
|
s.bound_impl(quote!(::rustc_type_ir::fold::TypeFoldable<I>), quote! {
|
||||||
fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder<I>>(
|
fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder<I>>(
|
||||||
self,
|
self,
|
||||||
@ -113,39 +179,3 @@ fn visit_type_path_mut(&mut self, i: &mut syn::TypePath) {
|
|||||||
|
|
||||||
ty
|
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…
Reference in New Issue
Block a user