This thread, and I think there was one other inbetween. Documentation on where they work, where they don't, and how it relates to inference would be a nice start -- at least, I failed to find any. There's a couple links in those comments; this issues about on how RFC 213 stalled out I think is the main one highlighting shortfalls. There are other issues linked in those discussions in turn (e.g. a documentation request and another one, this bug, and so on).
I was playing around with variations and came up with two more I don't think have been mentioned yet:
#[derive(Debug, Default)]
struct StructName<A = u32, B = String> {
field_a: A,
field_b: B,
}
fn main() {
let a = StructName::<_> {
field_a: String::from("Spring"),
..StructName::default()
};
println!("{:?}", a);
}
and
#[derive(Debug, Default)]
struct StructName<A = u32, B = String> {
field_a: A,
field_b: B,
}
fn main() {
let a = StructName {
field_a: String::from("Spring"),
..StructName::<_>::default()
};
println!("{:?}", a);
}
This one looks a bit more readable to me:
#[derive(Debug, Default)]
struct StructName<A = u32, B = String> {
field_a: A,
field_b: B,
}
fn main() {
let a = StructName::<_> {
field_a: String::from("Spring"),
..Default::default()
};
println!("{:?}", a);
}
Unfortunately, this is just a special case, the same as the one I described above. We have to write the required number of underscores. This is not a general solution. This will not work in many other cases, for example:
#[derive(Debug, Default)]
struct StructName<A = u32, B = String, C = bool> {
field_a: A,
field_b: B,
field_c: C,
}
fn main() {
let a = StructName::<_> {
field_a: String::from("Spring"),
field_b: true,
..<_>::default()
};
println!("{:?}", a);
}
Error:
mismatched types
--> src/main.rs:12:18
|
12 | field_b: true,
| ^^^^
| |
| expected struct `String`, found `bool`
| help: try using a conversion method: `true.to_string()`
The reason for this behavior is as follows:
We use the struct update syntax:
#[derive(Debug)]
struct StructName{
field_a: u32,
field_b: String,
field_c: bool,
}
fn main() {
// Type of this struct: `StructName<u32, String, bool>`
let defaulted_struct = StructName {
field_a: 42,
field_b: String::from("Spring"),
field_c: true,
};
// Type of this struct: `StructName<u32, String, bool>`
let a = StructName {
field_a: 2,
field_b: String::from("Summer"),
..defaulted_struct
};
println!("{:?}", a);
}
It's okay, because the types of structures are the same.
Instead of defaulted_struct
, we can use a method Default::default()
that will return a concrete structure with concrete types.
This example works (this is just a special case with comments, not a general solution):
#[derive(Debug, Default)]
struct StructName<A = u32, B = String, C = bool> {
field_a: A,
field_b: B,
field_c: C,
}
fn main() {
// Type of this struct: `StructName<u32, String, bool>`
let defaulted_struct = StructName {
..Default::default()
};
/*
// Commented code below will result in an error
// because `defaulted_struct` has type `StructName<u32, String, bool>
//
// Type of this struct: `StructName<String, bool, _>`
let a = StructName {
field_a: String::from("Spring"),
field_b: true,
..defaulted_struct
};
*/
// This is a different structure because their types are different
// We cannot use the struct update syntax
// for structures of different types.
// For this to be possible, we must use StructName::<_, _>
// But, this is very inconvenient, because
// the number of underscores must correspond
// to the number of filled fields.
// It works:
// `defaulted_struct` type: `StructName<u32, String, bool>`
// new struct type: `StructName<String, bool, _>`
let a = StructName::<_, _> { // we ignore (I think so) the first
// two types of `defaulted_struct`
// with `StructName::<_, _>`
field_a: String::from("Spring"),
field_b: true,
..defaulted_struct
};
println!("{:?}", a);
}
I am thinking of implementing default types for generics with trait bounds for a finite number of listed types (since negative bounds do not exist), and procedural macros to generate this.
You could do:
#[derive(Debug, Default)]
struct StructName<A = u32, B = String, C = bool> {
field_a: A,
field_b: B,
field_c: C,
}
fn main() {
let a = StructName::<_,_> {
field_a: String::from("Spring"),
field_b: true,
..Default::default()
};
println!("{:?}", a);
}
Sure. I wrote this as an example to make it clearer how it works.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.