Skip to content

Commit

Permalink
Use syn visitor to rewrite types
Browse files Browse the repository at this point in the history
  • Loading branch information
arnodb committed Oct 30, 2024
1 parent cf71404 commit 3420a1e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 138 deletions.
7 changes: 0 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@ jobs:
uses: ./.github/workflows/_build.yml
with:
rust_toolchain: stable
rust_features: --features "full"
with_rustfmt: true

main_1_56_1:
name: Rust 1.56.1
uses: ./.github/workflows/_build.yml
with:
rust_toolchain: 1.56.1
rust_features: --features "full"
with_clippy: true
pre_build_script: ./scripts/msrv_pin_dependencies.sh

Expand All @@ -28,37 +26,32 @@ jobs:
uses: ./.github/workflows/_build.yml
with:
rust_toolchain: nightly
rust_features: --all-features

cross_stable_i686:
name: Rust stable i686-unknown-linux-gnu
uses: ./.github/workflows/_cross_build.yml
with:
target: i686-unknown-linux-gnu
rust_toolchain: stable
rust_features: --features "full"

cross_stable_aarch64:
name: Rust stable aarch64-unknown-linux-gnu
uses: ./.github/workflows/_cross_build.yml
with:
target: aarch64-unknown-linux-gnu
rust_toolchain: stable
rust_features: --features "full"

cross_1_65_0_i686:
name: Rust 1.65.0 i686-unknown-linux-gnu
uses: ./.github/workflows/_cross_build.yml
with:
target: i686-unknown-linux-gnu
rust_toolchain: 1.65.0
rust_features: --features "full"

cross_1_65_0_aarch64:
name: Rust 1.65.0 aarch64-unknown-linux-gnu
uses: ./.github/workflows/_cross_build.yml
with:
target: aarch64-unknown-linux-gnu
rust_toolchain: 1.65.0
rust_features: --features "full"

7 changes: 1 addition & 6 deletions truc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,12 @@ proc-macro2 = "1"
quote = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
syn = { version = "1", features = ["full", "extra-traits"] }
syn = { version = "1", features = ["full", "extra-traits", "visit-mut"] }
truc_runtime = { version = "0.1.2-dev", path = "../truc_runtime" }

[dev-dependencies]
rand = "0.8"
rand_chacha = "0.3"

[features]
full = []
full_unstable = ["unstable"]
unstable = []

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage,coverage_nightly)'] }
1 change: 0 additions & 1 deletion truc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![cfg_attr(test, allow(clippy::many_single_char_names))]
#![cfg_attr(feature = "unstable", feature(non_exhaustive_omitted_patterns_lint))]
#![cfg_attr(coverage_nightly, feature(coverage_attribute))]

#[macro_use]
Expand Down
210 changes: 86 additions & 124 deletions truc/src/record/type_name.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
use syn::{
visit_mut::{visit_type_path_mut, VisitMut},
Path, TypePath,
};

