Partially applied default generics?

I wonder if it's possible to partially apply generics or there is a proposal for that.

Consider following code

#[derive(Default)]
struct Foo<T = i32, U = u64> {
    a: T,
    b: U,
}

fn main() {
    let foo: Foo<U=String> = Default::default();
}

It fails to compile because it seems to be invalid Rust code. What do I want is change U generic to String, but keep all the other generics as their defaults. In this particular example I could create a type alias and write type manually, but in real case there could be multiple arguments and making alias for each one would be inpractical.

1 Like

A possible solution:

#![feature(associated_type_defaults)]

trait Bar {
    type T = i32;
    type U = u64;
}

#[derive(Default)]
struct Foo<B: Bar> {
    a: B::T,
    b: B::U,
}

#[derive(Default)]
struct BarImpl;

impl Bar for BarImpl {
    type U = String;
}

fn main() {
    let foo: Foo<BarImpl> = Default::default();
}

However, as you see, it requires the Nightly channel.

Well I wouldn't call it a solution because it has absolutely different meaning. E.g. it won't work for external types where Foo has original signature.

This sounds like an extension to the language's syntax/semantics that just hasn't been implemented yet.

You may want to ask on the internals forum because that's where a lot of language design happens, and people who work on the compiler may be able to point you to solutions or a RFC.

Default type arguments on structs are a pretty niche feature that I haven't really seen outside of things like std::collections::HashMap. What sort of situations are you trying to use it in?

EDIT: I found the original RFC for default type parameters. Maybe you'll be able to find your answer there?

In my situation I'd like to encode optionality on fields by putting them into generic Something like

struct Foo<A,B> {
    foo: A<i32>,
    bar: B<bool>
}

Although Rust doesn't have GAT's yet so it's just like foo: A, bar: B.

Thanks for links

Optionality in this case can be handled by wrapping each field type in an Option<T> so e.g. Option<i32>.

It won't work because sometimes I statically know that it's not None and I don't want to call unwrap. Parse don't validate and stuff.

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