Skip to content

Redirecting factory constructors don't propagate generic type arguments #30855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
leafpetersen opened this issue Sep 21, 2017 · 8 comments
Closed
Assignees

Comments

@leafpetersen
Copy link
Member

This code:

class B<T> {
  B(a) : this.named(a);
  B.named(a) {}
  factory B.redirect(a) = B;
}

produces this error in current strong mode analyzer:

  error • The return type 'B<dynamic>' of the redirected constructor isn't assignable to 'B<T>' at /Users/leafp/tmp/test.dart:5:27 • redirect_to_invalid_return_type

I believe that redirecting factory constructors should propagate their type arguments unchanged.

cc @bkonyi @jmesserly @lrhn @eernstg @floitschG @munificent @stereotype441

@lrhn
Copy link
Member

lrhn commented Sep 22, 2017

The current specification requires (and allows!) you to write the type parameter of the target class.
It's needed in some cases, e.g., where the other class doesn't have the same number of type parameters.

class C<T> {
   C(T x) = GenericClass<T, Null>;
}
class GenericClass<T, S> implements C<T>, D<S> { ... }

So, no automatic propagation, and the current behavior is Dart 1-correct, but you might want to infer the type parameter for the target class. That sounds reasonable (the target constructor must create a B<T> so inferring the <T> should be easy). It's still inference, not propagation, for the pedantically inclined :)

@leafpetersen
Copy link
Member Author

Sounds right to me.

@leafpetersen
Copy link
Member Author

New front end does the right thing, so analyzer is more restrictive which makes this less of a priority.

@scheglov
Copy link
Contributor

@leafpetersen When you say "propagate unchanged", do you mean only the case of redirecting to a constructor of the same class?

class A<T, U> {
  A();
  factory A.redirected() = A;
}

So, as I understand, all we need to do here is to replace = A with = A<T, U>.

Is there anything that can be (or should be) done for redirecting from an interface to the implementation? So, is there a way to know that = B should be treated as = B<T1, U1>?

class B<T, U> implements C<T, U> {}

class C<T1, U1> {
  factory C() = B;
}

@lrhn
Copy link
Member

lrhn commented Mar 13, 2018

This shouldn't be special - effectively the redirecting factory constructor:

class A<T1, T2> {
  factory A.foo(parameters) = B;
}

is equivalent to:

class A<T1, T2> {
  factory A.foo(parameters) => new B(parameters);
}

If B is a raw version of a generic type, then we need to infer the type parameters the same way in both cases - the expression new B(parameters) is type-inferred in the context with expected type A<T1, T2> to provide whatever type arguments are needed on B.

@scheglov
Copy link
Contributor

OK, thanks.

What happens when there are no parameters?
Instantiate to bounds?

So, in this example we still get a warning, because = A is actually = A<dynamic, dynamic>?

class A<T, U> {
  A();
  factory A.redirected() = A;
}

@lrhn
Copy link
Member

lrhn commented Mar 13, 2018

The parameters shouldn't actually make much difference, I just had them there for completeness.

I would expect that to infer:

factory A.redirected() = A<T, U>;

since the constructor needs to create an A<T, U>, just as if it had been written:

factory A.redirected() => new A();  // inferred: new A<T, U>();

@scheglov scheglov self-assigned this Mar 15, 2018
@scheglov
Copy link
Contributor

dart-bot pushed a commit that referenced this issue Mar 15, 2018
[email protected]

Bug: #30855
Change-Id: I05e9102fe7b7a304be6ac6dd4d59e11bdafee59c
Reviewed-on: https://dart-review.googlesource.com/46575
Reviewed-by: Brian Wilkerson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants