FIDL 编译器错误目录

本文档列出了 FIDL 编译器发出的所有错误, fidlc。此网域中的错误标识符始终呈现此前缀 fi-,后跟四位数代码,例如 fi-0123

fi-0001:字符无效

词法分析器在 处未能将字符转换为词元 指定位置。

library test.bad.fi0001;

type ßar = struct {
    value uint64;
};

无效字符应通过替换或移除进行修复。

library test.good.fi0001;

type Foo = struct {
    value uint64;
};

无效字符取决于地理位置。请参阅 FIDL 语言规范以确定 FIDL 语法的各个部分允许使用哪些字符。

fi-0002:意外换行

字符串字面量不得拆分为多行:

library test.bad.fi0002;

const BAD_STRING string:1 = "Hello
World";

请改为使用转义序列 \n 来表示换行符:

library test.good.fi0002;

const GOOD_STRING string:11 = "Hello\nWorld";

fi-0003:转义序列无效

词法分析器在 转义序列。

library test.bad.fi0003;

const UNESCAPED_BACKSLASH string:2 = "\ ";
const BACKSLASH_TYPO string:1 = "\i";
const CODE_POINT_TYPO string:1 = "\Y1F604";

替换有效字符以开始转义序列,或者移除 非预期的反斜杠字符。

library test.good.fi0003;

const ESCAPED_BACKSLASH string:2 = "\\ ";
const REMOVED_BACKSLASH string:1 = "i";
const SMALL_CODE_POINT string:3 = "\u{2604}";
const BIG_CODE_POINT string:4 = "\u{01F604}";

请参阅 FIDL 语法规范 以获取有效的转义序列。

fi-0004:十六进制数字无效

字符串字面量中的 Unicode 转义字符不得包含无效的十六进制数字:

library test.bad.fi0004;

const SMILE string = "\u{1G600}";

您必须指定一个有效的十六进制 Unicode 码位,其范围为 0 到 10FFFF。 每个十六进制数字必须是从 0 到 9 的数字、从 af 的小写字母, 或从 AF 的大写字母。在本例中,GF 的拼写错误:

library test.good.fi0004;

const SMILE string = "\u{1F600}";

fi-0005

fi-0006:预期声明

当 FIDL 需要声明但查找其他内容时,就会发生此错误。 这通常是由于拼写错误导致的。有效的声明包括:typealiasconstusingprotocolservice

library test.bad.fi0006;

cosnt SPELLED_CONST_WRONG string:2 = ":("; // Expected a declaraction (such as const).

要修正此错误,请检查顶级声明中是否存在拼写错误,并确保 您只使用 FIDL 支持的功能。

library test.good.fi0006;

const SPELLED_CONST_RIGHT string:2 = ":)";

fi-0007:意外令牌

如果在解析过程中遇到意外标记,就会出现此错误。 一般来说,这是由拼写错误导致的:

library test.bad.fi0007;

alias MyType = vector<uint8>:<,256,optional>; // Extra leading comma

对此问题的解决方法通常是移除非预期的令牌, 请提供剩余的语法:

library test.good.fi0007;

alias MyType = vector<uint8>:<256, optional>;

fi-0008:意外令牌

只要 FIDL 解析器遇到语法上无效的 令牌。这种情况可能会通过多种方式发生,例如枚举成员缺少 =、 一个额外的令牌,如 library = what.is.that.equals.doing.there,依此类推。

library test.bad.unexpectedtokenofkind;

type Numbers = flexible enum {
    ONE; // FIDL enums don't have a default value.
};

通常,解决此问题的方法包括添加缺失的令牌或移除 额外的一个。

library test.good.fi0008;

type Numbers = flexible enum {
    ONE = 1;
};

为避免此错误,请对您的 *.fidl 文件执行一次检查,确保它们 语法正确。

fi-0009:非预期的标识符

当标识符在错误位置使用时,通常会出现此错误:

using test.bad.fi0009;

请改用正确的标识符:

library test.good.fi0009;

fi-0010:标识符无效

找到的标识符不符合有效 标识符。FIDL 标识符可以包含字母数字和下划线 (具体是指 A-Za-z0-9_),以及每个标识符 必须以字母开头并以字母或数字结尾。

library test.bad.fi0010a;

// Foo_ is not a valid identifier because it ends with '_'.
type Foo_ = struct {
    value uint64;
};

要解决此问题,请更改标识符,确保其仅包含有效的 字符,以字母开头并以字母或数字结尾。

library test.good.fi0010a;

type Foo = struct {
    value uint64;
};

如果将多部分(点号)标识符传递到 属性。

library test.bad.fi0010b;

@foo(bar.baz="Bar", zork="Zoom")
type Empty = struct{};

要解决此问题,请更改为在属性中仅使用单部分标识符。

library test.good.fi0010b;

@foo(bar="Bar", zork="Zoom")
type Empty = struct {};

fi-0011:库名称组件无效

库名称只能包含字母和数字(A-Za-z0-9), 并且必须以字母开头。

library test.bad.fi0011.name_with_underscores;

要解决此问题,请确保所有库名称组件都符合要求。

library test.good.fi0011.namewithoutunderscores;

fi-0012:类型布局类无效

类型声明必须指定 FIDL 已知的布局:

library test.bad.fi00012;

type Foo = invalid {};

有效布局包括 bitsenumstructtableunion

library test.good.fi0012;

type Empty = struct {};

布局是 FIDL 的可参数化说明 类型。它表示一系列可接收进一步 以指定其形状。例如,struct 就是一种布局。 定义了特定成员后,该字段将变为具体类型,而 array 是一种在给定重复类型后变得具体的布局 按指定次数。

布局全部内置在 FIDL 语言中,用户没有办法 可以指定自己的布局,也可以创建自己的泛型类型模板。

fi-0013:封装类型无效

当传递到枚举或位声明的值不是 类型的标识符,例如,改为提供字符串值作为 "支持类型":

library test.bad.fi0013;

type TypeDecl = enum : "int32" {
    FOO = 1;
    BAR = 2;
};

如需修复此错误,请确保枚举或位的后备类型是类型 标识符。

library test.good.fi0013;

type TypeDecl = enum : int32 {
    FOO = 1;
    BAR = 2;
};

fi-0014:带有空括号的属性

如果属性有括号但没有参数,就会出现此错误。

library test.bad.fi0014;

@discoverable()
protocol MyProtocol {};

要解决此问题,请从不带实参的属性中移除括号,或提供 参数(如果符合预期)。

library test.good.fi0014;

@discoverable
protocol MyProtocol {};

FIDL 禁止在属性上使用空参数列表,主要作为一种样式选择。

fi-0015:属性参数必须全部命名

为清楚起见,特此说明:当一个属性具有多个参数时, 属性的参数必须明确指定。

当属性有多个参数但参数未超出时,就会出现此错误 为参数明确提供名称。

library test.bad.fi0015;

@foo("abc", "def")
type MyStruct = struct {};

如需解决此问题,请使用 name=value 语法为所有参数提供名称。

library test.good.fi0015;

@foo(bar="abc", baz="def")
type MyStruct = struct {};

fi-0016:成员前缺少序号

当联合或表中的字段缺少序数时,会发生此错误。

library test.bad.fi0016a;

type Foo = table {
    x int64;
};
library test.bad.fi0016b;

type Bar = union {
    foo int64;
    bar vector<uint32>:10;
};

如需修复此错误,请明确指定表或联合的序数:

library test.good.fi0016;

type Foo = table {
    1: x int64;
};

type Bar = union {
    1: foo int64;
    2: bar vector<uint32>:10;
};

与结构体不同,表和联合旨在允许向后兼容 对其中的内容进行更改。为了实现这一点, 值(序数)来标识表字段或联合变体。接收者 避免混淆,并增加在更改时不易意外更改序数的概率 表或联合,必须始终明确指定序数。

fi-0017:序数超出限制

表和联合的序数必须是有效的无符号 32 位整数。负面 序数大于 4,294,967,295 会导致此错误。

library test.bad.fi0017a;

type Foo = table {
  -1: foo string;
};
library test.bad.fi0017b;

type Bar = union {
  -1: foo string;
};

要修正此错误,请确保所有序数都在允许的范围内。

library test.good.fi0017;

type Foo = table {
    1: foo string;
};

type Bar = union {
    1: foo string;
};

fi-0018:序数必须从 1 开始

tableunion 成员序数值都不能为 0:

library test.bad.fi0018;

type Foo = strict union {
    0: foo uint32;
    1: bar uint64;
};

而是应从 1 开始编号:

library test.good.fi0018;

type Foo = strict union {
    1: foo uint32;
    2: bar uint64;
};

fi-0019:严格位、枚举或联合体不能为空

严格的位、枚举或联合不允许零成员:

library test.bad.fi0019;

type Numbers = strict enum {};

而应至少包含一位成员:

library test.good.fi0019a;

type Numbers = flexible enum {};

或者,您也可以将声明标记为 flexible,而不是 strict

library test.good.fi0019b;

type Numbers = strict enum {
    ONE = 1;
};

空位、枚举或并集不携带任何信息,因此通常不应 可在 API 中使用但是,灵活的数据类型是专为进化而设计的, 定义最初为空的灵活位或枚举非常合理, (预期以后会添加成员)。您应该始终仔细考虑 在定义新数据类型时是使用 strict 还是 flexible

fi-0020:协议成员无效

如果协议中的某项内容未被识别为有效内容,就会出现此错误 协议成员,例如当协议中的内容不是协议时 组合、单向方法、双向方法或事件

library test.bad.fi0020;

protocol Example {
    NotAMethodOrCompose;
};

如需修正此错误,请移除无效商品或将它们转换为正确的商品 语法。

library test.good.fi0020;

protocol Example {
    AMethod();
};

fi-0021

fi-0022:无法将属性附加到标识符

如果将某个属性添加到声明的类型上,就会显示此错误。 该类型是标识符类型时。例如,将属性放置在 字段名称,但在结构体声明中的字段类型之前,会将 属性替换为字段的类型,而不是字段本身。如果 字段类型是通过名称引用其他类型, 属性。

library test.bad.fi0022;

type Foo = struct {
    // uint32 is an existing type, extra attributes cannot be added to it just
    // for this field.
    data @foo uint32;
};

如果意图是将属性应用于字段,则属性应为 已移到字段名称前面。

属性可以应用于声明它们的类型。这意味着,如果 结构体字段或其他类似声明的类型是匿名类型 而不是标识符类型,可以将属性应用于该类型。

library test.good.fi0022;

type Foo = struct {
    // The foo attribute is associated with the data1 field, not the uint32
    // type.
    @foo
    data1 uint32;
    // The type of data2 is a newly declared anonymous structure, so that new
    // type can have an attribute applied to it.
    data2 @foo struct {};
};

fi-0023:类型声明内的属性

使用内嵌布局时, 则可以直接将属性放在布局之前但是,声明 类型,则无法:

library test.bad.fi0023;

type Foo = @foo struct {};

相反,您必须将属性放在 type 关键字之前:

library test.good.fi0023;

@foo
type Foo = struct {};

我们之所以强制执行此要求,是因为在两个位置允许属性会造成混淆。

fi-0024:方法参数列表的文档注释

方法参数列表不能包含文档注释:

library test.bad.fi0024;

protocol Example {
    Method(/// This is a one-way method.
            struct {
        b bool;
    });
};

目前,请为该方法本身添加文档注释:

library test.good.fi0024;

