| // Copyright (c) 2021, 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 'package:analyzer/dart/element/type.dart'; | 
 | import 'package:analyzer/src/dart/element/element.dart'; | 
 | import 'package:analyzer/src/dart/element/replacement_visitor.dart'; | 
 | import 'package:analyzer/src/dart/element/type.dart'; | 
 | import 'package:analyzer/src/dart/element/type_algebra.dart'; | 
 | import 'package:analyzer/src/dart/element/type_system.dart'; | 
 |  | 
 | class LeastGreatestClosureHelper extends ReplacementVisitor { | 
 |   final TypeSystemImpl typeSystem; | 
 |   final TypeImpl topType; | 
 |   final TypeImpl topFunctionType; | 
 |   final TypeImpl bottomType; | 
 |   final Set<TypeParameterElementImpl2> eliminationTargets; | 
 |  | 
 |   late final bool _isLeastClosure; | 
 |   bool _isCovariant = true; | 
 |  | 
 |   LeastGreatestClosureHelper({ | 
 |     required this.typeSystem, | 
 |     required this.topType, | 
 |     required this.topFunctionType, | 
 |     required this.bottomType, | 
 |     required this.eliminationTargets, | 
 |   }); | 
 |  | 
 |   TypeImpl get _functionReplacement { | 
 |     return _isLeastClosure && _isCovariant || | 
 |             (!_isLeastClosure && !_isCovariant) | 
 |         ? bottomType | 
 |         : topFunctionType; | 
 |   } | 
 |  | 
 |   TypeImpl get _typeParameterReplacement { | 
 |     return _isLeastClosure && _isCovariant || | 
 |             (!_isLeastClosure && !_isCovariant) | 
 |         ? bottomType | 
 |         : topType; | 
 |   } | 
 |  | 
 |   @override | 
 |   void changeVariance() { | 
 |     _isCovariant = !_isCovariant; | 
 |   } | 
 |  | 
 |   /// Returns a supertype of [type] for all values of [eliminationTargets]. | 
 |   TypeImpl eliminateToGreatest(TypeImpl type) { | 
 |     _isCovariant = true; | 
 |     _isLeastClosure = false; | 
 |     return type.accept(this) ?? type; | 
 |   } | 
 |  | 
 |   /// Returns a subtype of [type] for all values of [eliminationTargets]. | 
 |   TypeImpl eliminateToLeast(TypeImpl type) { | 
 |     _isCovariant = true; | 
 |     _isLeastClosure = true; | 
 |     return type.accept(this) ?? type; | 
 |   } | 
 |  | 
 |   @override | 
 |   TypeImpl? visitFunctionType(FunctionType node) { | 
 |     // - if `S` is | 
 |     //   `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn, | 
 |     //       [Tn+1 xn+1, ..., Tm xm])` | 
 |     //   or `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn, | 
 |     //       {Tn+1 xn+1, ..., Tm xm})` | 
 |     //   and `L` contains any free type variables from any of the `Bi`: | 
 |     //  - The least closure of `S` with respect to `L` is `Never` | 
 |     //  - The greatest closure of `S` with respect to `L` is `Function` | 
 |     for (var typeParameter in node.typeParameters) { | 
 |       if (typeParameter.bound case TypeImpl bound? | 
 |           when bound.referencesAny2(eliminationTargets)) { | 
 |         return _functionReplacement; | 
 |       } | 
 |     } | 
 |  | 
 |     return super.visitFunctionType(node); | 
 |   } | 
 |  | 
 |   @override | 
 |   TypeImpl? visitTypeParameterType(TypeParameterType type) { | 
 |     if (eliminationTargets.contains(type.element3)) { | 
 |       var replacement = _typeParameterReplacement; | 
 |       return replacement.withNullability( | 
 |         uniteNullabilities( | 
 |           replacement.nullabilitySuffix, | 
 |           type.nullabilitySuffix, | 
 |         ), | 
 |       ); | 
 |     } | 
 |     return super.visitTypeParameterType(type); | 
 |   } | 
 | } | 
 |  | 
 | class PatternGreatestClosureHelper extends ReplacementVisitor { | 
 |   final TypeImpl topType; | 
 |   final TypeImpl bottomType; | 
 |   bool _isCovariant = true; | 
 |  | 
 |   PatternGreatestClosureHelper({ | 
 |     required this.topType, | 
 |     required this.bottomType, | 
 |   }); | 
 |  | 
 |   @override | 
 |   void changeVariance() { | 
 |     _isCovariant = !_isCovariant; | 
 |   } | 
 |  | 
 |   /// Returns a supertype of [type] for all values of type parameters. | 
 |   TypeImpl eliminateToGreatest(TypeImpl type) { | 
 |     _isCovariant = true; | 
 |     return type.accept(this) ?? type; | 
 |   } | 
 |  | 
 |   @override | 
 |   TypeImpl? visitTypeParameterType(TypeParameterType type) { | 
 |     var replacement = _isCovariant ? topType : bottomType; | 
 |     return replacement.withNullability( | 
 |       uniteNullabilities(replacement.nullabilitySuffix, type.nullabilitySuffix), | 
 |     ); | 
 |   } | 
 | } |