Skip to content

Commit b37469b

Browse files
authored
Merge pull request #61 from jbr/improved-pipeline
fix: address poorly-handled nested type detection
2 parents c0677e3 + a8a4b51 commit b37469b

23 files changed

+771
-368
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ keywords = ["macros"]
1313
categories = ["development-tools"]
1414

1515
[features]
16-
debug = ["syn/extra-traits"]
16+
debug = []
1717

1818
[lib]
1919
proc-macro = true
@@ -22,7 +22,7 @@ proc-macro = true
2222
[dependencies]
2323
proc-macro2 = "1.0.95"
2424
quote = "1.0.40"
25-
syn = { version = "2.0.101", features = ["full"] }
25+
syn = { version = "2.0.101", features = ["full", "extra-traits"] }
2626

2727
[dev-dependencies]
2828
macrotest = { version = "1.1.0" }

docs.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,9 @@ impl User {
280280
pub fn name(&self) -> &str {
281281
&*self.name
282282
}
283-
///Borrows the user's age, if set
284-
pub fn age(&self) -> Option<&u8> {
285-
self.age.as_ref()
283+
///Returns a copy of the user's age, if set
284+
pub fn age(&self) -> Option<u8> {
285+
self.age
286286
}
287287
///Borrows favorite color, if set
288288
pub fn favorite_color(&self) -> Option<&str> {

src/copy_detection.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use syn::{Path, Type, TypePath, TypeReference};
22

3-
pub(crate) fn enable_copy_for_type(ty: &Type) -> bool {
3+
use crate::Method;
4+
5+
pub(crate) fn enable_copy_for_type(ty: &Type, method: Method) -> bool {
46
match ty {
57
Type::Path(TypePath {
68
path: Path { segments, .. },
@@ -32,6 +34,11 @@ pub(crate) fn enable_copy_for_type(ty: &Type) -> bool {
3234
mutability: None, ..
3335
}) => true,
3436

37+
Type::Reference(TypeReference {
38+
mutability: Some(_),
39+
..
40+
}) => method == Method::GetMut,
41+
3542
_ => false,
3643
}
3744
}

src/deref_handling.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,51 @@
1-
use std::borrow::Cow;
2-
3-
use syn::{GenericArgument, Path, PathArguments, Type, TypeArray, TypePath, parse_quote};
1+
use proc_macro2::Span;
2+
use syn::{
3+
GenericArgument, Path, PathArguments, Type, TypeArray, TypePath, TypeReference,
4+
parse_quote_spanned,
5+
};
46

57
use crate::Method;
68

7-
pub(crate) fn auto_deref(ty: &Type, method: Method) -> Option<Cow<'_, Type>> {
9+
pub(crate) fn auto_deref(ty: &Type, method: Method, span: Span) -> Option<(Type, usize)> {
10+
let mut ty = ty.clone();
11+
let mut count = 0;
12+
13+
while let Some(next_ty) = auto_deref_inner(&ty, method, span) {
14+
ty = next_ty;
15+
count += 1;
16+
}
17+
18+
if count > 0 { Some((ty, count)) } else { None }
19+
}
20+
21+
pub(crate) fn auto_deref_inner(ty: &Type, method: Method, span: Span) -> Option<Type> {
822
let segments = match ty {
23+
Type::Reference(TypeReference {
24+
mutability: Some(_),
25+
elem,
26+
..
27+
}) => return Some(*elem.clone()),
928
Type::Path(TypePath {
1029
path: Path { segments, .. },
1130
..
1231
}) => segments,
13-
Type::Array(TypeArray { elem, .. }) => return Some(Cow::Owned(parse_quote!([#elem]))),
32+
Type::Array(TypeArray { elem, .. }) => return Some(parse_quote_spanned!(span => [#elem])),
1433
_ => {
1534
return None;
1635
}
1736
};
1837

1938
let last_segment = segments.last()?;
2039
if last_segment.ident == "String" {
21-
return Some(Cow::Owned(parse_quote!(str)));
40+
return Some(parse_quote_spanned!(span => str));
2241
}
2342

2443
if last_segment.ident == "PathBuf" {
25-
return Some(Cow::Owned(parse_quote!(std::path::Path)));
44+
return Some(parse_quote_spanned!(span => std::path::Path));
2645
}
2746

2847
if last_segment.ident == "OsString" {
29-
return Some(Cow::Owned(parse_quote!(std::ffi::OsStr)));
48+
return Some(parse_quote_spanned!(span => std::ffi::OsStr));
3049
}
3150

3251
if last_segment.ident == "Vec" {
@@ -38,7 +57,7 @@ pub(crate) fn auto_deref(ty: &Type, method: Method) -> Option<Cow<'_, Type>> {
3857
return None;
3958
};
4059

41-
return Some(Cow::Owned(parse_quote!([#inner_type])));
60+
return Some(parse_quote_spanned!(span => [#inner_type]));
4261
}
4362

4463
if last_segment.ident == "Box" {
@@ -50,7 +69,7 @@ pub(crate) fn auto_deref(ty: &Type, method: Method) -> Option<Cow<'_, Type>> {
5069
return None;
5170
};
5271

53-
return Some(Cow::Borrowed(inner_type));
72+
return Some(inner_type.clone());
5473
}
5574

5675
if method == Method::Get {
@@ -63,7 +82,7 @@ pub(crate) fn auto_deref(ty: &Type, method: Method) -> Option<Cow<'_, Type>> {
6382
return None;
6483
};
6584

66-
return Some(Cow::Borrowed(inner_type));
85+
return Some(inner_type.clone());
6786
}
6887

6988
if last_segment.ident == "Cow" {
@@ -79,7 +98,7 @@ pub(crate) fn auto_deref(ty: &Type, method: Method) -> Option<Cow<'_, Type>> {
7998
return None;
8099
};
81100

82-
return Some(Cow::Borrowed(t));
101+
return Some(t.clone());
83102
}
84103
}
85104

src/option_handling.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,17 @@ pub(crate) fn extract_option_type(ty: &Type) -> Option<&Type> {
2121
let Some(GenericArgument::Type(inner_type)) = bracketed_args.args.first() else {
2222
return None;
2323
};
24-
Some(strip_ref(inner_type))
24+
25+
Some(inner_type)
2526
}
2627

2728
pub(crate) fn strip_ref(ty: &Type) -> &Type {
29+
ref_inner(ty).unwrap_or(ty)
30+
}
31+
32+
pub(crate) fn ref_inner(ty: &Type) -> Option<&Type> {
2833
match ty {
29-
Type::Reference(TypeReference { elem, .. }) => elem,
30-
_ => ty,
34+
Type::Reference(TypeReference { elem, .. }) => Some(elem),
35+
_ => None,
3136
}
3237
}

0 commit comments

Comments
 (0)