Skip to content
Open
Changes from 3 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
120 changes: 120 additions & 0 deletions src/types/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,3 +759,123 @@ impl Display for BasicMetadataTypeEnum<'_> {
write!(f, "{}", self.print_to_string())
}
}

#[derive(thiserror::Error, Debug)]
#[error("This variant of `AnyTypeEnum` cannot be used with `{self:?}()`!")]
pub enum InvalidVariant {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think each variant should have the AnyTypeEnum inside like a tuple. And move the error macro to individual variants. So you'd have something like:

#[error("The fn_type method cannot be called by the {0} variant")]
FnType(AnyTypeEnum<'ctx>),

which would produce a really nice and explanatory error message

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me, I'll implement when I'm free

FnType,
ArrayType,
}

impl<'ctx> AnyTypeEnum<'ctx> {
/// Creates a [`FunctionType`] with [`Self`] for its return type.
///
/// # Errors
///
/// Returns [`InvalidVariant`] if [`Self`] cannot be used to create a function type.
///
/// In this case, the only variant which cannot be used to create a function type is [`Self::FunctionType`].
///
/// # Examples
///
/// Using a valid variant:
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::types::AnyTypeEnum;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let wrapped_type = AnyTypeEnum::from(i8_type);
/// let result = wrapped_type.fn_type(&[], false);
///
/// // `AnyTypeEnum::IntType` can be used to create a function type.
/// assert!(result.is_ok());
/// let fn_type = result.unwrap();
/// ```
///
/// Using an invalid variant:
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::types::AnyTypeEnum;
///
/// let context = Context::create();
/// let fn_type = context.i8_type().fn_type(&[], false);
/// let wrapped_type = AnyTypeEnum::from(fn_type);
/// let result = wrapped_type.fn_type(&[], false);
///
/// // `AnyTypeEnum::FunctionType` cannot be used to create a function type.
/// assert!(result.is_err());
/// ```
pub fn fn_type(
self,
param_types: &[BasicMetadataTypeEnum<'ctx>],
is_var_args: bool,
) -> Result<FunctionType<'ctx>, InvalidVariant> {
match self {
AnyTypeEnum::ArrayType(inner) => Ok(inner.fn_type(param_types, is_var_args)),
AnyTypeEnum::FloatType(inner) => Ok(inner.fn_type(param_types, is_var_args)),
AnyTypeEnum::IntType(inner) => Ok(inner.fn_type(param_types, is_var_args)),
AnyTypeEnum::PointerType(inner) => Ok(inner.fn_type(param_types, is_var_args)),
AnyTypeEnum::StructType(inner) => Ok(inner.fn_type(param_types, is_var_args)),
AnyTypeEnum::VectorType(inner) => Ok(inner.fn_type(param_types, is_var_args)),
AnyTypeEnum::ScalableVectorType(inner) => Ok(inner.fn_type(param_types, is_var_args)),
AnyTypeEnum::VoidType(inner) => Ok(inner.fn_type(param_types, is_var_args)),
AnyTypeEnum::FunctionType(_) => Err(InvalidVariant::FnType),
}
}

/// Creates an [`ArrayType`] with [`Self`] for its element type.
///
/// # Errors
///
/// Returns [`InvalidVariant`] if [`Self`] cannot be used to create an array type.
///
/// In this case, the only variants which cannot be used to create an array type are [`Self::FunctionType`] and [`Self::VoidType`].
///
/// # Examples
///
/// Using a valid variant:
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::types::AnyTypeEnum;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let wrapped_type = AnyTypeEnum::from(i8_type);
/// let result = wrapped_type.array_type(5);
///
/// // `AnyTypeEnum::IntType` can be used to create an array type.
/// assert!(result.is_ok());
/// let array_type = result.unwrap();
/// ```
///
/// Using an invalid variant:
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::types::AnyTypeEnum;
///
/// let context = Context::create();
/// let void_type = context.void_type();
/// let wrapped_type = AnyTypeEnum::from(void_type);
/// let result = wrapped_type.array_type(5);
///
/// // `AnyTypeEnum::VoidType` cannot be used to create an array type.
/// assert!(result.is_err());
/// ```
pub fn array_type(self, size: u32) -> Result<ArrayType<'ctx>, InvalidVariant> {
match self {
AnyTypeEnum::ArrayType(inner) => Ok(inner.array_type(size)),
AnyTypeEnum::FloatType(inner) => Ok(inner.array_type(size)),
AnyTypeEnum::IntType(inner) => Ok(inner.array_type(size)),
AnyTypeEnum::PointerType(inner) => Ok(inner.array_type(size)),
AnyTypeEnum::StructType(inner) => Ok(inner.array_type(size)),
AnyTypeEnum::VectorType(inner) => Ok(inner.array_type(size)),
AnyTypeEnum::ScalableVectorType(inner) => Ok(inner.array_type(size)),
AnyTypeEnum::VoidType(_) | AnyTypeEnum::FunctionType(_) => Err(InvalidVariant::ArrayType),
}
}
}
Loading