Skip to content
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

Inference failure around nested generic bounds #25740

Closed
munificent opened this issue Feb 9, 2016 · 8 comments
Closed

Inference failure around nested generic bounds #25740

munificent opened this issue Feb 9, 2016 · 8 comments
Assignees
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@munificent
Copy link
Member

Given this:

class Foo<T extends Pattern> {
  void method/*<U extends T>*/(dynamic/*=U*/ u) {}
}

I can analyze these without error in strong mode:

new Foo().method/*<String>*/("str");
new Foo();

But not these:

new Foo<String>().method("str");
new Foo().method("str");

The latter two yield:

[error] Type check failed: "str" (String) is not of type T (/Users/rnystrom/temp/temp.dart, line 11, col 28)
[error] Type check failed: "str" (String) is not of type T (/Users/rnystrom/temp/temp.dart, line 12, col 20)
[warning] The argument type 'String' cannot be assigned to the parameter type 'T' (/Users/rnystrom/temp/temp.dart, line 11, col 28)
[warning] The argument type 'String' cannot be assigned to the parameter type 'T' (/Users/rnystrom/temp/temp.dart, line 12, col 20)

cc @leafpetersen

@munificent munificent added area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. analyzer-strong-mode labels Feb 9, 2016
@jmesserly
Copy link

@munificent were you looking at this one? If not I'll take a look.

@jmesserly
Copy link

Psychic debugging :)

What we should have in inference is a type like {String/T}<U>(U) -> void We will infer U == String. What is probably going wrong is, when we lookup the bound of U in FunctionTypeImpl, we get back T. What should have happened is we take into account {String/T} and return the bound as String.

I believe this problem has always existed in usage of type parameter bounds, but it can only manifest when you have nested generic types, which can now happen with function types. (similar problem would show up with inner classes, if those were supported.)

@jmesserly jmesserly self-assigned this Feb 10, 2016
@jmesserly
Copy link

@kevmoo kevmoo added P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) and removed Priority-Medium labels Mar 1, 2016
@jmesserly
Copy link

jmesserly commented Aug 29, 2016

fyi, we might have a bug with this still. When I make inference failures an error, I see some errors in this test case. For this test case:

class Foo<T extends Pattern> {
  void method/*<U extends T>*/(dynamic/*=U*/ u) {}
}
main() {
  new Foo<String>().method("str");
}

we seem to think inference failed. My guess is it only works because we default substitute T and then that is resolved correctly to String.

@jmesserly jmesserly reopened this Aug 29, 2016
@jmesserly
Copy link

I think the existing test is insufficiently powerful to expose the 2nd problem (which was hidden under the 1st problem) ... I'm going to see about improving the test case.

@jmesserly
Copy link

Here's the failing version of the test:

class Foo<T extends Pattern> {
  /*=U*/ method/*<U extends T>*/(/*=U*/ u) => u;
}
main() {
  String s;
  var a = new Foo().method/*<String>*/("str");
  s = a;
  new Foo();

  var b = new Foo<String>().method("str");
  s = b;
  var c = new Foo().method("str");
  s = c;

  new Foo<String>().method(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/42);
}

the s = c assignment fails because it has a DOWN_CAST_IMPLICIT. Even though we've implicitly instantiated Foo<Pattern> that should still have the generic method as U extends Pattern which we can tighten to String

@jmesserly
Copy link

jmesserly commented Aug 30, 2016

yeah, confirmed generic method inference is not getting the substituted bound. "resolveToBound" also doesn't work, it fixes the above test case but not an example like U extends Iterable<T>. I'm going to need to poke at this a bit.

edit: what we probably want is to have gotten the TypeParameterMember from inside inference. I'll need to review the earlier fix and see if that logic applies.

@jmesserly
Copy link

https://codereview.chromium.org/2291103004/ is the second half of this fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

4 participants