protocol Example {
    /// This is a one-way method.
    Method(struct {
        b bool;
    });
};

解决此错误后,此错误将不再存在。通过 错误,保留迁移以描述方法负载 使用 FIDL 类型,而不是参数列表。

fi-0025:导入组必须位于文件顶部

除了文件顶部的 library 声明外,不能包含任何 在文件的 using 导入之前声明其他声明(如果存在):

library test.bad.fi0025;

alias i16 = int16;
using dependent;

type UsesDependent = struct {
    field dependent.Something;
};

如需解决此错误,请将所有 using 导入内容直接放在一个块中 在 library 声明之后:

library test.good.fi0025;

using dependent;

alias i16 = int16;
type UsesDependent = struct {
    field dependent.Something;
};

此规则主要反映了 FIDL 团队在审美方面的决定, 合理分组且易于找到的依赖项更易于阅读。

fi-0026:文档注释块内的注释

注释不应放在文档注释块内:

library test.bad.fi0026;

/// start
// middle
/// end
type Empty = struct {};

而应放在文档注释块的前面或后面:

library test.good.fi0026;

// some comments above,
// maybe about the doc comment
/// A
/// multiline
/// comment!
// another comment, maybe about the struct
type Empty = struct {};

一般来说,文档注释块前面的注释是最好的 用于放置有关文档注释本身的评论。

fi-0027:文档注释块中存在空白行

文档注释块中不应有空行:

library test.bad.fi0027;

/// start

/// end
type Empty = struct {};

而应仅将空白行放在文档注释之前或之后 屏蔽:

library test.good.fi0027a;

/// A doc comment
type Empty = struct {};

或者,考虑完全省略空白行:

library test.good.fi0027b;

/// A doc comment
type Empty = struct {};

fi-0028:文档注释必须后跟声明

与常规评论一样,文档评论一律不得自由浮动:

library test.bad.fi0028;

type Empty = struct {};
/// bad

在所有情况下,文档注释都必须直接放在 FIDL 声明的前面:

library test.good.fi0028a;

/// A doc comment
type Empty = struct {};

FIDL“降幅”在编译期间为 @doc 属性添加文档注释。事实上 可根据需要直接编写注释:

library test.good.fi0028b;

@doc("An attribute doc comment")
type Empty = struct {};

从技术角度来看,独立的文档注释是不可编译的, 还会在语义上造成混淆:什么是“记录”什么都没有?取消点赞 将文档注释处理成结构化文档 因此必须明确它们关联到哪个 FIDL 结构。

fi-0029:资源定义必须至少包含一个属性

禁止使用未指定属性的资源定义:

library test.bad.resourcedefinitionnoproperties;

resource_definition SomeResource : uint32 {
  properties {};
};

请至少指定一个属性:

library test.good.fi0029;

resource_definition SomeResource : uint32 {
    properties {
        subtype strict enum : uint32 {
            NONE = 0;
        };
    };
};

这是一个与 FIDL 的内部实现相关的错误,因此应仅 向负责 FIDL 核心库的开发者提供。最终用户 应该不会看到此错误。

它所引用的 resource_definition 声明是 FIDL 的内部方法, 定义资源,并且将来可能会作为 处理泛化工作的一部分。

fi-0030:修饰符无效

每个 FIDL 修饰符都有一组特定的声明供您使用。 不允许在被禁止的声明中使用修饰符:

library test.bad.fi0030;

type MyStruct = strict struct {
    i int32;
};

最佳做法是移除违规修饰符:

library test.good.fi0030;

type MyStruct = struct {
    i int32;
};

fi-0031:只有位和枚举可以具有子类型

并非所有 FIDL 布局都可以包含子类型:

library test.bad.fi0031;

type Foo = flexible union : uint32 {};

只有 bitsenum 布局是在底层类型上定义的。

library test.good.fi0031;

type Foo = flexible enum : uint32 {};

bitsenum 布局有些独特,因为它们 集成 FIDL 基元的受限子类型。正因如此, 指定充当此子类型的基础类型是合理的。 相反,structtableunion 布局可以任意大, 可以包含多个成员,因此全局、布局范围的子类型不会使 。

fi-0032:不允许使用重复的修饰符

禁止在单个声明中指定相同的修饰符:

library test.bad.fi0032;

type MyUnion = strict resource strict union {
    1: foo bool;
};

移除重复的修饰符:

library test.good.fi0032;

type MyUnion = resource strict union {
    1: foo bool;
};

fi-0033:修饰符冲突

某些修饰符相互排斥,并且不能同时修饰 相同的声明:

library test.bad.conflictingmodifiers;

type StrictFlexibleFoo = strict flexible union {
    1: b bool;
};

type FlexibleStrictBar = flexible strict union {
    1: b bool;
};

一个 strictflexible 修饰符只能用于单个 声明:

library test.good.fi0033;

type FlexibleFoo = flexible union {
    1: i int32;
};

type StrictBar = strict union {
    1: i int32;
};

目前,只有 strictflexible 修饰符是互斥的 。resource 修饰符没有倒数修饰符,因此具有 也不会对其应用此类限制

fi-0034:名称冲突

两个声明的名称不能相同:

library test.bad.fi0034;

const COLOR string = "red";
const COLOR string = "blue";

而应为每个声明指定一个唯一的名称:

library test.good.fi0034b;

const COLOR string = "red";
const OTHER_COLOR string = "blue";

或者,移除错误添加的声明之一:

library test.good.fi0034a;

const COLOR string = "red";

如需详细了解如何选择名称,请参阅 FIDL 样式指南

fi-0035:规范名称冲突

两个声明不能具有相同的规范名称:

library test.bad.fi0035;

const COLOR string = "red";

protocol Color {};

虽然 COLORColor 看起来不同,但它们都由 规范名称 color。您可通过将 将原始名称更改为 snake_case

如需修正该错误,请为每个声明指定一个唯一的名称, 规范化:

library test.good.fi0035;

const COLOR string = "red";

protocol ColorMixer {};

按照 FIDL 样式指南的命名准则, 以尽可能降低出现此错误的几率。规范名称冲突会导致 永远不会发生在使用相同大小写样式的声明之间, 由于其他原因,使用不同样式的广告之间 要求(例如,协议名称通常应该是以 -er 结尾的名词短语)。

FIDL 强制执行此规则,因为绑定生成器将名称转换为 目标语言的惯用命名样式。确保唯一规范化 名称,我们保证绑定可以执行此操作,而不会产生名称冲突。 如需了解详情,请参阅 RFC-0040:标识符唯一性

fi-0036:名称重叠

使用相同名称的声明不能有重叠的播出信息:

@available(added=1)
library test.bad.fi0036;

type Color = strict enum {
    RED = 1;
};

@available(added=2)
type Color = flexible enum {
    RED = 1;
};

而应使用 @available 属性,以确保只有 声明:

@available(added=1)
library test.good.fi0036;

@available(replaced=2)
type Color = strict enum {
    RED = 1;
};

@available(added=2)
type Color = flexible enum {
    RED = 1;
};

或者,您也可以重命名或移除某个声明,如 fi-0034

如需详细了解版本控制,请参阅 FIDL 版本控制

fi-0037:规范名称重叠

具有相同规范名称的声明不能重叠 可用性:

@available(added=1)
library test.bad.fi0037;

const COLOR string = "red";

@available(added=2)
protocol Color {};

虽然 COLORColor 看起来不同,但它们都由 规范名称 color。您可通过将 将原始名称更改为 snake_case

如需修正该错误,请为每个声明指定一个唯一的名称, 规范化。

@available(added=1)
library test.good.fi0037;

const COLOR string = "red";

@available(added=2)
protocol ColorMixer {};

或者,您也可以按照 fi-0036 或移除该声明。

请参阅 fi-0035,详细了解 FIDL 为何要求进行声明 具有唯一的规范名称。

fi-0038:名称与导入存在冲突

声明的名称不得与使用 using 导入的库同名:

library dependency;

const VALUE uint32 = 1;
library test.bad.fi0038b;

using dependency;

type dependency = struct {};

// Without this, we'd get fi-0178 instead.
const USE_VALUE uint32 = dependency.VALUE;

而是导入包含 using ... as 的不同名称的库。 语法:

library test.good.fi0038b;

using dependency as dep;

type dependency = struct {};

const USE_VALUE uint32 = dep.VALUE;

或者,您也可以重命名声明以避免冲突:

library test.good.fi0038c;

using dependency;

type OtherName = struct {};

const USE_VALUE uint32 = dependency.VALUE;

您可以在库名称中使用多个组件来避免此问题。对于 例如,Fuchsia SDK 中的 FIDL 库以 fuchsia. 开头,因此具有 且不能与声明名称冲突。

此错误是为了防止产生歧义。例如,如果 dependency 是一个 具有名为 VALUE 的成员的枚举,那么无论是 dependency.VALUE 引用了该枚举成员或 导入代码库。

fi-0039:规范名称与导入冲突

声明的规范名称不能与包含 using:

library dependency;

const VALUE uint32 = 1;
library test.bad.fi0039b;

using dependency;

type Dependency = struct {};

// Without this, we'd get fi-0178 instead.
const USE_VALUE uint32 = dependency.VALUE;

虽然 dependencyDependency 看起来不同,但它们都是 以规范名称 dependency 表示。您会获得规范名称 方法是将原始名称转换为 snake_case

如需修正该错误,请使用 using 以不同的名称导入库 ... as 语法:

library test.good.fi0039b;

using dependency as dep;

type Dependency = struct {};

const USE_VALUE uint32 = dep.VALUE;

或者,您也可以重命名声明以避免冲突:

library test.good.fi0039c;

using dependency;

type OtherName = struct {};

const USE_VALUE uint32 = dependency.VALUE;

请参阅 fi-0038,了解出现此错误的原因以及如何避免此错误。

请参阅 fi-0035,详细了解 FIDL 为何要求进行声明 具有唯一的规范名称。

fi-0040:文件在库名称上不一致

库可以由多个文件组成,但每个文件必须具有相同的 名称:

library test.bad.fi0040a;
library test.bad.fi0040b;

确保库使用的所有文件同名:

library test.good.fi0040;
library test.good.fi0040;

对于多文件库,建议创建一个 空 overview.fidl 文件,用作主“条目” 点”放入库overview.fidl 文件也是 用于将库级 @available 平台 规范

fi-0041:多个同名库

传递给 fidlc 的每个库都必须具有唯一的名称:

library test.bad.fi0041;
library test.bad.fi0041;

确保所有库的名称都是唯一的:

library test.good.fi0041a;
library test.good.fi0041b;

此错误通常是由于在fidlc 不正确。组成每个库的组成要素文件 编译(即正在编译的库及其所有传递的 依赖项)必须以单个空格分隔的文件列表的形式提供, 通过 --files 参数传递,每个库都有一个此类标志。一个常见的错误是 尝试在单个 --files 列表中传递所有库的文件。

fi-0042:重复库导入

依赖项无法多次导入:

library test.bad.fi0042a;

type Bar = struct {};
library test.bad.fi0042b;

using test.bad.fi0042a;
using test.bad.fi0042a; // duplicated
type Foo = struct {
    bar test.bad.fi0042a.Bar;
};

确保每个依赖项仅导入一次:

library test.good.fi0042a;

type Bar = struct {};
library test.good.fi0042b;

using test.good.fi0042a;
type Foo = struct {
    bar test.good.fi0042a.Bar;
};

