Skip to content

Commit

Permalink
Elements. Migrate InterfaceLeastUpperBoundHelper.
Browse files Browse the repository at this point in the history
Change-Id: I23faf1777e9fda023eeb00d548c27f39ad055cf5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/404400
Reviewed-by: Paul Berry <[email protected]>
Commit-Queue: Konstantin Shcheglov <[email protected]>
  • Loading branch information
scheglov authored and Commit Queue committed Jan 14, 2025
1 parent 2527793 commit dc709bb
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 43 deletions.
63 changes: 35 additions & 28 deletions pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
// 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.

// ignore_for_file: analyzer_use_new_elements

import 'dart:math' show max;

import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart'
show Variance;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/extensions.dart';
Expand Down Expand Up @@ -61,10 +59,10 @@ class InterfaceLeastUpperBoundHelper {
return type1.withNullability(nullability);
}

if (type1.element == type2.element) {
if (type1.element3 == type2.element3) {
var args1 = type1.typeArguments;
var args2 = type2.typeArguments;
var params = type1.element.typeParameters;
var params = type1.element3.typeParameters2;
assert(args1.length == args2.length);
assert(args1.length == params.length);

Expand Down Expand Up @@ -93,8 +91,8 @@ class InterfaceLeastUpperBoundHelper {
}
}

return InterfaceTypeImpl(
element: type1.element,
return InterfaceTypeImpl.v2(
element: type1.element3,
typeArguments: args,
nullabilitySuffix: nullability,
);
Expand Down Expand Up @@ -124,7 +122,7 @@ class InterfaceLeastUpperBoundHelper {
return;
}

if (type.element is ExtensionTypeElement) {
if (type.element3 is ExtensionTypeElement2) {
set.add(typeSystem.objectQuestion);
}

Expand Down Expand Up @@ -180,7 +178,7 @@ class InterfaceLeastUpperBoundHelper {
/// Object.
@visibleForTesting
static int computeLongestInheritancePathToObject(InterfaceType type) {
return _computeLongestInheritancePathToObject(type, <InterfaceElement>{});
return _computeLongestInheritancePathToObject(type, <InterfaceElement2>{});
}

static NullabilitySuffix _chooseNullability(
Expand All @@ -202,8 +200,8 @@ class InterfaceLeastUpperBoundHelper {
/// The set of [visitedElements] is used to prevent infinite recursion in the
/// case of a cyclic type structure.
static int _computeLongestInheritancePathToObject(
InterfaceType type, Set<InterfaceElement> visitedElements) {
var element = type.element;
InterfaceType type, Set<InterfaceElement2> visitedElements) {
var element = type.element3;
// recursion
if (visitedElements.contains(element)) {
return 0;
Expand All @@ -213,14 +211,14 @@ class InterfaceLeastUpperBoundHelper {
return 1;
}
// Object case
if (element is ClassElement) {
if (element is ClassElement2) {
if (element.isDartCoreObject) {
return type.nullabilitySuffix == NullabilitySuffix.none ? 1 : 0;
}
}

// Extension type without interfaces, implicit `Object?`
if (element is ExtensionTypeElement) {
if (element is ExtensionTypeElement2) {
if (element.interfaces.isEmpty) {
return 1;
}
Expand All @@ -232,7 +230,7 @@ class InterfaceLeastUpperBoundHelper {

// loop through each of the superinterfaces recursively calling this
// method and keeping track of the longest path to return
if (element is MixinElement) {
if (element is MixinElement2) {
for (InterfaceType interface in element.superclassConstraints) {
var pathLength = _computeLongestInheritancePathToObject(
interface, visitedElements);
Expand All @@ -248,7 +246,7 @@ class InterfaceLeastUpperBoundHelper {
longestPath = max(longestPath, 1 + pathLength);
}

if (element is! ClassElement) {
if (element is! ClassElement2) {
return longestPath;
}

Expand Down Expand Up @@ -321,7 +319,7 @@ class LeastUpperBoundHelper {
LeastUpperBoundHelper(this._typeSystem);

InterfaceType get _interfaceTypeFunctionNone {
return _typeSystem.typeProvider.functionType.element.instantiate(
return _typeSystem.typeProvider.functionType.element3.instantiate(
typeArguments: const [],
nullabilitySuffix: NullabilitySuffix.none,
);
Expand Down Expand Up @@ -625,8 +623,8 @@ class LeastUpperBoundHelper {
/// https://github.com/dart-lang/language
/// See `resources/type-system/upper-lower-bounds.md`
DartType _functionType(FunctionType f, FunctionType g) {
var fTypeFormals = f.typeFormals;
var gTypeFormals = g.typeFormals;
var fTypeFormals = f.typeParameters;
var gTypeFormals = g.typeParameters;

// The number of type parameters must be the same.
// Otherwise the result is `Function`.
Expand All @@ -636,18 +634,21 @@ class LeastUpperBoundHelper {

// The bounds of type parameters must be equal.
// Otherwise the result is `Function`.
var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
var fresh = _typeSystem.relateTypeParameters2(
f.typeParameters,
g.typeParameters,
);
if (fresh == null) {
return _interfaceTypeFunctionNone;
}

f = f.instantiate(fresh.typeParameterTypes);
g = g.instantiate(fresh.typeParameterTypes);

var fParameters = f.parameters;
var gParameters = g.parameters;
var fParameters = f.formalParameters;
var gParameters = g.formalParameters;

var parameters = <ParameterElement>[];
var parameters = <FormalParameterElement>[];
var fIndex = 0;
var gIndex = 0;
while (fIndex < fParameters.length && gIndex < gParameters.length) {
Expand Down Expand Up @@ -679,7 +680,13 @@ class LeastUpperBoundHelper {
}
} else if (fParameter.isNamed) {
if (gParameter.isNamed) {
var compareNames = fParameter.name.compareTo(gParameter.name);
var fName = fParameter.name3;
var gName = gParameter.name3;
if (fName == null || gName == null) {
return _interfaceTypeFunctionNone;
}

var compareNames = fName.compareTo(gName);
if (compareNames == 0) {
fIndex++;
gIndex++;
Expand Down Expand Up @@ -729,9 +736,9 @@ class LeastUpperBoundHelper {

var returnType = getLeastUpperBound(f.returnType, g.returnType);

return FunctionTypeImpl(
typeFormals: fresh.typeParameters,
parameters: parameters,
return FunctionTypeImpl.v2(
typeParameters: fresh.typeParameters,
formalParameters: parameters,
returnType: returnType,
nullabilitySuffix: NullabilitySuffix.none,
);
Expand Down Expand Up @@ -787,7 +794,7 @@ class LeastUpperBoundHelper {
return null;
}

DartType _parameterType(ParameterElement a, ParameterElement b) {
DartType _parameterType(FormalParameterElement a, FormalParameterElement b) {
return _typeSystem.greatestLowerBound(a.type, b.type);
}

Expand Down Expand Up @@ -841,7 +848,7 @@ class LeastUpperBoundHelper {

/// Return the promoted or declared bound of the type parameter.
DartType _typeParameterBound(TypeParameterTypeImpl type) {
var bound = type.promotedBound ?? type.element.bound;
var bound = type.promotedBound ?? type.element3.bound;
if (bound != null) {
return bound;
}
Expand Down
10 changes: 1 addition & 9 deletions pkg/analyzer/lib/src/dart/element/type_algebra.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,7 @@ FreshTypeParameters getFreshTypeParameters2(
List<TypeParameterElement2> typeParameters) {
var freshParameters = List<TypeParameterElementImpl2>.generate(
typeParameters.length,
(i) {
var name = typeParameters[i].name3;
var fragment = TypeParameterElementImpl(name ?? '', -1);
return TypeParameterElementImpl2(
firstFragment: fragment,
name3: name,
bound: null,
);
},
(i) => typeParameters[i].freshCopy(),
growable: false,
);

Expand Down
10 changes: 6 additions & 4 deletions pkg/analyzer/lib/src/utilities/extensions/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -570,11 +570,13 @@ extension TypeParameterElement2Extension on TypeParameterElement2 {
}

TypeParameterElementImpl2 freshCopy() {
var fragment = TypeParameterElementImpl(
name3 ?? '',
-1,
);
fragment.bound = bound;
return TypeParameterElementImpl2(
firstFragment: TypeParameterElementImpl(
name3 ?? '',
-1,
),
firstFragment: fragment,
name3: name3,
bound: bound,
);
Expand Down
5 changes: 5 additions & 0 deletions pkg/analyzer/test/generated/elements_types_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,11 @@ extension ClassElementImplExtension on ClassElementImpl {
];
}
}

void updateElement() {
element.interfaces = interfaces;
element.mixins = mixins;
}
}

extension MixinElementImplExtension on MixinElementImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../../generated/elements_types_mixin.dart';
import '../../../generated/type_system_base.dart';

main() {
Expand Down Expand Up @@ -135,6 +136,10 @@ class PathToObjectTest extends AbstractTypeSystemTest {
interfaceTypeNone(classB),
interfaceTypeNone(classD)
];
classB.updateElement();
classC.updateElement();
classD.updateElement();
classE.updateElement();
// assertion: even though the longest path to Object for typeB is 2, and
// typeE implements typeB, the longest path for typeE is 4 since it also
// implements typeD
Expand Down Expand Up @@ -163,6 +168,7 @@ class PathToObjectTest extends AbstractTypeSystemTest {
ClassElementImpl classE =
class_(name: "E", superType: interfaceTypeNone(classB));
classE.interfaces = <InterfaceType>[interfaceTypeNone(classD)];
classE.updateElement();
// assertion: even though the longest path to Object for typeB is 2, and
// typeE extends typeB, the longest path for typeE is 4 since it also
// implements typeD
Expand Down Expand Up @@ -202,8 +208,10 @@ class PathToObjectTest extends AbstractTypeSystemTest {
ClassElementImpl classA = class_(name: "A");
ClassElementImpl classB = class_(name: "B");
ClassElementImpl classC = class_(name: "C");
classB.interfaces = <InterfaceType>[interfaceTypeNone(classA)];
classC.interfaces = <InterfaceType>[interfaceTypeNone(classB)];
classB.interfaces = [interfaceTypeNone(classA)];
classC.interfaces = [interfaceTypeNone(classB)];
classB.updateElement();
classC.updateElement();
expect(_toElement(classA), 2);
expect(_toElement(classB), 3);
expect(_toElement(classC), 4);
Expand Down

0 comments on commit dc709bb

Please sign in to comment.