Created
July 7, 2018 13:21
-
-
Save danielhenrymantilla/95189c68e15f1f2b252a71dce132d2b2 to your computer and use it in GitHub Desktop.
Rust: &self sugar vs other &identifier bindings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* The following lib tests illustrate a lack of consistency in rust: | |
* the &identifier binding leads to 2 different behaviors based on whether | |
* - the identifier is the special 'self' first argument of a method, | |
* - or a simple variable / argument (called slf in the following tests) | |
*/ | |
#![allow(dead_code, unused_variables, unused_parens)] | |
/* compiler ensures that check_ref::<T>(x) can only be called iff x: &T */ | |
fn check_ref<T> (_: &T) {} | |
#[derive(PartialEq)] | |
struct Slf; | |
#[derive(Clone, Copy, PartialEq)] | |
struct SlfCpy; | |
#[cfg(test)] | |
mod inline_tests { | |
use {check_ref, Slf, SlfCpy}; | |
#[test] | |
fn amptype_notation () // slf: &Slf | |
{ | |
let slf: &Slf = &Slf; // <-- self: &Self logic here | |
check_ref::<Slf>(slf); | |
assert!(slf == &Slf); | |
/* => slf is a ref */ | |
} | |
#[test] | |
fn refself_notation () // ref slf = Slf | |
{ | |
let ref slf = Slf; | |
check_ref::<Slf>(slf); | |
assert!(slf == &Slf); | |
/* => slf is a ref */ | |
} | |
#[test] | |
fn ampself_notation () // &slf | |
{ | |
let &slf = &SlfCpy; // <-- &self logic here */ | |
// check_ref::<SlfCpy>(slf); // does not compile! | |
check_ref::<SlfCpy>(&slf); // this does | |
assert!(&slf == &SlfCpy); | |
assert!(slf == SlfCpy); | |
/* => slf is NOT a ref /!\ */ | |
} | |
#[test] | |
fn ampself_notation_equivalent () // Explanation: | |
{ | |
// let &slf = (&SlfCpy); // does a pattern-match equivalent to: | |
let slf = *(&SlfCpy); // move borrowed value => requires Copy | |
// check_ref::<SlfCpy>(slf); // Can't compile => slf isn't a ref | |
check_ref::<SlfCpy>(&slf); // &slf is. | |
assert!(slf == SlfCpy); | |
} | |
/* ===== (&slf) vs (slf: &Slf) -> NOT THE SAME TYPE ===== */ | |
} | |
#[cfg(test)] | |
mod function_tests { | |
use {check_ref, Slf, SlfCpy}; | |
#[test] | |
fn classic_case () | |
{ | |
/* slf functions */ | |
let amptype_notation = |slf: &Slf| { | |
check_ref::<Slf>(slf); | |
assert!(slf == &Slf); | |
/* => slf is a ref */ | |
}; | |
// let ampself_notation_wrong = |&slf| { | |
// check_ref::<Slf>(slf); // Can't compile => slf isn't a ref | |
// } | |
let ampself_notation_right = |&slf| { | |
check_ref::<SlfCpy>(&slf); | |
assert!(slf == SlfCpy); | |
/* => slf is NOT a ref /!\ */ | |
}; | |
let refself_notation = |ref slf| { | |
check_ref::<Slf>(slf); | |
assert!(slf == &Slf); | |
/* => slf is a ref */ | |
}; | |
/* inputs taken */ | |
amptype_notation(&Slf); // a ref | |
ampself_notation_right(&SlfCpy); // a ref | |
refself_notation(Slf); // owned value | |
/* ===== (&slf) vs (slf: &Slf) -> NOT THE SAME TYPE ===== */ | |
} | |
/* self functions / (static) methods */ | |
impl Slf { | |
fn amptype_notation (self: &Self) { | |
check_ref::<Self>(self); | |
assert!(self == &Slf); | |
/* => self is a ref */ | |
} | |
fn ampself_notation_wrong (&self) { | |
check_ref::<Slf>(self); | |
assert!(self == &Slf); | |
/* => self is a ref */ | |
} | |
// fn ampself_notation_right (&self) { | |
// check_ref::<Slf>(&self); | |
// /* => self is indeed a ref */ | |
// } | |
fn refself_notation (ref slf: Self) { | |
check_ref::<Self>(slf); | |
assert!(slf == &Slf); | |
/* => self is a ref */ | |
} | |
} | |
#[test] | |
fn self_case () | |
{ | |
/* inputs taken */ | |
Slf::amptype_notation(&Slf); // a ref | |
Slf::ampself_notation_wrong(&Slf); // a ref | |
Slf::refself_notation(Slf); // owned value | |
/* ===== (&self) vs (self: &Self) -> THE SAME TYPE !?? ===== */ | |
} | |
#[test] | |
fn bonus_refself_move_semantics () | |
{ | |
let slf = Slf; | |
Slf::refself_notation(slf); /* slf moved here */ | |
// Slf::refself_notation(slf); /* value cannot be used after move */ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment