diff options
Diffstat (limited to 'syn/examples/lazy-static')
-rw-r--r-- | syn/examples/lazy-static/Cargo.toml | 2 | ||||
-rw-r--r-- | syn/examples/lazy-static/README.md | 42 | ||||
-rw-r--r-- | syn/examples/lazy-static/example/Cargo.toml | 10 | ||||
-rw-r--r-- | syn/examples/lazy-static/example/src/main.rs | 20 | ||||
-rw-r--r-- | syn/examples/lazy-static/lazy-static/Cargo.toml | 14 | ||||
-rw-r--r-- | syn/examples/lazy-static/lazy-static/src/lib.rs | 143 |
6 files changed, 0 insertions, 231 deletions
diff --git a/syn/examples/lazy-static/Cargo.toml b/syn/examples/lazy-static/Cargo.toml deleted file mode 100644 index 586e547..0000000 --- a/syn/examples/lazy-static/Cargo.toml +++ /dev/null @@ -1,2 +0,0 @@ -[workspace] -members = ["example", "lazy-static"] diff --git a/syn/examples/lazy-static/README.md b/syn/examples/lazy-static/README.md deleted file mode 100644 index bc64585..0000000 --- a/syn/examples/lazy-static/README.md +++ /dev/null @@ -1,42 +0,0 @@ -An example of parsing a custom syntax within a `functionlike!(...)` procedural -macro. Demonstrates how to trigger custom warnings and error messages on -individual tokens of the input. - -- [`lazy-static/src/lib.rs`](lazy-static/src/lib.rs) -- [`example/src/main.rs`](example/src/main.rs) - -The library implements a `lazy_static!` macro similar to the one from the real -[`lazy_static`](https://docs.rs/lazy_static/1.0.0/lazy_static/) crate on -crates.io. - -```rust -lazy_static! { - static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap(); -} -``` - -Compile and run the example by doing `cargo run` in the directory of the -`example` crate. - -The implementation shows how to trigger custom warnings and error messages on -the macro input. For example if you try adding an uncreatively named `FOO` lazy -static, the macro will scold you with the following warning. - -``` -warning: come on, pick a more creative name - --> src/main.rs:10:16 - | -10 | static ref FOO: String = "lazy_static".to_owned(); - | ^^^ -``` - -And if you try to lazily initialize `() = ()`, the macro will outright refuse to -compile it for you. - -``` -error: I can't think of a legitimate use for lazily initializing the value `()` - --> src/main.rs:10:27 - | -10 | static ref UNIT: () = (); - | ^^ -``` diff --git a/syn/examples/lazy-static/example/Cargo.toml b/syn/examples/lazy-static/example/Cargo.toml deleted file mode 100644 index 716b08c..0000000 --- a/syn/examples/lazy-static/example/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "example" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[dependencies] -lazy_static = { path = "../lazy-static" } -regex = "0.2" diff --git a/syn/examples/lazy-static/example/src/main.rs b/syn/examples/lazy-static/example/src/main.rs deleted file mode 100644 index c4f64af..0000000 --- a/syn/examples/lazy-static/example/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use lazy_static::lazy_static; -use regex::Regex; - -lazy_static! { - static ref USERNAME: Regex = { - println!("Compiling username regex..."); - Regex::new("^[a-z0-9_-]{3,16}$").unwrap() - }; -} - -fn main() { - println!("Let's validate some usernames."); - validate("fergie"); - validate("will.i.am"); -} - -fn validate(name: &str) { - // The USERNAME regex is compiled lazily the first time its value is accessed. - println!("is_match({:?}): {}", name, USERNAME.is_match(name)); -} diff --git a/syn/examples/lazy-static/lazy-static/Cargo.toml b/syn/examples/lazy-static/lazy-static/Cargo.toml deleted file mode 100644 index bf65787..0000000 --- a/syn/examples/lazy-static/lazy-static/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "lazy_static" -version = "0.0.0" -authors = ["David Tolnay <dtolnay@gmail.com>"] -edition = "2018" -publish = false - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = { version = "1.0", features = ["nightly"] } -quote = "1.0" -syn = { path = "../../../", features = ["full"] } diff --git a/syn/examples/lazy-static/lazy-static/src/lib.rs b/syn/examples/lazy-static/lazy-static/src/lib.rs deleted file mode 100644 index 254ca72..0000000 --- a/syn/examples/lazy-static/lazy-static/src/lib.rs +++ /dev/null @@ -1,143 +0,0 @@ -#![recursion_limit = "128"] -#![feature(proc_macro_diagnostic)] - -extern crate proc_macro; -use self::proc_macro::TokenStream; - -use quote::{quote, quote_spanned}; -use syn::parse::{Parse, ParseStream, Result}; -use syn::spanned::Spanned; -use syn::{parse_macro_input, Expr, Ident, Token, Type, Visibility}; - -/// Parses the following syntax, which aligns with the input of the real -/// `lazy_static` crate. -/// -/// lazy_static! { -/// $VISIBILITY static ref $NAME: $TYPE = $EXPR; -/// } -/// -/// For example: -/// -/// lazy_static! { -/// static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap(); -/// } -struct LazyStatic { - visibility: Visibility, - name: Ident, - ty: Type, - init: Expr, -} - -impl Parse for LazyStatic { - fn parse(input: ParseStream) -> Result<Self> { - let visibility: Visibility = input.parse()?; - input.parse::<Token![static]>()?; - input.parse::<Token![ref]>()?; - let name: Ident = input.parse()?; - input.parse::<Token![:]>()?; - let ty: Type = input.parse()?; - input.parse::<Token![=]>()?; - let init: Expr = input.parse()?; - input.parse::<Token![;]>()?; - Ok(LazyStatic { - visibility, - name, - ty, - init, - }) - } -} - -#[proc_macro] -pub fn lazy_static(input: TokenStream) -> TokenStream { - let LazyStatic { - visibility, - name, - ty, - init, - } = parse_macro_input!(input as LazyStatic); - - // The warning looks like this. - // - // warning: come on, pick a more creative name - // --> src/main.rs:10:16 - // | - // 10 | static ref FOO: String = "lazy_static".to_owned(); - // | ^^^ - if name == "FOO" { - name.span() - .unwrap() - .warning("come on, pick a more creative name") - .emit(); - } - - // The error looks like this. - // - // error: I can't think of a legitimate use for lazily initializing the value `()` - // --> src/main.rs:10:27 - // | - // 10 | static ref UNIT: () = (); - // | ^^ - if let Expr::Tuple(ref init) = init { - if init.elems.is_empty() { - init.span() - .unwrap() - .error("I can't think of a legitimate use for lazily initializing the value `()`") - .emit(); - return TokenStream::new(); - } - } - - // Assert that the static type implements Sync. If not, user sees an error - // message like the following. We span this assertion with the field type's - // line/column so that the error message appears in the correct place. - // - // error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied - // --> src/main.rs:10:21 - // | - // 10 | static ref PTR: *const () = &(); - // | ^^^^^^^^^ `*const ()` cannot be shared between threads safely - let assert_sync = quote_spanned! {ty.span()=> - struct _AssertSync where #ty: std::marker::Sync; - }; - - // Check for Sized. Not vital to check here, but the error message is less - // confusing this way than if they get a Sized error in one of our - // implementation details where it assumes Sized. - // - // error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied - // --> src/main.rs:10:19 - // | - // 10 | static ref A: str = ""; - // | ^^^ `str` does not have a constant size known at compile-time - let assert_sized = quote_spanned! {ty.span()=> - struct _AssertSized where #ty: std::marker::Sized; - }; - - let init_ptr = quote_spanned! {init.span()=> - Box::into_raw(Box::new(#init)) - }; - - let expanded = quote! { - #visibility struct #name; - - impl std::ops::Deref for #name { - type Target = #ty; - - fn deref(&self) -> &#ty { - #assert_sync - #assert_sized - - static ONCE: std::sync::Once = std::sync::Once::new(); - static mut VALUE: *mut #ty = 0 as *mut #ty; - - unsafe { - ONCE.call_once(|| VALUE = #init_ptr); - &*VALUE - } - } - } - }; - - TokenStream::from(expanded) -} |