feat(ast): add method to widen inherited enum ref to parent ref (#23961)

We already had conversion methods to narrow from e.g. `&Expression` to `&MemberExpression`.

Add methods to convert in opposite direction - to widen from `&MemberExpression` to `&Expression`.

Note that a method to convert `&mut MemberExpression` to `&mut Expression` is NOT added. This would be unsound, as you'd be able to widen a `&mut MemberExpression` to `&mut Expression`, and assign a `Expression::NullLiteral` to it. This would make the original `&mut MemberExpression` contain an illegal value - there is no such thing as `MemberExpression::NullLiteral`.
This commit is contained in:
overlookmotel committed 2026-06-30 16:32:04 +00:00
1 parent be1795021b
commit 26dd9e2394
2 files changed
+411

No files matched your search

@@ -82,6 +82,19 @@ impl<'a> Expression<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to an [`&Expression`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&Expression`]: Expression
#[inline]
pub fn as_expression(&self) -> &Expression<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<Expression>() }
}
}
impl<'a> TryFrom<Expression<'a>> for MemberExpression<'a> {
type Error = ();
@@ -240,6 +253,19 @@ impl<'a> ArrayExpressionElement<'a> {
}
}
impl<'a> Expression<'a> {
/// Convert an [`&Expression`] to an [`&ArrayExpressionElement`].
///
/// [`&Expression`]: Expression
/// [`&ArrayExpressionElement`]: ArrayExpressionElement
#[inline]
pub fn as_array_expression_element(&self) -> &ArrayExpressionElement<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ArrayExpressionElement>() }
}
}
impl<'a> TryFrom<ArrayExpressionElement<'a>> for Expression<'a> {
type Error = ();
@@ -476,6 +502,19 @@ impl<'a> ArrayExpressionElement<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to an [`&ArrayExpressionElement`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&ArrayExpressionElement`]: ArrayExpressionElement
#[inline]
pub fn as_array_expression_element(&self) -> &ArrayExpressionElement<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ArrayExpressionElement>() }
}
}
impl<'a> TryFrom<ArrayExpressionElement<'a>> for MemberExpression<'a> {
type Error = ();
@@ -638,6 +677,19 @@ impl<'a> PropertyKey<'a> {
}
}
impl<'a> Expression<'a> {
/// Convert an [`&Expression`] to a [`&PropertyKey`].
///
/// [`&Expression`]: Expression
/// [`&PropertyKey`]: PropertyKey
#[inline]
pub fn as_property_key(&self) -> &PropertyKey<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<PropertyKey>() }
}
}
impl<'a> TryFrom<PropertyKey<'a>> for Expression<'a> {
type Error = ();
@@ -830,6 +882,19 @@ impl<'a> PropertyKey<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to a [`&PropertyKey`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&PropertyKey`]: PropertyKey
#[inline]
pub fn as_property_key(&self) -> &PropertyKey<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<PropertyKey>() }
}
}
impl<'a> TryFrom<PropertyKey<'a>> for MemberExpression<'a> {
type Error = ();
@@ -988,6 +1053,19 @@ impl<'a> Argument<'a> {
}
}
impl<'a> Expression<'a> {
/// Convert an [`&Expression`] to an [`&Argument`].
///
/// [`&Expression`]: Expression
/// [`&Argument`]: Argument
#[inline]
pub fn as_argument(&self) -> &Argument<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<Argument>() }
}
}
impl<'a> TryFrom<Argument<'a>> for Expression<'a> {
type Error = ();
@@ -1178,6 +1256,19 @@ impl<'a> Argument<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to an [`&Argument`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&Argument`]: Argument
#[inline]
pub fn as_argument(&self) -> &Argument<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<Argument>() }
}
}
impl<'a> TryFrom<Argument<'a>> for MemberExpression<'a> {
type Error = ();
@@ -1295,6 +1386,19 @@ impl<'a> AssignmentTarget<'a> {
}
}
impl<'a> SimpleAssignmentTarget<'a> {
/// Convert a [`&SimpleAssignmentTarget`] to an [`&AssignmentTarget`].
///
/// [`&SimpleAssignmentTarget`]: SimpleAssignmentTarget
/// [`&AssignmentTarget`]: AssignmentTarget
#[inline]
pub fn as_assignment_target(&self) -> &AssignmentTarget<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<AssignmentTarget>() }
}
}
impl<'a> TryFrom<AssignmentTarget<'a>> for SimpleAssignmentTarget<'a> {
type Error = ();
@@ -1439,6 +1543,19 @@ impl<'a> AssignmentTarget<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to an [`&AssignmentTarget`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&AssignmentTarget`]: AssignmentTarget
#[inline]
pub fn as_assignment_target(&self) -> &AssignmentTarget<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<AssignmentTarget>() }
}
}
impl<'a> TryFrom<AssignmentTarget<'a>> for MemberExpression<'a> {
type Error = ();
@@ -1556,6 +1673,19 @@ impl<'a> AssignmentTarget<'a> {
}
}
impl<'a> AssignmentTargetPattern<'a> {
/// Convert an [`&AssignmentTargetPattern`] to an [`&AssignmentTarget`].
///
/// [`&AssignmentTargetPattern`]: AssignmentTargetPattern
/// [`&AssignmentTarget`]: AssignmentTarget
#[inline]
pub fn as_assignment_target(&self) -> &AssignmentTarget<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<AssignmentTarget>() }
}
}
impl<'a> TryFrom<AssignmentTarget<'a>> for AssignmentTargetPattern<'a> {
type Error = ();
@@ -1672,6 +1802,19 @@ impl<'a> SimpleAssignmentTarget<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to a [`&SimpleAssignmentTarget`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&SimpleAssignmentTarget`]: SimpleAssignmentTarget
#[inline]
pub fn as_simple_assignment_target(&self) -> &SimpleAssignmentTarget<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<SimpleAssignmentTarget>() }
}
}
impl<'a> TryFrom<SimpleAssignmentTarget<'a>> for MemberExpression<'a> {
type Error = ();
@@ -1801,6 +1944,19 @@ impl<'a> AssignmentTargetMaybeDefault<'a> {
}
}
impl<'a> AssignmentTarget<'a> {
/// Convert an [`&AssignmentTarget`] to an [`&AssignmentTargetMaybeDefault`].
///
/// [`&AssignmentTarget`]: AssignmentTarget
/// [`&AssignmentTargetMaybeDefault`]: AssignmentTargetMaybeDefault
#[inline]
pub fn as_assignment_target_maybe_default(&self) -> &AssignmentTargetMaybeDefault<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<AssignmentTargetMaybeDefault>() }
}
}
impl<'a> TryFrom<AssignmentTargetMaybeDefault<'a>> for AssignmentTarget<'a> {
type Error = ();
@@ -1968,6 +2124,19 @@ impl<'a> AssignmentTargetMaybeDefault<'a> {
}
}
impl<'a> SimpleAssignmentTarget<'a> {
/// Convert a [`&SimpleAssignmentTarget`] to an [`&AssignmentTargetMaybeDefault`].
///
/// [`&SimpleAssignmentTarget`]: SimpleAssignmentTarget
/// [`&AssignmentTargetMaybeDefault`]: AssignmentTargetMaybeDefault
#[inline]
pub fn as_assignment_target_maybe_default(&self) -> &AssignmentTargetMaybeDefault<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<AssignmentTargetMaybeDefault>() }
}
}
impl<'a> TryFrom<AssignmentTargetMaybeDefault<'a>> for SimpleAssignmentTarget<'a> {
type Error = ();
@@ -2120,6 +2289,19 @@ impl<'a> AssignmentTargetMaybeDefault<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to an [`&AssignmentTargetMaybeDefault`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&AssignmentTargetMaybeDefault`]: AssignmentTargetMaybeDefault
#[inline]
pub fn as_assignment_target_maybe_default(&self) -> &AssignmentTargetMaybeDefault<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<AssignmentTargetMaybeDefault>() }
}
}
impl<'a> TryFrom<AssignmentTargetMaybeDefault<'a>> for MemberExpression<'a> {
type Error = ();
@@ -2237,6 +2419,19 @@ impl<'a> AssignmentTargetMaybeDefault<'a> {
}
}
impl<'a> AssignmentTargetPattern<'a> {
/// Convert an [`&AssignmentTargetPattern`] to an [`&AssignmentTargetMaybeDefault`].
///
/// [`&AssignmentTargetPattern`]: AssignmentTargetPattern
/// [`&AssignmentTargetMaybeDefault`]: AssignmentTargetMaybeDefault
#[inline]
pub fn as_assignment_target_maybe_default(&self) -> &AssignmentTargetMaybeDefault<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<AssignmentTargetMaybeDefault>() }
}
}
impl<'a> TryFrom<AssignmentTargetMaybeDefault<'a>> for AssignmentTargetPattern<'a> {
type Error = ();
@@ -2353,6 +2548,19 @@ impl<'a> ChainElement<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to a [`&ChainElement`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&ChainElement`]: ChainElement
#[inline]
pub fn as_chain_element(&self) -> &ChainElement<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ChainElement>() }
}
}
impl<'a> TryFrom<ChainElement<'a>> for MemberExpression<'a> {
type Error = ();
@@ -2477,6 +2685,19 @@ impl<'a> Statement<'a> {
}
}
impl<'a> Declaration<'a> {
/// Convert a [`&Declaration`] to a [`&Statement`].
///
/// [`&Declaration`]: Declaration
/// [`&Statement`]: Statement
#[inline]
pub fn as_statement(&self) -> &Statement<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<Statement>() }
}
}
impl<'a> TryFrom<Statement<'a>> for Declaration<'a> {
type Error = ();
@@ -2604,6 +2825,19 @@ impl<'a> Statement<'a> {
}
}
impl<'a> ModuleDeclaration<'a> {
/// Convert a [`&ModuleDeclaration`] to a [`&Statement`].
///
/// [`&ModuleDeclaration`]: ModuleDeclaration
/// [`&Statement`]: Statement
#[inline]
pub fn as_statement(&self) -> &Statement<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<Statement>() }
}
}
impl<'a> TryFrom<Statement<'a>> for ModuleDeclaration<'a> {
type Error = ();
@@ -2770,6 +3004,19 @@ impl<'a> ForStatementInit<'a> {
}
}
impl<'a> Expression<'a> {
/// Convert an [`&Expression`] to a [`&ForStatementInit`].
///
/// [`&Expression`]: Expression
/// [`&ForStatementInit`]: ForStatementInit
#[inline]
pub fn as_for_statement_init(&self) -> &ForStatementInit<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ForStatementInit>() }
}
}
impl<'a> TryFrom<ForStatementInit<'a>> for Expression<'a> {
type Error = ();
@@ -2980,6 +3227,19 @@ impl<'a> ForStatementInit<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to a [`&ForStatementInit`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&ForStatementInit`]: ForStatementInit
#[inline]
pub fn as_for_statement_init(&self) -> &ForStatementInit<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ForStatementInit>() }
}
}
impl<'a> TryFrom<ForStatementInit<'a>> for MemberExpression<'a> {
type Error = ();
@@ -3109,6 +3369,19 @@ impl<'a> ForStatementLeft<'a> {
}
}
impl<'a> AssignmentTarget<'a> {
/// Convert an [`&AssignmentTarget`] to a [`&ForStatementLeft`].
///
/// [`&AssignmentTarget`]: AssignmentTarget
/// [`&ForStatementLeft`]: ForStatementLeft
#[inline]
pub fn as_for_statement_left(&self) -> &ForStatementLeft<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ForStatementLeft>() }
}
}
impl<'a> TryFrom<ForStatementLeft<'a>> for AssignmentTarget<'a> {
type Error = ();
@@ -3268,6 +3541,19 @@ impl<'a> ForStatementLeft<'a> {
}
}
impl<'a> SimpleAssignmentTarget<'a> {
/// Convert a [`&SimpleAssignmentTarget`] to a [`&ForStatementLeft`].
///
/// [`&SimpleAssignmentTarget`]: SimpleAssignmentTarget
/// [`&ForStatementLeft`]: ForStatementLeft
#[inline]
pub fn as_for_statement_left(&self) -> &ForStatementLeft<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ForStatementLeft>() }
}
}
impl<'a> TryFrom<ForStatementLeft<'a>> for SimpleAssignmentTarget<'a> {
type Error = ();
@@ -3412,6 +3698,19 @@ impl<'a> ForStatementLeft<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to a [`&ForStatementLeft`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&ForStatementLeft`]: ForStatementLeft
#[inline]
pub fn as_for_statement_left(&self) -> &ForStatementLeft<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ForStatementLeft>() }
}
}
impl<'a> TryFrom<ForStatementLeft<'a>> for MemberExpression<'a> {
type Error = ();
@@ -3529,6 +3828,19 @@ impl<'a> ForStatementLeft<'a> {
}
}
impl<'a> AssignmentTargetPattern<'a> {
/// Convert an [`&AssignmentTargetPattern`] to a [`&ForStatementLeft`].
///
/// [`&AssignmentTargetPattern`]: AssignmentTargetPattern
/// [`&ForStatementLeft`]: ForStatementLeft
#[inline]
pub fn as_for_statement_left(&self) -> &ForStatementLeft<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ForStatementLeft>() }
}
}
impl<'a> TryFrom<ForStatementLeft<'a>> for AssignmentTargetPattern<'a> {
type Error = ();
@@ -3685,6 +3997,19 @@ impl<'a> ExportDefaultDeclarationKind<'a> {
}
}
impl<'a> Expression<'a> {
/// Convert an [`&Expression`] to an [`&ExportDefaultDeclarationKind`].
///
/// [`&Expression`]: Expression
/// [`&ExportDefaultDeclarationKind`]: ExportDefaultDeclarationKind
#[inline]
pub fn as_export_default_declaration_kind(&self) -> &ExportDefaultDeclarationKind<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ExportDefaultDeclarationKind>() }
}
}
impl<'a> TryFrom<ExportDefaultDeclarationKind<'a>> for Expression<'a> {
type Error = ();
@@ -3945,6 +4270,19 @@ impl<'a> ExportDefaultDeclarationKind<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to an [`&ExportDefaultDeclarationKind`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&ExportDefaultDeclarationKind`]: ExportDefaultDeclarationKind
#[inline]
pub fn as_export_default_declaration_kind(&self) -> &ExportDefaultDeclarationKind<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<ExportDefaultDeclarationKind>() }
}
}
impl<'a> TryFrom<ExportDefaultDeclarationKind<'a>> for MemberExpression<'a> {
type Error = ();
@@ -4107,6 +4445,19 @@ impl<'a> JSXExpression<'a> {
}
}
impl<'a> Expression<'a> {
/// Convert an [`&Expression`] to a [`&JSXExpression`].
///
/// [`&Expression`]: Expression
/// [`&JSXExpression`]: JSXExpression
#[inline]
pub fn as_jsx_expression(&self) -> &JSXExpression<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<JSXExpression>() }
}
}
impl<'a> TryFrom<JSXExpression<'a>> for Expression<'a> {
type Error = ();
@@ -4303,6 +4654,19 @@ impl<'a> JSXExpression<'a> {
}
}
impl<'a> MemberExpression<'a> {
/// Convert a [`&MemberExpression`] to a [`&JSXExpression`].
///
/// [`&MemberExpression`]: MemberExpression
/// [`&JSXExpression`]: JSXExpression
#[inline]
pub fn as_jsx_expression(&self) -> &JSXExpression<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<JSXExpression>() }
}
}
impl<'a> TryFrom<JSXExpression<'a>> for MemberExpression<'a> {
type Error = ();
@@ -4455,6 +4819,19 @@ impl<'a> TSTupleElement<'a> {
}
}
impl<'a> TSType<'a> {
/// Convert a [`&TSType`] to a [`&TSTupleElement`].
///
/// [`&TSType`]: TSType
/// [`&TSTupleElement`]: TSTupleElement
#[inline]
pub fn as_ts_tuple_element(&self) -> &TSTupleElement<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<TSTupleElement>() }
}
}
impl<'a> TryFrom<TSTupleElement<'a>> for TSType<'a> {
type Error = ();
@@ -4631,6 +5008,19 @@ impl<'a> TSTypeQueryExprName<'a> {
}
}
impl<'a> TSTypeName<'a> {
/// Convert a [`&TSTypeName`] to a [`&TSTypeQueryExprName`].
///
/// [`&TSTypeName`]: TSTypeName
/// [`&TSTypeQueryExprName`]: TSTypeQueryExprName
#[inline]
pub fn as_ts_type_query_expr_name(&self) -> &TSTypeQueryExprName<'a> {
// SAFETY: Transmute is safe because discriminants + types are identical between
// `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<TSTypeQueryExprName>() }
}
}
impl<'a> TryFrom<TSTypeQueryExprName<'a>> for TSTypeName<'a> {
type Error = ();
@@ -11,6 +11,7 @@
//! This generator produces, for each such `Parent` / `Child` pair:
//!
//! * Methods on `Parent`: `is_child`, `into_child`, `as_child`, `as_child_mut`, `to_child`, `to_child_mut`
//! * Methods on `Child`: `as_parent`
//! * `impl TryFrom<Parent> for Child`
//! * `impl From<Child> for Parent`
//!
@@ -260,6 +261,7 @@ fn generate_match_macro(enum_def: &EnumDef, schema: &Schema) -> TokenStream {
/// where `parent` inherits all of `child`'s variants.
fn generate_conversions(parent: &EnumDef, child: &EnumDef, schema: &Schema) -> TokenStream {
let parent_ident = parent.ident();
let parent_snake = parent.snake_name();
let child_ident = child.ident();
let child_snake = child.snake_name();
@@ -272,6 +274,7 @@ fn generate_conversions(parent: &EnumDef, child: &EnumDef, schema: &Schema) -> T
let as_mut_fn = format_ident!("as_{child_snake}_mut");
let to_fn = format_ident!("to_{child_snake}");
let to_mut_fn = format_ident!("to_{child_snake}_mut");
let as_reverse_fn = format_ident!("as_{parent_snake}");
let parent_name = parent.name();
let child_name = child.name();
@@ -292,6 +295,10 @@ fn generate_conversions(parent: &EnumDef, child: &EnumDef, schema: &Schema) -> T
let as_doc2 = format!(" [`&{parent_name}`]: {parent_name}");
let as_doc3 = format!(" [`&{child_name}`]: {child_name}");
let as_reverse_doc = format!(
" Convert {child_article} [`&{child_name}`] to {parent_article} [`&{parent_name}`]."
);
let as_mut_doc1 = format!(
" Convert {parent_article} [`&mut {parent_name}`] to {child_article} [`&mut {child_name}`]."
);
@@ -376,6 +383,20 @@ fn generate_conversions(parent: &EnumDef, child: &EnumDef, schema: &Schema) -> T
}
}
///@@line_break
impl<'a> #child_ident<'a> {
#[doc = #as_reverse_doc]
///
#[doc = #as_doc3]
#[doc = #as_doc2]
#[inline]
pub fn #as_reverse_fn(&self) -> &#parent_ident<'a> {
///@ SAFETY: Transmute is safe because discriminants + types are identical between
///@ `parent` and `child` for the shared variants
unsafe { &*std::ptr::from_ref(self).cast::<#parent_ident>() }
}
}
///@@line_break
impl<'a> TryFrom<#parent_ident<'a>> for #child_ident<'a> {
type Error = ();