Default trait implementation and PhantomData


#1

Not sure if it is the right place to ask, but I’ll try :slight_smile:

I’m struggling with default trait implementation in type parameters of structure, which stores it as PhantomData.

Here is the snippet that illustrates the problem:

use std::marker::PhantomData;

trait Trait {}
struct Struct;

impl Trait for Struct {}

struct GenericStruct<T: Trait = Struct> {
    _marker: PhantomData<T>
}

impl<T: Trait> GenericStruct<T> {
    fn new() -> Self {
        GenericStruct {
            _marker: PhantomData
        }
    }
}

fn main() {
    GenericStruct::new();
}

https://play.rust-lang.org/?gist=7b3c32d39600a2de0df08593ced9134d&version=stable&mode=debug

Rustc says that it cannot infer the type. Why so? And what can I do in this situation to not to have an API that asks the user to make explicit annotation for the default implementation of the trait I ship within the crate?

Thanks!


#2

If you change the line in the main function to:

<GenericStruct<>>::new();

it compiles and runs. I think the GenericStruct by itself isn’t considered a concrete type, because it is generic, even though its only argument is defaulted. You need to use the “<>” syntax to actually instantiate a concrete GenericStruct<Struct>.


#3

Yes I noticed this as well in one of my projects and to be honest I don’t really get why it is this way. Would there be any problem with allowing you to leave out the <> when all generic types have a default?


#4

<GenericStruct>::new() is enough, the empty angle brackets are not necessary.
It moves GenericStruct from “value context” where inference is used to “type context” where defaults for type parameters are used.
Ideally, type inference should fall back to using default type parameters somehow, but it’s not clear how exactly this should be done (the recent iteration can be found in https://github.com/rust-lang/rfcs/pull/2321).


#5

Thanks! Unfortunately the <GenericStruct>::new() is not working in my case, I have 4 type parameters actually, one default and 3 infered from context.