fix double sorting in record layout

This commit is contained in:
Folkert 2021-08-07 12:25:56 +02:00
parent ff505f695c
commit 3ca2140b69

View file

@ -1209,11 +1209,22 @@ fn layout_from_flat_type<'a>(
}
Record(fields, ext_var) => {
// extract any values from the ext_var
// TODO short-circuit the sorting here
let fields_map: MutMap<_, _> = fields.sorted_iterator(subs, ext_var).collect();
// discard optional fields
let mut layouts = sort_stored_record_fields(env, fields_map);
let variables = fields
.sorted_iterator(subs, ext_var)
.filter_map(|(_, field)| {
// drop optional fields
match field {
RecordField::Optional(_) => None,
RecordField::Required(var) => Some(var),
RecordField::Demanded(var) => Some(var),
}
});
let layouts_it =
variables.map(|var| Layout::from_var(env, var).expect("invalid layout from var"));
let mut layouts = Vec::from_iter_in(layouts_it, arena);
if layouts.len() == 1 {
// If the record has only one field that isn't zero-sized,
@ -1392,43 +1403,6 @@ fn sort_record_fields_help<'a>(
sorted_fields
}
// drops optional fields
fn sort_stored_record_fields<'a>(
env: &mut Env<'a, '_>,
fields_map: MutMap<Lowercase, RecordField<Variable>>,
) -> Vec<'a, Layout<'a>> {
// Sort the fields by label
let mut sorted_fields = Vec::with_capacity_in(fields_map.len(), env.arena);
for (label, field) in fields_map {
let var = match field {
RecordField::Demanded(v) => v,
RecordField::Required(v) => v,
RecordField::Optional(_) => {
continue;
}
};
let layout = Layout::from_var(env, var).expect("invalid layout from var");
sorted_fields.push((label, layout));
}
sorted_fields.sort_by(|(label1, layout1), (label2, layout2)| {
let ptr_bytes = 8;
let size1 = layout1.alignment_bytes(ptr_bytes);
let size2 = layout2.alignment_bytes(ptr_bytes);
size2.cmp(&size1).then(label1.cmp(label2))
});
let mut result = Vec::with_capacity_in(sorted_fields.len(), env.arena);
result.extend(sorted_fields.into_iter().map(|t| t.1));
result
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum UnionVariant<'a> {
Never,