Skip to content

Commit a20c94b

Browse files
committed
Update lazy-static to use Span::resolved_at
1 parent 7df3eba commit a20c94b

File tree

1 file changed

+49
-7
lines changed
  • examples/lazy-static/lazy-static/src

1 file changed

+49
-7
lines changed

examples/lazy-static/lazy-static/src/lib.rs

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ extern crate syn;
66
#[macro_use]
77
extern crate quote;
88
extern crate proc_macro;
9+
extern crate proc_macro2;
910

1011
use syn::{Visibility, Ident, Type, Expr};
1112
use syn::synom::Synom;
1213
use syn::spanned::Spanned;
1314
use proc_macro::TokenStream;
15+
use proc_macro2::Span;
1416

1517
/// Parses the following syntax, which aligns with the input of the real
1618
/// `lazy_static` crate.
@@ -49,13 +51,28 @@ impl Synom for LazyStatic {
4951
#[proc_macro]
5052
pub fn lazy_static(input: TokenStream) -> TokenStream {
5153
let LazyStatic { visibility, name, ty, init } = syn::parse(input).unwrap();
54+
let def_site = Span::def_site();
5255

56+
// The warning looks like this.
57+
//
58+
// warning: come on, pick a more creative name
59+
// --> src/main.rs:10:16
60+
// |
61+
// 10 | static ref FOO: String = "lazy_static".to_owned();
62+
// | ^^^
5363
if name == "FOO" {
5464
name.span().unstable()
5565
.warning("come on, pick a more creative name")
5666
.emit();
5767
}
5868

69+
// The error looks like this.
70+
//
71+
// error: I can't think of a legitimate use for lazily initializing the value `()`
72+
// --> src/main.rs:10:27
73+
// |
74+
// 10 | static ref UNIT: () = ();
75+
// | ^^
5976
if let Expr::Tuple(ref init) = init {
6077
if init.elems.is_empty() {
6178
init.span().unstable()
@@ -65,14 +82,38 @@ pub fn lazy_static(input: TokenStream) -> TokenStream {
6582
}
6683
}
6784

68-
// FIXME: ty.span().resolved_at(def_site)
69-
let ty_span = ty.span();
85+
// Assert that the static type implements Sync. If not, user sees an error
86+
// message like the following. We span this assertion with the field type's
87+
// line/column so that the error message appears in the correct place, but
88+
// resolve it at the def site so that we are guaranteed it is checking the
89+
// correct Sync. If the `Sync` token were resolved at the call site, the
90+
// user could circumvent the check by defining their own Sync trait that is
91+
// implemented for their type.
92+
//
93+
// error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied
94+
// --> src/main.rs:10:21
95+
// |
96+
// 10 | static ref PTR: *const () = &();
97+
// | ^^^^^^^^^ `*const ()` cannot be shared between threads safely
98+
let ty_span = ty.span().resolved_at(def_site);
7099
let assert_sync = quote_spanned! {ty_span,
71-
struct _Assert where #ty: Sync;
100+
struct _AssertSync where #ty: Sync;
72101
};
73102

74-
// FIXME: init.span().resolved_at(def_site)
75-
let init_span = init.span();
103+
// Check for Sized. Not vital to check here, but the error message is less
104+
// confusing this way than if they get a Sized error in one of our
105+
// implementation details where it assumes Sized.
106+
//
107+
// error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
108+
// --> src/main.rs:10:19
109+
// |
110+
// 10 | static ref A: str = "";
111+
// | ^^^ `str` does not have a constant size known at compile-time
112+
let assert_sized = quote_spanned! {ty_span,
113+
struct _AssertSized where #ty: Sized;
114+
};
115+
116+
let init_span = init.span().resolved_at(def_site);
76117
let init_ptr = quote_spanned! {init_span,
77118
Box::into_raw(Box::new(#init))
78119
};
@@ -87,9 +128,10 @@ pub fn lazy_static(input: TokenStream) -> TokenStream {
87128

88129
fn deref(&self) -> &#ty {
89130
#assert_sync
131+
#assert_sized
90132

91133
static ONCE: std::sync::Once = std::sync::ONCE_INIT;
92-
static mut VALUE: *const #ty = 0 as *const #ty;
134+
static mut VALUE: *mut #ty = 0 as *mut #ty;
93135

94136
unsafe {
95137
ONCE.call_once(|| VALUE = #init_ptr);
@@ -98,6 +140,6 @@ pub fn lazy_static(input: TokenStream) -> TokenStream {
98140
}
99141
}
100142
};
101-
143+
102144
expanded.into()
103145
}

0 commit comments

Comments
 (0)