Skip to content

Commit 38c05b8

Browse files
committed
mlua_derive: Improve error reporting for #[lua] attributes
1 parent 8d1841f commit 38c05b8

6 files changed

Lines changed: 30 additions & 22 deletions

File tree

mlua_derive/src/userdata/attr.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use proc_macro2::Span;
12
use syn::meta::ParseNestedMeta;
23
use syn::{Ident, LitStr, Result};
34

@@ -8,6 +9,7 @@ use syn::{Ident, LitStr, Result};
89
/// - Impl methods: `getter`, `setter`, `field`, `meta`, `infallible`, `name`, `skip`
910
#[derive(Default)]
1011
pub(crate) struct LuaAttr {
12+
pub(crate) span: Option<Span>,
1113
pub(crate) name: Option<String>,
1214
pub(crate) infallible: bool,
1315
pub(crate) skip: bool,
@@ -64,6 +66,11 @@ impl LuaAttr {
6466
self.name.clone().unwrap_or_else(|| ident.to_string())
6567
}
6668

69+
/// Returns the span to use for error reporting.
70+
pub(crate) fn span(&self) -> Span {
71+
self.span.unwrap_or_else(Span::call_site)
72+
}
73+
6774
/// Returns the effective Lua metamethod name.
6875
///
6976
/// If `name` is set via attribute, use it. Otherwise, if the function name

mlua_derive/src/userdata/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ mod attr;
22
pub(crate) mod userdata_impl;
33

44
use proc_macro::TokenStream;
5-
use proc_macro2::Span;
65
use quote::{format_ident, quote};
76
use syn::spanned::Spanned;
87
use syn::{Attribute, Data, DeriveInput, Error, Fields, FieldsNamed, Meta, parse_macro_input};
@@ -32,8 +31,9 @@ fn parse_field_lua_attr(attrs: &[Attribute]) -> syn::Result<LuaAttr> {
3231
}
3332
match &attr.meta {
3433
Meta::List(_) => {
34+
lua_attr.span = Some(attr.span());
3535
attr.parse_nested_meta(|meta| lua_attr.parse_inner(meta))?;
36-
validate_field_lua_attr(&lua_attr, attr.span())?;
36+
validate_field_lua_attr(&lua_attr)?;
3737
}
3838
Meta::Path(_) => {}
3939
Meta::NameValue(_) => {
@@ -47,7 +47,7 @@ fn parse_field_lua_attr(attrs: &[Attribute]) -> syn::Result<LuaAttr> {
4747
Ok(lua_attr)
4848
}
4949

50-
fn validate_field_lua_attr(attr: &LuaAttr, span: Span) -> syn::Result<()> {
50+
fn validate_field_lua_attr(attr: &LuaAttr) -> syn::Result<()> {
5151
for (set, name) in [
5252
(attr.getter, "getter"),
5353
(attr.setter, "setter"),
@@ -57,7 +57,7 @@ fn validate_field_lua_attr(attr: &LuaAttr, span: Span) -> syn::Result<()> {
5757
] {
5858
if set {
5959
return Err(syn::Error::new(
60-
span,
60+
attr.span(),
6161
format!("`{name}` is not valid for struct fields"),
6262
));
6363
}

mlua_derive/src/userdata/userdata_impl.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::sync::atomic::{AtomicUsize, Ordering};
22

33
use proc_macro::TokenStream;
4-
use proc_macro2::{Span, TokenStream as TokenStream2};
4+
use proc_macro2::TokenStream as TokenStream2;
55
use quote::{format_ident, quote};
66
use syn::spanned::Spanned;
77
use syn::{
@@ -183,8 +183,9 @@ fn parse_lua_attr(attrs: &[Attribute]) -> syn::Result<LuaAttr> {
183183
}
184184
match &attr.meta {
185185
Meta::List(_) => {
186+
lua_attr.span = Some(attr.span());
186187
attr.parse_nested_meta(|meta| lua_attr.parse_inner(meta))?;
187-
validate_lua_attr(&lua_attr, attr.span())?;
188+
validate_lua_attr(&lua_attr)?;
188189
}
189190
Meta::Path(_) => {}
190191
Meta::NameValue(_) => {
@@ -198,11 +199,11 @@ fn parse_lua_attr(attrs: &[Attribute]) -> syn::Result<LuaAttr> {
198199
Ok(lua_attr)
199200
}
200201

201-
fn validate_lua_attr(attr: &LuaAttr, span: Span) -> syn::Result<()> {
202+
fn validate_lua_attr(attr: &LuaAttr) -> syn::Result<()> {
202203
for (set, name) in [(attr.get, "get"), (attr.set, "set")] {
203204
if set {
204205
return Err(syn::Error::new(
205-
span,
206+
attr.span(),
206207
format!("`{name}` is not valid for methods"),
207208
));
208209
}
@@ -250,8 +251,8 @@ pub fn userdata_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
250251
continue;
251252
}
252253
if lua_attr.getter || lua_attr.setter {
253-
return syn::Error::new_spanned(
254-
&const_item.ident,
254+
return syn::Error::new(
255+
lua_attr.span(),
255256
"const items do not support `getter` or `setter`",
256257
)
257258
.to_compile_error()
@@ -285,15 +286,15 @@ pub fn userdata_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
285286
let primary = [lua_attr.getter, lua_attr.setter, lua_attr.field];
286287
let primary_count = primary.iter().filter(|&&x| x).count();
287288
if primary_count > 1 {
288-
return syn::Error::new_spanned(
289-
&method.sig,
289+
return syn::Error::new(
290+
lua_attr.span(),
290291
"at most one of `getter`, `setter`, `field` can be specified",
291292
)
292293
.to_compile_error()
293294
.into();
294295
}
295296
if lua_attr.meta && primary_count == 1 && !lua_attr.field {
296-
return syn::Error::new_spanned(&method.sig, "`meta` can only be combined with `field`")
297+
return syn::Error::new(lua_attr.span(), "`meta` can only be combined with `field`")
297298
.to_compile_error()
298299
.into();
299300
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: const items do not support `getter` or `setter`
2-
--> tests/compile/userdata_const_getter.rs:7:11
2+
--> tests/compile/userdata_const_getter.rs:6:5
33
|
4-
7 | const X: u32 = 42;
5-
| ^
4+
6 | #[lua(getter)]
5+
| ^^^^^^^^^^^^^^
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: `meta` can only be combined with `field`
2-
--> tests/compile/userdata_getter_and_meta.rs:7:5
2+
--> tests/compile/userdata_getter_and_meta.rs:6:5
33
|
4-
7 | fn bar(&self) -> mlua::Result<u32> {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
6 | #[lua(getter, meta)]
5+
| ^^^^^^^^^^^^^^^^^^^^
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: at most one of `getter`, `setter`, `field` can be specified
2-
--> tests/compile/userdata_getter_and_setter.rs:9:5
2+
--> tests/compile/userdata_getter_and_setter.rs:8:5
33
|
4-
9 | fn x(&self) -> mlua::Result<u32> {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
8 | #[lua(getter, setter)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)