linter
linter copied to clipboard
[prefer_const_constructors] .call related false positive
class Abc {
const Abc();
int call() => 0;
}
class Xyz {
final int Function() fn;
const Xyz(this.fn);
}
void main() {
Xyz(const Abc()); // prefer_const_constructors is wrong here because Xyz is not allowed to be const.
}
@eernstg If we add const before Xyz the analyzer reports:
error: A value of type 'Abc' can't be assigned to a parameter of type 'int Function()' in a const constructor. (const_constructor_param_type_mismatch at [nnbd_test_package] lib/test.dart:12)
Is that intentional?
I would also love @eernstg 's opinion here.
We don't have a rule against performing an implicit call tear-off (aka .call insertion) on a constant expression, and Xyz(const Abc()) is exactly the situation that triggers this mechanism, making it Xyz((const Abc()).call).
But e.call is never a constant expression when call is a method (in particular, it's never a constant expression when it is added by .call insertion). So we can't make it const Xyz(Abc()).
So if the message from prefer_const_constructors is recommending to change Xyz(const Abc()) to const Xyz(const Abc()) or const Xyz(Abc()) then it's a false positive.
However, I think the reported error message from the analyzer should be scrutinized a bit:
error: A value of type 'Abc' can't be assigned to a parameter of type 'int Function()' in a const constructor
This sounds like the analyzer failed to perform the .call insertion even though it encountered an expression of type Abc in a situation where the context type is int Function(). I think it should perform that .call insertion (as it would elsewhere), and then it should detect that the resulting actual argument isn't a constant expression, so const Xyz(Abc()) is an error.
Thanks, @eernstg !
Thanks! ;-)
This appears to have been fixed.