|  | // 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), | 
|  | ); | 
|  | } | 
|  | } |