pub fn truc_type_name<T: ?Sized>() -> String {
let std_type_name = std::any::type_name::<T>();
let mut syn_type = syn::parse_str::<syn::Type>(std_type_name).expect("syn type");
Expand All @@ -11,162 +16,119 @@ pub fn truc_dynamic_type_name(type_name: &str) -> String {
quote!(#syn_type).to_string()
}

fn rewrite_type(syn_type: &mut syn::Type) {
#[cfg_attr(all(test, feature = "unstable"), deny(non_exhaustive_omitted_patterns))]
match syn_type {
syn::Type::Array(syn::TypeArray {
bracket_token: _,
elem,
semi_token: _,
len: _,
}) => {
rewrite_type(elem);
}
syn::Type::BareFn(_)
| syn::Type::Group(_)
| syn::Type::ImplTrait(_)
| syn::Type::Infer(_)
| syn::Type::Macro(_)
| syn::Type::Never(_) => {
unimplemented!("{:?}", syn_type);
}
syn::Type::Paren(syn::TypeParen {
paren_token: _,
elem,
}) => {
rewrite_type(elem);
}
syn::Type::Path(syn::TypePath {
struct TypeRewriter;

impl VisitMut for TypeRewriter {
fn visit_type_path_mut(&mut self, i: &mut TypePath) {
let TypePath {
qself: _,
path: syn::Path {
path: Path {
leading_colon,
segments,
},
}) => {
let mut matched;
} = i;
let mut matched;
matched = {
leading_colon.is_none() && {
let mut seg_iter = segments.iter_mut();
match_segment(seg_iter.next(), "alloc", || {
match_segment(seg_iter.next(), "string", || {
match_segment(seg_iter.next(), "String", || seg_iter.next().is_none())
})
})
}
};
if matched {
let mut seg = segments.pop().expect("segment").into_value();
seg.ident = syn::Ident::new("String", proc_macro2::Span::call_site());
segments.clear();
segments.push(seg);
}
if !matched {
matched = {
leading_colon.is_none() && {
let mut seg_iter = segments.iter_mut();
match_segment(seg_iter.next(), "alloc", || {
match_segment(seg_iter.next(), "string", || {
match_segment(seg_iter.next(), "String", || seg_iter.next().is_none())
match_segment(seg_iter.next(), "boxed", || {
match_segment_with_arguments(seg_iter.next(), "Box", || {
seg_iter.next().is_none()
})
})
})
}
};
if matched {
let mut seg = segments.pop().expect("segment").into_value();
seg.ident = syn::Ident::new("String", proc_macro2::Span::call_site());
seg.ident = syn::Ident::new("Box", proc_macro2::Span::call_site());
segments.clear();
segments.push(seg);
}
if !matched {
matched = {
leading_colon.is_none() && {
let mut seg_iter = segments.iter_mut();
match_segment(seg_iter.next(), "alloc", || {
match_segment(seg_iter.next(), "boxed", || {
match_segment_with_arguments(seg_iter.next(), "Box", || {
seg_iter.next().is_none()
})
})
})
}
};
if matched {
let mut seg = segments.pop().expect("segment").into_value();
seg.ident = syn::Ident::new("Box", proc_macro2::Span::call_site());
segments.clear();
segments.push(seg);
}
}
if !matched {
matched = leading_colon.is_none() && {
let mut seg_iter = segments.iter_mut();
match_segment(seg_iter.next(), "core", || {
match_segment(seg_iter.next(), "option", || {
match_segment_with_arguments(seg_iter.next(), "Option", || {
seg_iter.next().is_none()
})
}
if !matched {
matched = leading_colon.is_none() && {
let mut seg_iter = segments.iter_mut();
match_segment(seg_iter.next(), "core", || {
match_segment(seg_iter.next(), "option", || {
match_segment_with_arguments(seg_iter.next(), "Option", || {
seg_iter.next().is_none()
})
})
};
if matched {
let mut seg = segments.pop().expect("segment").into_value();
seg.ident = syn::Ident::new("Option", proc_macro2::Span::call_site());
segments.clear();
segments.push(seg);
}
})
};
if matched {
let mut seg = segments.pop().expect("segment").into_value();
seg.ident = syn::Ident::new("Option", proc_macro2::Span::call_site());
segments.clear();
segments.push(seg);
}
if !matched {
matched = leading_colon.is_none() && {
let mut seg_iter = segments.iter_mut();
match_segment(seg_iter.next(), "core", || {
match_segment(seg_iter.next(), "result", || {
match_segment_with_arguments(seg_iter.next(), "Result", || {
seg_iter.next().is_none()
})
}
if !matched {
matched = leading_colon.is_none() && {
let mut seg_iter = segments.iter_mut();
match_segment(seg_iter.next(), "core", || {
match_segment(seg_iter.next(), "result", || {
match_segment_with_arguments(seg_iter.next(), "Result", || {
seg_iter.next().is_none()
})
})
};
if matched {
let mut seg = segments.pop().expect("segment").into_value();
seg.ident = syn::Ident::new("Result", proc_macro2::Span::call_site());
segments.clear();
segments.push(seg);
}
})
};
if matched {
let mut seg = segments.pop().expect("segment").into_value();
seg.ident = syn::Ident::new("Result", proc_macro2::Span::call_site());
segments.clear();
segments.push(seg);
}
for seg in segments.iter_mut() {
match &mut seg.arguments {
syn::PathArguments::None => {}
syn::PathArguments::AngleBracketed(args) => {
for arg in &mut args.args {
match arg {
syn::GenericArgument::Lifetime(_) => {}
syn::GenericArgument::Type(r#type) => rewrite_type(r#type),
syn::GenericArgument::Binding(_) => {}
syn::GenericArgument::Constraint(_) => {}
syn::GenericArgument::Const(_) => {}
}
}
for seg in segments.iter_mut() {
match &mut seg.arguments {
syn::PathArguments::None => {}
syn::PathArguments::AngleBracketed(args) => {
for arg in &mut args.args {
match arg {
syn::GenericArgument::Lifetime(_) => {}
syn::GenericArgument::Type(r#type) => rewrite_type(r#type),
syn::GenericArgument::Binding(_) => {}
syn::GenericArgument::Constraint(_) => {}
syn::GenericArgument::Const(_) => {}
}
}
syn::PathArguments::Parenthesized(args) => {
for r#type in &mut args.inputs {
rewrite_type(r#type)
}
}
syn::PathArguments::Parenthesized(args) => {
for r#type in &mut args.inputs {
rewrite_type(r#type)
}
}
}
}
syn::Type::Ptr(_) | syn::Type::Reference(_) => {
unimplemented!("{:?}", syn_type);
}
syn::Type::Slice(syn::TypeSlice {
bracket_token: _,
elem,
}) => {
rewrite_type(elem);
}
syn::Type::TraitObject(_) => {
unimplemented!("{:?}", syn_type);
}
syn::Type::Tuple(syn::TypeTuple {
paren_token: _,
elems,
}) => {
for r#type in &mut elems.iter_mut() {
rewrite_type(r#type)
}
}
syn::Type::Verbatim(_) => {
unimplemented!("{:?}", syn_type);
}
_ => {
unimplemented!("{:?}", syn_type);
}
visit_type_path_mut(self, i);
}
}

fn rewrite_type(syn_type: &mut syn::Type) {
TypeRewriter.visit_type_mut(syn_type);
}

fn match_segment<F>(segment: Option<&mut syn::PathSegment>, value: &str, f: F) -> bool
where
F: FnOnce() -> bool,
Expand Down

0 comments on commit 3420a1e

Please sign in to comment.