{"action":"created","issue":{"url":"https://api.github.com/repos/dart-lang/sdk/issues/33806","repository_url":"https://api.github.com/repos/dart-lang/sdk","labels_url":"https://api.github.com/repos/dart-lang/sdk/issues/33806/labels{/name}","comments_url":"https://api.github.com/repos/dart-lang/sdk/issues/33806/comments","events_url":"https://api.github.com/repos/dart-lang/sdk/issues/33806/events","html_url":"https://github.com/dart-lang/sdk/issues/33806","id":339908903,"node_id":"MDU6SXNzdWUzMzk5MDg5MDM=","number":33806,"title":"Propagation of inner type with Future with Dart 2","user":{"login":"sestegra","id":109060,"node_id":"MDQ6VXNlcjEwOTA2MA==","avatar_url":"https://avatars3.githubusercontent.com/u/109060?v=4","gravatar_id":"","url":"https://api.github.com/users/sestegra","html_url":"https://github.com/sestegra","followers_url":"https://api.github.com/users/sestegra/followers","following_url":"https://api.github.com/users/sestegra/following{/other_user}","gists_url":"https://api.github.com/users/sestegra/gists{/gist_id}","starred_url":"https://api.github.com/users/sestegra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sestegra/subscriptions","organizations_url":"https://api.github.com/users/sestegra/orgs","repos_url":"https://api.github.com/users/sestegra/repos","events_url":"https://api.github.com/users/sestegra/events{/privacy}","received_events_url":"https://api.github.com/users/sestegra/received_events","type":"User","site_admin":false},"labels":[{"id":219928175,"node_id":"MDU6TGFiZWwyMTk5MjgxNzU=","url":"https://api.github.com/repos/dart-lang/sdk/labels/area-language","name":"area-language","color":"c7def8","default":false}],"state":"closed","locked":false,"assignee":{"login":"leafpetersen","id":8484504,"node_id":"MDQ6VXNlcjg0ODQ1MDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/8484504?v=4","gravatar_id":"","url":"https://api.github.com/users/leafpetersen","html_url":"https://github.com/leafpetersen","followers_url":"https://api.github.com/users/leafpetersen/followers","following_url":"https://api.github.com/users/leafpetersen/following{/other_user}","gists_url":"https://api.github.com/users/leafpetersen/gists{/gist_id}","starred_url":"https://api.github.com/users/leafpetersen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leafpetersen/subscriptions","organizations_url":"https://api.github.com/users/leafpetersen/orgs","repos_url":"https://api.github.com/users/leafpetersen/repos","events_url":"https://api.github.com/users/leafpetersen/events{/privacy}","received_events_url":"https://api.github.com/users/leafpetersen/received_events","type":"User","site_admin":false},"assignees":[{"login":"leafpetersen","id":8484504,"node_id":"MDQ6VXNlcjg0ODQ1MDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/8484504?v=4","gravatar_id":"","url":"https://api.github.com/users/leafpetersen","html_url":"https://github.com/leafpetersen","followers_url":"https://api.github.com/users/leafpetersen/followers","following_url":"https://api.github.com/users/leafpetersen/following{/other_user}","gists_url":"https://api.github.com/users/leafpetersen/gists{/gist_id}","starred_url":"https://api.github.com/users/leafpetersen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leafpetersen/subscriptions","organizations_url":"https://api.github.com/users/leafpetersen/orgs","repos_url":"https://api.github.com/users/leafpetersen/repos","events_url":"https://api.github.com/users/leafpetersen/events{/privacy}","received_events_url":"https://api.github.com/users/leafpetersen/received_events","type":"User","site_admin":false}],"milestone":null,"comments":5,"created_at":"2018-07-10T16:03:57Z","updated_at":"2018-07-10T21:06:01Z","closed_at":"2018-07-10T21:06:01Z","author_association":"NONE","body":"Dart VM version: 2.0.0-dev.67.0 (Tue Jul 3 18:17:07 2018 +0200) on \"macos_x64\"\r\n\r\nLet's assume following code.\r\n\r\n``` dart\r\nimport 'dart:async';\r\n\r\nclass Zoo {\r\n  Map<String, Animal> animals = <String, Animal>{};\r\n\r\n  void add(Animal animal) => animals[animal.name] = animal;\r\n\r\n  Animal get(String name) => animals[name];\r\n  Cat getCat(String name) => get(name);\r\n  Dog getDog(String name) => get(name);\r\n\r\n  Future<Animal> asyncGet(String name) async => await new Future<Animal>.value(animals[name]);\r\n  Future<Cat> asyncGetCat(String name) async => await asyncGet(name);\r\n  Future<Dog> asyncGetDog(String name) async => await asyncGet(name);\r\n\r\n  Future<Cat> badAsyncGetCat(String name) => asyncGet(name);\r\n  Future<Dog> badAsyncGetDog(String name) => asyncGet(name);\r\n\r\n  String toString() => \"Zoo: $animals\";\r\n}\r\n\r\nclass Animal {\r\n  String name;\r\n  String toString() => \"$runtimeType: $name\";\r\n}\r\n\r\nclass Cat extends Animal {\r\n  void meow() => print(\"$name: Meow !\");\r\n}\r\n\r\nclass Dog extends Animal {\r\n  void waouf() => print(\"$name: Waouf !\");\r\n}\r\n\r\nFuture<Null> main() async {\r\n  var zoo = new Zoo()..add(new Animal()..name = 'Foo')..add(new Cat()..name = 'Felix')..add(new Dog()..name = 'Brutus');\r\n  print(zoo);\r\n\r\n  // Sync zoo\r\n  {\r\n    var animal = zoo.get('Felix');\r\n    print(animal.runtimeType);\r\n\r\n    var cat = zoo.getCat('Felix');\r\n    print(cat.runtimeType);\r\n\r\n    var dog = zoo.getDog('Brutus');\r\n    print(dog.runtimeType);\r\n\r\n    var nobody = zoo.getCat('Nobody');\r\n    print(nobody.runtimeType);\r\n  }\r\n\r\n  // Async zoo\r\n  {\r\n    var animal = await zoo.asyncGet('Felix');\r\n    print(animal.runtimeType);\r\n\r\n    var cat = await zoo.asyncGetCat('Felix');\r\n    print(cat.runtimeType);\r\n\r\n    var dog = await zoo.asyncGetDog('Brutus');\r\n    print(dog.runtimeType);\r\n\r\n    var nobody = await zoo.asyncGetCat('Nobody');\r\n    print(nobody.runtimeType);\r\n  }\r\n\r\n  // Bad async zoo\r\n  {\r\n    var cat = await zoo.badAsyncGetCat('Felix');\r\n    print(cat.runtimeType);\r\n\r\n    var dog = await zoo.badAsyncGetDog('Brutus');\r\n    print(dog.runtimeType);\r\n\r\n    var nobody = await zoo.badAsyncGetCat('Nobody');\r\n    print(nobody.runtimeType);\r\n  }\r\n}\r\n```\r\n\r\nThe output result is following.\r\n```\r\n$ dart animal.dart\r\nZoo: {Foo: Animal: Foo, Felix: Cat: Felix, Brutus: Dog: Brutus}\r\nCat\r\nCat\r\nDog\r\nNull\r\nCat\r\nCat\r\nDog\r\nNull\r\nCat\r\nUnhandled exception:\r\ntype 'Future<Animal>' is not a subtype of type 'Future<Cat>'\r\n#0      Zoo.badAsyncGetCat (async.dart:17:46)\r\n#1      main (file:///async.dart:75:25)\r\n#2      _RootZone.runUnary (dart:async/zone.dart:1381:54)\r\n#3      _FutureListener.handleValue (dart:async/future_impl.dart:129:18)\r\n#4      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:638:45)\r\n#5      Future._propagateToListeners (dart:async/future_impl.dart:667:32)\r\n#6      Future._completeWithValue (dart:async/future_impl.dart:482:5)\r\n#7      Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:512:7)\r\n#8      _microtaskLoop (dart:async/schedule_microtask.dart:41:21)\r\n#9      _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)\r\n#10     _runPendingImmediateCallback (dart:isolate/runtime/libisolate_patch.dart:113:13)\r\n#11     _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:166:5)\r\n```\r\n\r\nI understand well the thrown exception.\r\n\r\nI would like to raise the point, because I found the \"workaround\" with async/await that sounds weird.\r\n\r\nSo, as Future is a kind of special type, I suggest that the inner type propagation should be allowed for Future.\r\n\r\nWhat do you think about it ?\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/dart-lang/sdk/issues/comments/403965771","html_url":"https://github.com/dart-lang/sdk/issues/33806#issuecomment-403965771","issue_url":"https://api.github.com/repos/dart-lang/sdk/issues/33806","id":403965771,"node_id":"MDEyOklzc3VlQ29tbWVudDQwMzk2NTc3MQ==","user":{"login":"leafpetersen","id":8484504,"node_id":"MDQ6VXNlcjg0ODQ1MDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/8484504?v=4","gravatar_id":"","url":"https://api.github.com/users/leafpetersen","html_url":"https://github.com/leafpetersen","followers_url":"https://api.github.com/users/leafpetersen/followers","following_url":"https://api.github.com/users/leafpetersen/following{/other_user}","gists_url":"https://api.github.com/users/leafpetersen/gists{/gist_id}","starred_url":"https://api.github.com/users/leafpetersen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leafpetersen/subscriptions","organizations_url":"https://api.github.com/users/leafpetersen/orgs","repos_url":"https://api.github.com/users/leafpetersen/repos","events_url":"https://api.github.com/users/leafpetersen/events{/privacy}","received_events_url":"https://api.github.com/users/leafpetersen/received_events","type":"User","site_admin":false},"created_at":"2018-07-10T21:06:01Z","updated_at":"2018-07-10T21:06:01Z","author_association":"MEMBER","body":"@lrhn Right you are, I missed that those were non-async.\r\n\r\n\r\n\r\n> Changing => to async => await fixes the type issue, and so would just chaning it to async =>.\r\n\r\nThe latter part isn't really true though, unfortunately, since we cast to `FutureOr<Animal>` which fails.  We might want to fix that later - it should be non-breaking to relax this."}}
{"actor":{"display_login":"leafpetersen"}}