值得注意的是,FIDL 不支持导入 同一个库系统针对整个 fidlc 解析了 @available 版本 通过 --available 标志进行编译,这意味着 其所有依赖项对于任何给定的 编译运行。

fi-0043:库导入冲突

禁止将导入的库化为 与其他导入的库的无别名名称冲突:

library test.bad.fi0043a;

type Bar = struct {};

// This library has a one component name to demonstrate the error.
library fi0043b;

type Baz = struct {};
library test.bad.fi0043c;

using test.bad.fi0043a as fi0043b; // conflict
using fi0043b;

type Foo = struct {
    a fi0043b.Bar;
    b fi0043b.Baz;
};

请选择其他别名来解决名称冲突:

library test.good.fi0043a;

type Bar = struct {};
library fi0043b;

type Baz = struct {};
library test.good.fi0043c;

using test.good.fi0043a as dep;
using fi0043b;

type Foo = struct {
    a dep.Bar;
    b fi0043b.Baz;
};

fi-0044:库导入别名冲突

禁止将导入的库化为 与分配给其他导入库的别名冲突:

library test.bad.fi0044a;

type Bar = struct {};
library test.bad.fi0044b;

type Baz = struct {};
library test.bad.fi0044c;

using test.bad.fi0044a as dep;
using test.bad.fi0044b as dep; // conflict
type Foo = struct {
    a dep.Bar;
    b dep.Baz;
};

选择非冲突的别名来解决名称冲突:

library test.good.fi0044a;

type Bar = struct {};
library test.good.fi0044b;

type Baz = struct {};
library test.good.fi0044c;

using test.good.fi0044a as dep1;
using test.good.fi0044b as dep2;
type Foo = struct {
    a dep1.Bar;
    b dep2.Baz;
};

fi-0045:使用声明时不允许使用的属性

属性无法附加到 using 声明:

library test.bad.fi0045a;

type Bar = struct {};
library test.bad.fi0045b;

/// not allowed
@also_not_allowed
using test.bad.fi0045a;

type Foo = struct {
    bar test.bad.fi0045a.Bar;
};

请移除该属性以修正错误:

library test.good.fi0045a;

type Bar = struct {};
library test.good.fi0045b;

using test.good.fi0045a;

type Foo = struct {
    bar test.good.fi0045a.Bar;
};

此限制也适用于 /// ... 文档注释,因为这些只是 @doc("...") 属性的语法糖。

fi-0046:未知库

在大多数情况下,此问题是由于依赖项拼写有误或构建系统未提供依赖项所致。 如果相关依赖项故意使用,则必须移除相关的使用行:

library test.bad.fi0046;

using dependent; // unknown using.

type Foo = struct {
    dep dependent.Bar;
};

确保所有导入都使用构建系统作为依赖项添加到库中。

library test.good.fi0046;

type Foo = struct {
    dep int64;
};

fi-0047

fi-0048:可选的表成员

表成员类型不能为 optional

library test.bad.fi0048;

type Foo = table {
    // Strings can be optional in general, but not in table member position.
    1: t string:optional;
};

从所有成员中移除 optional 限制条件:

library test.good.fi0048;

type Foo = table {
    1: t string;
};

表成员始终是可选的,因此在成员的基础类型上指定这一事实是多余的。

表成员始终是可选的,因为在网络上,每个表成员都表示为矢量中的一个条目。 该矢量始终表示表上的所有已知字段,因此表示省略的每个表成员 作为 null 信封 - 与省略的可选类型的表示完全相同。

fi-0049:可选的联盟成员

联合成员不得为可选项:

library test.bad.fi0049;

type Foo = strict union {
    // Strings can be optional in general, but not in unions.
    1: bar string:optional;
};

移除 optional 限制条件:

library test.good.fi0049;

type Foo = strict union {
    1: bar string;
};

FIDL 不允许将联合成员设为可选,因为这可能导致以多种方式表示相同值。 例如,有三个可选成员的联盟将有 6 个州(每个成员 2 个)。相反,应使用 第四个成员,其类型为 struct {},或者使用 Foo:optional 使整体联合变为可选。

fi-0050:禁止使用已弃用的结构体默认语法

之前,FIDL 允许为 struct 成员设置默认值:

library test.bad.fi0050;

type MyStruct = struct {
    field int64 = 20;
};

RFC-0160:移除对 FIDL 结构体默认值的支持,此行为 不允许:

library test.good.fi0050;

type MyStruct = struct {
    field int64;
};

系统不再允许 struct 个成员使用默认值。用户应设置 默认应用于应用逻辑

此语法的少数旧版用户可继续使用它 但不会再出现新的例外情况 可添加到此列表。这些用户迁移完成后,这项功能 将从 FIDL 中永久移除。

fi-0051:未知的依赖库

当您使用来自未知库的符号时,就会出现此错误。

library test.bad.fi0051;

type Company = table {
    1: employees vector<unknown.dependent.library.Person>;
    2: name string;
};

如需解决此问题,请使用 using 声明导入缺失的依赖库。

library known.dependent.library;

type Person = table {
    1: age uint8;
    2: name string;
};
library test.good.fi0051;
using known.dependent.library;

type Company = table {
    1: employees vector<known.dependent.library.Person>;
    2: name string;
};

在执行 fidlc 命令行调用时,通常会出现此错误。 格式不当。如果您确信未知库存在,并且 应可解析,请确保您传递的是依赖库的文件 正确传递。--files

fi-0052:未找到名称

如果您使用 FIDL 编译器找不到的名称,就会发生此错误。

library test.bad.fi0052;

protocol Parser {
    Tokenize() -> (struct {
        tokens vector<string>;
    }) error ParsingError; // ParsingError doesn't exist.
};

要解决此问题,请移除未找到的名称:

library test.good.fi0052a;

protocol Parser {
    Tokenize() -> (struct {
        tokens vector<string>;
    });
};

或定义未找到的名称:

library test.good.fi0052b;

type ParsingError = flexible enum {
    UNEXPECTED_EOF = 0;
};

protocol Parser {
    Tokenize() -> (struct {
        tokens vector<string>;
    }) error ParsingError;
};

fi-0053:无法引用成员

如果引用的成员不是 bitsenum 条目,则会出现此错误。

library test.bad.fi0053a;

type Person = struct {
    name string;
    birthday struct {
        year uint16;
        month uint8;
        day uint8;
    };
};

const JOHNS_NAME Person.name = "John Johnson"; // Cannot refer to member of struct 'Person'.
library test.bad.fi0053b;

type Person = struct {
    name string;
    birthday struct {
        year uint16;
        month uint8;
        day uint8;
    };
};

type Cat = struct {
    name string;
    age Person.birthday; // Cannot refer to member of struct 'Person'.
};

要修正此错误,请更改为已命名的类型:

library test.good.fi0053a;

type Person = struct {
    name string;
    birthday struct {
        year uint16;
        month uint8;
        day uint8;
    };
};

const JOHNS_NAME string = "John Johnson";

或提取成员的类型:

library test.good.fi0053b;

type Date = struct {
    year uint16;
    month uint8;
    day uint8;
};

type Person = struct {
    name string;
    birthday Date;
};

type Cat = struct {
    name string;
    age Date;
};

fi-0054:位/枚举成员无效

如果引用了 enumbits 成员而之前未定义,就会出现此错误。

library test.bad.fi0054;

type Enum = enum {
    foo_bar = 1;
};

const EXAMPLE Enum = Enum.FOO_BAR;

为避免此错误,请确认您之前已针对引用的 成员值。这些值区分大小写。

library test.good.fi0054;

type Enum = enum {
    foo_bar = 1;
};

const EXAMPLE Enum = Enum.foo_bar;

fi-0055:对已弃用项的引用无效

如果对 typeconst 的引用使用 @available 属性不兼容。这通常发生在使用 废弃了更高版本中的 typesconsts

@available(added=1)
library test.bad.fi0055;

@available(added=1, deprecated=2, note="use Color instead")
alias RGB = array<uint8, 3>;

@available(added=2)
type Color = struct {
    r uint8;
    g uint8;
    b uint8;
    a uint8;
};

@available(added=3)
type Config = table {
    // RGB is deprecated in version 2.
    1: color RGB;
};

如需修正此错误,请使用未废弃的 typeconst

@available(added=1)
library test.good.fi0055;

@available(added=1, deprecated=2, note="use Color instead")
alias RGB = array<uint8, 3>;

@available(added=2)
type Color = struct {
    r uint8;
    g uint8;
    b uint8;
    a uint8;
};

@available(added=3)
type Config = table {
    // Using a non-deprecated type.
    1: color Color;
};

fi-0056:对已弃用的其他平台的引用无效

当您使用对 typeconst 的引用时,会发生此错误 具有不兼容的 @available 属性的平台。这种情况通常发生 使用更高版本中已废弃的 typesconsts 时。

@available(platform="foo", added=1)
library test.bad.fi0056a;

@available(added=1, deprecated=2, note="use Color instead")
alias RGB = array<uint8, 3>;

@available(added=2)
type Color = struct {
    r uint8;
    g uint8;
    b uint8;
    a uint8;
};
@available(platform="bar", added=2)
library test.bad.fi0056b;

using test.bad.fi0056a;

@available(added=3)
type Config = table {
    // RGB is deprecated in version 2.
    1: color test.bad.fi0056a.RGB;
};

如需修正此错误,请使用未废弃的 typeconst

@available(platform="foo", added=1)
library test.good.fi0056a;

@available(added=1, deprecated=2, note="use Color instead")
alias RGB = array<uint8, 3>;

@available(added=2)
type Color = struct {
    r uint8;
    g uint8;
    b uint8;
    a uint8;
};
@available(platform="bar", added=2)
library test.good.fi0056b;

using test.good.fi0056a;

@available(added=2)
type Config = table {
    // Change to use a non-deprecated type.
    1: color test.good.fi0056a.Color;
};

fi-0057:包含周期

可能造成该问题的原因多种多样, 归根结底是 FIDL 声明,在 解决方案。此错误的最简单形式是,当某个类型或协议 直接指代其自身:

library test.bad.fi0057c;

type MySelf = struct {
    me MySelf;
};

当某个类型或协议以传递方式传递时,可能会发生更复杂的故障情况 至少通过一种层次的间接指代:

library test.bad.fi0057a;

type Yin = struct {
    yang Yang;
};

type Yang = struct {
    yin Yin;
};
library test.bad.fi0057b;

protocol Yin {
    compose Yang;
};

protocol Yang {
    compose Yin;
};

要解决此错误,可以在 包含循环,因为这样会导致该循环被“打破”在编码/解码 时间:

library test.good.fi0057;

type MySelf = struct {
    me box<MySelf>;
};
library test.bad.fi0057d;

type MySelf = table {
    1: me MySelf;
};

不允许使用被信封打开的递归类型,因为它们 无法编码。在上面的第一个示例中,编码 MySelf 为 需要先对 MySelf 的实例进行编码,这反过来需要 对 MySelf 的实例进行编码,即 ad inifitum。要解决这个问题, 添加“break”在这个链中,可以选择 对 MySelf 的另一个嵌套实例进行编码,或以其他方式对 null 信封进行编码 而不再有其他数据

fi-0058:引用编译器生成的载荷名称

FIDL 会自动为匿名方法载荷生成名称 这样,使用生成的后端代码的用户就可以引用 根据需要进行表示在 *.fidl 文件中引用这些类型 但禁止:

library test.bad.fi0058;

