[IDEA] Implied enum types

That disagrees with the following code:

use std::borrow::Borrow;
use std::collections::BTreeMap;

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
enum KeyType {
    One,
    Two,
}

impl Default for KeyType {
    fn default() -> Self {
        Self::One
    }
}

#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
enum KeyWrapper {
    Alpha(KeyType),
    Beta(KeyType),
}

impl Default for KeyWrapper {
    fn default() -> Self {
        Self::Alpha(KeyType::One)
    }
}

impl Borrow<KeyType> for KeyWrapper {
    fn borrow(&self) -> &KeyType {
        match self {
            Self::Alpha(ty) => &ty,
            Self::Beta(ty) => &ty,
        }
    }
}

fn main() {
    let mut map = BTreeMap::new();
    map.insert(KeyWrapper::Alpha(KeyType::One), "unus");
    map.insert(KeyWrapper::Alpha(KeyType::Two), "duo");
    
    let lookup_key = Default::default();
    
    println!("{:?}", map.get(&lookup_key));
}

(see Rust Playground).

As-is, this code does not compile, because there are two types that lookup_key could be. If you remove the impl Borrow<KeyType> for KeyWrapper, the code compiles.

And this is the problem case, as far as I'm concerned. I've added an extra trait implementation, which causes lookup_key to go from "can only be KeyWrapper" to "can be KeyType or KeyWrapper", and thus causing type inference of Default::default() to fail. To avoid this, you'd need a different rule for enums than is used elsewhere, otherwise adding a trait implementation could cause this very same class of breakage.

1 Like