#[derive(Debug)]
pub enum UnfoldError {
UnknownFunction(syn::Ident),
UnknownAccessor(syn::Ident),
NoDeconstructor {
func: syn::Ident,
target: String,
},
AccessorTargetMismatch {
accessor: String,
takes: String,
expected: String,
},
MultipleIdentity {
target: String,
},
Cycle {
target: String,
},
ConvertNotSingle {
func: syn::Ident,
reason: &'static str,
},
RecordNotAccessor {
func: syn::Ident,
},
Unsupported {
func: syn::Ident,
reason: &'static str,
},
DuplicateLeafName {
target: String,
name: String,
},
ReservedSeparator {
name: String,
},
RootIdentityBeforeNested {
target: String,
},
ReturnTypeMismatch {
func: syn::Ident,
declared: String,
actual: String,
},
InvalidDeclarations {
entries: Vec<UnfoldDeclError>,
},
}
#[derive(Debug)]
pub enum UnfoldDeclError {
DuplicateDeconstructor { target: String },
DuplicateOutput {
func: syn::Ident,
target: super::DeconTarget,
},
}
impl std::fmt::Display for UnfoldDeclError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnfoldDeclError::DuplicateDeconstructor { target } => {
write!(f, "duplicate deconstructor declaration for `{target}`")
}
UnfoldDeclError::DuplicateOutput { func, target } => write!(
f,
"duplicate output expansion for `{func}` ({target:?} position)"
),
}
}
}
impl std::fmt::Display for UnfoldError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnfoldError::UnknownFunction(name) => write!(
f,
"output expansion: function `{}` is not a #[prebindgen] item",
name
),
UnfoldError::UnknownAccessor(name) => write!(
f,
"output expansion: accessor `{}` is not a #[prebindgen] item",
name
),
UnfoldError::ReturnTypeMismatch {
func,
declared,
actual,
} => write!(
f,
"output expansion: `{}`.expand_return(expand_return!({declared})): the \
function's return type is `{actual}`, not `{declared}` — declare the decl \
for the actual return type",
func
),
UnfoldError::NoDeconstructor { func, target } => write!(
f,
"output expansion: no deconstructor registered for `{}` (return of `{}`)",
target, func
),
UnfoldError::AccessorTargetMismatch {
accessor,
takes,
expected,
} => write!(
f,
"output expansion: accessor `{}` takes `{}` but the deconstructor decomposes `{}`",
accessor, takes, expected
),
UnfoldError::MultipleIdentity { target } => write!(
f,
"output expansion: deconstructor for `{}` has more than one identity record",
target
),
UnfoldError::Cycle { target } => write!(
f,
"output expansion: nested deconstructors form a cycle through `{}`",
target
),
UnfoldError::ConvertNotSingle { func, reason } => write!(
f,
"convert_output: `{}` is not a single-value deconstructor: {}",
func, reason
),
UnfoldError::RecordNotAccessor { func } => write!(
f,
"deconstructor record `{}` is not a `.fun_accessor` — decomposer records may only \
reference functions declared via `.fun_accessor(...)`",
func
),
UnfoldError::Unsupported { func, reason } => write!(
f,
"output expansion: `{}` not yet supported: {}",
func, reason
),
UnfoldError::DuplicateLeafName { target, name } => write!(
f,
"deconstructor for `{}` has two output records named `{}` — leaf names must be \
unique (they are emitted literally)",
target, name
),
UnfoldError::ReservedSeparator { name } => write!(
f,
"output record name `{}` contains the reserved `__` separator (used to join \
nested deconstructor segments)",
name
),
UnfoldError::RootIdentityBeforeNested { target } => write!(
f,
"return-field list of `{}`: `.field_self()` (the root identity) must be \
declared AFTER fields that splice a nested identity — the root identity moves the owned \
value while nested identities borrow it, so this order would generate \
non-compiling Rust. Declare the `_self` field last.",
target
),
UnfoldError::InvalidDeclarations { entries } => {
writeln!(f, "output expansion: invalid declarations:")?;
for e in entries {
writeln!(f, " - {e}")?;
}
Ok(())
}
}
}
}
impl std::error::Error for UnfoldError {}