| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | import '../ast.dart'; | 
 | import '../core_types.dart'; | 
 |  | 
 | import 'merge_visitor.dart'; | 
 |  | 
 | /// Returns the NNBD_TOP_MERGE of [a] and [b]. If [a] and [b] have no defined | 
 | /// NNBD_TOP_MERGE `null` is returned. | 
 | Supertype? nnbdTopMergeSupertype( | 
 |     CoreTypes coreTypes, Supertype a, Supertype b) { | 
 |   assert(a.classNode == b.classNode); | 
 |   if (a.typeArguments.isEmpty) { | 
 |     return a; | 
 |   } | 
 |   List<DartType> newTypeArguments = | 
 |       new List<DartType>.filled(a.typeArguments.length, dummyDartType); | 
 |   for (int i = 0; i < a.typeArguments.length; i++) { | 
 |     DartType? newTypeArgument = | 
 |         nnbdTopMerge(coreTypes, a.typeArguments[i], b.typeArguments[i]); | 
 |     if (newTypeArgument == null) return null; | 
 |     newTypeArguments[i] = newTypeArgument; | 
 |   } | 
 |   return new Supertype(a.classNode, newTypeArguments); | 
 | } | 
 |  | 
 | /// Returns the NNBD_TOP_MERGE of [a] and [b]. If [a] and [b] have no defined | 
 | /// NNBD_TOP_MERGE `null` is returned. | 
 | DartType? nnbdTopMerge(CoreTypes coreTypes, DartType a, DartType b) { | 
 |   if (a == b) return a; | 
 |   return a.accept1(new NnbdTopMergeVisitor(coreTypes), b); | 
 | } | 
 |  | 
 | class NnbdTopMergeVisitor extends MergeVisitor { | 
 |   final CoreTypes coreTypes; | 
 |  | 
 |   NnbdTopMergeVisitor(this.coreTypes); | 
 |  | 
 |   @override | 
 |   Nullability? mergeNullability(Nullability a, Nullability b) { | 
 |     if (a == b) { | 
 |       return a; | 
 |     } | 
 |     return null; | 
 |   } | 
 |  | 
 |   @override | 
 |   DartType? visitInterfaceType(InterfaceType a, DartType b) { | 
 |     if (a == coreTypes.objectNullableRawType) { | 
 |       if (b is DynamicType) { | 
 |         // NNBD_TOP_MERGE(Object?, dynamic) = Object? | 
 |         return coreTypes.objectNullableRawType; | 
 |       } else if (b is VoidType) { | 
 |         // NNBD_TOP_MERGE(Object?, void) = Object? | 
 |         return coreTypes.objectNullableRawType; | 
 |       } else if (b == coreTypes.objectNullableRawType) { | 
 |         // NNBD_TOP_MERGE(Object?, Object?) = Object? | 
 |         return coreTypes.objectNullableRawType; | 
 |       } | 
 |     } | 
 |     return super.visitInterfaceType(a, b); | 
 |   } | 
 |  | 
 |   @override | 
 |   DartType? visitVoidType(VoidType a, DartType b) { | 
 |     if (b is DynamicType) { | 
 |       // NNBD_TOP_MERGE(void, dynamic) = Object? | 
 |       return coreTypes.objectNullableRawType; | 
 |     } else if (b is VoidType) { | 
 |       // NNBD_TOP_MERGE(void, void) = void | 
 |       return const VoidType(); | 
 |     } else if (b == coreTypes.objectNullableRawType) { | 
 |       // NNBD_TOP_MERGE(void, Object?) = Object? | 
 |       return coreTypes.objectNullableRawType; | 
 |     } | 
 |     return super.visitVoidType(a, b); | 
 |   } | 
 |  | 
 |   @override | 
 |   DartType? visitDynamicType(DynamicType a, DartType b) { | 
 |     if (b is DynamicType) { | 
 |       // NNBD_TOP_MERGE(dynamic, dynamic) = dynamic | 
 |       return const DynamicType(); | 
 |     } else if (b is VoidType) { | 
 |       // NNBD_TOP_MERGE(dynamic, void) = Object? | 
 |       return coreTypes.objectNullableRawType; | 
 |     } else if (b == coreTypes.objectNullableRawType) { | 
 |       // NNBD_TOP_MERGE(dynamic, Object?) = Object? | 
 |       return coreTypes.objectNullableRawType; | 
 |     } | 
 |     return super.visitDynamicType(a, b); | 
 |   } | 
 | } |