let s: &[u8] = "0100".as_bytes();
assert_eq!(s.iter().filter(|i| i.to_string() == b'1'.to_string()).count(), 1);// dot pierce. ok.
assert_eq!(s.iter().filter(|i| (&i).to_string() == b'1'.to_string()).count(), 1);// dot pierce. ok.
assert_eq!(s.iter().map(|&i| i - b'0').sum::<u8>(), 1);// referece pattern. ok.
assert_eq!(s.iter().map(|i| i - b'0').sum::<u8>(), 1);// why rustc allow this?
assert_eq!(s.iter().map(|i| (&i) - b'0').sum::<u8>(), 1);// but rustc don't allow this.
1 Like
Your code can be simplified to:
fn main() {
let val = 1u8;
let ref1 = &val;
let ref2 = &&val;
val - 1;
ref1 - 1; // ok
ref2 - 1; // err
}
So it looks like there's a magic auto-dereferencing behavior for a single level of reference, but not double reference.
Initially, I suspected it's related to magic auto-dereferencing of method calls, but methods work on any depth of references, so I'm surprised myself too:
use std::ops::Sub;
fn main() {
let val = 1u8;
let ref1 = &val;
let ref2 = &&val;
val.sub(1);
ref1.sub(1); // ok
ref2.sub(1); // ok, too!
}
I think it's simply because there are the required impls:
impl Sub<u8> for u8 // val - 1
impl<'a> Sub<u8> for &'a u8 // ref1 - 1
There's no impl<'a, 'b> Sub<u8> for &'a &'b u8
(or similar).
1 Like
you are right.
use std::ops::Sub;
struct x8(u8);
impl<'a, 'b> Sub<u8> for &'a &'b x8 {
type Output = u8;
fn sub(self, rhs: u8) -> u8 {
self.0 - rhs
}
}
let s = x8(1);
assert_eq!((&&s) - 1, 0);