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

#[derive(thiserror::Error, Debug)]
#[error("The variant `AnyTypeEnum::{}` cannot be used with `{}()`!", self.variant, self.function)]
pub struct InvalidVariant {
// TODO: Shorten lifetime?

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.

(Wasn't sure how else to display the variant and function name; If there's a better way let me know)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You should add a lifetime generic, that's more flexible.

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.

I'll get on this once I'm home

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oh, wait, what is this? Is this an error message? Why is it implemented with strings? This could very well be an enum.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also, this error type would clash with inkwell's internal error types. It would make working with errors unwieldy if users have to switch between incompatible error types.

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.

Oh, wait, what is this? Is this an error message? Why is it implemented with strings? This could very well be an enum.

Yeah admittedly I was probably a bit too tired for implementing this yesterday. I'll try to fix it up now

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.

Now uses enumeration variant, but if there's a different way to implement the error type then lmk

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The error type I was referring to is in src/error.rs

@ErisianArchitect ErisianArchitect Jun 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry, I typed the last comment on my phone and didn't feel like being detailed.

It would be a good idea to add your new error type to the main error in src/error.rs.

pub enum Error {

You can add a new error variant to it that implements #[from] for your error type. This will enable users to use the ? operator on your error type and it will be recognized by inkwell's top-level error type.

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.

As per the other comments I have below: this is causing issues related to lifetimes; need to find the best way to fix

variant: &'static str,
function: &'static str,
}

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 {
variant: "FunctionType",
function: "fn_type",
}),
}
}

/// 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(_) => Err(InvalidVariant {
variant: "VoidType",
function: "array_type",
}),
AnyTypeEnum::FunctionType(_) => Err(InvalidVariant {
variant: "FunctionType",
function: "array_type",
}),
}
}
}