diff --git a/src/ast/transform/TypeChecker.cpp b/src/ast/transform/TypeChecker.cpp index c639cd3ce3b..c482aac95b5 100644 --- a/src/ast/transform/TypeChecker.cpp +++ b/src/ast/transform/TypeChecker.cpp @@ -383,10 +383,12 @@ void TypeCheckerImpl::visit_(type_identity, const Atom& atom) { // Declared attribute and deduced type agree if: // They are the same type, or // They are derived from the same constant type. + // They are equivalent types. bool validAttribute = all_of(argTypes, [&](const analysis::Type& type) { - return type == attributeType || any_of(typeEnv.getConstantTypes(), [&](auto& constantType) { - return isSubtypeOf(attributeType, constantType) && isSubtypeOf(type, constantType); - }); + return type == attributeType || areEquivalentTypes(type, attributeType) || + any_of(typeEnv.getConstantTypes(), [&](auto& constantType) { + return isSubtypeOf(attributeType, constantType) && isSubtypeOf(type, constantType); + }); }); if (!validAttribute) { diff --git a/tests/syntactic/CMakeLists.txt b/tests/syntactic/CMakeLists.txt index 54b4c660824..8754a6fbeeb 100644 --- a/tests/syntactic/CMakeLists.txt +++ b/tests/syntactic/CMakeLists.txt @@ -66,6 +66,7 @@ positive_test(dot_identifiers) positive_test(input_adt_names1) positive_test(input_adt_names2) positive_test(input_directive_rfc4180) +positive_test(equivalent_types_in_negation) if (NOT MSVC) # does not pass with Visual Studio pre-processor because it preserves all whitespaces positive_test(whitespaces) diff --git a/tests/syntactic/equivalent_types_in_negation/equivalent_types_in_negation.dl b/tests/syntactic/equivalent_types_in_negation/equivalent_types_in_negation.dl new file mode 100644 index 00000000000..d6a8c8e0297 --- /dev/null +++ b/tests/syntactic/equivalent_types_in_negation/equivalent_types_in_negation.dl @@ -0,0 +1,28 @@ +.type List = [name: symbol, rest: List] +.decl list_decl(l:List) +list_decl(["A", ["B", ["C", nil]]]). +list_decl(["D", ["E", ["F", nil]]]). + +.type Alias = List + +.decl flatten_list(l:List) +.output flatten_list +flatten_list(l) :- list_decl(l). +flatten_list(l) :- flatten_list([_, l]). + +.decl alias_map(a: Alias, l:List) +alias_map(l, l) :- + flatten_list(l). + +.decl alias(a: Alias) +alias(a) :- alias_map(a, _). + +.decl parent(a: Alias, p: Alias) +.output parent +parent(a, p) :- + alias_map(a, [_, parent]), + alias_map(p, parent). + +.decl has_no_parent(a: Alias) +has_no_parent(a) :- + alias(a), !parent(a, _). // No more error here diff --git a/tests/syntactic/equivalent_types_in_negation/equivalent_types_in_negation.err b/tests/syntactic/equivalent_types_in_negation/equivalent_types_in_negation.err new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/syntactic/equivalent_types_in_negation/equivalent_types_in_negation.out b/tests/syntactic/equivalent_types_in_negation/equivalent_types_in_negation.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/syntactic/equivalent_types_in_negation/flatten_list.csv b/tests/syntactic/equivalent_types_in_negation/flatten_list.csv new file mode 100644 index 00000000000..b0293a814a7 --- /dev/null +++ b/tests/syntactic/equivalent_types_in_negation/flatten_list.csv @@ -0,0 +1,7 @@ +nil +[C, nil] +[B, [C, nil]] +[A, [B, [C, nil]]] +[F, nil] +[E, [F, nil]] +[D, [E, [F, nil]]] diff --git a/tests/syntactic/equivalent_types_in_negation/parent.csv b/tests/syntactic/equivalent_types_in_negation/parent.csv new file mode 100644 index 00000000000..3cba1622e9c --- /dev/null +++ b/tests/syntactic/equivalent_types_in_negation/parent.csv @@ -0,0 +1,6 @@ +[C, nil] nil +[B, [C, nil]] [C, nil] +[A, [B, [C, nil]]] [B, [C, nil]] +[F, nil] nil +[E, [F, nil]] [F, nil] +[D, [E, [F, nil]]] [E, [F, nil]]