diff --git a/impl/src/declaration.rs b/impl/src/declaration.rs index 0e88e83..6d9ac1e 100644 --- a/impl/src/declaration.rs +++ b/impl/src/declaration.rs @@ -1,11 +1,8 @@ -use crate::{attr, linker}; +use crate::{attr, linker, ty}; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::parse::{Parse, ParseStream, Result}; -use syn::{ - bracketed, Attribute, Error, GenericArgument, Ident, Lifetime, PathArguments, Token, Type, - Visibility, -}; +use syn::{bracketed, Attribute, Error, Ident, Token, Type, Visibility}; struct Declaration { attrs: Vec, @@ -69,7 +66,7 @@ pub fn expand(input: TokenStream) -> TokenStream { Err(err) => return err.to_compile_error(), }; - populate_static_lifetimes(&mut ty); + ty::populate_static_lifetimes(&mut ty); let used = if cfg!(feature = "used_linker") { quote!(#[used(linker)]) @@ -266,44 +263,3 @@ pub fn expand(input: TokenStream) -> TokenStream { #vis use #link_section_macro as #ident; } } - -fn populate_static_lifetimes(ty: &mut Type) { - match ty { - #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] - Type::Array(ty) => populate_static_lifetimes(&mut ty.elem), - Type::Group(ty) => populate_static_lifetimes(&mut ty.elem), - Type::Paren(ty) => populate_static_lifetimes(&mut ty.elem), - Type::Path(ty) => { - if let Some(qself) = &mut ty.qself { - populate_static_lifetimes(&mut qself.ty); - } - for segment in &mut ty.path.segments { - if let PathArguments::AngleBracketed(segment) = &mut segment.arguments { - for arg in &mut segment.args { - if let GenericArgument::Type(arg) = arg { - populate_static_lifetimes(arg); - } - } - } - } - } - Type::Ptr(ty) => populate_static_lifetimes(&mut ty.elem), - Type::Reference(ty) => { - if ty.lifetime.is_none() { - ty.lifetime = Some(Lifetime::new("'static", ty.and_token.span)); - } - populate_static_lifetimes(&mut ty.elem); - } - Type::Slice(ty) => populate_static_lifetimes(&mut ty.elem), - Type::Tuple(ty) => ty.elems.iter_mut().for_each(populate_static_lifetimes), - Type::ImplTrait(_) - | Type::Infer(_) - | Type::Macro(_) - | Type::Never(_) - | Type::TraitObject(_) - | Type::BareFn(_) - | Type::Verbatim(_) => {} - - _ => unimplemented!("unknown Type"), - } -} diff --git a/impl/src/element.rs b/impl/src/element.rs index 331213a..b464b67 100644 --- a/impl/src/element.rs +++ b/impl/src/element.rs @@ -1,4 +1,4 @@ -use crate::attr; +use crate::{attr, ty}; use proc_macro2::{Span, TokenStream, TokenTree}; use quote::{format_ident, quote, quote_spanned}; use syn::parse::{Error, Parse, ParseStream, Result}; @@ -204,10 +204,12 @@ fn do_expand(path: Path, pos: Option, input: Element) -> TokenStream { let mut attrs = input.attrs; let vis = input.vis; let ident = input.ident; - let ty = input.ty; + let mut ty = input.ty; let expr = input.expr; let orig_item = input.orig_item; + ty::populate_static_lifetimes(&mut ty); + let linkme_path = match attr::linkme_path(&mut attrs) { Ok(path) => path, Err(err) => return err.to_compile_error(), @@ -215,8 +217,8 @@ fn do_expand(path: Path, pos: Option, input: Element) -> TokenStream { let sort_key = pos.into_iter().map(|pos| format!("{:04}", pos)); - let new = quote_spanned!(input.start_span=> __new); - let uninit = quote_spanned!(input.end_span=> #new()); + let factory = quote_spanned!(input.start_span=> __new); + let get = quote_spanned!(input.end_span=> #factory()); quote! { #path ! { @@ -228,9 +230,9 @@ fn do_expand(path: Path, pos: Option, input: Element) -> TokenStream { #vis static #ident : #ty = { #[allow(clippy::no_effect_underscore_binding)] unsafe fn __typecheck(_: #linkme_path::__private::Void) { - let #new = || (|| &#ident) as fn() -> _; + let #factory = || -> fn() -> &'static #ty { || &#ident }; unsafe { - #linkme_path::DistributedSlice::private_typecheck(#path, #uninit); + #linkme_path::DistributedSlice::private_typecheck(#path, #get); } } diff --git a/impl/src/lib.rs b/impl/src/lib.rs index d08aba8..2b300c0 100644 --- a/impl/src/lib.rs +++ b/impl/src/lib.rs @@ -12,6 +12,7 @@ mod declaration; mod element; mod hash; mod linker; +mod ty; use crate::args::Args; use crate::hash::hash; diff --git a/impl/src/ty.rs b/impl/src/ty.rs new file mode 100644 index 0000000..60bd30a --- /dev/null +++ b/impl/src/ty.rs @@ -0,0 +1,42 @@ +use syn::{GenericArgument, Lifetime, PathArguments, Type}; + +pub(crate) fn populate_static_lifetimes(ty: &mut Type) { + match ty { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] + Type::Array(ty) => populate_static_lifetimes(&mut ty.elem), + Type::Group(ty) => populate_static_lifetimes(&mut ty.elem), + Type::Paren(ty) => populate_static_lifetimes(&mut ty.elem), + Type::Path(ty) => { + if let Some(qself) = &mut ty.qself { + populate_static_lifetimes(&mut qself.ty); + } + for segment in &mut ty.path.segments { + if let PathArguments::AngleBracketed(segment) = &mut segment.arguments { + for arg in &mut segment.args { + if let GenericArgument::Type(arg) = arg { + populate_static_lifetimes(arg); + } + } + } + } + } + Type::Ptr(ty) => populate_static_lifetimes(&mut ty.elem), + Type::Reference(ty) => { + if ty.lifetime.is_none() { + ty.lifetime = Some(Lifetime::new("'static", ty.and_token.span)); + } + populate_static_lifetimes(&mut ty.elem); + } + Type::Slice(ty) => populate_static_lifetimes(&mut ty.elem), + Type::Tuple(ty) => ty.elems.iter_mut().for_each(populate_static_lifetimes), + Type::ImplTrait(_) + | Type::Infer(_) + | Type::Macro(_) + | Type::Never(_) + | Type::TraitObject(_) + | Type::BareFn(_) + | Type::Verbatim(_) => {} + + _ => unimplemented!("unknown Type"), + } +} diff --git a/src/private.rs b/src/private.rs index 93140aa..f9f859b 100644 --- a/src/private.rs +++ b/src/private.rs @@ -18,8 +18,3 @@ impl Slice for [T] { #[doc(hidden)] pub enum Void {} - -#[doc(hidden)] -pub fn value() -> T { - panic!() -} diff --git a/tests/ui/attempted_coercion.stderr b/tests/ui/attempted_coercion.stderr index 79ff62b..eee2a63 100644 --- a/tests/ui/attempted_coercion.stderr +++ b/tests/ui/attempted_coercion.stderr @@ -4,10 +4,10 @@ error[E0308]: mismatched types 8 | #[distributed_slice(SLICE)] | --------------------------- arguments to this function are incorrect 9 | static ELEMENT: &&str = &"uhoh"; - | ^^^^^ expected `str`, found `&str` + | ^^^^^ expected `str`, found `&'static str` | = note: expected fn pointer `fn() -> &'static &'static _` - found fn pointer `fn() -> &&&_` + found fn pointer `fn() -> &'static &'static &'static _` note: method defined here --> src/distributed_slice.rs | diff --git a/tests/ui/mismatched_types.stderr b/tests/ui/mismatched_types.stderr index b888c97..3ce2fb0 100644 --- a/tests/ui/mismatched_types.stderr +++ b/tests/ui/mismatched_types.stderr @@ -7,7 +7,7 @@ error[E0308]: mismatched types | ^^^^^ expected fn pointer, found `usize` | = note: expected fn pointer `fn() -> &'static for<'a> fn(&'a mut Bencher)` - found fn pointer `fn() -> &usize` + found fn pointer `fn() -> &'static usize` note: method defined here --> src/distributed_slice.rs | @@ -23,7 +23,7 @@ error[E0308]: mismatched types | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Bencher`, found `()` | = note: expected fn pointer `fn() -> &'static for<'a> fn(&'a mut Bencher)` - found fn pointer `fn() -> &for<'a> fn(&'a mut ())` + found fn pointer `fn() -> &'static for<'a> fn(&'a mut ())` note: method defined here --> src/distributed_slice.rs |