Skip to content

📝 update dependencies #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.2.2"
authors = ["CodeChain Team <hi@codechain.io>"]
license = "MIT OR Apache-2.0"
description = "Allow for inter-trait casting"
edition = "2018"
edition = "2021"
repository = "https://github.com/CodeChain-io/intertrait"
documentation = "https://docs.rs/intertrait"
readme = "README.md"
Expand All @@ -14,7 +14,7 @@ include = ["src/**/*", "Cargo.toml", "LICENSE-*", "README.md"]

[dependencies]
once_cell = "1.4"
linkme = "0.2"
linkme = "0.3"
intertrait-macros = { version = "=0.2.2", path = "macros" }

[dev-dependencies]
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ Add the following two dependencies to your `Cargo.toml`:
```toml
[dependencies]
intertrait = "0.2"
linkme = "0.2"
```

The `linkme` dependency is required due to the use of `linkme` macro in the output of `intertrait` macros.
Expand Down Expand Up @@ -129,7 +128,7 @@ To use with `Arc`, the following steps should be taken:

# How it works
First of all, [`CastFrom`] trait makes it possible to retrieve an object of [`std::any::Any`]
from an object for a sub-trait of [`CastFrom`].
from an object for a sub-trait of [`CastFrom`].

And the macros provided by `intertrait` generates trampoline functions for downcasting a trait object
for [`std::any::Any`] back to its concrete type and then creating a trait object for the target trait from it.
Expand Down
5 changes: 2 additions & 3 deletions macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description = "Macros for intertrait crate, which allows for direct casting betw
version = "0.2.2"
authors = ["CodeChain Team <hi@codechain.io>"]
license = "MIT OR Apache-2.0"
edition = "2018"
edition = "2021"
repository = "https://github.com/CodeChain-io/intertrait"
include = ["src/**/*", "Cargo.toml", "LICENSE-*"]

Expand All @@ -15,8 +15,7 @@ proc-macro = true
proc-macro2 = "1.0"
syn = { version = "1.0", features = ["full"] }
quote = "1.0"
uuid = { version = "0.8", features = ["v4"] }
uuid = { version = "1", features = ["v4"] }

