Discussion on irlo: https://internals.rust-lang.org/t/somewhat-random-idea-deref-patterns/13813
Discussion on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Deref.20patterns
Older irlo discussion: https://internals.rust-lang.org/t/pre-pre-rfc-match-ergonomics-for-container-types-restricted-method-calls-in-patterns/13371
Also discussed on the box patterns issue: https://github.com/rust-lang/rust/issues/29641
Be able to match through a Deref
or DerefMut
smart pointer ergonomically.
let x: Option<Rc<bool>> = ...;
match x {
Some(deref true) => ...,
Some(x) => ...,
None => ...,
}
String
with "hello"
), keyword or sigil for non-literals (matching String
with x
and having x
work as type &str
)*
: *<pattern>
&
: &<pattern>
&
patternbox
: box <pattern>
box_pattern
syntaxBox
typesderef
: deref <pattern>
Deref
impls, then it is unsound to consider the following as exhaustive:
let x: Option<SomePointer<bool>> = ...;
match x {
Some(deref true) => ...,
Some(deref false) => ...,
None => ...,
}
deref
ing once per subpattern, because e.g.:
match x {
Some(deref 0) => ...,
Some(deref mut 1) => ...,
Some(deref 2) => ...,
}
deref_mut
, then reborrowing. However, this would not work in a case like this:
match &mut x {
Some(deref v@0..3) => ..., // (1)
Some(deref mut v@4..7) => ..., // (2)
v@&None => ..., // (3)
Some(deref v@8..11) => ..., // (4)
}
Deref
impl, the shared borrow in pattern 3 may invalidate the mutable reference used in 1 and 2 (at the very least, for wrapper types like ManuallyDrop
)x
is immutable, it should be valid to only deref once.Deref
impls, then people may start depending on the number and order of the deref
calls, like they depended on drop order even if it was supposed to be unspecified.
Deref
impls. But what about impure Deref
that are idempotent (like Lazy
/SyncLazy
)x
in Some(x)
and Some(x @ true)
could be different
&
and match ergonomics I thinkDeref
impl
Cow
and AssertUnwindSafe
let cowcow: Cow<Cow<bool>> = ...
match &cowcow {
Cow::Owned(x) => {} // what's the type of `x`?
}
let unwind_safe: AssertUnwindSafe<bool> = ...;
match &unwind_safe{
AssertUnwindSafe(true) => {},
deref false => {},
/* Would the above be considered exhasutive */
}
#[lang]
items to Cow
and AssertUnwindSafe
).T::Owned
is not T
(str
, [T]
, custom ToOwned
impl)DerefMove
still isn't a thing, yet we'd like to accomodate moving out of smart pointers in patterns in the future
ref
s where in the future we would want to move outlet x: Box<Option<bool>> = ...
match x {
Some(ref x) => {} // ok
Some(ref mut x) => {} // ok
Some(x) => {} // should error for now
}
deref
vs deref_mut
depends on subpatterns
let x: Box<Option<bool>> = ...
match x {
Some(ref x) => {}
Some(ref mut x) => {}
}
ref
and ref mut
in a same pattern? Probably using deref_mut
is ok.Restrict to only a chosen set of Standard Library types
Current List:
&T
and &mut T
Box
, Arc
, Rc
Vec
, String
, OsString
, CString
, PathBuf
[T]
and str
resp.)Ref
, RefMut
, MutexGuard
, RwLockReadGuard
, RwLockWriteGuard
IOSlice
, IOSliceMut
, ManuallyDrop
, AssertUnwindSafe
(note: AssertUnwindSafe can be destructured)
Pin<P>
where P
is a qualifying type
Box
, Arc
and Rc
, this has precedent in being special-cased in the language.Lazy
and SyncLazy
qualify?
Cow
qualify?
Deref
is idempotent wrt. structure and addressDerefMut
is not. The address stability question cannot be resolved. Additionally, it can invoke a user-provided Clone
, which is a safe trait and may not produce a structurally equivalent value.Cow
does not implement DefefMut
so this is not an issueDeref
and DerefMut
accesses in patternsCow
can qualify for deref patterns, provided a DerefMut
impl is not added.Initial Project will persue this solution, providing the list of requirements for a standard library type to qualify, as well as propose an initial list
The standard library implementation would provide an unstable trait or attribute or otherwise (at it's option), applied to all qualifying types
Require a _
pattern for the match to count as exhaustive
let x: Option<SomePointer<bool>> = ...;
match x {
Some(true) => ...,
Some(false) => ...,
Some(_) => ...,
None => ...,
}
deref
calls, which would limit future changesAn unsafe DerefPure
trait that restricts deref
.
deref{,_mut}
calls without an intervening access through &mut
to the pointer or pointee, other than a deref_mut
call.DerefMut
for Cow
since it must clone
which may not preserve structural stabilityCow
is not DerefMut
Clone
impls, akin to how only auto-derived PartialEq
impls are allowed for constants in patternsderef
and deref_mut
on a same pointer&mut
.
Lazy
restrict to const
deref
impls
&mut
ref and thus not be idempotentDerefMut
?Lazy
that reads a file)