go cmd/vet: check for failure to use result of a 'yield' call

zzlelutf  于 5个月前  发布在  Go
关注(0)|答案(5)|浏览(106)

Go 1.23引入了"push"迭代器,也称为"range over func",在这种情况下,编译器将循环体(消费者)转换为无栈协程yield func(T) bool,然后将其传递给push迭代器(生产者)。生产者对每个元素调用yield,如果任何调用yield返回false,表示循环体的期望延续不是continue(例如break、外部continue、return、panic、goto),则必须停止。
未能尊重任何调用yield的结果是程序员的错误。在这种情况下,运行时reports a dynamic error会处理,但最好能早一点用静态检查捕获它。
我们应该添加一个新的分析器(或者可能增强现有的unusedresult分析器),以报告当动态调用名为yield(对于某些T类型为func(T) bool)的函数的结果被忽略时的情况。

tp5buhyn

tp5buhyn1#

There are three conditions for vet checks, as listed in its README. We don't know yet whether this is a large enough problem in the wild to satisfy the frequency criterion.

mbzjlibv

mbzjlibv2#

在README中列出了三个进行兽医检查的条件。我们还不知道这是否是一个足够大的问题,以满足频率标准。

显然,这不是一个在野外的大问题,因为还没有人将代码与推送迭代器合并... ...但是,我在我的实验中已经犯过这个错误好几次了。不过,你的观点是正确的。

ie3xauqp

ie3xauqp3#

我们应该添加一个新的分析器(或者说增强现有的未使用结果分析器),以便在动态调用名为yield(类型为func(T) bool,其中T为某种类型)的函数时忽略其结果时进行报告。我不确定这是否足够精确。对于GoVersion<=1.21的情况,人们可能已经编写了这样的函数并忽略了名为'yield'的函数的返回值。这种情况永远不会出现在"遍历func"语句中,而且是可以接受的。

我认为我们可以通过将此更改为查看for range f示例来获得足够好的精度,其中f是函数类型,f(yield)是静态调用,而f忽略了对其yield函数的调用。然而,这种方法的一个主要缺点在于在哪里报告诊断信息。在f的主体中更有操作性,但如果我们正在查看包含for range f语句的包,这并不总是可行的。

mrzz3bfm

mrzz3bfm4#

我不确定这是否足够精确。对于GoVersion<=1.21,人们可能已经编写了这样一个函数,并忽略了名为'yield'的函数的返回值。这在"range over func"语句中永远不会被使用,而且没问题。
你完全正确,这可能是巧合,但我怀疑调用一个操作数为本地变量名为'yield'的函数,以及适当的类型组合,在今天是非常罕见的,我们可以(通过新约定)实际上将这个名字作为新的循环语义的非正式保留字。

oug3syen

oug3syen5#

我怀疑将一个操作数命名为'yield'的局部变量与适当的类型结合在一起,在今天是非常罕见的。
当然可以。
我们可以通过一种新的约定来实际地将这个名字作为新循环语义的非正式保留字。
只检查当这个被调用为'yield'时让我有点紧张。这是新的,而且约定有些薄弱。'yield'有什么特别之处?为什么不是'y'或'f'?如果有多个怎么办?我个人很容易拼错'yield'。
如果我有一个备用方案来警告其他情况,那么我对特殊对待'yield'会更舒服一些。这属于“错过太多它正在寻找的情况将给人一种虚假的安全感”的观点。也许在错过的检查中报告'yield'示例,无论是否被调用,报告在错过的检查中的包内调用,并在调用站点报告包间示例(#65795(评论))。这有点复杂,但仍然是可行的。

相关问题