[dev-dependencies]
intertrait = { version = "=0.2.2", path = ".." }
linkme = "0.2"
12 changes: 11 additions & 1 deletion macros/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,26 @@ impl Parse for Targets {
pub struct Casts {
pub ty: Type,
pub targets: Targets,
pub intertrait_path: Path,
}

impl Parse for Casts {
fn parse(input: ParseStream) -> Result<Self> {
let intertrait_path = if input.peek(Token![@]) {
input.parse::<Token![@]>()?;
input.parse()?
} else {
syn::parse(quote::quote!(::intertrait).into())?
};

let ty: Type = input.parse()?;
input.parse::<Token![=>]>()?;
let targets: Targets = input.parse()?;

Ok(Casts {
ty,
targets: input.parse()?,
targets,
intertrait_path,
})
}
}
31 changes: 31 additions & 0 deletions macros/src/attr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use syn::parse::{Error, ParseStream, Result};
use syn::{parse_quote, Attribute, Path, Token};

// #[intertrait(crate = path::to::intertrait)]
pub(crate) fn intertrait_path(attrs: &mut Vec<Attribute>) -> Result<Path> {
let mut intertrait_path = None;
let mut errors: Option<Error> = None;

attrs.retain(|attr| {
if !attr.path.is_ident("intertrait") {
return true;
}
match attr.parse_args_with(|input: ParseStream| {
input.parse::<Token![crate]>()?;
input.parse::<Token![=]>()?;
input.call(Path::parse_mod_style)
}) {
Ok(path) => intertrait_path = Some(path),
Err(err) => match &mut errors {
None => errors = Some(err),
Some(errors) => errors.combine(err),
},
}
false
});

match errors {
None => Ok(intertrait_path.unwrap_or_else(|| parse_quote!(::intertrait))),
Some(errors) => Err(errors),
}
}
22 changes: 15 additions & 7 deletions macros/src/gen_caster.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
use std::str::from_utf8_unchecked;

use proc_macro2::TokenStream;
use uuid::adapter::Simple;
use uuid::fmt::Simple;
use uuid::Uuid;

use quote::format_ident;
use quote::quote;
use quote::ToTokens;

pub fn generate_caster(ty: &impl ToTokens, trait_: &impl ToTokens, sync: bool) -> TokenStream {
use syn::Path;

pub fn generate_caster(
ty: &impl ToTokens,
trait_: &impl ToTokens,
sync: bool,
intertrait_path: &Path,
) -> TokenStream {
let mut fn_buf = [0u8; FN_BUF_LEN];
let fn_ident = format_ident!("{}", new_fn_name(&mut fn_buf));
let new_caster = if sync {
quote! {
::intertrait::Caster::<dyn #trait_>::new_sync(
#intertrait_path::Caster::<dyn #trait_>::new_sync(
|from| from.downcast_ref::<#ty>().unwrap(),
|from| from.downcast_mut::<#ty>().unwrap(),
|from| from.downcast::<#ty>().unwrap(),
Expand All @@ -23,7 +30,7 @@ pub fn generate_caster(ty: &impl ToTokens, trait_: &impl ToTokens, sync: bool) -
}
} else {
quote! {
::intertrait::Caster::<dyn #trait_>::new(
#intertrait_path::Caster::<dyn #trait_>::new(
|from| from.downcast_ref::<#ty>().unwrap(),
|from| from.downcast_mut::<#ty>().unwrap(),
|from| from.downcast::<#ty>().unwrap(),
Expand All @@ -33,8 +40,9 @@ pub fn generate_caster(ty: &impl ToTokens, trait_: &impl ToTokens, sync: bool) -
};

quote! {
#[::linkme::distributed_slice(::intertrait::CASTERS)]
fn #fn_ident() -> (::std::any::TypeId, ::intertrait::BoxedCaster) {
#[#intertrait_path::linkme::distributed_slice(#intertrait_path::CASTERS)]
#[linkme(crate = #intertrait_path::linkme)]
fn #fn_ident() -> (::std::any::TypeId, #intertrait_path::BoxedCaster) {
(::std::any::TypeId::of::<#ty>(), Box::new(#new_caster))
}
}
Expand All @@ -46,7 +54,7 @@ const FN_BUF_LEN: usize = FN_PREFIX.len() + Simple::LENGTH;
fn new_fn_name(buf: &mut [u8]) -> &str {
buf[..FN_PREFIX.len()].copy_from_slice(FN_PREFIX);
Uuid::new_v4()
.to_simple()
.as_simple()
.encode_lower(&mut buf[FN_PREFIX.len()..]);
unsafe { from_utf8_unchecked(&buf[..FN_BUF_LEN]) }
}
12 changes: 10 additions & 2 deletions macros/src/item_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ use PathArguments::AngleBracketed;
use crate::args::Flag;
use crate::gen_caster::generate_caster;

pub fn process(flags: &HashSet<Flag>, input: ItemImpl) -> TokenStream {
pub fn process(flags: &HashSet<Flag>, mut input: ItemImpl) -> TokenStream {
let ItemImpl {
ref mut attrs,
ref self_ty,
ref trait_,
ref items,
..
} = input;

let intertrait_path = crate::attr::intertrait_path(attrs).unwrap();

let generated = match trait_ {
None => quote_spanned! {
self_ty.span() => compile_error!("#[cast_to] should only be on an impl of a trait");
Expand All @@ -32,7 +35,12 @@ pub fn process(flags: &HashSet<Flag>, input: ItemImpl) -> TokenStream {
},
(None, path, _) => {
let path = fully_bound_trait(path, items);
generate_caster(self_ty, &path, flags.contains(&Flag::Sync))
generate_caster(
self_ty,
&path,
flags.contains(&Flag::Sync),
&intertrait_path,
)
}
},
};
Expand Down
8 changes: 6 additions & 2 deletions macros/src/item_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ use quote::{quote, quote_spanned};
use crate::args::Flag;
use crate::gen_caster::generate_caster;

pub fn process(flags: &HashSet<Flag>, paths: Vec<Path>, input: DeriveInput) -> TokenStream {
pub fn process(flags: &HashSet<Flag>, paths: Vec<Path>, mut input: DeriveInput) -> TokenStream {
let DeriveInput {
ref mut attrs,
ref ident,
ref generics,
..
} = input;

let intertrait_path = crate::attr::intertrait_path(attrs).unwrap();

let generated = if generics.lt_token.is_some() {
quote_spanned! {
generics.span() => compile_error!("#[cast_to(..)] can't be used on a generic type definition");
}
} else {
paths
.into_iter()
.flat_map(|t| generate_caster(ident, &t, flags.contains(&Flag::Sync)))
.flat_map(|t| generate_caster(ident, &t, flags.contains(&Flag::Sync), &intertrait_path))
.collect()
};
quote! {
Expand Down
4 changes: 3 additions & 1 deletion macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use args::{Casts, Flag, Targets};
use gen_caster::generate_caster;

mod args;
mod attr;
mod gen_caster;
mod item_impl;
mod item_type;
Expand Down Expand Up @@ -134,11 +135,12 @@ pub fn castable_to(input: TokenStream) -> TokenStream {
let Casts {
ty,
targets: Targets { flags, paths },
intertrait_path,
} = parse_macro_input!(input);

paths
.iter()
.map(|t| generate_caster(&ty, t, flags.contains(&Flag::Sync)))
.map(|t| generate_caster(&ty, t, flags.contains(&Flag::Sync), &intertrait_path))
.collect::<proc_macro2::TokenStream>()
.into()
}
9 changes: 4 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;

use linkme::distributed_slice;
// re-export linkme
pub use linkme;
use once_cell::sync::Lazy;

pub use intertrait_macros::*;
Expand All @@ -84,7 +85,7 @@ doc_comment::doctest!("../README.md");
///
/// [`Caster<T>`]: ./struct.Caster.html
#[doc(hidden)]
#[distributed_slice]
#[linkme::distributed_slice]
pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..];

/// A `HashMap` mapping `TypeId` of a [`Caster<T>`] to an instance of it.
Expand Down Expand Up @@ -287,14 +288,12 @@ mod tests {
use std::any::{Any, TypeId};
use std::fmt::{Debug, Display};

use linkme::distributed_slice;

use crate::{BoxedCaster, CastFromSync};

use super::cast::*;
use super::*;

#[distributed_slice(super::CASTERS)]
#[linkme::distributed_slice(super::CASTERS)]
static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster;

#[derive(Debug)]
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/on-generic-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ error: #[cast_to(..)] can't be used on a generic type definition
--> $DIR/on-generic-type.rs:6:12
|
6 | struct Data<T: 'static> {
| ^
| ^^^^^^^^^^^^