From f70d9fb7b8120067677e024153efb3e80575ab31 Mon Sep 17 00:00:00 2001 From: Michael Tingley Date: Tue, 7 Mar 2017 11:23:08 -0800 Subject: [PATCH] Implement HHVM type structure correctness for unknown shape fields Summary: The type structure now prints and represents shapes with unknown fields correctly. A shape that allows unknown fields is indicated by having a field `allows_unknown_fields=true` in the type structure, and their field list is printed with a following `...`. Reviewed By: paulbiss Differential Revision: D4613828 fbshipit-source-id: bc93e41983d3f556843b3fc197ec5ee7f204cf79 --- hphp/compiler/type_annotation.cpp | 6 ++++++ hphp/runtime/base/type-structure.cpp | 9 +++++++++ .../shape_typedef_with_known_and_unknown_fields.php.expect | 6 ++++-- .../type_annotation/shape_typedef_with_unknown_fields.php.expect | 6 ++++-- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/hphp/compiler/type_annotation.cpp b/hphp/compiler/type_annotation.cpp index 424a53bc215..01d3b736279 100644 --- a/hphp/compiler/type_annotation.cpp +++ b/hphp/compiler/type_annotation.cpp @@ -330,6 +330,7 @@ const StaticString s_root_name("root_name"), s_access_list("access_list"), s_fields("fields"), + s_allows_unknown_fields("allows_unknown_fields"), s_is_cls_cns("is_cls_cns"), s_optional_shape_field("optional_shape_field"), s_value("value"), @@ -379,6 +380,11 @@ Array TypeAnnotation::getScalarArrayRep() const { rep.add(s_nullable, true_varNR); } + bool allowsUnknownFields = (bool) m_allowsUnknownFields; + if (allowsUnknownFields) { + rep.add(s_allows_unknown_fields, true_varNR); + } + TypeStructure::Kind kind = getKind(); rep.add(s_kind, Variant(static_cast(kind))); diff --git a/hphp/runtime/base/type-structure.cpp b/hphp/runtime/base/type-structure.cpp index e3b327b73b2..efccce27985 100644 --- a/hphp/runtime/base/type-structure.cpp +++ b/hphp/runtime/base/type-structure.cpp @@ -52,6 +52,7 @@ const StaticString s_root_name("root_name"), s_access_list("access_list"), s_fields("fields"), + s_allows_unknown_fields("allows_unknown_fields"), s_is_cls_cns("is_cls_cns"), s_optional_shape_field("optional_shape_field"), s_value("value"), @@ -196,6 +197,10 @@ void shapeTypeName(const Array& arr, std::string& name) { sep = ", "; } + if (arr.exists(s_allows_unknown_fields)) { + folly::toAppend(sep, "...", &name); + } + name += ")"; } @@ -510,6 +515,10 @@ Array resolveTS(const Array& arr, if (arr.exists(s_nullable)) newarr.add(s_nullable, true_varNR); newarr.add(s_kind, Variant(static_cast(kind))); + if (arr.exists(s_allows_unknown_fields)) { + newarr.add(s_allows_unknown_fields, true_varNR); + } + switch (kind) { case TypeStructure::Kind::T_tuple: { assert(arr.exists(s_elem_types)); diff --git a/hphp/test/slow/type_annotation/shape_typedef_with_known_and_unknown_fields.php.expect b/hphp/test/slow/type_annotation/shape_typedef_with_known_and_unknown_fields.php.expect index deff12ffd20..242b94016f1 100644 --- a/hphp/test/slow/type_annotation/shape_typedef_with_known_and_unknown_fields.php.expect +++ b/hphp/test/slow/type_annotation/shape_typedef_with_known_and_unknown_fields.php.expect @@ -1,7 +1,9 @@ -string(21) "HH\shape('a'=>HH\int)" -array(2) { +string(26) "HH\shape('a'=>HH\int, ...)" +array(3) { ["kind"]=> int(14) + ["allows_unknown_fields"]=> + bool(true) ["fields"]=> array(1) { ["a"]=> diff --git a/hphp/test/slow/type_annotation/shape_typedef_with_unknown_fields.php.expect b/hphp/test/slow/type_annotation/shape_typedef_with_unknown_fields.php.expect index 3513549252b..8a4d0989661 100644 --- a/hphp/test/slow/type_annotation/shape_typedef_with_unknown_fields.php.expect +++ b/hphp/test/slow/type_annotation/shape_typedef_with_unknown_fields.php.expect @@ -1,7 +1,9 @@ -string(10) "HH\shape()" -array(2) { +string(13) "HH\shape(...)" +array(3) { ["kind"]=> int(14) + ["allows_unknown_fields"]=> + bool(true) ["fields"]=> array(0) { } -- 2.11.4.GIT