From 48c295150f98ba9c723ea978fee2e34b997e3126 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Wed, 13 Apr 2022 17:38:26 +0200 Subject: [PATCH] checker: fixes typechecking for a sum type with an alias type (#13974) --- vlib/v/ast/table.v | 53 ++++++++++++++----- ...mbination_of_alias_and_sumtype.c.must_have | 1 + .../check_combination_of_alias_and_sumtype.vv | 32 +++++++++++ .../testdata/cast_aliases_on_generics_type.vv | 6 +-- 4 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 vlib/v/gen/c/testdata/check_combination_of_alias_and_sumtype.c.must_have create mode 100644 vlib/v/gen/c/testdata/check_combination_of_alias_and_sumtype.vv diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index e9d0028f1e..53a489ab4b 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1280,25 +1280,54 @@ pub fn (t &Table) sumtype_has_variant(parent Type, variant Type, is_as bool) boo if parent_sym.kind == .sum_type { parent_info := parent_sym.info as SumType var_sym := t.sym(variant) - if var_sym.kind == .aggregate { - var_info := var_sym.info as Aggregate - for var_type in var_info.types { - if !t.sumtype_has_variant(parent, var_type, is_as) { - return false - } + match var_sym.kind { + .aggregate { + return t.sumtype_check_aggregate_variant(parent, variant, is_as) } - return true - } else { - for v in parent_info.variants { - if v.idx() == variant.idx() && (!is_as || v.nr_muls() == variant.nr_muls()) { - return true - } + .alias { + return t.sumtype_check_alias_variant(parent, variant, is_as) + } + else { + return t.sumtype_check_variant_in_type(parent_info, variant, is_as) } } } return false } +fn (t &Table) sumtype_check_variant_in_type(parent_info SumType, variant Type, is_as bool) bool { + for v in parent_info.variants { + if v.idx() == variant.idx() && (!is_as || v.nr_muls() == variant.nr_muls()) { + return true + } + } + return false +} + +fn (t &Table) sumtype_check_aggregate_variant(parent_type Type, aggregate_type &Type, is_as bool) bool { + aggregate_sym := t.sym(aggregate_type).info as Aggregate + for var_type in aggregate_sym.types { + if !t.sumtype_has_variant(parent_type, var_type, is_as) { + return false + } + } + return true +} + +fn (t &Table) sumtype_check_alias_variant(parent_type Type, alias_type Type, is_as bool) bool { + parent_sym := t.sym(parent_type).info as SumType + if !t.sumtype_check_variant_in_type(parent_sym, alias_type, is_as) { + alias_info := t.sym(alias_type).info as Alias + // The alias is an alias or of the same sumtype parent, or one + // of the SumType variant. e.g: alias of another sum type. + // https://github.com/vlang/v/issues/14029 + return parent_type == alias_info.parent_type + || t.sumtype_has_variant(parent_type, alias_info.parent_type, is_as) + } + // the alias_type is inside one of the variant of the sum type + return true +} + pub fn (t &Table) is_sumtype_or_in_variant(parent Type, typ Type) bool { if typ == 0 { return false diff --git a/vlib/v/gen/c/testdata/check_combination_of_alias_and_sumtype.c.must_have b/vlib/v/gen/c/testdata/check_combination_of_alias_and_sumtype.c.must_have new file mode 100644 index 0000000000..24f0673eeb --- /dev/null +++ b/vlib/v/gen/c/testdata/check_combination_of_alias_and_sumtype.c.must_have @@ -0,0 +1 @@ +// THE END. diff --git a/vlib/v/gen/c/testdata/check_combination_of_alias_and_sumtype.vv b/vlib/v/gen/c/testdata/check_combination_of_alias_and_sumtype.vv new file mode 100644 index 0000000000..7fa58f5183 --- /dev/null +++ b/vlib/v/gen/c/testdata/check_combination_of_alias_and_sumtype.vv @@ -0,0 +1,32 @@ +type ParseRes = Result<[]Token, ParseErr> + +struct ParseErr {} + +type Opt = None | Some + +struct None {} + +struct Some { + value T +} + +type Result = Err | Ok + +struct Ok { + value T +} + +struct Err { + value U +} + +fn main() { + r := Opt(None{}) + match r { + Some { + // make possible cast fo the same type! + rx := Result<[]Token, ParseErr>(r.value) + } + None {} + } +} diff --git a/vlib/v/tests/known_errors/testdata/cast_aliases_on_generics_type.vv b/vlib/v/tests/known_errors/testdata/cast_aliases_on_generics_type.vv index dbfe25977c..05cbbad4f1 100644 --- a/vlib/v/tests/known_errors/testdata/cast_aliases_on_generics_type.vv +++ b/vlib/v/tests/known_errors/testdata/cast_aliases_on_generics_type.vv @@ -1,8 +1,6 @@ type ParseRes = Result<[]Token, ParseErr> -struct ParseErr{ - -} +struct ParseErr {} type Opt = None | Some @@ -26,7 +24,7 @@ fn test_report() { r := Opt(None{}) match r { Some { - rx := Result<[]Token, ParseErr>(r) + rx := Result<[]Token, ParseErr>(r.value) } None {} }