linter icon indicating copy to clipboard operation
linter copied to clipboard

False positive for "avoid_types_on_closure_parameters" when contravariance applies

Open vsevolod19860507 opened this issue 4 years ago • 3 comments

When contravariance applies

class Unused {
  const Unused();
}

const unused = Unused();

@immutable
class User {
  final String name;

  const User({this.name});

  User Function({String name}) get copyWith => ({
        Object name = unused, // False positive
      }) =>
          User(
            name: name == unused ? this.name : name as String,
          );
}

vsevolod19860507 avatar Jun 08 '20 14:06 vsevolod19860507

+1

Along with https://github.com/dart-lang/linter/issues/2131 this would make the lint match omit_local_variable_types, which seems desirable.

davidmorgan avatar Aug 13 '20 15:08 davidmorgan

I find the motivating example to be extremely non-idiomatic. But I don't want to discount the idea.

In the example, we create a copyWith function, which is a User Function({String name}), but secretly under the covers, it is a User Function({Object name}), with a default value for name, which is not a String, but is a sentinel value. It's very clever, but I've never used or seen this design before.

The fix, to account for this example, would be to never complain about a parameter type if it is not exactly equal to the type that would be inferred, were the type omitted. I don't know that we have the tooling to answer hypothetical inference questions like this.

srawlins avatar Nov 14 '22 15:11 srawlins

I encountered this earlier.

The fix, to account for this example, would be to never complain about a parameter type if it is not exactly equal to the type that would be inferred, were the type omitted. I don't know that we have the tooling to answer hypothetical inference questions like this.

An alternative is to silence the lint if it is a downcast and is not required.

So:

Function(int) cb = (num a) {}; // KO

Function({int}) cb = ({int? a}) {}; // OK
Function({int}) cb = ({Object a = _sentinel}) {}; // OK

rrousselGit avatar Dec 31 '23 02:12 rrousselGit