carbon-lang
carbon-lang copied to clipboard
Does struct field order matter for impl lookup and type structure?
Summary of issue:
interface Z {
let X:! type;
}
impl {.a: (), .b: ()} as Z where .X = i32 {}
impl {.b: (), .a: ()} as Z where .X = i64 {}
fn F() {
let x: auto = 1 as ({.a: (), .b: ()} as Z).X;
let y: auto = 1 as ({.b: (), .a: ()} as Z).X;
}
Is this an error because the two impls overlap? If not, is the type of x i32 and the type of y i64?
Details:
No response
Any other information that you want to share?
No response
I want to add that structs with different fields orders but the same names are different types, but are implicitly convertible.
https://carbon.godbolt.org/z/hPdvY1e53
fn F() {
let a: {.a: (), .b: ()} = {.b = (), .a = ()};
}
Here we see two types:
%struct_type.a.b: type = struct_type {.a: %empty_tuple.type, .b: %empty_tuple.type} [concrete]
%struct_type.b.a: type = struct_type {.b: %empty_tuple.type, .a: %empty_tuple.type} [concrete]
And a conversion between them:
%.loc3_48.1: %struct_type.b.a = struct_literal (%.loc3_38, %.loc3_47)
%struct: %struct_type.a.b = struct_value (%.loc3_48.2, %.loc3_48.3) [concrete = constants.%struct]
%.loc3_48.4: %struct_type.a.b = converted %.loc3_48.1, %struct [concrete = constants.%struct]
I think the "different types but convertible" model is going to be the simplest choice here. I also think it's going to be necessary in some cases -- the field order affects things like the layout of the struct, and unless we want to revisit that, we need impls for types with different field orders to be different.
Let's call this decided with "different types but convertible", with rationale as provided previously.
Great, thanks!