externref/processor/
error.rs1use std::{error, fmt};
4
5use crate::ReadError;
6
7#[derive(Debug)]
9pub enum Location {
10 Arg(usize),
12 ReturnType(usize),
14}
15
16impl fmt::Display for Location {
17 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
18 match self {
19 Self::Arg(idx) => write!(formatter, "arg #{idx}"),
20 Self::ReturnType(idx) => write!(formatter, "return type #{idx}"),
21 }
22 }
23}
24
25#[derive(Debug)]
29#[non_exhaustive]
30pub enum Error {
31 Read(ReadError),
33 Wasm(anyhow::Error),
35
36 UnexpectedImportType {
38 module: String,
40 name: String,
42 },
43 NoExport(String),
45 UnexpectedExportType(String),
47 UnexpectedArity {
49 module: Option<String>,
51 name: String,
53 expected_arity: usize,
55 real_arity: usize,
57 },
58 UnexpectedType {
60 module: Option<String>,
62 name: String,
64 location: Location,
66 real_type: walrus::ValType,
68 },
69
70 IncorrectGuard {
73 function_name: Option<String>,
75 code_offset: Option<u32>,
77 },
78 UnexpectedCall {
82 function_name: Option<String>,
84 code_offset: Option<u32>,
86 },
87}
88
89impl fmt::Display for Error {
90 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
91 const EXTERNAL_TOOL_TIP: &str = "This can be caused by an external WASM manipulation tool \
92 such as `wasm-opt`. Please run such tools *after* the externref processor.";
93
94 match self {
95 Self::Read(err) => write!(formatter, "failed reading WASM custom section: {err}"),
96 Self::Wasm(err) => write!(formatter, "failed reading WASM module: {err}"),
97
98 Self::UnexpectedImportType { module, name } => {
99 write!(
100 formatter,
101 "unexpected type of import `{module}::{name}`; expected a function"
102 )
103 }
104
105 Self::NoExport(name) => {
106 write!(formatter, "missing exported function `{name}`")
107 }
108 Self::UnexpectedExportType(name) => {
109 write!(
110 formatter,
111 "unexpected type of export `{name}`; expected a function"
112 )
113 }
114
115 Self::UnexpectedArity {
116 module,
117 name,
118 expected_arity,
119 real_arity,
120 } => {
121 let module_descr = module
122 .as_ref()
123 .map_or_else(String::new, |module| format!(" imported from `{module}`"));
124 write!(
125 formatter,
126 "unexpected arity for function `{name}`{module_descr}: \
127 expected {expected_arity}, got {real_arity}"
128 )
129 }
130 Self::UnexpectedType {
131 module,
132 name,
133 location,
134 real_type,
135 } => {
136 let module_descr = module
137 .as_ref()
138 .map_or_else(String::new, |module| format!(" imported from `{module}`"));
139 write!(
140 formatter,
141 "{location} of function `{name}`{module_descr} has unexpected type; \
142 expected `i32`, got {real_type}"
143 )
144 }
145
146 Self::IncorrectGuard {
147 function_name,
148 code_offset,
149 } => {
150 let function_name = function_name
151 .as_ref()
152 .map_or("(unnamed function)", String::as_str);
153 let code_offset = code_offset
154 .as_ref()
155 .map_or_else(String::new, |offset| format!(" at {offset}"));
156 write!(
157 formatter,
158 "incorrectly placed externref guard in {function_name}{code_offset}. \
159 {EXTERNAL_TOOL_TIP}"
160 )
161 }
162 Self::UnexpectedCall {
163 function_name,
164 code_offset,
165 } => {
166 let function_name = function_name
167 .as_ref()
168 .map_or("(unnamed function)", String::as_str);
169 let code_offset = code_offset
170 .as_ref()
171 .map_or_else(String::new, |offset| format!(" at {offset}"));
172 write!(
173 formatter,
174 "unexpected call to an `externref`-returning function \
175 in {function_name}{code_offset}. {EXTERNAL_TOOL_TIP}"
176 )
177 }
178 }
179 }
180}
181
182impl From<ReadError> for Error {
183 fn from(err: ReadError) -> Self {
184 Self::Read(err)
185 }
186}
187
188impl error::Error for Error {
189 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
190 match self {
191 Self::Read(err) => Some(err),
192 Self::Wasm(err) => Some(err.as_ref()),
193 _ => None,
194 }
195 }
196}