From a1789bf4abc29ff0cfeb670d35879adfa938e6f5 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 10 Dec 2018 17:04:06 +0100 Subject: [PATCH 1/2] Change rules for when a set-or-map-literal is a set literal. The existing rule had some issue. My immediate fix would have different issues. The `FutureOr` case is particularly annoying because `FutureOr>` as a context type should create a `Set`, and `FutureOr` is a super-type of `V` and we don't want to get into zig-zag problems (`Iterable` is incomarable to `List`, and `Iterable` is incomparable to `FutureOr>`). This change requires answering a negative universal property, but I believe the types in question must be available in the context type, so it should be simple (get the `T` type as the type parameter of `Iterable` if the context type implements iterable, get the `K` and `V` as the type parmeters of `Map` if the context type implements `Map`, and you only need to check those). --- .../set-literals/feature-specification.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/accepted/future-releases/set-literals/feature-specification.md b/accepted/future-releases/set-literals/feature-specification.md index b9b24bca1e..0395f080e0 100644 --- a/accepted/future-releases/set-literals/feature-specification.md +++ b/accepted/future-releases/set-literals/feature-specification.md @@ -1,5 +1,6 @@ # Set Literals Design Document Author: lrn@google.com +Version: 1.1 Solution for [Set Literals Problem](http://github.com/dart-lang/language/issues/36). Based on feature proposal [Issue 37](http://github.com/dart-lang/language/issues/37) @@ -84,10 +85,11 @@ if *s* has a `typeArguments` with two type arguments, *s* is a *map literal*. (*Three or more type arguments is a compile time error, so the remaining possible case is having no type arguments*). If *s* is an `emptySetOrMapLiteral` with no `typeArguments` and static context type *C*, then -if `Set` is assignable to *C* and `Map` is not assignable to *C*, then *s* is a *set literal*, +if there exists a type `T` such that `LinkedHashSet` is assignable to *C* and there are no types `K` and `V` such that +`LinkedHashMap` is assignable to *C*, then *s* is a *set literal*, otherwise *s* is a *map literal*. -(*So if *C* is, for example, `Iterable` or `Set` or `FutureOr>` or a type variable with any of +(*So if *C* is, for example, `Iterable`, `Set`, `LinkedHashSet` or `FutureOr>` or a type variable with any of those as bound, then *s* is a set literal. If *C* is `Object` or `dynamic` or `Null` or `String`, then *s* is a map literal, *and* potentially a compile-time error due to static typing*). @@ -357,3 +359,7 @@ var s6 = {...{1: 1}, ...?d}; // Map // var s7 = {...?d}; // Compile-time error, ambiguous // var s8 = {...{1}, ...{1: 1}}; // Compile-time error, incompatible ``` + +##Revisions +1.0: Initial version plus type fixes. +1.1: Changed type rules for selecting set literals over map literals. From 01ec8eeb7762ba62361e238bc51f6e2c669ba75f Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 11 Dec 2018 12:44:49 +0100 Subject: [PATCH 2/2] Simplify. Do not attempt to match type variables because they won't work. --- .../set-literals/feature-specification.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/accepted/future-releases/set-literals/feature-specification.md b/accepted/future-releases/set-literals/feature-specification.md index 0395f080e0..e8162061a1 100644 --- a/accepted/future-releases/set-literals/feature-specification.md +++ b/accepted/future-releases/set-literals/feature-specification.md @@ -85,13 +85,14 @@ if *s* has a `typeArguments` with two type arguments, *s* is a *map literal*. (*Three or more type arguments is a compile time error, so the remaining possible case is having no type arguments*). If *s* is an `emptySetOrMapLiteral` with no `typeArguments` and static context type *C*, then -if there exists a type `T` such that `LinkedHashSet` is assignable to *C* and there are no types `K` and `V` such that -`LinkedHashMap` is assignable to *C*, then *s* is a *set literal*, -otherwise *s* is a *map literal*. - -(*So if *C* is, for example, `Iterable`, `Set`, `LinkedHashSet` or `FutureOr>` or a type variable with any of -those as bound, then *s* is a set literal. If *C* is `Object` or `dynamic` or `Null` or `String`, then *s* is a map literal, -*and* potentially a compile-time error due to static typing*). +if `LinkedHashSet` is assignable to *C* and `LinkedHashMap` is not assignable to *C*, +then *s* is a *set literal*, otherwise *s* is a *map literal*. + +(*So if *C* is, for example, `Iterable`, `Set`, `LinkedHashSet` or `FutureOr>`, +then *s* is a set literal. If *C* is `Object` or `dynamic` or `Null` or `String`, then *s* is a map literal, +*and* potentially a compile-time error due to static typing*. If *C* is some subclass of `Set` other than `LinkedHashSet`, then the literal is a map literal, but it is also a guaranteed type error even if the literal +is a set. If *C* is a subtype of `LinkedHashSet` *and* a subtype of `LinkedHashMap`, then *s* is again +a map literal, and a guaranteed run-time type error). ### Map literals