RFC-0036:结构体声明的更新

RFC-0036:结构体声明更新
状态已拒绝
领域
  • FIDL
说明

为了更好地传达重新排序和重命名字段的 ABI 含义,我们提议进行语法更改,为结构体字段引入序数,其语法规则与表的语法规则类似。

作者
提交日期(年-月-日)2019-03-07
审核日期(年-月-日)2019-03-14

遭拒原因

优点

  • 名称对 ABI 重要或不存在感到困惑: xunion、结构体和协议都看起来很相似,但 不同规则

缺点

  • 不过,所有人的担忧都远远超出了 在结构体上引入序数会加重您的困惑, 尤其是与 protobuf 相比。

  • 还有其他一些措施来解决“这会更改 ABI 吗”问题,即:

    • DIFL
    • API 差异,例如库签名
  • 名称对文本格式(JSON、FIDLText 等)和 不能更改名称。

摘要

为了更好地表达对字段重新排序和重命名对 ABI 产生的影响, 提出语法更改以引入结构体字段序数, 它们的语法规则与表的语法规则类似。

设计初衷

仅关注在 Google Cloud 中 存在语法差异,这些差异在逐渐 自然而然地,不要传达任何可能的 更改。

此外,当前的结构体声明语法使得 在发生更改时提供帮助和指导

我们来看一些示例,这些示例选择为小而统一:

struct Name {      table Name {        enum Name {
    T abc;           1: T abc;           ABC = 1;
    U xyz;           2: U xyz;           XYZ = 2;
};                 };                  };

protocol Name {    xunion Name {       bits Name {
    Abc(T t);        T abc;              ABC = 1;
    Xyz(U u);        U xyz;              XYZ = 2;
};                 };                  };

从 ABI 的角度来看一些观察结果:

  • 重新排序:可以对除结构体之外的所有项重新排序,没有任何影响。
  • 重命名: <ph type="x-smartling-placeholder">
      </ph>
    • 结构体、表、枚举和位可以重命名,不会影响
    • 并且重命名后,xunion 的 ABI 会受到影响。

(从源代码兼容性的角度来看,大多数绑定都是源代码的 在重新排序下兼容,而在重命名下不兼容。)

根据这些观察结果,我们提议引入一个 struct 声明。 现在,上面的示例为:

struct Name {
    1: T abc;
    2: U xyz;
};

具体而言:

  • 序数必须从 1 开始,序数空间中不允许出现间隙(如果 最大序数为 7,则 1、2、3、4、5、6、7 必须全部出现)。请参阅 原因
  • 不能两个字段声明相同的序号。
  • 字段序号决定了具有结构体的字段的位置,而不是 语法位置。
  • v1 中的 JSON IR 没有变化,顺序通过 结构体声明中成员的数量。请参阅计划在 v2 中对 JSON IR 进行的更改。

编译器指南

作为指南的例子,编译器可以通过 语法,我们考虑了一些示例并比较它们的处理方式。

移除字段(中间)

No Ordinals        With Ordinals
----------------   -------------
struct Name {      struct Name {
    T abc;           1: T abc;
-   U def;       -   2: U def;
    V ghi;           3: V ghi;
};                 };
----------------   ---------------
Breaks ABI, no     Breaks ABI,
compiler help      compiler error

移除字段 (end)

No Ordinals        With Ordinals
----------------   -------------
struct Name {      struct Name {
    T abc;           1: T abc;
    U def;           2: U def;
-   V ghi;       -   3: V ghi;
};                 };
----------------   ---------------
Breaks ABI, no     Breaks ABI, no
compiler help      compiler help

添加字段

No Ordinals        With Ordinals
----------------   -------------
struct Name {      struct Name {
    T abc;           1: T abc;
+   U def;       +   3: U def;
    V ghi;           2: V ghi;
};                 };
----------------   ---------------
Breaks ABI, no     Breaks ABI, no
compiler help      compiler error

对字段重新排序

No Ordinals        With Ordinals
----------------   -------------
struct Name {      struct Name {
+   U def;       +   2: U def;
    T abc;           1: T abc;
-   U def;       -   2: U def;
    V ghi;           3: V ghi;
};                 };
----------------   ---------------
Breaks ABI, no     Safe
compiler warning

禁止“已保留”关键字

由于我们要对齐表结构体的序数规则, 还是允许“预留”关键字。

我们应该执行完全相反的操作:正确解析对 保留关键字,并提供明确的编译器错误和说明。对于 实例“无法在结构体中预留成员。添加或移除成员 更改结构体布局,请考虑手动中立成员 初始化。”

此外,还有其他重要原因,不允许 “预留”关键字:

  1. 与表不同,在结构体中引入内边距时,必须通过 明确的大小(即字节数);
  2. 在结构体中使用填充是为了非常具体, 开发者需要特定的内存布局 这种用例很少见,甚至不存在,因为 FIDL 布局始终为 已对齐 8 个字节。
  3. 对于实现,我们已在 RFC-0066: 程序员警告明确默认值,可以保证 某些值过于严格,对于某些 绑定(例如 C、LLCPP)。 因此,我们是否应引入“预留”结构体中的槽, 我们需要将其公开给后端, 以进行适当的初始化 所有这些似乎都没有必要。

驾车上路 JSON IR

为了既支持字段排序(按序数),又支持对 文档目的(应遵循声明顺序), 最好是:

  • 将声明顺序表示为 “成员”键。
  • 通过引入序数 (ordinal) 来表示序数顺序键。

设计

待定

实施策略

  1. 引入对新语法的支持,同时支持 上一个;
  2. 将所有源文件迁移到新语法;
  3. 在使用之前的语法时添加一条警告,并在 1 周内 确保不再使用旧语法的新用途;
  4. 取消了对旧版语法的支持。

工效学设计

此方案将 ABI 的含义传达给了客户,改善了人体工学 通过语法来为开发者提供查看与此相反的观点 下文

文档和示例

至少:

向后兼容性

这并非源代码级向后兼容。 如需软迁移,请参阅实现策略

性能

无影响。

安全

无影响。

测试

fidlc 中进行单元测试,以便验证以下各项:

  • 解析;
  • 序数从 1 开始,不得有间隙;
  • JSON IR 没有变化。

缺点、替代方案和未知问题

替代方案:表的序数哈希

我们还考虑对表使用序数哈希:语法变化 会丢弃显式序数,使结构体成为唯一的声明 (而之前它位于协议和表中)。

首先,为结构体使用显式序数的好处将保持不变。 开发者仍然可以在语法上对字段重新排序, 序数表示 ABI 损坏。

其次,我们不太可能在探索中采取措施来移除序数 因为需要在运行时成本(性能较低)之间权衡取舍 超过人体工程学优势的不足。

缺点:结构体和表可能会混淆

结构体和表之间的语法收敛,并且简介 有些可能会将结构体与表混淆,并误以为 移除字段与 ABI 兼容。 删除结构体中间的字段会导致错误, 序数序列中出现的间隙,删除带有 最大序数将是静音的。

先验技术和参考资料

待定