1
Fork 0

Auto merge of #132044 - lcnr:no-relate-abi, r=compiler-errors

do not implement `Relate`  for "boring" types

and update some macros while we're at it. This means we don't have to implement `TypeVisitable` for them.

r? `@compiler-errors`
This commit is contained in:
bors 2024-10-23 08:41:24 +00:00
commit ffd978b7bf
9 changed files with 110 additions and 115 deletions

View file

@ -35,9 +35,6 @@ impl<'tcx> TypeError<'tcx> {
TypeError::CyclicTy(_) => "cyclic type of infinite size".into(), TypeError::CyclicTy(_) => "cyclic type of infinite size".into(),
TypeError::CyclicConst(_) => "encountered a self-referencing constant".into(), TypeError::CyclicConst(_) => "encountered a self-referencing constant".into(),
TypeError::Mismatch => "types differ".into(), TypeError::Mismatch => "types differ".into(),
TypeError::ConstnessMismatch(values) => {
format!("expected {} bound, found {} bound", values.expected, values.found).into()
}
TypeError::PolarityMismatch(values) => { TypeError::PolarityMismatch(values) => {
format!("expected {} polarity, found {} polarity", values.expected, values.found) format!("expected {} polarity, found {} polarity", values.expected, values.found)
.into() .into()

View file

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

View file

@ -264,8 +264,6 @@ TrivialTypeTraversalImpls! {
// 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 @@ TrivialTypeTraversalAndLiftImpls! {
rustc_target::abi::Size, rustc_target::abi::Size,
} }
TrivialLiftImpls! {
::rustc_hir::Safety,
::rustc_target::spec::abi::Abi,
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Lift implementations // Lift implementations

View file

@ -27,10 +27,9 @@ impl<T> ExpectedFound<T> {
#[cfg_attr(feature = "nightly", rustc_pass_by_value)] #[cfg_attr(feature = "nightly", rustc_pass_by_value)]
pub enum TypeError<I: Interner> { pub enum TypeError<I: Interner> {
Mismatch, Mismatch,
ConstnessMismatch(ExpectedFound<ty::BoundConstness>), PolarityMismatch(#[type_visitable(ignore)] ExpectedFound<ty::PredicatePolarity>),
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>), SafetyMismatch(#[type_visitable(ignore)] ExpectedFound<I::Safety>),
SafetyMismatch(ExpectedFound<I::Safety>), AbiMismatch(#[type_visitable(ignore)] ExpectedFound<I::Abi>),
AbiMismatch(ExpectedFound<I::Abi>),
Mutability, Mutability,
ArgumentMutability(usize), ArgumentMutability(usize),
TupleSize(ExpectedFound<usize>), TupleSize(ExpectedFound<usize>),
@ -73,9 +72,9 @@ impl<I: Interner> TypeError<I> {
pub fn must_include_note(self) -> bool { pub fn must_include_note(self) -> bool {
use self::TypeError::*; use self::TypeError::*;
match self { match self {
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_) CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | PolarityMismatch(_) | Mismatch
| PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_) | AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_)
| ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false, | VariadicMismatch(_) | TargetFeatureCast(_) => false,
Mutability Mutability
| ArgumentMutability(_) | ArgumentMutability(_)

View file

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

View file

@ -174,12 +174,17 @@ impl<I: Interner> Relate<I> for ty::FnSig<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,26 +217,12 @@ impl<I: Interner> Relate<I> for ty::FnSig<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,
}) })
} }
} }
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> { impl<I: Interner> Relate<I> for ty::AliasTy<I> {
fn relate<R: TypeRelation<I>>( fn relate<R: TypeRelation<I>>(
relation: &mut R, relation: &mut R,
@ -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> { impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
fn relate<R: TypeRelation<I>>( fn relate<R: TypeRelation<I>>(
relation: &mut R, relation: &mut R,
a: ty::TraitPredicate<I>, a: ty::TraitPredicate<I>,
b: ty::TraitPredicate<I>, b: ty::TraitPredicate<I>,
) -> RelateResult<I, ty::TraitPredicate<I>> { ) -> RelateResult<I, ty::TraitPredicate<I>> {
Ok(ty::TraitPredicate { let trait_ref = relation.relate(a.trait_ref, b.trait_ref)?;
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?, if a.polarity != b.polarity {
polarity: relation.relate(a.polarity, b.polarity)?, return Err(TypeError::PolarityMismatch(ExpectedFound::new(
}) true, a.polarity, b.polarity,
)));
}
Ok(ty::TraitPredicate { trait_ref, polarity: a.polarity })
} }
} }

View file

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

View file

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

View file

@ -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 lift(mut ty: syn::Type) -> syn::Type {
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()
}
})
}