Uplift TraitPredicate
This commit is contained in:
parent
d5797e938a
commit
204cde4564
13 changed files with 114 additions and 90 deletions
|
@ -1,9 +1,8 @@
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath};
|
||||||
self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable,
|
use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable};
|
||||||
};
|
|
||||||
use rustc_session::{declare_lint, declare_lint_pass};
|
use rustc_session::{declare_lint, declare_lint_pass};
|
||||||
use rustc_span::{symbol::kw, Span};
|
use rustc_span::{symbol::kw, Span};
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
|
|
@ -299,37 +299,6 @@ impl fmt::Display for ImplPolarity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Polarity for a trait predicate. May either be negative or positive.
|
|
||||||
/// Distinguished from [`ImplPolarity`] since we never compute goals with
|
|
||||||
/// "reservation" level.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
|
||||||
#[derive(TypeFoldable, TypeVisitable)]
|
|
||||||
pub enum PredicatePolarity {
|
|
||||||
/// `Type: Trait`
|
|
||||||
Positive,
|
|
||||||
/// `Type: !Trait`
|
|
||||||
Negative,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PredicatePolarity {
|
|
||||||
/// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
|
|
||||||
pub fn flip(&self) -> PredicatePolarity {
|
|
||||||
match self {
|
|
||||||
PredicatePolarity::Positive => PredicatePolarity::Negative,
|
|
||||||
PredicatePolarity::Negative => PredicatePolarity::Positive,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for PredicatePolarity {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Positive => f.write_str("positive"),
|
|
||||||
Self::Negative => f.write_str("negative"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
||||||
#[derive(TypeFoldable, TypeVisitable)]
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
pub enum Asyncness {
|
pub enum Asyncness {
|
||||||
|
|
|
@ -5,6 +5,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||||
use rustc_type_ir::ClauseKind as IrClauseKind;
|
use rustc_type_ir::ClauseKind as IrClauseKind;
|
||||||
use rustc_type_ir::PredicateKind as IrPredicateKind;
|
use rustc_type_ir::PredicateKind as IrPredicateKind;
|
||||||
|
use rustc_type_ir::TraitPredicate as IrTraitPredicate;
|
||||||
use rustc_type_ir::TraitRef as IrTraitRef;
|
use rustc_type_ir::TraitRef as IrTraitRef;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ use crate::ty::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>;
|
pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>;
|
||||||
|
pub type TraitPredicate<'tcx> = IrTraitPredicate<TyCtxt<'tcx>>;
|
||||||
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
|
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
|
||||||
pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
|
pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
|
||||||
|
|
||||||
|
@ -578,37 +580,8 @@ impl<'tcx> Clause<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
|
||||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
|
||||||
pub struct TraitPredicate<'tcx> {
|
|
||||||
pub trait_ref: TraitRef<'tcx>,
|
|
||||||
|
|
||||||
/// If polarity is Positive: we are proving that the trait is implemented.
|
|
||||||
///
|
|
||||||
/// If polarity is Negative: we are proving that a negative impl of this trait
|
|
||||||
/// exists. (Note that coherence also checks whether negative impls of supertraits
|
|
||||||
/// exist via a series of predicates.)
|
|
||||||
///
|
|
||||||
/// If polarity is Reserved: that's a bug.
|
|
||||||
pub polarity: PredicatePolarity,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
||||||
|
|
||||||
impl<'tcx> TraitPredicate<'tcx> {
|
|
||||||
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
|
|
||||||
Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn def_id(self) -> DefId {
|
|
||||||
self.trait_ref.def_id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn self_ty(self) -> Ty<'tcx> {
|
|
||||||
self.trait_ref.self_ty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> PolyTraitPredicate<'tcx> {
|
impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||||
pub fn def_id(self) -> DefId {
|
pub fn def_id(self) -> DefId {
|
||||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||||
|
|
|
@ -2953,8 +2953,9 @@ impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[extension(pub trait PrintTraitPredicateExt<'tcx>)]
|
||||||
impl<'tcx> ty::TraitPredicate<'tcx> {
|
impl<'tcx> ty::TraitPredicate<'tcx> {
|
||||||
pub fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> {
|
fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> {
|
||||||
TraitPredPrintModifiersAndPath(self)
|
TraitPredPrintModifiersAndPath(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3037,6 +3038,15 @@ define_print! {
|
||||||
p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
|
p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ty::TraitPredicate<'tcx> {
|
||||||
|
p!(print(self.trait_ref.self_ty()), ": ");
|
||||||
|
p!(pretty_print_bound_constness(self.trait_ref));
|
||||||
|
if let ty::PredicatePolarity::Negative = self.polarity {
|
||||||
|
p!("!");
|
||||||
|
}
|
||||||
|
p!(print(self.trait_ref.print_trait_sugared()))
|
||||||
|
}
|
||||||
|
|
||||||
ty::TypeAndMut<'tcx> {
|
ty::TypeAndMut<'tcx> {
|
||||||
p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
|
p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
|
||||||
}
|
}
|
||||||
|
@ -3176,15 +3186,6 @@ define_print_and_forward_display! {
|
||||||
p!(print(self.b))
|
p!(print(self.b))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::TraitPredicate<'tcx> {
|
|
||||||
p!(print(self.trait_ref.self_ty()), ": ");
|
|
||||||
p!(pretty_print_bound_constness(self.trait_ref));
|
|
||||||
if let ty::PredicatePolarity::Negative = self.polarity {
|
|
||||||
p!("!");
|
|
||||||
}
|
|
||||||
p!(print(self.trait_ref.print_trait_sugared()))
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::ProjectionPredicate<'tcx> {
|
ty::ProjectionPredicate<'tcx> {
|
||||||
p!(print(self.projection_ty), " == ");
|
p!(print(self.projection_ty), " == ");
|
||||||
cx.reset_type_limit();
|
cx.reset_type_limit();
|
||||||
|
|
|
@ -158,13 +158,6 @@ impl fmt::Debug for ty::ParamConst {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
// FIXME(effects) printing?
|
|
||||||
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
|
impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term)
|
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term)
|
||||||
|
|
|
@ -45,7 +45,9 @@ use std::iter;
|
||||||
use crate::infer::InferCtxtExt as _;
|
use crate::infer::InferCtxtExt as _;
|
||||||
use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
|
use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
|
||||||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
|
use rustc_middle::ty::print::{
|
||||||
|
with_forced_trimmed_paths, with_no_trimmed_paths, PrintTraitPredicateExt as _,
|
||||||
|
};
|
||||||
|
|
||||||
use itertools::EitherOrBoth;
|
use itertools::EitherOrBoth;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
|
@ -38,7 +38,8 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::print::{
|
use rustc_middle::ty::print::{
|
||||||
with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitRefExt as _,
|
with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitPredicateExt as _,
|
||||||
|
PrintTraitRefExt as _,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
|
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
|
||||||
|
|
|
@ -11,10 +11,10 @@ rustc_ast_ir = { path = "../rustc_ast_ir" }
|
||||||
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
||||||
rustc_index = { path = "../rustc_index", default-features = false }
|
rustc_index = { path = "../rustc_index", default-features = false }
|
||||||
rustc_macros = { path = "../rustc_macros", optional = true }
|
rustc_macros = { path = "../rustc_macros", optional = true }
|
||||||
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
|
|
||||||
rustc_serialize = { path = "../rustc_serialize", optional = true }
|
rustc_serialize = { path = "../rustc_serialize", optional = true }
|
||||||
rustc_span = { path = "../rustc_span", optional = true }
|
rustc_span = { path = "../rustc_span", optional = true }
|
||||||
smallvec = { version = "1.8.1" }
|
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
|
||||||
|
smallvec = { version = "1.8.1", default-features = false }
|
||||||
# tidy-alphabetical-end
|
# tidy-alphabetical-end
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
|
@ -5,9 +5,9 @@ use std::hash::Hash;
|
||||||
use crate::inherent::*;
|
use crate::inherent::*;
|
||||||
use crate::ir_print::IrPrint;
|
use crate::ir_print::IrPrint;
|
||||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||||
use crate::{CanonicalVarInfo, DebugWithInfcx, TraitRef};
|
use crate::{CanonicalVarInfo, DebugWithInfcx, TraitPredicate, TraitRef};
|
||||||
|
|
||||||
pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
|
pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> + IrPrint<TraitPredicate<Self>> {
|
||||||
type DefId: Copy + Debug + Hash + Eq;
|
type DefId: Copy + Debug + Hash + Eq;
|
||||||
type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
|
type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
|
||||||
type AdtDef: Copy + Debug + Hash + Eq;
|
type AdtDef: Copy + Debug + Hash + Eq;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::{Interner, TraitRef};
|
use crate::{Interner, TraitPredicate, TraitRef};
|
||||||
|
|
||||||
pub trait IrPrint<T> {
|
pub trait IrPrint<T> {
|
||||||
fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
|
fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||||
|
@ -15,7 +15,13 @@ macro_rules! define_display_via_print {
|
||||||
<I as IrPrint<$ty<I>>>::print(self, fmt)
|
<I as IrPrint<$ty<I>>>::print(self, fmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! define_debug_via_print {
|
||||||
|
($($ty:ident),+ $(,)?) => {
|
||||||
|
$(
|
||||||
impl<I: Interner> fmt::Debug for $ty<I> {
|
impl<I: Interner> fmt::Debug for $ty<I> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
<I as IrPrint<$ty<I>>>::print_debug(self, fmt)
|
<I as IrPrint<$ty<I>>>::print_debug(self, fmt)
|
||||||
|
@ -25,4 +31,6 @@ macro_rules! define_display_via_print {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
define_display_via_print!(TraitRef,);
|
define_display_via_print!(TraitRef, TraitPredicate,);
|
||||||
|
|
||||||
|
define_debug_via_print!(TraitRef,);
|
||||||
|
|
|
@ -53,4 +53,5 @@ TrivialTypeTraversalImpls! {
|
||||||
crate::UniverseIndex,
|
crate::UniverseIndex,
|
||||||
rustc_ast_ir::Mutability,
|
rustc_ast_ir::Mutability,
|
||||||
rustc_ast_ir::Movability,
|
rustc_ast_ir::Movability,
|
||||||
|
crate::PredicatePolarity,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||||
|
|
||||||
|
@ -67,3 +69,78 @@ impl<I: Interner> TraitRef<I> {
|
||||||
self.args.type_at(0)
|
self.args.type_at(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(derivative::Derivative)]
|
||||||
|
#[derivative(
|
||||||
|
Clone(bound = ""),
|
||||||
|
Copy(bound = ""),
|
||||||
|
Hash(bound = ""),
|
||||||
|
PartialEq(bound = ""),
|
||||||
|
Eq(bound = "")
|
||||||
|
)]
|
||||||
|
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||||
|
pub struct TraitPredicate<I: Interner> {
|
||||||
|
pub trait_ref: TraitRef<I>,
|
||||||
|
|
||||||
|
/// If polarity is Positive: we are proving that the trait is implemented.
|
||||||
|
///
|
||||||
|
/// If polarity is Negative: we are proving that a negative impl of this trait
|
||||||
|
/// exists. (Note that coherence also checks whether negative impls of supertraits
|
||||||
|
/// exist via a series of predicates.)
|
||||||
|
///
|
||||||
|
/// If polarity is Reserved: that's a bug.
|
||||||
|
pub polarity: PredicatePolarity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> TraitPredicate<I> {
|
||||||
|
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
|
||||||
|
Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), polarity: self.polarity }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn def_id(self) -> I::DefId {
|
||||||
|
self.trait_ref.def_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn self_ty(self) -> I::Ty {
|
||||||
|
self.trait_ref.self_ty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> fmt::Debug for TraitPredicate<I> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
// FIXME(effects) printing?
|
||||||
|
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Polarity for a trait predicate. May either be negative or positive.
|
||||||
|
/// Distinguished from [`ImplPolarity`] since we never compute goals with
|
||||||
|
/// "reservation" level.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||||
|
pub enum PredicatePolarity {
|
||||||
|
/// `Type: Trait`
|
||||||
|
Positive,
|
||||||
|
/// `Type: !Trait`
|
||||||
|
Negative,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PredicatePolarity {
|
||||||
|
/// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
|
||||||
|
pub fn flip(&self) -> PredicatePolarity {
|
||||||
|
match self {
|
||||||
|
PredicatePolarity::Positive => PredicatePolarity::Negative,
|
||||||
|
PredicatePolarity::Negative => PredicatePolarity::Positive,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for PredicatePolarity {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Positive => f.write_str("positive"),
|
||||||
|
Self::Negative => f.write_str("negative"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use synstructure::decl_derive;
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{parse_quote, visit_mut::VisitMut};
|
use syn::{parse_quote, visit_mut::VisitMut};
|
||||||
|
use synstructure::decl_derive;
|
||||||
|
|
||||||
decl_derive!(
|
decl_derive!(
|
||||||
[TypeFoldable_Generic] => type_foldable_derive
|
[TypeFoldable_Generic] => type_foldable_derive
|
||||||
|
@ -156,4 +156,4 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue