Skip to content

CFE fails to notice record field name differences when performing subtype matches #55802

@stereotype441

Description

@stereotype441

The following code is accepted by the CFE but rejected by the analyzer:

({T foo}) f<T>(T x) => (foo: x);

g(Object y) {
  if (y is ({double bar})) {
    y = f(1..h()); // (1)
    print(y);
  }
}

extension on double {
  void h() {
    print('$this.h() called');
  }
}

main() {
  g((bar: 0.5));
}

The analyzer's error message (at the line marked (1)) is:

The method 'h' isn't defined for the type 'int'. Try correcting the name to the name of an existing method, or defining a method named 'h'.

The analyzer is correct to reject the code.

What's going wrong on the CFE side is that when performing type inference on the call f(1..h()), the context is ({double bar}), and the CFE is called upon to try to match that to the return type of f, which is ({T foo}). Due to a bug in TypeConstraintGatherer._isNullabilityAwareSubtypeMatch, the CFE fails to notice that the names foo and bar disagree, so it infers a type of double for T. As a result, the argument of f (1..h()) gets type inferred with a context of double, so 1 gets interpreted as 1.0, and so the CFE thinks the extension method h is available.

I'll send out a fix for review shortly.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions