Skip to content

Implement a set of "strict" static analysis rules #33749

@srawlins

Description

@srawlins

The new Dart 2 runtime semantics added several changes that have really surprised users. As a prime example, this code:

List<String> list = ['hello'];
List<String> foos = list.where(condition);

will fail at runtime, because List<String>.where returns an Iterable<String>. The frustration is that this really looks like it should be caught at compile-time, or with static analysis.

To help users to detect errors like this early on (instead of relying on really good test coverage), we're proposing a set of "strict" errors that can be enforced in static analysis. We propose that the analyzer supports a --strict- flag for each error.

Todo

  • --strict-inference
    • Specify the rule
    • Implement the rules, and support the flag, in the analyzer
  • --strict-raw-types
    • Specify the rule
    • Implement the rules and flag in the analyzer
  • --strict-casts
    • Specify the rule
    • Implement the rules and flag in the analyzer

The rules

The first rule we intend to implement is --strict-raw-types, more or less addressing #33119.

Off-hand, @leafpetersen mentioned a few other possible rules might include:

  • --strict-inference - don't allow inference to produce top types unless top was an input,
  • --strict-casts - don't allow implicit casts at all,
  • --strict-raw-types - don't allow "raw" types, missing type arguments, on declarations,
  • --strict - some default subset of the above that we recommend as a best practice setting.

implicit-casts and implicit-dynamic

In many cases, these are teasing out individual error codes from the --no-implicit-casts and --no-implicit-dynamic flags. These have been declared more or less "an experiment" (unofficial) as they are today. Additionally, they don't provide good ergonomics; in order to "upgrade" a codebase to be free of "implicit dynamic" code, one needs to update their analysis_options.yaml to look like:

analyzer:
  strong-mode:
    implicit-dynamic: false
  errors:
    strong_mode_implicit_dynamic_list_literal: ignore
    strong_mode_implicit_dynamic_map_literal: ignore
    strong_mode_implicit_dynamic_parameter: ignore
    strong_mode_implicit_dynamic_variable: ignore
    ...

And then work their way through individual codes. In the end, the analysis_options.yaml file is still not expressive. It reads something like "Enforce 'no-implicit-casts' and 'no-implicit-dynamic', except don't enforce 6 of the 8 'implicit-dynamic' codes."

I can see the individual --strict- flags/rules replacing the implicit-casts and implicit-dynamic flags, but that isn't a primary goal of this work.

Metadata

Metadata

Labels

area-metaCross-cutting, high-level issues (for tracking many other implementation issues, ...).type-enhancementA request for a change that isn't a bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions