Skip to content

Commit c0677e3

Browse files
authored
Merge pull request #60 from jbr/fix-deref-mut
fix: Do not auto-deref Rc, Cow, or Arc
2 parents d54a0f8 + 31737e4 commit c0677e3

File tree

4 files changed

+53
-37
lines changed

4 files changed

+53
-37
lines changed

docs.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -164,17 +164,17 @@ dereferenced as such. So for example, a field that contains a `String` will retu
164164
or `&mut str` from `get_mut` by default. This behavior can be opted out of, at any configuration
165165
level.
166166

167-
| Owned Type | Borrowed Type |
168-
|------------|---------------|
169-
| `String` | `&str` |
170-
| `OsString | `&OsStr` |
171-
| `Vec<T>` | `&[T]` |
172-
| `Box<T>` | `&T` |
173-
| `Arc<T>` | `&T` |
174-
| `Rc<T>` | `&T` |
175-
| `PathBuf` | `&Path` |
176-
| `Cow<T>` | `&T` |
177-
| `[T; N]` | `&[T]` |
167+
| Owned Type | Borrowed Type | DerefMut
168+
|------------|---------------|------
169+
| `String` | `&str` | yes
170+
| `OsString | `&OsStr` | yes
171+
| `Vec<T>` | `&[T]` | yes
172+
| `Box<T>` | `&T` | yes
173+
| `Arc<T>` | `&T` | no
174+
| `Rc<T>` | `&T` | no
175+
| `PathBuf` | `&Path` | yes
176+
| `Cow<T>` | `&T` | no
177+
| `[T; N]` | `&[T]` | yes
178178

179179
### Common copy types are detected by default
180180

src/deref_handling.rs

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use std::borrow::Cow;
22

33
use syn::{GenericArgument, Path, PathArguments, Type, TypeArray, TypePath, parse_quote};
44

5-
pub(crate) fn auto_deref(ty: &Type) -> Option<Cow<'_, Type>> {
5+
use crate::Method;
6+
7+
pub(crate) fn auto_deref(ty: &Type, method: Method) -> Option<Cow<'_, Type>> {
68
let segments = match ty {
79
Type::Path(TypePath {
810
path: Path { segments, .. },
@@ -39,7 +41,7 @@ pub(crate) fn auto_deref(ty: &Type) -> Option<Cow<'_, Type>> {
3941
return Some(Cow::Owned(parse_quote!([#inner_type])));
4042
}
4143

42-
if last_segment.ident == "Box" || last_segment.ident == "Arc" || last_segment.ident == "Rc" {
44+
if last_segment.ident == "Box" {
4345
let PathArguments::AngleBracketed(ref bracketed_args) = last_segment.arguments else {
4446
return None;
4547
};
@@ -51,20 +53,34 @@ pub(crate) fn auto_deref(ty: &Type) -> Option<Cow<'_, Type>> {
5153
return Some(Cow::Borrowed(inner_type));
5254
}
5355

54-
if last_segment.ident == "Cow" {
55-
let PathArguments::AngleBracketed(ref bracketed_args) = last_segment.arguments else {
56-
return None;
57-
};
56+
if method == Method::Get {
57+
if last_segment.ident == "Arc" || last_segment.ident == "Rc" {
58+
let PathArguments::AngleBracketed(ref bracketed_args) = last_segment.arguments else {
59+
return None;
60+
};
5861

59-
let Some(GenericArgument::Lifetime(_)) = bracketed_args.args.first() else {
60-
return None;
61-
};
62+
let Some(GenericArgument::Type(inner_type)) = bracketed_args.args.first() else {
63+
return None;
64+
};
6265

63-
let Some(GenericArgument::Type(t)) = bracketed_args.args.get(1) else {
64-
return None;
65-
};
66+
return Some(Cow::Borrowed(inner_type));
67+
}
68+
69+
if last_segment.ident == "Cow" {
70+
let PathArguments::AngleBracketed(ref bracketed_args) = last_segment.arguments else {
71+
return None;
72+
};
6673

67-
return Some(Cow::Borrowed(t));
74+
let Some(GenericArgument::Lifetime(_)) = bracketed_args.args.first() else {
75+
return None;
76+
};
77+
78+
let Some(GenericArgument::Type(t)) = bracketed_args.args.get(1) else {
79+
return None;
80+
};
81+
82+
return Some(Cow::Borrowed(t));
83+
}
6884
}
6985

7086
None

src/query.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ impl<'a> Query<'a> {
257257

258258
fn auto_deref(&self, ty: &'a Type) -> Option<Cow<'a, Type>> {
259259
if self.common_setting(|x| x.auto_deref) {
260-
auto_deref(ty)
260+
auto_deref(ty, *self.method)
261261
} else {
262262
None
263263
}

tests/expand/15-auto-deref.expanded.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,20 @@ impl<'a, T> Detection<'a, T> {
3939
pub fn arc(&self) -> &T {
4040
&*self.arc
4141
}
42-
pub fn arc_mut(&mut self) -> &mut T {
43-
&mut *self.arc
42+
pub fn arc_mut(&mut self) -> &mut std::sync::Arc<T> {
43+
&mut self.arc
4444
}
4545
pub fn rc(&self) -> &T {
4646
&*self.rc
4747
}
48-
pub fn rc_mut(&mut self) -> &mut T {
49-
&mut *self.rc
48+
pub fn rc_mut(&mut self) -> &mut std::rc::Rc<T> {
49+
&mut self.rc
5050
}
5151
pub fn cow(&self) -> &T {
5252
&*self.cow
5353
}
54-
pub fn cow_mut(&mut self) -> &mut T {
55-
&mut *self.cow
54+
pub fn cow_mut(&mut self) -> &mut Cow<'a, T> {
55+
&mut self.cow
5656
}
5757
pub fn path(&self) -> &std::path::Path {
5858
&*self.path
@@ -218,20 +218,20 @@ impl<'a, T> OptionDeref<'a, T> {
218218
pub fn arc(&self) -> Option<&T> {
219219
self.arc.as_deref()
220220
}
221-
pub fn arc_mut(&mut self) -> Option<&mut T> {
222-
self.arc.as_deref_mut()
221+
pub fn arc_mut(&mut self) -> Option<&mut std::sync::Arc<T>> {
222+
self.arc.as_mut()
223223
}
224224
pub fn rc(&self) -> Option<&T> {
225225
self.rc.as_deref()
226226
}
227-
pub fn rc_mut(&mut self) -> Option<&mut T> {
228-
self.rc.as_deref_mut()
227+
pub fn rc_mut(&mut self) -> Option<&mut std::rc::Rc<T>> {
228+
self.rc.as_mut()
229229
}
230230
pub fn cow(&self) -> Option<&T> {
231231
self.cow.as_deref()
232232
}
233-
pub fn cow_mut(&mut self) -> Option<&mut T> {
234-
self.cow.as_deref_mut()
233+
pub fn cow_mut(&mut self) -> Option<&mut Cow<'a, T>> {
234+
self.cow.as_mut()
235235
}
236236
pub fn path(&self) -> Option<&std::path::Path> {
237237
self.path.as_deref()

0 commit comments

Comments
 (0)