diff --git a/src/Expr.cc b/src/Expr.cc index 6d08955113..9b32b535c7 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3977,7 +3977,7 @@ VectorConstructorExpr::VectorConstructorExpr(ListExprPtr constructor_list, TypeP return; } - if ( auto t = merge_type_list(op->AsListExpr()) ) + if ( auto t = maximal_type(op->AsListExpr()) ) SetType(make_intrusive(std::move(t))); else { diff --git a/src/Type.cc b/src/Type.cc index ae0cfddb66..c6029489b5 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -63,6 +63,11 @@ const char* type_name(TypeTag t) return type_names[int(t)]; } +// Given two types, returns the "merge", in which promotable types +// are promoted to the maximum of the two. Returns nil (and generates +// an error message) if the types are incompatible. +static TypePtr merge_types(const TypePtr& t1, const TypePtr& t2); + Type::Type(TypeTag t, bool arg_base_type) : tag(t), internal_tag(to_internal_type_tag(tag)), is_network_order(zeek::is_network_order(t)), base_type(arg_base_type) @@ -2673,7 +2678,7 @@ TypePtr merge_types(const TypePtr& arg_t1, const TypePtr& arg_t2) } } -TypePtr merge_type_list(detail::ListExpr* elements) +TypePtr maximal_type(detail::ListExpr* elements) { TypeList* tl_type = elements->GetType()->AsTypeList(); const auto& tl = tl_type->GetTypes(); @@ -2690,7 +2695,21 @@ TypePtr merge_type_list(detail::ListExpr* elements) return t; for ( size_t i = 1; t && i < tl.size(); ++i ) - t = merge_types(t, tl[i]); + { + auto& tl_i = tl[i]; + + if ( t == tl_i ) + continue; + + if ( BothArithmetic(t->Tag(), tl_i->Tag()) ) + t = merge_types(t, tl_i); + + else if ( t->Tag() == TYPE_ENUM && tl_i->Tag() == TYPE_ENUM ) + t = merge_enum_types(t.get(), tl_i.get()); + + else if ( ! same_type(t, tl_i) ) + t = nullptr; + } if ( ! t ) reporter->Error("inconsistent types in list"); diff --git a/src/Type.h b/src/Type.h index f9541fb1b7..96517a7727 100644 --- a/src/Type.h +++ b/src/Type.h @@ -923,15 +923,10 @@ extern Type* flatten_type(Type* t); // Returns the "maximum" of two type tags, in a type-promotion sense. extern TypeTag max_type(TypeTag t1, TypeTag t2); -// Given two types, returns the "merge", in which promotable types -// are promoted to the maximum of the two. Returns nil (and generates -// an error message) if the types are incompatible. -TypePtr merge_types(const TypePtr& t1, const TypePtr& t2); - -// Given a list of expressions, returns a (ref'd) type reflecting -// a merged type consistent across all of them, or nil if this -// cannot be done. -TypePtr merge_type_list(detail::ListExpr* elements); +// Given a list of expressions, returns the maximal type consistent across +// all of them, or nil if this cannot be done. "Maximal" incorporates +// notions of arithmetic coercion, but otherwise requires type-equivalence. +TypePtr maximal_type(detail::ListExpr* elements); // Given an expression, infer its type when used for an initialization. TypePtr init_type(const detail::ExprPtr& init); diff --git a/testing/btest/Baseline/language.vector-coerce-expr2/output b/testing/btest/Baseline/language.vector-coerce-expr2/output index d2ecf26c04..2b2db4ee2d 100644 --- a/testing/btest/Baseline/language.vector-coerce-expr2/output +++ b/testing/btest/Baseline/language.vector-coerce-expr2/output @@ -3,3 +3,13 @@ [11, 5, , 107, , , 1046] [-2, -4, , -7, , -18, -999] [, -1, 11, 15] +[connT +{ +return (T); +}, connF +{ +return (F); +}, connMaybe +{ +return (c$id$orig_p < c$id$resp_p); +}] diff --git a/testing/btest/language/vector-coerce-expr2.zeek b/testing/btest/language/vector-coerce-expr2.zeek index 96c4be43a4..a3ec7ed345 100644 --- a/testing/btest/language/vector-coerce-expr2.zeek +++ b/testing/btest/language/vector-coerce-expr2.zeek @@ -51,3 +51,30 @@ event zeek_init() print d; } + +type recursive: record { + placeholder: bool; +}; + +redef record recursive += { rec: table[count] of recursive &optional; }; + +function connT(c: connection, r: recursive): bool + { + return T; + } + +function connF(c: connection, r: recursive): bool + { + return F; + } + +function connMaybe(c: connection, r: recursive): bool + { + return c$id$orig_p < c$id$resp_p; + } + +event zeek_init() + { + local v = vector(connT, connF, connMaybe); + print v; + }