Skip to content

Commit

Permalink
frontend: Support named fields for class and enum patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Nov 8, 2024
1 parent c3af653 commit 45c5e20
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 28 deletions.
51 changes: 30 additions & 21 deletions dora-frontend/src/typeck/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,16 @@ fn check_pattern_enum(
ck.sa.report(ck.file_id, pattern.span(), msg);
}

let expected_types = variant
.fields
.iter()
.map(|f| specialize_type(ck.sa, f.parsed_type.ty(), &value_type_params))
.collect::<Vec<_>>();
check_subpatterns(ck, ctxt, pattern, &expected_types);
if variant.field_name_style.is_named() {
check_subpatterns_named(ck, ctxt, pattern, variant, &value_type_params);
} else {
let expected_types = variant
.fields
.iter()
.map(|f| specialize_type(ck.sa, f.parsed_type.ty(), &value_type_params))
.collect::<Vec<_>>();
check_subpatterns(ck, ctxt, pattern, &expected_types);
}
} else {
if !ty.is_error() {
let ty = ty.name(ck.sa);
Expand Down Expand Up @@ -397,13 +401,16 @@ fn check_pattern_class(
IdentType::Class(cls_id, value_type_params.clone()),
);

let expected_types = cls
.fields
.iter()
.map(|f| specialize_type(ck.sa, f.ty(), &value_type_params))
.collect::<Vec<_>>();

check_subpatterns(ck, ctxt, pattern, &expected_types);
if cls.field_name_style.is_named() {
check_subpatterns_named(ck, ctxt, pattern, cls, &value_type_params);
} else {
let expected_types = cls
.fields
.iter()
.map(|f| specialize_type(ck.sa, f.ty(), &value_type_params))
.collect::<Vec<_>>();
check_subpatterns(ck, ctxt, pattern, &expected_types);
}
} else {
if !ty.is_error() {
let ty = ty.name(ck.sa);
Expand Down Expand Up @@ -442,15 +449,15 @@ fn check_pattern_struct(
IdentType::Struct(struct_id, value_type_params.clone()),
);

let expected_types = struct_
.fields
.iter()
.map(|f| specialize_type(ck.sa, f.ty(), &value_type_params))
.collect::<Vec<_>>();

if struct_.field_name_style.is_named() {
check_subpatterns_named(ck, ctxt, pattern, struct_);
check_subpatterns_named(ck, ctxt, pattern, struct_, &value_type_params);
} else {
let expected_types = struct_
.fields
.iter()
.map(|f| specialize_type(ck.sa, f.ty(), &value_type_params))
.collect::<Vec<_>>();

check_subpatterns(ck, ctxt, pattern, &expected_types);
}
} else {
Expand All @@ -469,6 +476,7 @@ fn check_subpatterns_named<'a>(
ctxt: &mut Context,
pattern: &ast::PatternAlt,
element: &dyn ElementWithFields,
element_type_params: &SourceTypeArray,
) {
let params = match pattern {
ast::PatternAlt::ClassOrStructOrEnum(ref p) => p.params.as_ref(),
Expand Down Expand Up @@ -514,7 +522,8 @@ fn check_subpatterns_named<'a>(
if let Some(idx) = used_names.remove(&name) {
let field_pattern = &params[idx];
ck.analysis.map_field_ids.insert(field_pattern.id, field.id);
check_pattern_inner(ck, ctxt, &field_pattern.pattern, field.ty);
let ty = specialize_type(ck.sa, field.ty, element_type_params);
check_pattern_inner(ck, ctxt, &field_pattern.pattern, ty);
} else if !rest_seen {
let name = ck.sa.interner.str(name).to_string();
let msg = ErrorMessage::MissingNamedArgument(name);
Expand Down
14 changes: 7 additions & 7 deletions tests/language/pattern-rest3.dora
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
class Foo { a: Int64, b: Int64, c: Int64 }
class Foo(Int64, Int64, Int64)

fn main() {
assert(fst(Foo(a=1, b=3, c=7)) == 1);
assert(mid(Foo(a=1, b=3, c=7)) == 3);
assert(lst(Foo(a=1, b=3, c=7)) == 7);
assert(fst(Foo(1, 3, 7)) == 1);
assert(mid(Foo(1, 3, 7)) == 3);
assert(lst(Foo(1, 3, 7)) == 7);

assert(fst(Foo(a=7, b=4, c=1)) == 7);
assert(mid(Foo(a=7, b=4, c=1)) == 4);
assert(lst(Foo(a=7, b=4, c=1)) == 1);
assert(fst(Foo(7, 4, 1)) == 7);
assert(mid(Foo(7, 4, 1)) == 4);
assert(lst(Foo(7, 4, 1)) == 1);
}

fn fst(x: Foo): Int64 {
Expand Down

0 comments on commit 45c5e20

Please sign in to comment.