Skip to content

strong mode: future flattening diverges #25611

@jmesserly

Description

@jmesserly

Given:

import 'dart:async';

class Divergent<T> implements Future<Divergent<Divergent<T>>> {
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

test() async {
  // flatten(Divergent<int>) = Divergent<Divergent<int>>
  Divergent<Divergent<int>> x = await new Divergent<int>(); /// 09: runtime error
  Future<Divergent<Divergent<int>>> f() async => new Divergent<int>(); /// 10: ok
  Future<Divergent<Divergent<int>>> f() async { return new Divergent<int>(); } /// 11: ok
  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())(); /// 12: runtime error
}

When we flatten this, we sometimes run into problems. Note that this is hard to reproduce, it seems to happen when dev_compiler tries to compile this example, but a straightforward test in Analyzer works correctly. We seem to get confused sometimes whether we're in strong mode or not when we recurse into Future, letting us short circuit the problem (not for the right reason).

I did some investigation and I think there's a problem in how the code is structured:

flattenFutures calls _searchTypeHierarchyForFutureTypeParameters.
That uses "type.superclass" and "type.interfaces"

BTW: mixins aren't looked at. This could be another, unrelated bug in normal mode, that existed before the Future< flatten(T) > change. Need to investigate.

type.superclass performs substitutions. That's good too, if you've got class Foo<T> implements Map<int, List<T>> ... you want to Map<int, List<T>>, not Map<K, V>

But then in substitute, we try to flatten again. BAD. We're already flattening! Flatten is not supposed to recurse. It's specifically defined so recursion doesn't happen.

Easy to fix. The question is, what is the cleanest way to make "we're already flattening" known at that point in the code where we choose to flatten.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2A bug or feature request we're likely to work onlegacy-area-analyzerUse area-devexp instead.type-bugIncorrect behavior (everything from a crash to more subtle misbehavior)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions