RFC-0160:取消对 FIDL 结构体默认值的支持 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 此 RFC 提议移除在 FIDL 结构体字段上指定默认值的功能。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021-12-29 |
审核日期(年-月-日) | 2022-05-17 |
摘要
此 RFC 提议移除在 FIDL 上指定默认值的功能 struct 字段。
设计初衷
目前可以在结构体字段上指定默认值,如 如以下示例中所示:
type MyStruct = struct{
x int8 = 123; // 123 is the default value
};
目的是让结构体默认值成为所有绑定 对未分配字段应用相同的值,从而产生一致的 行为然而,在实践中并非如此。 目前,只有 HLCPP 和 Dart 绑定实际支持结构体默认值 值。事实上,在 Go 等一些绑定中, 需要重构网域对象以支持默认设置 因为没有语言级别的字段默认值支持。
此外,虽然请求和响应结构体的 FIDL 语言中指定的值,则会被忽略,并为 请求和响应缺少默认值。这不仅仅是因为 在当前阶段,我们很难提供默认值, API。例如,在 C++ 绑定中,通过函数调用进行回复 但 C++ 仅支持函数调用形参的尾随默认实参。
表和联合不支持字段,这增加了一致性 因为添加支持时会比较复杂和微妙, 可进化类型在绑定和实现方面的差异甚至更大 比结构体更复杂一些。
因此,对于没有明确路径的默认值的支持不一致 获得全面支持。应避免继续提供不一致的 完全移除支持服务是更好的选择。
除了实现方面的顾虑之外, 移除对结构体默认值的支持。默认值更精细 常量不是由绑定用户明确分配的, 这种微妙之处可能会令用户感到惊讶并导致错误。用户 需要知道某个特定类型是否具有默认值,以及 给定绑定是否支持默认值,或者不知道如何使用给定类型, 相当复杂。
利益相关方
教员:hjfreyer@google.com
审核者:
ianloic@google.com、yifeit@google.com
已咨询:
azaslavsky@google.com、mkember@google.com
社交化:
通过 eng-council-discuss@fuchsia.dev 开展讨论
设计
无法在 FIDL 中的结构体字段中指定默认值。
实现
目前,13 个 FIDL 库中有 119 种结构体默认值, 使用非零值。
默认值将立即被弃用,之后最终 已移除。
在弃用阶段,“@allow_deprecation_struct_defaults” (或类似)注解将引入,以便在给定 文件。
随着时间的推移,我们将不再使用默认值,并且启用的指令 结构体默认值将随其一起移除。届时,我们会 已经彻底移除
性能
不会对性能产生任何影响。
工效学设计
在支持生成默认值的绑定中,此 RFC 可能看起来 在人体工程学方面,但是,移除结构体默认支持 可以提高绑定之间的一致性,并且许多用例可以被替换 以及常量。
向后兼容性
此 RFC 会破坏对现有功能的支持,但 将涉及很长的弃用期,从而降低影响。
关于 FIDL 源代码更改的兼容性,此 RFC 消除了 结构体默认值的变化会导致复杂的行为变化 很难推断例如,明确设置 现在,初始默认值的行为与未设置的代码不同 一个默认值此外,在不同的情况下,可能希望 将所有值更改为新的默认值,或将所有值更改为 未更改。
安全注意事项
移除默认设置可能会带来安全风险,因为 在这种情况下,默认值可能是初始化原本未初始化的内存。不过, 但实际情况并非如此。HLCPP 和 Dart 目前支持默认值,请确保结构体字段已初始化 而不考虑是否提供默认值。
因此,应该不会对安全性产生实质性的影响。
隐私注意事项
不会对隐私造成任何影响。
测试
在弃用阶段,将添加测试以确保没有新的结构体 默认选项。
文档
结构体默认值功能的文档将被移除。
缺点、替代方案和未知问题
文档的默认值
一些用户在文档中使用结构体默认值来代替注释。 默认结构体字段值具有更正式的优势 并经过类型检查。不过,如果没有默认值 则系统仍然有可能记录用户应 对字段进行初始化,但应通过注释或常量来完成。 定义。
与常量的比较
在使用常量的情况下,默认值可以优于常量 作为默认设置默认值会将值附加到字段,而不是 则视为全局变量,并自动应用默认值 需要由用户手动指定
尽管如此,默认值还是可以替换为更明确的常量 只需要用户多做一点工作
更具表现力的常量
常量在未来可能会更具表现力, 可以定义结构体常量。
例如:
type MyStruct = struct { x int8; };
const DEFAULT_MY_STRUCT = MyStruct{ x: 123 };
然后,在绑定中,可以将 DEFAULT_MY_STRUCT
复制到变量中
(例如 Go 中的 myStruct := DEFAULT_MY_STRUCT
)并用作基础值,
哪些字段可以设置这与
结构体,但应该更容易跨绑定提供更广泛的支持。
替代方案:为默认设置添加更广泛的支持
可以考虑为默认值添加更广泛的绑定支持, 作为弃用的替代方案不过,这并不切实际。
考虑出发。生成的结构体如下所示:
type MyStruct struct {
_ struct{}
X int8
}
无法通过此 API 自动填充默认值。 此外,这些字段不能“取消设置”,因此 未设置字段,并在编码阶段填充默认值。主要 需要调整 API 结构以支持默认设置。
替代方案:对 FIDL 提供零值支持
某些语言(如 Go)和某些编码格式(如协议缓冲区) 3 的概念为零值。也就是说,未初始化的字段接受 规范的“zero”值(通常为 0)。
可以考虑向 FIDL 添加对零值的支持。一方面 这会提高内存安全性,但另一方面,支持零值 可能与 FIDL 的“只需为实际用量付费”的原则相冲突。 虽然在某些情况下或许可以避免额外的工作,但在其他情况下, 可能是一个额外的步骤,用于确保未设置的值为零。
如今,是否初始化字段都属于绑定级别问题, 对于应该采取什么行为,并没有最高级别的要求。对于 例如,Go 语言会将所有未设置的结构字段清零,但 FIDL 不会 必须这样做。
这可能已经足够。零值是否生效取决于 用户是如何与绑定 API 交互的 因此绑定 API 看似合理 单独决定在未设置某个字段时会出现什么情况。部分 绑定可能会要求必须明确设置所有字段,这意味着 没有默认值。
大约一半的现有 FIDL 结构体默认值为零,一半不是。 这意味着大约一半的现有结构体默认值仍然需要 否则,其值将需要“重新校准”以零为中心 (例如,使用从 0 开始的索引,而不是从 1 开始的索引)。
跨绑定共享零值的概念将赋予 FIDL 中的值零,这在某些协议中可能很重要,但对 其他。在许多情况下,可取的做法可能是明确定义,并使用 常数。为此, 无论该常量值实际上是否是默认值。
此 RFC 的主要目标是阻止广泛使用某个故障功能。 考虑到这一点,以及具有约束力的零价值强制性授权具有不明确的好处 默认值,所以我们的文档中不包含对零值概念的介绍, 此 RFC 的设计
先验技术和参考资料
Protocol Buffers 版本 3 ( 查看文档 ),并已替换为零值默认值。 有多种原因可能会导致这一变化。其中一个原因是 没有默认值,因此可以使用 "普通的旧结构体"缺少访问函数 (链接)。 另一个原因是,我们发现大部分使用 会将默认值分配给零值。
在 FTP-047“必需表字段”遭拒,但支持默认 已提议使用表格字段的值。这只是整个提案的一部分 因此拒绝并不一定意味着默认 值。