RFC-0044:可扩展方法参数 | |
---|---|
状态 | 已拒绝 |
领域 |
|
说明 | 如果需要可扩展性,我们建议 FIDL 库作者使用表,而不是结构体,但方法参数编码为结构体。它提出了一种基于表构建可扩展方法参数的方法。 |
作者 | |
提交日期(年-月-日) | 2019-04-08 |
遭拒原因
已被 RFC-0050:语法改进停用。
摘要
我们建议 FIDL 库作者在遇到以下情况时使用表,而不是结构体 要求可扩展性,不过方法参数编码为结构体。这个 提出了一种基于表构建可扩展方法参数的方法。
设计初衷
缺少可扩展方法参数的语法让库的编写人员望而生畏 使用表格使方法参数可扩展将此内容包含在 语法时,在设计时将可扩展性放在首位 协议
模块化团队正在设计同时需要维护 ABI 的协议 的兼容性和可扩展性,因为它们会发现新要求和演变 自己的设计他们正在考虑根据表定义方法 与声明的规范不同
设计
此提案扩展了 FIDL 源语言,并影响了该语言 绑定。
FIDL 语法
它提供了方法和事件请求和响应语法的扩展 实参。
例如此协议:
protocol Example {
Foo(int32 arg1, { 1: string arg2, 2: bool arg3 }) -> ({});
};
声明一个方法,其中包含一个必需参数、两个可选参数、 可扩展请求和响应的扩展。它相当于 声明:
table ExampleFooRequestExtension {
1: string arg2;
2: bool arg3;
};
table ExampleFooResponseExtension {
};
protocol Example {
Foo(int32 arg1, ExampleFooRequestExtension extension)
-> (ExampleFooResponseExtension extension);
}
IR
当前版本的 IR 可以向后兼容的方式扩展。
可扩展的方法参数具有具有以下名称的表:
{Protocol}{Method}RequestExtension
、{Protocol}{Method}ResponseExtension
或
已包含 {Protocol}{Method}EventExtension
张。[ExtensionArgument]
属性
会在这些生成的表上设置,以便绑定生成器可以处理
尤其是他们愿意的话
未来的 IR 可能会将这一想法提升为更高级的结构。未来的 IR 应允许采用更灵活的声明命名方法,以便语言 可以在扩展表命名方面做出更好的选择,例如,C++ 可以 将它们嵌套在协议定义类中。
绑定
绑定不需要对可扩展方法参数的特殊支持。现有账号 绑定生成器只会将生成的表添加为 方法的参数。
C++
例如,如果不对上述协议进行任何更改,C++ 绑定将产生 大致如下所示:
class ExampleFooRequestExtension;
class ExampleFooResponseExtension;
class Example {
using FooCallback = fit::function<void(ExampleFooResponseExtension)>;
virtual void Foo(int32_t arg1,
ExampleFooRequestExtension extension,
FooCallback callback) = 0;
};
绑定此协议的另一种方法是:
class Example {
using FooCallback = fit::function<void()>;
virtual void Foo(int32_t arg1,
FooCallback callback,
std::optional<std::string> arg2 = std::optional<std::string>(),
std::optional<bool> arg3 = std::optional<bool>()) = 0;
};
这样会更接近方法的声明方式, 静态参数和可扩展参数之间的回调参数。
Dart
Dart 支持可选的具名实参,因此能够很好地映射 FIDL 概念并结合到其语法中。Dart 缺少对元组或可变 Future 的支持 仍然有局限性。绑定接口可能如下所示:
abstract class Example {
Future<ExampleFooResponseExtension> foo(int arg1, {String arg2, bool arg3});
}
使用此语法添加其他扩展参数,保留源 兼容性。
Rust
待定
Go
待定
简单 C
简单 C 绑定不支持表,因此此功能不兼容 。
实施策略
第一步是将对新语法的支持添加到 fidlc
中,
更新参考文档和教程文档。
接下来,我们将添加对 Dart 绑定的支持,因为它们是最常 显而易见的人体工程学优势。
工效学设计
允许 FIDL 协议的演变是用户 。目前,更改方法的参数会破坏 ABI 和 API 更改。软化方法要么引入新方法 并继续支持旧方法,前提是 仍然是调用方,或者包含表作为参数并添加新参数 添加到该表中此方案允许在 更符合人体工程学的要求。它保留了方法定义中定义的参数, 并可在文档注释中轻松引用
可选参数在许多编程语言中很常见。不会 对图书馆作者来说是一个意外的概念。
表中需要显式序数,使得扩展参数不一致 包含必需参数,但最好将它们与表保持一致 而不是引入包含哈希序数的新表类结构。
文档和示例
作为 FIDL 语言的扩展,FIDL 参考文档和教程 文档。
向后兼容性
现有的 FIDL 库不受此更改的影响。
此方案可显著提高库作者维护 ABI 的能力 兼容的接口。
有关源代码兼容性的限制仍处于待定状态,其依据为 绑定至受支持语言的方式
性能
表的编码和解码开销比结构体更高,因此性能 关键协议应谨慎使用此功能
安全
无影响
测试
应将测试添加到 fidlc
。危险标识符测试应测试
使用危险标识符作为可选参数。
缺点、替代方案和未知问题
替代方案
我们可以按方法或按协议从结构体切换到表。周三 甚至可以将默认设置从结构体切换为表。这种方法 灵活性降低。通常,只有请求或响应 扩展。通常情况下,其中一些参数(例如,在模块化场景中,一个模块 id)预计会长期保持稳定,而其他则不是。
我们不再使用表并要求每个扩展参数使用序数, 可以定义类似表的数据结构,对名称进行哈希处理以计算 序数。这会简化源语言的语法,但会在后面添加 提高编码器、解码器和语言绑定的复杂性。
我们可以使用版本化方法。我们尚未深入探讨此选项。
开放性问题
我们应该决定在 C++、Rust 和 Go 中如何绑定。
是否应允许添加参数来破坏源代码兼容性?
先验技术和参考资料
Protobuf 声明消息与协议方法不符。
Flatbuffer 和 cap'n proto 使用版本控制。