kikap
kikap

Reputation: 862

Why dart analyzer fails to recognize a type error?

Here's the code:

static const _defaults = <String, dynamic>{
  'api_key': '4839234792374',
  'enabled': false,
  'concurrency': 4,
};

String getString(String key) {
  return _remoteConfig == null ?
    _defaults.containsKey(key) && _defaults[key] :
    _remoteConfig.getString(key);
}

The bug is obvious (and shame on me, was produced by blind copy-paste from similar getBool(key) function. If the _remoteConfig is null, the execution hits the bool && String path and I get the runtime exception type 'String' is not a subtype of type 'bool'. Totally legit, but why does analyzer not see it? The execution flow is crystal clear, one path returns String another path (theoretically) returns dynamic and the return type is String which means that all paths return String. What I don't understand?

Dart 2.12.0 pedantic 1.11.0

Analyzer options:

include: package:pedantic/analysis_options.yaml

analyzer:
  exclude:
    - lib/generated/*
    - lib/**/*.g.dar

Upvotes: 0

Views: 104

Answers (1)

jamesdlin
jamesdlin

Reputation: 89926

I think you're asking two questions:

  1. Why doesn't the analyzer complain about _defaults.containsKey(key) && _defaults[key]?

  2. Why doesn't the analyzer complain about the ternary expression with different types along its two paths?

For #1: Since _defaults[key] returns type dynamic (which could be a bool at runtime), I wouldn't expect an analysis complaint.

For #2: Since the two paths have different types, the type of the ternary expression is the common base type: Object. If implicit casts are enabled, Object is then automatically cast to the String return type.

The analyzer does catch both errors if you disable implicit casts in your analysis_options.yaml configuration file:

analyzer:
  strong-mode:
    implicit-casts: false

Running the analyzer then prints:

error • The operands of the operator '&&' must be assignable to 'bool' at ... • (non_bool_operand)

error • A value of type 'Object' can't be returned from the function 'getString' because it has a return type of 'String' at ... • (return_of_invalid_type)

(I'm surprised that implicit-casts: false triggers an analysis error for the && expression with a dynamic operand,; maybe my understanding isn't quite accurate, or maybe that's a bug in the analyzer.)

Upvotes: 1

Related Questions