protocol MyProtocol {
    strict MyInfallible(struct {
        in uint8;
    }) -> (struct {
        out int8;
    });
    strict MyFallible(struct {
        in uint8;
    }) -> (struct {
        out int8;
    }) error flexible enum {};
    strict -> MyEvent(struct {
        out int8;
    });
};

type MyAnonymousReferences = struct {
    a MyProtocolMyInfallibleRequest;
    b MyProtocolMyInfallibleResponse;
    c MyProtocolMyFallibleRequest;
    d MyProtocol_MyFallible_Result;
    e MyProtocol_MyFallible_Response;
    f MyProtocol_MyFallible_Error;
    g MyProtocolMyEventRequest;
};

如果您希望直接引用载荷类型,则应将 payload 类型转换为其自有的命名类型声明:

library test.good.fi0058;

type MyRequest = struct {
    in uint8;
};
type MyResponse = struct {
    out int8;
};
type MyError = flexible enum {};

protocol MyProtocol {
    strict MyInfallible(MyRequest) -> (MyResponse);
    strict MyFallible(MyRequest) -> (MyResponse) error MyError;
    strict -> MyEvent(MyResponse);
};

type MyAnonymousReferences = struct {
    a MyRequest;
    b MyResponse;
    c MyRequest;
    // There is no way to explicitly name the error result union.
    // d MyProtocol_MyFallible_Result;
    e MyResponse;
    f MyError;
    g MyResponse;
};

所有 FIDL 方法和事件均预留 [PROTOCOL_NAME][METHOD_NAME]Request 为其匿名请求载荷指定名称严格、绝对可靠的双向方法 另外预留 [PROTOCOL_NAME][METHOD_NAME]Response。双向方法 灵活或易用的备用关键字:

  • [PROTOCOL_NAME]_[METHOD_NAME]_Result
  • [PROTOCOL_NAME]_[METHOD_NAME]_Response
  • [PROTOCOL_NAME]_[METHOD_NAME]_Error

由于历史原因,这些名称使用下划线,与其他名称不同。

fi-0059:常量类型无效

并非所有类型都可以在 const 声明中使用:

library test.bad.fi0059;

const MY_CONST string:optional = "foo";

如果可能,转换为允许的类型:

library test.good.fi0059;

const MY_CONST string = "foo";

仅限 FIDL 基元(boolint8int16int32int64uint8uint16uint32uint64float32float64 和非可选 string 类型可在 const 声明的左侧使用。

fi-0060:无法解析常量值

常量值必须可解析为已知值:

library test.bad.fi0060;

const MY_CONST bool = optional;

请确保使用的常量是有效值:

library test.good.fi0060;

const MY_CONST bool = true;

此错误通常伴随其他错误,这些错误可提供关于 不可解析预期常量的性质。

fi-0061:非基元值的 OR 运算符

二进制或运算符只能用于基元:

library test.bad.fi0061;

const HI string = "hi";
const THERE string = "there";
const OR_OP string = HI | THERE;

请尝试改为将操作的数据表示为 bits 枚举:

library test.good.fi0061;

type MyBits = flexible bits {
    HI = 0x1;
    THERE = 0x10;
};
const OR_OP MyBits = MyBits.HI | MyBits.THERE;

fi-0062:不允许使用 newtype

不支持 RFC-0052: Type aliasing and new types 中的新类型 已完全实施,尚无法使用:

library test.bad.fi0062;

type Matrix = array<float64, 9>;

在此期间,您可以通过使用 单个元素:

library test.good.fi0062a;

type Matrix = struct {
    elements array<float64, 9>;
};

或者,您也可以定义别名,但请注意,与 newtype 不同, 不提供类型安全(也就是说,它可以与 基础类型):

library test.good.fi0062b;

alias Matrix = array<float64, 9>;

fi-0063:预期值,但类型为

const 声明的右侧必须解析为常量值, 不是类型:

library test.bad.fi0063;

type MyType = struct {};
const MY_CONST uint32 = MyType;

确保右侧是一个值:

library test.good.fi0063;

const MY_VALUE uint32 = 8;
const MY_CONST uint32 = MY_VALUE;

fi-0064:位或枚举值类型不正确

bitsenum 变体用作 const 声明中的值时, bits/enum 值的类型必须与左侧的 const 声明:

library test.bad.fi0064;

type MyEnum = enum : int32 {
    VALUE = 1;
};
type OtherEnum = enum : int32 {
    VALUE = 5;
};
const MY_CONST MyEnum = OtherEnum.VALUE;

一种解决方法是更改 const 声明的类型,以匹配 存储的值:

library test.good.fi0064;

type MyEnum = enum : int32 {
    VALUE = 1;
};
type OtherEnum = enum : int32 {
    VALUE = 5;
};
const MY_CONST OtherEnum = OtherEnum.VALUE;

或者,也可以选择其他值来匹配 const 声明的类型:

library test.good.fi0064;

type MyEnum = enum : int32 {
    VALUE = 1;
};
type OtherEnum = enum : int32 {
    VALUE = 5;
};
const MY_CONST MyEnum = MyEnum.VALUE;

fi-0065:无法将值转换为预期的类型

常量值的类型必须适合其所在位置 。

导致此错误的最常见原因是 const 声明的值 与其声明的类型不匹配:

library test.bad.fi0065a;

const MY_CONST bool = "foo";

如果在 v3 中使用正确定义的 const 值, 底层类型无效的位置:

library test.bad.fi0065b;

const ONE uint8 = 0x0001;
const TWO_FIFTY_SIX uint16 = 0x0100;
const TWO_FIFTY_SEVEN uint8 = ONE | TWO_FIFTY_SIX;

此外,FIDL 的官方人员会检查其参数 架构。由于这些参数本身就是常量值, 可能也会出现同种类型不匹配的情况:

library test.bad.fi0065c;

protocol MyProtocol {
    @selector(3840912312901827381273)
    MyMethod();
};

在所有这些情况下,解决方法是仅使用预期 在接受 const 值的位置类型。上述情况包括 分别为:

library test.good.fi0065a;

const MY_CONST string = "foo";
library test.good.fi0065b;

const ONE uint8 = 0x0001;
const TWO_FIFTY_SIX uint16 = 0x0100;
const TWO_FIFTY_SEVEN uint16 = ONE | TWO_FIFTY_SIX;
library test.good.fi0065c;

protocol MyProtocol {
    @selector("MyOldMethod")
    MyMethod();
};

fi-0066:常量溢出类型

常数值不能超出其底层所固有的范围 类型:

library test.bad.fi0066;

const NUM uint64 = -42;

可以通过更改值以符合类型的 范围:

library test.good.fi0066a;

const NUM uint64 = 42;

或者,通过更改为 类型以适应当前溢出 值:

library test.good.fi0066b;

const NUM int64 = -42;

此错误仅与 FIDL 的数字类型有关,且所有数字类型都具有 容量上限。范围来自 C++ std::numeric_limits 接口,如下所示:

类型 最小值 最大
int8 -128 127
int16 32768 32767
int32 2147483648 2147483647
int64 9223372036854775808 9223372036854775807
uint8 0 255
uint16 0 65536
uint32 0 4294967295
uint64 0 18446744073709551615
float32 -3.40282e+38 3.40282e+38
float64 -1.79769e+308 1.79769e+308

fi-0067:位成员必须是 2 的幂

bits 声明中所有成员的值都不能是 不是 2 的幂:

library test.bad.fi0067;

type NonPowerOfTwo = bits : uint64 {
    THREE = 3;
};

相反,成员值应始终为 2 的幂:

library test.good.fi0067a;

type Fruit = bits : uint64 {
    ORANGE = 1;
    APPLE = 2;
    BANANA = 4;
};

避免受此限制影响的一种简单方法是只使用 位成员值使用掩码,而不是十进制数字:

library test.good.fi0067b;

type Life = bits {
    A = 0b000010;
    B = 0b001000;
    C = 0b100000;
};

bits 结构体表示一个位数组。这是 用于表示一系列布尔标志的节省内存的方法。因为每个 bits 声明的成员会映射到其底层的某个特定位 因此用于该映射的值必须明确标识 要分配给的无符号整数。

fi-0068:灵活枚举具有预留的未知值

如果您定义的枚举成员的值与 预留的未知值。

灵活的枚举可能会包含 FIDL 架构未知的值。此外, 灵活枚举始终会预留一些值,该值将被视为未知值。 默认情况下,该值是由 该枚举的基础整数类型(例如,如果为 uint8,则为 255)。

library test.bad.fi0068;

type Foo = flexible enum : uint8 {
    ZERO = 0;
    ONE = 1;
    MAX = 255;
};

要修正该错误,您可以移除该成员或更改其值:

library test.good.fi0068a;

type Foo = flexible enum : uint8 {
    ZERO = 0;
    ONE = 1;
};
library test.good.fi0068b;

type Foo = flexible enum : uint8 {
    ZERO = 0;
    ONE = 1;
    MAX = 254;
};

最后,如果您在将 strict 枚举转换为 flexible 枚举,您可以使用 @unknown 属性来指定 特定成员的值作为未知值。请参阅 @unknown

fi-0069:位必须使用无符号整数子类型

使用带符号数字作为 bits 声明的基础类型是 禁止:

library test.bad.fi0069;

type Fruit = bits : int64 {
    ORANGE = 1;
    APPLE = 2;
    BANANA = 4;
};

请改用以下任意一种:uint8uint16uint32uint64

library test.good.fi0069;

type Fruit = bits : uint64 {
    ORANGE = 1;
    APPLE = 2;
    BANANA = 4;
};

与允许有符号和无符号整数的 enum 声明不同(请参阅: fi-0070),则 bits 声明只允许后者。这是 因为每个 bits 成员都必须代表 bit 数组(这就是导致 fi-0067 存在)。这可以最清晰地表示为单个无符号整数。通过 无符号整数的二进制表示法直接映射到单个位(2 到 索引的次幂),而带符号整数中的负数几乎是 总是选择多位,这是由于二进制补码的机制所致 表示法

fi-0070:枚举必须使用 integral 子类型

使用非整数数字 float32float64 作为基础类型 enum 声明:

library test.bad.fi0070;

type MyEnum = enum : float64 {
    ONE_POINT_FIVE = 1.5;
};

请改用以下任意一种:int8int16int32int64uint8uint16uint32uint64

library test.good.fi0070;

type MyEnum = enum : uint64 {
    ONE = 1;
};

fi-0071:不允许对严格枚举成员使用未知属性

strict enum 不得包含任何带有 @unknown 注解的成员 属性:

library test.bad.fi0071;

type MyEnum = strict enum : int8 {
    @unknown
    UNKNOWN = 0;
    FOO = 1;
    MAX = 127;
};

如需继续使用 @unknown 属性,请更改为 flexible enum

library test.good.fi0071a;

type MyEnum = flexible enum : int8 {
    @unknown
    UNKNOWN = 0;
    FOO = 1;
    MAX = 127;
};

否则,只需完全移除该属性即可保留 strict enum

library test.good.fi0071;

type MyEnum = strict enum : int8 {
    UNKNOWN = 0;
    FOO = 1;
    MAX = 127;
};

@unknown 属性的用途是 从具有用户定义的未知值的 strict enum 过渡到平滑过渡, 转换为 flexible enum,其中包含已知并由 处理的未知值 FIDL。在上例中,它用于从第二个 使用正确的方法。

fi-0072:只有枚举成员可以带有未知属性

禁止使用 @unknown 属性修饰多个 enum 成员:

library test.bad.fi0072;

type MyEnum = flexible enum : uint8 {
    @unknown
    UNKNOWN = 0;
    @unknown
    OTHER = 1;
};

仅选择被用作特定域“未知”的成员并对其进行注释 值:

library test.good.fi0071a;

type MyEnum = flexible enum : int8 {
    @unknown
    UNKNOWN = 0;
    OTHER = 1;
};

@unknown 属性的用途是 从具有用户定义的未知值的 strict enum 过渡到过渡时平滑, 转换为 flexible enum,其中包含已知并由 处理的未知值 FIDL:

library test.good.fi0072;

type MyEnum = strict enum : int8 {
    UNKNOWN = 0;
    OTHER = 1;
};
library test.good.fi0071a;

type MyEnum = flexible enum : int8 {
    @unknown
    UNKNOWN = 0;
    OTHER = 1;
};

fi-0073:编写非协议

compose 语句中只能使用协议:

library test.bad.fi0073;

type MyStruct = struct {};

protocol MyProtocol {
    compose MyStruct;
};

请确保您所指的名称指向协议:

library test.good.fi0073;

protocol MyOtherProtocol {};

protocol MyProtocol {
    compose MyOtherProtocol;
};

fi-0074:方法载荷使用的布局无效

只能使用 structtableunion 布局来描述方法 载荷:

library test.bad.fi0074;

protocol MyProtocol {
    MyMethod(enum {
        FOO = 1;
    });
};

请改用下列布局之一:

library test.good.fi0074;

protocol MyProtocol {
    MyMethod(struct {
        foo bool;
    });
};

fi-0075:方法载荷使用的基元无效

基元不能用作方法载荷:

library test.bad.fi0075;

protocol MyProtocol {
    MyMethod(uint32);
};

请改用 structtableunion 布局的类型:

library test.good.fi0075;

protocol MyProtocol {
    MyMethod(struct {
        wrapped_in_struct uint32;
    });
};

当所需载荷实际上只是一个原始值时, 不必考虑未来的演变,将值封装在 struct 布局中 其大小与所需值本身的大小相同。

fi-0076

fi-0077:互动载荷不能为空结构体

方法或事件中的载荷不得为空结构体:

library test.bad.fi0077a;

protocol Test {
    MyMethod(struct {}) -> (struct {});
};
library test.bad.fi0077b;

protocol Test {
    -> MyEvent(struct {});
};

如果您想说明特定请求/响应不受任何 删除空结构体,将 () 保留在该位置:

library test.good.fi0077a;

protocol Test {
    MyMethod() -> ();
};
library test.good.fi0077b;

protocol Test {
    -> MyEvent();
};

空结构体无法扩展,并且会在线路上占用 1 个字节。从 FIDL 开始 支持无载荷的互动,这样使用空结构体是 多余且效率低下因此,它们是不允许的。

fi-0078

fi-0079

fi-0080:生成零值序数

此错误绝不应发生。如果您能做到这一点 恭喜,您可能破坏了 SHA-256!

开个玩笑,如果 fidlc 编译器生成序数值,就会出现这个错误。 为 0。这种情况绝不应发生,因此如果确实发生了, FIDL 编译器。如果发生这种情况,请向我们的问题跟踪器报告此问题。

fi-0081:重复方法序数

使用 @selector 属性时,通常会出现此错误 使两个方法名称产生相同的序号。

library test.bad.fi0081;

protocol Parser {
    ParseLine();

    // Multiple methods with the same ordinal...
    @selector("ParseLine")
    ParseOneLine();
};

若要解决此问题,请更新方法名称或选择器,以确保它们不会发生冲突。

library test.good.fi0081;

protocol Parser {
    ParseLine();

    @selector("Parse1Line")
    ParseOneLine();
};

如果存在 SHA-256 冲突,也会发生此错误,但 因此基本为零如果你确定,你的选择器没有错, 还是会遇到此错误,则表明您可能是在 FIDL 编译器中发现了 bug。 如果发生这种情况,请向我们的问题跟踪器报告此问题。

fi-0082:选择器值无效

如果为 @selector 使用的值无效,就会出现此错误。 这通常是由于拼写错误所致。选择器必须是独立的 方法名称或完全限定的方法名称。

library test.bad.fi0082;

protocol Parser {
    @selector("test.old.fi0082.Parser.Parse")
    Parse();
};

要解决此问题,请将选择器更新为有效的独立选择器,或 限定方法名称:

library test.good.fi0082;

protocol Parser {
    @selector("test.old.fi0082/Parser.Parse")
    Parse();
};

fi-0083:fuchsia.io 必须使用显式序数

FIDL 编译器用于将 fuchsia.io 序数自动重命名为 fuchsia.io1。这种神奇之处在于 fuchsia.io2,方法是让方法的 io2 版本具有“normal” 序数。不过,这个系统后来变得有点神奇了,所以现在 需要手动为 fuchsia.io 提供序数。

library fuchsia.io;

protocol SomeProtocol {
    SomeMethod();
};

要解决此问题,请手动提供一个选择器,使用 fuchsia.io1 作为 库名称以允许将 fuchsia.io 名称用于 io2。

library fuchsia.io;

protocol SomeProtocol {
    @selector("fuchsia.io1/SomeProtocol.SomeMethod")
    SomeMethod();
};

fi-0084:方法载荷结构体不允许默认成员

用作方法负载的结构体不能指定默认成员:

library test.bad.fi0084;

type MyStruct = struct {
    @allow_deprecated_struct_defaults
    a bool = false;
};

protocol MyProtocol {
    MyMethod(MyStruct) -> (MyStruct);
};

从相关的 struct 声明中移除默认成员:

library test.good.fi0084;

type MyStruct = struct {
    a bool;
};

protocol MyProtocol {
    MyMethod(MyStruct) -> (MyStruct);
};

fi-0085

fi-0086

fi-0087

fi-0088:服务成员不能是可选项

将服务成员标记为 optional 时会发生此错误。标记 服务成员(因为 optional)是不允许的,因为服务成员始终是 可选属性。

library test.bad.fi0088;

protocol Sorter {
    Sort(struct {
        input vector<int32>;
    }) -> (struct {
        output vector<int32>;
    });
};

service SortService {
    quicksort client_end:<Sorter, optional>;
    mergesort client_end:<Sorter, optional>;
};

要解决此问题,请移除可选子句:

library test.good.fi0088;

protocol Sorter {
    Sort(struct {
        input vector<int32>;
    }) -> (struct {
        output vector<int32>;
    });
};

service SortService {
    quicksort client_end:Sorter;
    mergesort client_end:Sorter;
};

fi-0089

fi-0090

fi-0091:结构体成员类型无效

当您尝试为不受支持的对象设置默认结构体值时,就会发生此错误 类型。只允许数字和布尔值类型设置默认结构体值。

library test.bad.fi0091;

type Person = struct {
    @allow_deprecated_struct_defaults
    name string:optional = "";
};

要解决此问题,请移除默认值:

library test.good.fi0091;

type Person = struct {
    @allow_deprecated_struct_defaults
    name string:optional;
};

fi-0092:表序数过大

FIDL 表序数不能大于 64:

library test.bad.fi0092;

type Table64thField = table {
    1: x int64;
};

type Example = table {
    1: v1 int64;
    2: v2 int64;
    3: v3 int64;
    4: v4 int64;
    5: v5 int64;
    6: v6 int64;
    7: v7 int64;
    8: v8 int64;
    9: v9 int64;
    10: v10 int64;
    11: v11 int64;
    12: v12 int64;
    13: v13 int64;
    14: v14 int64;
    15: v15 int64;
    16: v16 int64;
    17: v17 int64;
    18: v18 int64;
    19: v19 int64;
    20: v20 int64;
    21: v21 int64;
    22: v22 int64;
    23: v23 int64;
    24: v24 int64;
    25: v25 int64;
    26: v26 int64;
    27: v27 int64;
    28: v28 int64;
    29: v29 int64;
    30: v30 int64;
    31: v31 int64;
    32: v32 int64;
    33: v33 int64;
    34: v34 int64;
    35: v35 int64;
    36: v36 int64;
    37: v37 int64;
    38: v38 int64;
    39: v39 int64;
    40: v40 int64;
    41: v41 int64;
    42: v42 int64;
    43: v43 int64;
    44: v44 int64;
    45: v45 int64;
    46: v46 int64;
    47: v47 int64;
    48: v48 int64;
    49: v49 int64;
    50: v50 int64;
    51: v51 int64;
    52: v52 int64;
    53: v53 int64;
    54: v54 int64;
    55: v55 int64;
    56: v56 int64;
    57: v57 int64;
    58: v58 int64;
    59: v59 int64;
    60: v60 int64;
    61: v61 int64;
    62: v62 int64;
    63: v63 int64;
    // The 64th field of a table must be another table, otherwise it will cause
    // fi-0093: Max Ordinal In Table Must Be Table.
    64: v64 Table64thField;
    65: v65 int64;
};

为了支持 64 个序数以上的增长,FIDL 需要 转换为另一个表格。任何超出 64 的表字段都必须放置在一个嵌套层中, 表格。

library test.good.fi0092;

type Table64thField = table {
    1: x int64;
    // Any fields beyond 64 of table Example must be move to the nested table in
    // ordinal 64 of Example.
    2: v65 int64;
};

type Example = table {
    1: v1 int64;
    2: v2 int64;
    3: v3 int64;
    4: v4 int64;
    5: v5 int64;
    6: v6 int64;
    7: v7 int64;
    8: v8 int64;
    9: v9 int64;
    10: v10 int64;
    11: v11 int64;
    12: v12 int64;
    13: v13 int64;
    14: v14 int64;
    15: v15 int64;
    16: v16 int64;
    17: v17 int64;
    18: v18 int64;
    19: v19 int64;
    20: v20 int64;
    21: v21 int64;
    22: v22 int64;
    23: v23 int64;
    24: v24 int64;
    25: v25 int64;
    26: v26 int64;
    27: v27 int64;
    28: v28 int64;
    29: v29 int64;
    30: v30 int64;
    31: v31 int64;
    32: v32 int64;
    33: v33 int64;
    34: v34 int64;
    35: v35 int64;
    36: v36 int64;
    37: v37 int64;
    38: v38 int64;
    39: v39 int64;
    40: v40 int64;
    41: v41 int64;
    42: v42 int64;
    43: v43 int64;
    44: v44 int64;
    45: v45 int64;
    46: v46 int64;
    47: v47 int64;
    48: v48 int64;
    49: v49 int64;
    50: v50 int64;
    51: v51 int64;
    52: v52 int64;
    53: v53 int64;
    54: v54 int64;
    55: v55 int64;
    56: v56 int64;
    57: v57 int64;
    58: v58 int64;
    59: v59 int64;
    60: v60 int64;
    61: v61 int64;
    62: v62 int64;
    63: v63 int64;
    64: v64 Table64thField;
};

表中的每个字段都会产生 FIDL 信封的开销, 该字段为选填字段这样一来,表格中的每个字段 缺失字段,您可以通过添加或移除字段来改进表,但 内存开销比结构体大得多。

一般来说,您可以避免此错误并减少开销, 小型的精细字段。相反,您可以将 需要同时添加或移除到结构体中,并使用 用作表格中的字段这样可以减少开销,避免资源耗尽 代价是一些无法持续改进。

这成为 RFC-0132: FIDL 表大小中的错误 限制 旨在防止用户意外导致 大型表格。这种额外的开销在架构中并不明显,尤其是当存在 只有少数字段(序号很大),或者有很多字段,但是 一次只能使用几个

fi-0093:表中的最大序数必须是表

FIDL 表中第 64 个成员的类型本身必须是表:

library test.bad.fi0093;

type Example = table {
    1: v1 int64;
    2: v2 int64;
    3: v3 int64;
    4: v4 int64;
    5: v5 int64;
    6: v6 int64;
    7: v7 int64;
    8: v8 int64;
    9: v9 int64;
    10: v10 int64;
    11: v11 int64;
    12: v12 int64;
    13: v13 int64;
    14: v14 int64;
    15: v15 int64;
    16: v16 int64;
    17: v17 int64;
    18: v18 int64;
    19: v19 int64;
    20: v20 int64;
    21: v21 int64;
    22: v22 int64;
    23: v23 int64;
    24: v24 int64;
    25: v25 int64;
    26: v26 int64;
    27: v27 int64;
    28: v28 int64;
    29: v29 int64;
    30: v30 int64;
    31: v31 int64;
    32: v32 int64;
    33: v33 int64;
    34: v34 int64;
    35: v35 int64;
    36: v36 int64;
    37: v37 int64;
    38: v38 int64;
    39: v39 int64;
    40: v40 int64;
    41: v41 int64;
    42: v42 int64;
    43: v43 int64;
    44: v44 int64;
    45: v45 int64;
    46: v46 int64;
    47: v47 int64;
    48: v48 int64;
    49: v49 int64;
    50: v50 int64;
    51: v51 int64;
    52: v52 int64;
    53: v53 int64;
    54: v54 int64;
    55: v55 int64;
    56: v56 int64;
    57: v57 int64;
    58: v58 int64;
    59: v59 int64;
    60: v60 int64;
    61: v61 int64;
    62: v62 int64;
    63: v63 int64;
    64: v64 int64;
};

如果用户发现自己需要添加第 64 位成员,则应为每个成员分别创建 表存储第 64 位及之后的成员,并将该成员放入表中:

library test.good.fi0093;

type Table64thField = table {
    1: x int64;
};

type Example = table {
    1: v1 int64;
    2: v2 int64;
    3: v3 int64;
    4: v4 int64;
    5: v5 int64;
    6: v6 int64;
    7: v7 int64;
    8: v8 int64;
    9: v9 int64;
    10: v10 int64;
    11: v11 int64;
    12: v12 int64;
    13: v13 int64;
    14: v14 int64;
    15: v15 int64;
    16: v16 int64;
    17: v17 int64;
    18: v18 int64;
    19: v19 int64;
    20: v20 int64;
    21: v21 int64;
    22: v22 int64;
    23: v23 int64;
    24: v24 int64;
    25: v25 int64;
    26: v26 int64;
    27: v27 int64;
    28: v28 int64;
    29: v29 int64;
    30: v30 int64;
    31: v31 int64;
    32: v32 int64;
    33: v33 int64;
    34: v34 int64;
    35: v35 int64;
    36: v36 int64;
    37: v37 int64;
    38: v38 int64;
    39: v39 int64;
    40: v40 int64;
    41: v41 int64;
    42: v42 int64;
    43: v43 int64;
    44: v44 int64;
    45: v45 int64;
    46: v46 int64;
    47: v47 int64;
    48: v48 int64;
    49: v49 int64;
    50: v50 int64;
    51: v51 int64;
    52: v52 int64;
    53: v53 int64;
    54: v54 int64;
    55: v55 int64;
    56: v56 int64;
    57: v57 int64;
    58: v58 int64;
    59: v59 int64;
    60: v60 int64;
    61: v61 int64;
    62: v62 int64;
    63: v63 int64;
    64: v64 Table64thField;
};

该要求背后的推理和动机在 RFC-0132:FIDL 表大小限制。简而言之,FIDL 表需要包含 对它们允许的字段数量有相对有限的限制,否则 一次仅使用几个字段的编码表格式将具有 大量不可接受的无效空间(每个省略 16 个字节)。

FIDL 为希望表中超过 64 个字段的用户提供了一种临时解决方案, 强制为“连续表”保留最后一个序数包含 extra 字段。在此位置使用任何其他类型都会呈现表格 且无法扩展

fi-0094:重复的表成员序数

table 声明中用于成员的序数不得重复:

library test.bad.fi0094;

type MyTable = table {
    1: my_field string;
    1: my_other_field uint32;
};

根据需要递增序数,以确保声明具有唯一的 序号:

library test.good.fi0094a;

type MyTable = table {
    1: my_field string;
    2: my_other_field uint32;
};

或者,也可以移除具有重复名称的某个成员:

library test.good.fi0094b;

type MyTable = table {
    1: my_field string;
};

序数用于标识电线上的字段。如果两位成员共用一个 序数,没有可靠的方法分辨在何时引用了哪个字段 对 FIDL 消息进行解码。

fi-0095

fi-0096

fi-0097:重复的联盟成员序号

union 声明中用于成员的序数不得重复:

library test.bad.fi0097;

type MyUnion = strict union {
    1: my_variant string;
    1: my_other_variant int32;
};

根据需要递增序数,以确保声明具有唯一的 序号:

library test.good.fi0097a;

type MyUnion = strict union {
    1: my_variant string;
    2: my_other_variant int32;
};

或者,也可以移除具有重复名称的某个成员:

library test.good.fi0097b;

type MyUnion = strict union {
    1: my_variant string;
};

序数用于标识线上的变体。如果两位成员共用一个 没有可靠的方法分辨被引用的是哪个变体 读取 FIDL 消息。

fi-0098

fi-0099

fi-0100

fi-0101:无法解析大小限制

应用于 vectorstring 类型定义的大小限制必须是 uint32 类型的有效值:

library test.bad.fi0101a;

alias MyBoundedOptionalVector = vector<uint32>:<"255", optional>;
library test.bad.fi0101b;

alias MyBoundedOptionalVector = vector<uint32>:<uint8, optional>;

请确保满足此条件:

library test.good.fi0101;

alias MyBoundedOptionalVector = vector<uint32>:<255, optional>;

fi-0102:成员值无法解析

bitsenum 声明的成员必须是 指定的子类型:

library test.bad.fi0102;

type Fruit = bits : uint64 {
    ORANGE = 1;
    APPLE = 2;
    BANANA = -4;
};

确保所有值都与声明的基础类型匹配:

library test.good.fi0102;

type Fruit = bits : uint64 {
    ORANGE = 1;
    APPLE = 2;
    BANANA = 4;
};

fi-0103:结构体默认值无法解析

struct 声明的成员的默认值必须与其 相应成员声明的类型:

library test.bad.fi0103;

type MyEnum = enum : int32 {
    A = 1;
};

type MyStruct = struct {
    @allow_deprecated_struct_defaults
    field MyEnum = 1;
};

确保该值与声明的类型匹配:

library test.good.fi0103;

type MyEnum = enum : int32 {
    A = 1;
};

type MyStruct = struct {
    @allow_deprecated_struct_defaults
    field MyEnum = MyEnum.A;
};

fi-0104:属性参数无法解析

官方的参数值 根据属性架构的预期,FIDL 属性不得无效 该参数:

library test.bad.fi0104;

type MyStruct = struct {
    my_field @generated_name(true) struct {};
};

确保用作属性参数的值类型正确无误:

library test.good.fi0104;

type MyStruct = struct {
    my_field @generated_name("my_inner_type") struct {};
};

fi-0105

fi-0106

fi-0107:重复成员值

bitsenum 声明都不能有具有相同值的成员:

library test.bad.fi0107;

type Fruit = flexible enum {
    ORANGE = 1;
    APPLE = 1;
};

将成员值全部更改为唯一值:

library test.good.fi0107a;

type Fruit = flexible enum {
    ORANGE = 1;
    APPLE = 2;
};

或者,移除其中一个重复的成员:

library test.good.fi0107b;

type Fruit = flexible enum {
    ORANGE = 1;
};

fi-0108

fi-0109

fi-0110:包含类型的资源必须标记为资源

包含句柄的类型,可直接或通过传递 包含另一个包含句柄的类型,否则无法声明该类型 指定为 resource 的类型:

library test.bad.fi0110;

using zx;

type Foo = struct {
    handle zx.Handle;
};

有两种可能的解决方案。第一种是为违规内容添加注释 声明:

library test.good.fi0110a;

using zx;

type Foo = resource struct {
    handle zx.Handle;
};

或者,您也可以选择彻底移除包含 resource 的类型, 因此无需对所属声明使用修饰符:

library test.good.fi0110b;

type Foo = struct {
    value uint32;
};

添加 resource 修饰符的推理和动机 “具有感染力”的可以通过此错误强制执行的使用模式的性质 (在 RFC-0057:默认无句柄中)。

fi-0111:内嵌大小超出限制

不允许使用内嵌大小为 64 KiB 或更大的 FIDL 类型:

library test.bad.fi0111;

type MyStruct = struct {
    numbers array<uint8, 65536>;
};

请确保该类型的内嵌大小小于 64 KiB。在此示例中 我们可以调整数组边界:

library test.good.fi0111;

type MyStruct = struct {
    numbers array<uint8, 65535>;
};

此限制是出于性能方面的考虑而存在。这意味着编码器和解码器 可以假设大小和偏移量适合无符号的 16 位整数。

除非您使用大型数组或 深度嵌套的结构体。大多数 FIDL 结构(例如字符串、矢量、表、 和联合)使用外行存储空间,这不会计入其 单独的内嵌大小。

fi-0112:服务成员不是 client_end

服务成员只能是客户端,而不能是任何其他类型:

library test.bad.fi0112;

protocol Calculator {};

service Service {
    calculator server_end:Calculator;
};

如需修正该错误,请确保成员采用某些协议 Pclient_end:P 格式:

library test.good.fi0112;

protocol Calculator {};

service Service {
    calculator client_end:Calculator;
};

服务是协议实例的集合,而非通用数据 所以允许任意类型就毫无意义。

fi-0113:服务中的传输不匹配

FIDL 服务不得包含使用不同传输的协议:

library test.bad.fi0113;

protocol ChannelProtocol {};

@transport("Driver")
protocol DriverProtocol {};

service SomeService {
    a client_end:ChannelProtocol;
    b client_end:DriverProtocol;
};

相反,请针对每种传输使用单独的服务:

library test.good.fi0113;

protocol ChannelProtocol {};

@transport("Driver")
protocol DriverProtocol {};

service ChannelService {
    protocol client_end:ChannelProtocol;
};

service DriverService {
    protocol client_end:DriverProtocol;
};

请注意,服务是 FIDL 中尚未完成的功能。它们最初是 RFC-0041:支持统一 Serviceas 和 设备。 请参阅 https://fxbug.dev/42160684 了解截至 2022 年 10 月的状态。

fi-0114:Composed 协议过于开放

一个协议不能构成比自身更开放的其他协议:

library test.bad.fi0114;

open protocol Composed {};

ajar protocol Composing {
    compose Composed;
};

您可以通过提高撰写协议的开放性来解决此问题,即 将其从 closed 更改为 ajar,或从 ajar 更改为 open

library test.good.fi0114a;

open protocol Composed {};

open protocol Composing {
    compose Composed;
};

或者,您也可以降低组合协议的开放性,例如将 从 open 更改为 ajar,或者从 ajar 更改为 closed

library test.good.fi0114b;

ajar protocol Composed {};

ajar protocol Composing {
    compose Composed;
};

这种规则之所以存在,是因为协议的开放性限制了 方法。例如,Ajar 协议不能包含 灵活的双向方法,但开放协议可以,因此对于 JAR 文件并不安全 构成一个开放式协议

请参阅 RFC-0138:处理未知 互动 ,详细了解协议修饰符。

fi-0115:灵活的双向方法需要开放协议

封闭式和半开式协议不得包含灵活的双向方法:

library test.bad.fi0115;

ajar protocol Protocol {
    flexible Method() -> ();
};

请改为将双向方法标记为 strict,而不是 flexible

library test.good.fi0115a;

ajar protocol Protocol {
    strict Method() -> ();
};

或者,将协议标记为 open,而不是 closedajar

library test.good.fi0115b;

open protocol Protocol {
    flexible Method() -> ();
};

出现此错误是因为 closed(或 ajar)修饰符的作用是 确保某个方法不包含任何灵活的(双向)方法。首次 创建协议时,您应该仔细考虑是否应该使用 闭合、半开或开合。

请参阅 RFC-0138:处理未知 互动 ,详细了解协议修饰符。

fi-0116:灵活的单向方法需要 ajar 或开放协议

封闭协议不得包含灵活的单向方法:

library test.bad.fi0116;

closed protocol Protocol {
    flexible Method();
};

请改为将单向方法标记为 strict,而不是 flexible

library test.good.fi0116;

closed protocol Protocol {
    strict Method();
};

或者,将协议标记为 ajaropen,而不是 closed

library test.good.fi0116;

ajar protocol Protocol {
    flexible Method();
};

出现此错误是因为 closed 修饰符的作用是确保 方法不包含任何灵活的方法。首次创建协议时 你应该仔细考虑是应该封闭、半开还是开放 进行微调。

请参阅 RFC-0138:处理未知 互动 ,详细了解协议修饰符。

fi-0117:在不兼容的传输中使用的句柄

协议只能引用与其传输兼容的句柄。 例如,Zircon 信道传输上的协议不能引用 Fuchsia 驱动程序框架的句柄:

library test.bad.fi0117;

using fdf;

protocol Protocol {
    Method(resource struct {
        h fdf.handle;
    });
};

而应使用与协议传输兼容的句柄:

library test.good.fi0117a;

using zx;

protocol Protocol {
    Method(resource struct {
        h zx.Handle;
    });
};

或者,更改协议的传输以匹配标识名:

library test.good.fi0117b;

using fdf;

@transport("Driver")
protocol Protocol {
    Method(resource struct {
        h fdf.handle;
    });
};

fi-0118:在不兼容的传输中使用传输结束

协议只能指代以下项的传输端(client_endserver_end) 共享协议。例如,使用 Syscall 的协议 transport 不能指使用驱动程序传输的协议的客户端端:

library test.bad.fi0118;

@transport("Driver")
protocol DriverProtocol {};

@transport("Syscall")
protocol P {
    M(resource struct {
        s client_end:DriverProtocol;
    });
};

如需修正该错误,请移除传输结束成员:

library test.good.fi0118;

@transport("Driver")
protocol DriverProtocol {};

@transport("Syscall")
protocol Protocol {
    M();
};

fi-0119

fi-0120:属性展示位置无效

部分官方属性 允许出现某些情况。例如,@selector 属性只能是 用于:

library test.bad.fi0120a;

@selector("Nonsense")
type MyUnion = union {
    1: hello uint8;
};

要修正该错误,请移除此属性:

library test.good.fi0120a;

type MyUnion = union {
    1: hello uint8;
};

打算以某种方式使用某个属性时,您也可能会遇到此错误 但将其放在错误的位置。例如, @generated_name 属性不能直接应用于成员:

library test.bad.fi0120a;

@selector("Nonsense")
type MyUnion = union {
    1: hello uint8;
};

而应紧挨着放在成员匿名布局的前面:

library test.good.fi0120a;

type MyUnion = union {
    1: hello uint8;
};

fi-0121:属性已弃用

部分官方属性包括 已弃用,不应再使用:

library test.bad.fi0121;

@example_deprecated_attribute
type MyStruct = struct {};

解决方法取决于该属性被弃用的原因。例如,错误消息可能会显示使用其他属性。在本例中,我们只需移除该属性:

library test.good.fi0121;

type MyStruct = struct {};

fi-0122:属性名称重复

一个元素不能有多个同名的属性:

library test.bad.fi0122;

@custom_attribute("first")
@custom_attribute("second")
type Foo = struct {};

正确做法是,每个属性仅指定一次:

library test.good.fi0122;

@custom_attribute("first")
type Foo = struct {};

fi-0123:规范属性名称重复

一个元素不能有多个具有相同规范名称的属性:

library test.bad.fi0123;

@custom_attribute("first")
@CustomAttribute("second")
type Foo = struct {};

虽然 custom_attributeCustomAttribute 看起来有所不同,但它们确实一样 两者均以规范名称 custom_attribute 表示。您将获得 规范名称(具体方法为将原始名称转换为 snake_case)。

如需修正该错误,请为每个属性指定一个唯一的名称, 规范化。

library test.good.fi0123;

@custom_attribute("first")
@AnotherCustomAttribute("first")
type Foo = struct {};

请参阅 fi-0035,详细了解 FIDL 为何要求进行声明 具有唯一的规范名称。

fi-0124:自定义属性参数必须是 string 或 bool

用户定义的 FIDL 属性的参数仅限于字符串或 布尔值类型:

library test.bad.fi0124;

@my_custom_attr(foo=1, bar=2.3)
type MyStruct = struct {};
library test.good.fi0124;

@my_custom_attr(foo=true, bar="baz")
type MyStruct = struct {};

官方属性不同,用户定义的架构 属性。因此, 编译器推断任何给定数字参数的类型 - 是 2int8uint64 还是 float32?编译器无从得知。

此问题的一个可能的解决方案是实现一个 numeric 类型。但是,由于 自定义属性参数是目前已知的唯一用例, 功能尚未优先。

fi-0125:Attribute 参数不得命名

使用官方属性时 ,则您不能为该参数命名:

library test.bad.fi0125;

@transport(value="Driver")
protocol Foo {};

正确做法是传递参数而不为其指定名称:

library test.good.fi0125;

@discoverable(name="example.Bar")
protocol Foo {};

FIDL 强制执行此要求以使属性更简洁一致。在 将参数名称推断为 value(这会显示在 JSON IR),因为这是属性接受的唯一参数。

fi-0126:Attribute 参数必须命名

使用官方属性时 ,则不能传递未命名的实参:

@available(1)
library test.bad.fi0126;

而应指定实参的名称:

@available(added=1)
library test.good.fi0126;

出现此错误的原因是您无法得知想要的参数 属性接受多个参数时设置的值。

fi-0127:缺少必需的属性参数

使用官方属性时 不能省略:

library test.bad.fi0127;

@has_required_arg
type Foo = struct {};

请改为提供所需的实参:

library test.good.fi0127;

@has_required_arg(required="something")
type Foo = struct {};

fi-0128:缺少单个属性参数

使用官方属性时 不能省略:

library test.bad.fi0128;

@transport
protocol Protocol {};

请改为提供参数:

library test.good.fi0128;

@transport("Driver")
protocol Protocol {};

fi-0129:未知属性参数

使用官方属性时, 您不能提供不在其架构中的参数:

@available(added=1, discontinued=2)
library test.bad.fi0129;

如果您想要传递不同的实参,但弄错了名称,请将其更改为使用正确的名称:

@available(added=1, deprecated=2)
library test.good.fi0129a;

或者,移除该参数:

@available(added=1)
library test.good.fi0129b;

出现此错误是因为官方属性是根据架构进行验证的。如果 FIDL 允许任意参数,它们不会产生任何影响,还可能导致 通过遮盖错别字来找出错误。

fi-0130:属性参数重复

属性不能有两个名称相同的参数:

library test.bad.fi0130;

@custom_attribute(custom_arg=true, custom_arg=true)
type Foo = struct {};

请改为仅提供一个具有该名称的参数:

library test.good.fi0130;

@custom_attribute(custom_arg=true)
type Foo = struct {};

fi-0131:规范属性参数重复

属性不能有两个具有相同规范名称的参数:

library test.bad.fi0131;

@custom_attribute(custom_arg=true, CustomArg=true)
type Foo = struct {};

虽然 custom_argCustomArg 看起来不同,但它们都是 以规范名称 custom_arg 表示。您会获得规范名称 方法是将原始名称转换为 snake_case

如需修正该错误,请为每个参数指定一个唯一的名称, 规范化:

library test.good.fi0131a;

@custom_attribute(custom_arg=true, AnotherCustomArg=true)
type Foo = struct {};

或者,移除其中一个参数:

library test.good.fi0131b;

@custom_attribute(custom_arg=true)
type Foo = struct {};

请参阅 fi-0035,详细了解 FIDL 为何要求进行声明 具有唯一的规范名称。

fi-0132:非预期的属性参数

使用官方属性时 ,则您不能提供参数:

library test.bad.fi0132;

type Foo = flexible enum : uint8 {
    @unknown("hello")
    BAR = 1;
};

请改为移除该参数:

library test.good.fi0132;

type Foo = flexible enum : uint8 {
    @unknown
    BAR = 1;
};

fi-0133:属性参数必须是字面量

某些官方属性可以 不允许使用是对常量的引用的参数:

library test.bad.fi0133;

const NAME string = "MyTable";

type Foo = struct {
    bar @generated_name(NAME) table {};
};

请改为将字面量值作为实参传递:

library test.good.fi0133;

type Foo = struct {
    bar @generated_name("MyTable") table {};
};

这些属性需要使用字面量参数,因为它们的值会影响 编译。支持非文字参数将难以实现, 或者在某些情况下是不可行的,因为这会引发矛盾。

fi-0134

fi-0135:可发现名称无效

如果您为 @discoverable 属性使用了错误的名称,就会出现此错误。 @discoverable 属性应该是库名称,后跟 ., 协议名称。

library test.bad.fi0135;

@discoverable(name="test.bad.fi0135/Parser")
protocol Parser {
    Tokenize() -> (struct {
        tokens vector<string>;
    });
};

如需修正此错误,请使用有效的可发现名称:

library test.good.fi0135;

@discoverable(name="test.good.fi0135.Parser")
protocol Parser {
    Tokenize() -> (struct {
        tokens vector<string>;
    });
};

fi-0136

fi-0137

fi-0138

fi-0139

fi-0140

fi-0141:错误类型无效

方法响应载荷的 error 类型必须是 int32uint32 或 其中 enum 个:

library test.bad.fi0141;

protocol MyProtocol {
    MyMethod() -> () error float32;
};

error 类型更改为某个有效选项即可修复此错误:

library test.good.fi0141;

protocol MyProtocol {
    MyMethod() -> () error int32;
};

如需了解详情,请参阅 RFC-0060:错误处理

fi-0142:协议传输类型无效

protocol 声明中的 @transport(...) 属性不得指定 传输无效:

library test.bad.fi0142;

@transport("Invalid")
protocol MyProtocol {
    MyMethod();
};

请改用一种受支持的传输方式:

library test.good.fi0142;

@transport("Syscall")
protocol MyProtocol {
    MyMethod();
};

哪些构成支持的传输仍在最终确定。请参阅 FIDL 属性以获取最新信息。

fi-0143

fi-0144

fi-0145:属性拼写错误

属性名称,其拼写与某 FIDL 官方名称的拼写过于相似。 attributes 则会导致编译器警告:

library test.bad.fi0145;

@duc("should be doc")
protocol Example {
    Method();
};

在上面的示例中,属性@duc在拼写上与 官方 FIDL 属性 @doc。在这种情况下,属性命名方式为 而不是有意将官方 FIDL 属性拼错, 应进行修改,使其足够唯一:

library test.good.fi0145;

@duck("quack")
protocol Example {
    Method();
};

除了拼写检查,此警告的目的是阻止使用 与官方 FIDL 属性过于相似的名称。

拼写错误检测算法的工作原理是计算 属性名称与每个官方 FIDL 的距离 属性。名称过于相似,指修改内容过小 触发拼写错误检测器。

fi-0146:生成的名称无效

如果将 @generated_name 属性与无效的 名称。生成的名称必须遵循与所有 FIDL 标识符相同的规则。

library test.bad.fi0146;

type Device = table {
    1: kind flexible enum {
        DESKTOP = 1;
        PHONE = 2;
    };
};

type Input = table {
    1: kind @generated_name("_kind") flexible enum {
        KEYBOARD = 1;
        MOUSE = 2;
    };
};

若要解决此问题,请将 @generated_name 值更改为有效的标识符。

library test.good.fi0146;

type Device = table {
    1: kind flexible enum {
        DESKTOP = 1;
        PHONE = 2;
    };
};

type Input = table {
    1: kind @generated_name("input_kind") flexible enum {
        KEYBOARD = 1;
        MOUSE = 2;
    };
};

fi-0147:@available 缺少参数

如果您使用 @available 属性但未提供 必需的参数。@available 至少需要 addeddeprecatedremoved

@available(added=1)
library test.bad.fi0147;

@available
type Foo = struct {};

如需解决此问题,请添加以下必需参数之一:

@available(added=1)
library test.good.fi0147;

@available(added=2)
type Foo = struct {};

如需了解详情,请参阅 FIDL 版本控制

fi-0148:未弃用的说明

当您对 @available 使用 note 参数时,会发生此错误 属性,而不使用 deprecated 参数。note仅适用于 弃用。

@available(added=1, note="My note")
library test.bad.fi0148;

要修正此错误,请移除备注:

@available(added=1)
library test.good.fi0148a;

或添加必要的 deprecated 通知:

@available(added=1, deprecated=2, note="Removed in 2; use X instead.")
library test.good.fi0148b;

如需了解详情,请参阅 FIDL 版本控制

fi-0149:平台不在库中

当您尝试使用 @available 属性的 platform 时,会发生此错误 参数。platform 参数仅在 library 级别有效。

@available(added=1)
library test.bad.fi0149;

@available(platform="foo")
type Person = struct {
    name string;
};

如需解决此问题,请将 platform 参数移到库 @available 中 属性:

@available(added=1, platform="foo")
library test.good.fi0149a;

type Person = struct {
    name string;
};

或彻底移除 platform 参数:

@available(added=1)
library test.good.fi0149b;

type Person = struct {
    name string;
};

fi-0150:缺少库可用性

如果您在没有添加 @available 属性的情况下将 @available 属性添加到库中, 提供 added 参数。library 需要使用 added 参数 @available 属性。

@available(removed=2)
library test.bad.fi0150a;
@available(platform="foo")
library test.bad.fi0150b;

如需解决此问题,请将 added 参数添加到库的 @available 中 属性:

@available(added=1, removed=2)
library test.good.fi0150a;
@available(added=1, platform="foo")
library test.good.fi0150b;

fi-0151:缺少库可用性

在非 library 上添加 @available 属性时,会发生此错误 library 声明中不包含 @available 属性的声明。

library test.bad.fi0151;

@available(added=1)
type Person = struct {
    name string;
};

如需修复此错误,请将 @available 属性添加到 library 声明中:

@available(added=1)
library test.good.fi0151a;

@available(added=1)
type Person = struct {
    name string;
};

或者从非 library 声明中移除 @available 属性:

library test.good.fi0151b;

type Person = struct {
    name string;
};

fi-0152:平台无效

当您对以下对象的 platform 参数使用无效字符时,就会出现此错误 @available 属性。platform 参数必须是有效的 FIDL 库 标识符

@available(added=1, platform="Spaces are not allowed")
library test.bad.fi0152;

如需修正此错误,请移除不允许使用的字符:

@available(added=1, platform="foo")
library test.good.fi0152;

fi-0153:版本无效

如果对 addedremoved 使用无效版本,就会出现此错误 一个 @available 属性。addedremoved 参数必须 1 到 2^63-1 之间的正整数,或特殊常量 HEAD

@available(added=0)
library test.bad.fi0153;

要解决此问题,请将版本更改为有效值:

@available(added=1)
library test.good.fi0153;

fi-0154:可用性订单无效

如果 addeddeprecated@available 属性的 remove 参数。以下限制条件必须 尊重:

  • added 必须小于或等于 deprecated
  • deprecated 必须小于 removed
  • added 必须小于 removed
@available(added=2, removed=2)
library test.bad.fi0154a;
@available(added=2, deprecated=3, removed=3)
library test.bad.fi0154b;

若要解决此问题,请将 addeddeprecatedremoved 参数更新为 所需的排序:

@available(added=1, removed=2)
library test.good.fi0154a;
@available(added=2, deprecated=2, removed=3)
library test.good.fi0154b;

fi-0155:与父级发布商产生可用性冲突

@availability 属性添加到非 library 时, 声明与 library 的声明冲突。

@available(added=2, deprecated=3, removed=4)
library test.bad.fi0155a;

@available(added=1)
type Person = struct {
    name string;
};
@available(added=2, deprecated=3, removed=4)
library test.bad.fi0155b;

@available(added=4)
type Person = struct {
    name string;
};

如需修正此错误,请将 @availability 属性更新为必需的属性 限制条件:

@available(added=2, deprecated=3, removed=4)
library test.good.fi0155;

@available(added=2)
type Person = struct {
    name string;
};

fi-0156:不能是可选项

当您尝试将不能标记为可选的类型时,就会出现此错误 可选属性。

library test.bad.fi0156;

type Person = struct {
    name string;
    age int16:optional;
};

如需修复此错误,请移除可选约束条件:

library test.good.fi0156;

type Person = struct {
    name string;
    age int16;
};

只有可以在不更改线形形状的情况下可选的 FIDL 类型 可以使用 optional 限制条件。请参阅 可选指南或下方的展开内容,了解详情。

FIDL 配方:可选性

您可以将某些 FIDL 类型设置为可选,而无需更改 包含 :optional 约束条件的消息。 此外,table 布局始终是可选的,而 struct 布局从不 。如需将 struct 设为可选,必须将其封装在 box<T> 中,从而 更改其所含消息的导线形状。

基本类型 可选版本 可选设置会改变电线布局吗?
struct {...} box<struct {...}>
table {...} table {...}
union {...} union {...}:optional
vector<T> vector<T>:optional
string string:optional
zx.Handle zx.Handle:optional
client_end:P client_end:<P, optional>
server_end:P server_end:<P, optional>

所有其他类型(bitsenumarray<T, N> 和基元类型)都不可以 都是可选的

在此变体中,我们允许键值存储区将其他键值存储区视为 成员。简而言之,我们把它变成了一棵树。为此,我们会使用 value 的定义,其中定义使用双成员 union:一种变体 存储使用与之前相同的 vector<byte> 类型的叶节点,而另一个 以其他嵌套存储区的形式存储分支节点。

推理

在这里,我们可以看到“可选性”的多种用途,通过它可以声明一个类型, 可能会存在。FIDL 中有三种可选性:

  • 始终存储的类型 不符合要求 因此有一种内置方式可以描述“缺失”通过 null 信封。正在启用 这些类型的可选性不会影响它们所属的消息的电线形状 它只是更改对特定标签有效的值 类型。unionvector<T>client_endserver_endzx.Handle 都可以通过添加 :optional 约束条件使所有类型都是可选的。 通过将 value union 设置为可选,我们能够引入 null条目,采用不存在的 value 的形式。这意味着,空 bytes 和不存在/空的 store 属性是无效值。
  • 与上述类型不同,struct 布局没有额外的空间, 可以存储 null 标头。因此,需要将其封装在 信封、更改所包含邮件的网线形状 位置为确保这种电线修改效果清晰易读,Item struct 类型必须封装在 box<T> 类型模板中。
  • 最后,table 布局始终是可选的。缺失 table 只是一种 且未设置任何成员。

树状结构是自然的自引用数据结构:树中的任何节点都可以 包含具有纯数据(本例中为字符串)的叶,或具有 节点。这需要递归:Item 的定义现在以传递方式传递 需要依赖自身!在 FIDL 中表示递归类型可能有点棘手, 特别是考虑到我们目前获得的支持 受限。只要有 自引用创建的循环中至少有一个可选类型。对于 实例,在这里我们将 items struct 成员定义为 box<Item>, 从而打破 include 循环。

这些更改还大量使用了匿名类型,即 声明是内嵌在它们的唯一使用点,而不是直接使用, 它们自己的顶级 type 声明。默认情况下 生成的语言绑定中的类型取自其本地上下文。对于 实例中,新引入的 flexible union 会使用其所属成员的 名称为 Value,新引入的 struct 将变为 Store,依此类推。 由于这种启发法有时可能会导致冲突,因此 FIDL 提供了一种逃逸方法。 允许作者手动替换匿名类型生成的 名称。这是通过 @generated_name 属性完成的,该属性允许 更改后端生成的名称在这里,我们可以使用 Store 类型已重命名为 NestedStore,以防止与 protocol 声明。

实现

FIDL、CML 和 Realm 接口定义修改如下:

FIDL

// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library examples.keyvaluestore.supporttrees;

/// An item in the store. The key must match the regex `^[A-z][A-z0-9_\.\/]{2,62}[A-z0-9]$`. That
/// is, it must start with a letter, end with a letter or number, contain only letters, numbers,
/// periods, and slashes, and be between 4 and 64 characters long.
type Item = struct {
    key string:128;
    value strict union {
        // Keep the original `bytes` as one of the options in the new union. All leaf nodes in the
        // tree must be `bytes`, or absent unions (representing empty). Empty byte arrays are
        // disallowed.
        1: bytes vector<byte>:64000;

        // Allows a store within a store, thereby turning our flat key-value store into a tree
        // thereof. Note the use of `@generated_name` to prevent a type-name collision with the
        // `Store` protocol below, and the use of `box<T>` to ensure that there is a break in the
        // chain of recursion, thereby allowing `Item` to include itself in its own definition.
        //
        // This is a table so that added fields, like for example a `hash`, can be easily added in
        // the future.
        2: store @generated_name("nested_store") table {
            1: items vector<box<Item>>;
        };
    }:optional;
};

/// An enumeration of things that may go wrong when trying to write a value to our store.
type WriteError = flexible enum {
    UNKNOWN = 0;
    INVALID_KEY = 1;
    INVALID_VALUE = 2;
    ALREADY_EXISTS = 3;
};

/// A very basic key-value store.
@discoverable
open protocol Store {
    /// Writes an item to the store.
    flexible WriteItem(struct {
        attempt Item;
    }) -> () error WriteError;
};

CML

客户端

// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
{
    include: [ "syslog/client.shard.cml" ],
    program: {
        runner: "elf",
        binary: "bin/client_bin",
    },
    use: [
        { protocol: "examples.keyvaluestore.supporttrees.Store" },
    ],
    config: {
        write_items: {
            type: "vector",
            max_count: 16,