fix(check): record field access properly restricted to single constr types

This commit is contained in:
rvcas 2023-03-08 23:36:13 -05:00 committed by Lucas
parent ba4635a8b0
commit 553eb88d3d
3 changed files with 9 additions and 29 deletions

View File

@ -9,6 +9,7 @@
### Changed
- **aiken-lang**: block `Data` and `String` from unifying when casting
- **aiken-lang**: remove ability for a type with many variants with matching field labels and types to support field access
- **aiken-project**: tests filtering with `-m` during check now happens in `Project::collect_tests`
## [v0.0.29] - 2023-MM-DD

View File

@ -177,6 +177,7 @@ impl<'a> Environment<'a> {
},
);
}
Ok(Some(fields))
}
@ -1780,44 +1781,22 @@ fn get_compatible_record_fields<A>(
) -> Vec<(usize, &str, &Annotation)> {
let mut compatible = vec![];
if constructors.len() > 1 {
return compatible;
}
let first = match constructors.get(0) {
Some(first) => first,
None => return compatible,
};
'next_argument: for (index, first_argument) in first.arguments.iter().enumerate() {
for (index, first_argument) in first.arguments.iter().enumerate() {
// Fields without labels do not have accessors
let label = match first_argument.label.as_ref() {
Some(label) => label.as_str(),
None => continue 'next_argument,
None => continue,
};
// Check each variant to see if they have an field in the same position
// with the same label and the same type
for constructor in constructors.iter().skip(1) {
// The field must exist in all variants
let argument = match constructor.arguments.get(index) {
Some(argument) => argument,
None => continue 'next_argument,
};
// The labels must be the same
if argument.label != first_argument.label {
continue 'next_argument;
}
// The types must be the same
if !argument
.annotation
.is_logically_equal(&first_argument.annotation)
{
continue 'next_argument;
}
}
// The previous loop did not find any incompatible fields in the other
// variants so this field is compatible across variants and we should
// generate an accessor for it.
compatible.push((index, label, &first_argument.annotation))
}

View File

@ -745,7 +745,7 @@ Perhaps, try the following:
#[diagnostic(code("unknown::record_field"))]
#[diagnostic(help(
"{}",
suggest_neighbor(label, fields.iter(), "Did you forget to make it public?")
suggest_neighbor(label, fields.iter(), "Did you forget to make it public?\n\nAlso record access is only supported on types with one constructor.")
))]
UnknownRecordField {
#[label]