Move void to top of type hierarchy

Fixes #33341

Change-Id: Ib2b7b5542b702a04b38dee5261fc80664a7fcc18
Reviewed-on: https://dart-review.googlesource.com/59822
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44b7ed0..3b7a74a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,22 @@
 
 ### Language
 
+Inference chooses `void` when combining `Object` or `dynamic` and `void` ([issue
+3341]).  When combining with other top types, inference now prefers `void`.  So
+for example, given:
+
+```dart
+void foo() {};
+dynamic bar() {};
+var a = [foo(), bar()];
+```
+
+the variable `a` would previously have been inferred as `dynamic`, and will now
+be inferred as `void`.
+
+[issue 3341]: https://github.com/dart-lang/sdk/issues/33341
+
+
 #### Strong Mode
 
 ### Dart VM
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 5656daf..e54318a 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -35,9 +35,9 @@
   assert(_isTop(t), 'only Top types have a topiness');
 
   // Highest top
-  if (t.isDynamic) return 3;
-  if (t.isObject) return 2;
-  if (t.isVoid) return 1;
+  if (t.isVoid) return 3;
+  if (t.isDynamic) return 2;
+  if (t.isObject) return 1;
   if (t.isDartAsyncFutureOr)
     return -3 + _getTopiness((t as InterfaceType).typeArguments[0]);
   // Lowest top
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index a7ec816..f3e44dd 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -637,7 +637,7 @@
 
   void test_dynamic_void() {
     // Note: _checkLeastUpperBound tests `LUB(x, y)` as well as `LUB(y, x)`
-    _checkLeastUpperBound(dynamicType, voidType, dynamicType);
+    _checkLeastUpperBound(dynamicType, voidType, voidType);
   }
 
   void test_functionsDifferentRequiredArity() {
@@ -1553,15 +1553,15 @@
 
     final orderedTops = [
       // Lower index, so lower Top
+      voidType,
       dynamicType,
       objectType,
-      voidType,
+      futureOrVoidType,
       futureOrDynamicType,
       futureOrObjectType,
-      futureOrVoidType,
+      futureOrFutureOrVoidType,
       futureOrFutureOrDynamicType,
       futureOrFutureOrObjectType,
-      futureOrFutureOrVoidType,
       // Higher index, higher Top
     ];
 
@@ -1593,7 +1593,7 @@
     // Sanity check specific cases of top for GLB/LUB.
     _checkLeastUpperBound(objectType, dynamicType, dynamicType);
     _checkGreatestLowerBound(objectType, dynamicType, objectType);
-    _checkLeastUpperBound(objectType, voidType, objectType);
+    _checkLeastUpperBound(objectType, voidType, voidType);
     _checkLeastUpperBound(futureOrDynamicType, dynamicType, dynamicType);
     _checkGreatestLowerBound(
         futureOrDynamicType, objectType, futureOrDynamicType);
@@ -1644,7 +1644,7 @@
 
   void test_dynamic_void() {
     // Note: _checkGreatestLowerBound tests `GLB(x, y)` as well as `GLB(y, x)`
-    _checkGreatestLowerBound(dynamicType, voidType, voidType);
+    _checkGreatestLowerBound(dynamicType, voidType, dynamicType);
   }
 
   void test_functionsDifferentNamedTakeUnion() {