Skip to content

Promoting type variables #3837

@FMorschel

Description

@FMorschel

Context

As I've commented on dart-lang/sdk#56028.

Consider:

mixin M {
  void m();
}

class M1 with M {
  const M1();
  @override
  void m() {}
}

class A<T> {
  const A(this.o);
  final T o;
}

class B<T extends M> extends A<T> with M {
  const B(super.o);
  @override
  void m() => o.m();
}

void foo<T>(T o) {
  late A<T> a;
  if (o is M) {
    a = B<T>(o); // 'T' doesn't conform to the bound 'M' of the type parameter 'T'. Try using a type that is or is a subclass of 'M'.
  } else {
    a = A<T>(o);
  }
}

Today this code has only "bad" solutions (the basic ways I could think of were not able to solve this and I could not think of another solution than the following), one which was proposed later on that same issue involves calling a helper function with (fn as Function)<T>(...). This is doable by the programmer but it's easier to get it wrong.

From @eernstg in dart-lang/sdk#56028:

void foo<T>(T o) {
  B<S> fooHelper<S extends M>(S o) {
    // In this body the type system knows that `S extends M`,
    // so we can create a `B<S>`.
    return B<S>(o);
  }
  
  late A<T> a;
  if (o is M && <T>[] is List<M>) {
    // At this time we know that `T extends M`. The type system
    // won't recognize that, but we can force it using a dynamic
    // invocation of a generic function.
    a = (fooHelper as Function)<T>(o);
  } else {
    a = A<T>(o);
  }
}

Request

I'd like to request/propose that type arguments could be tested for specific bounds.

That would not only return a true or false for the test expression, but it would also consider that in the inner context.

That would make it so that in this context:

void foo<T>(T o) {
  late A<T> a;
  if (T <: M) { // Trying to imitate your writings from previous issues but if I got it the wrong way around please disconsider
    a = B<T>(o); // Here `T` would then be considered as a subtype of `M` and could be used as the type parameter on `B`
  } else {
    a = A<T>(o);
  }
}

This would be more of a "help" for the language to type-solve harder contexts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureProposed language feature that solves one or more problemsflow-analysisDiscussions about possible future improvements to flow analysis

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions