Why access subtyping is not allowed in type extensions?

I just tried it in playground, and it doent. [Rust Playground]

Yes, realized that just now, editted. This has nothing to do with sub-typing though.

7 | impl &Animal {}
  |      ^^^^^^^ impl requires a base type

impl requeres a base type error screams about presence of sybtyping

Base type here has nothing to do with subtyping, maybe the error should be reworded to alleviate the confusion. It is trying to tell you that you didn't define &_ so you can't add inherent impls to &_

see the note:

note: either implement a trait on it or create a newtype to wrap it instead

also see rustc --explain E0118, which explains the error message more clearly

$ rustc --explain E0118 An inherent implementation was defined for something which isn't a struct nor an enum.

Erroneous code example:

impl (u8, u8) { // error: no base type found for inherent implementation
    fn get_state(&self) -> String {
        // ...
    }
}

To fix this error, please implement a trait on the type or wrap it in a struct. Example:

// we create a trait here
trait LiveLongAndProsper {
    fn get_state(&self) -> String;
}

// and now you can implement it on (u8, u8)
impl LiveLongAndProsper for (u8, u8) {
    fn get_state(&self) -> String {
        "He's dead, Jim!".to_owned()
    }
}

Alternatively, you can create a newtype. A newtype is a wrapping tuple-struct. For example, NewType is a newtype over Foo in struct NewType(Foo). Example:

struct TypeWrapper((u8, u8));

impl TypeWrapper {
    fn get_state(&self) -> String {
        "Fascinating!".to_owned()
    }
}
3 Likes

I opened an issue to suggest improving the "base type" wording to be less subtype/inheritance suggestive. Instead, noting that this is not a "local type" alongside what that means (roughly) would probably be a better on-ramp.

8 Likes

I think one could also argue that atomic types (and their ilk) not requiring let mut to be modified is an inconsistency. From the Rust book:

In Rust, the compiler guarantees that when you state that a value won’t change, it really won’t change.

This promise is ostensibly broken by atomic types:

// For reasons, this must be immutable. 
let a = AtomicU32::new(32u32);      // no `let mut`, so TOTALLY immutable!
a.store(64u32, Ordering::Relaxed);  // This still compiles!?! WHAAaaa?

In fact, if you declare that variable with let mut you even get a warning: variable does not need to be mutable, which I think can further the confusion.

This is because &mut really means &unique and & really means &shared. Mutability is just a simplification that we use when teaching beginners to reduce the weirdness factor of the language a bit, at the cost of people later having to un-learn this semi-lie when they become more familiar with the language.

5 Likes

So you mean it is possible to break any guaranties that type system provides?

This then moves the confustion back to the "simple mutability view". However, this is really a separate discussion from this topic.

I opened a new question entry at users.rust-lang.org to discuss further.

2 Likes

Moderator note: This discussion is now mainly about clarifying how Rust works today, and would probably be better as help questions on the users forum.

4 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.