切换到健全的空安全后,简单赋值中的空性不匹配



我切换到声音零安全,并开始在一个简单的赋值中获得运行时错误,这在声音零安全中是不应该发生的:

final widgetOnPressed = widget.onPressed;

错误:

type '(LogData) => void' is not a subtype of type '((LogData?) => void)?'

我可以为Flutter版本2.12.0-4.1.pre2.13.0-0.0.pre.505重新编程。

公关:https://github.com/flutter/devtools/pull/3971

故障线路:https://github.com/flutter/devtools/blob/9fc560ff2e6749459e2ca6a1dc00bf6fb16ed93b/packages/devtools_app/lib/src/shared/table.dart#L1184

要重新编程,请在此PR启动适用于macos的DevTools,连接到应用程序并单击选项卡"日志记录"。DevTools将在控制台中显示红色屏幕和错误。

是飞镖错误还是应用程序错误?如果是应用程序错误,我该如何调试它?

这是代码中的一个错误。

您没有说明发生了哪种错误——编译时错误还是运行时错误。我猜是运行时错误。(好吧,你确实说过要在调试器中启动它,所以这也是一个很好的提示。(

线路final widgetOnPressed = widget.onPressed;看起来不可能发生故障。毕竟,局部变量的类型是从分配给它的表达式中推断出来的,并且该表达式的运行时值肯定是静态类型的子类型,因为类型系统是健全的!不是吗?不是吗?

不是,对不起。Dart 2的类型系统是大多数的声音,在零安全的情况下更是如此,但类泛型是协变的,这仍然是不健全的。很难找到其中一种情况,即这种不确定性显示出其丑陋的头部,但返回函数,其中参数类型是类的类型变量。

您的state类扩展了State<TableRow<T?>>,因此widgetgetter返回一个TableRow<T?>。该类型的onPressed具有类型ItemCallback<T?>?,也就是void Function(T?)?

您创建了一个_TableRowState<LogData>,其widget具有静态类型TableRow<LogData?>,但您不知何故设法将TableRow<LogData>传递给它。没关系。类泛型是协变的,所以在编译时一切都很好。

然后你做final widgetOnPressed = widget.onPressed;。此处widgetOnPressed的静态类型为void Function(LogData?)onPressed实际运行时类型void Function(LogData),因为它来自TableRow<LogData>

void Function(LogData)不是void Function(LogData?),因为前者不能在后者可以使用的所有地方使用(特别是,它不能在用null调用的地方使用(。

这种转让可能是不合理的,在这种情况下实际上也是不合理的。编译器知道这一点,并插入一个额外的检查,以确保您不会为实际无效的变量赋值。该检查触发并抛出您看到的错误。

你如何避免这种情况?

不要在需要TableRow<LogData?>的地方创建TableRow<LogData>

或者将变量键入为:

final ItemCallback<T>? widgetOnPressed = widget.onPressed;

(T上没有?(。

或者重写所有内容,以避免返回带有协变类型参数(来自类(的函数(作为参数类型(。

哪种解决方案适合你取决于你想做什么。

最新更新