Today I ran into an error that I can hardly even believe that I have never encountered before. Apparently, incomplete patterns and complete patterns differ in how they interpret the pattern NameBelongingToAUnitStruct
.
#[derive(Debug,Copy,Clone)]
struct MyUnit;
// '()' in an incomplete pattern destructures the unit
if let Some(()) = Some(()) {}
match () { () => {} };
// '()' in a complete pattern destructures the unit.
let ((), _) = ((), 0);
Some(()).map(|()| ());
// 'MyUnit' in an incomplete pattern destructures MyUnit
if let Some(MyUnit) = Some(MyUnit) {}
match MyUnit { MyUnit => () };
// 'MyUnit' in a complete pattern... actually names a binding?
let (MyUnit, _) = (MyUnit, 0); // [E0530]: let bindings cannot shadow unit structs
Some(MyUnit).map(|MyUnit| ()); // [E0530]: function parameters cannot shadow unit structs
(playground)
(E0530 in the error index)
The workarounds are to use a path like ::MyPath
, the name: ty
syntax, or to use _
and let type inference work.
let (::MyUnit, _) = (MyUnit, 0); // ok
Some(MyUnit).map(|_: MyUnit| ()); // ok
Some(MyUnit).map(|_| ()); // ok
I find this to be odd and inconsistent.
Note: Lest it be thought that MyUnit
as a pattern is useless, my use case was to make an unusual usage of types self-documentiong:
fn_with_non_obvious_return_type()
.map(|MeaningfullyNamedUnit| {
// ...
})