[analyzer] Fix type of transformedParameters when inheriting covariance
In `InheritanceManager3._inheritCovariance`, if the original
`ExecutableElement` is in fact an `ExecutableMember`, then its
parameters will be `ParameterMember`s. These `ParameterMember`s need
to be converted to `ParameterElementImpl`s in order to be safely
stored in the synthetic `ExecutableElementImpl` that
`_inheritCovariance` returns.
I will follow up with a fix that changes the type accepted by
`ExecutableElementImpl.parameters=` in order to prevent similar
problems happening in the future.
Fixes https://github.com/dart-lang/sdk/issues/59849.
Bug: https://github.com/dart-lang/sdk/issues/59849
Change-Id: I636fd8cca0411745aedb3cd834354b4dcc0aadc1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/403322
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/extensions.dart b/pkg/analyzer/lib/src/dart/element/extensions.dart
index d1cf93d..9a0f497 100644
--- a/pkg/analyzer/lib/src/dart/element/extensions.dart
+++ b/pkg/analyzer/lib/src/dart/element/extensions.dart
@@ -205,7 +205,7 @@
extension ParameterElementExtensions on ParameterElement {
/// Return [ParameterElement] with the specified properties replaced.
- ParameterElement copyWith({
+ ParameterElementImpl copyWith({
DartType? type,
ParameterKind? kind,
bool? isCovariant,
@@ -217,6 +217,11 @@
kind ?? parameterKind,
)..isExplicitlyCovariant = isCovariant ?? this.isCovariant;
}
+
+ /// Returns `this`, converted to a [ParameterElementImpl] if it isn't one
+ /// already.
+ ParameterElementImpl toImpl() =>
+ switch (this) { ParameterElementImpl p => p, _ => copyWith() };
}
extension RecordTypeExtension on RecordType {
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index f0cd694..4723bdc 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -1042,14 +1042,16 @@
}
// Update covariance of the parameters of the chosen executable.
- List<ParameterElement>? transformedParameters;
+ List<ParameterElementImpl>? transformedParameters;
for (var index = 0; index < parameters.length; index++) {
var parameter = parameters[index];
var shouldBeCovariant = covariantParameters.contains(
_ParameterDesc(index, parameter),
);
if (parameter.isCovariant != shouldBeCovariant) {
- transformedParameters ??= parameters.toList();
+ transformedParameters ??= [
+ for (var parameter in parameters) parameter.toImpl()
+ ];
transformedParameters[index] = parameter.copyWith(
isCovariant: shouldBeCovariant,
);
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index 9a9bf82..09e1505 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -2400,6 +2400,28 @@
expect(returnType.element, same(T));
}
+ test_getMember_method_covariantAfterSubstitutedParameter_merged() async {
+ await resolveTestCode(r'''
+class A<T> {
+ void foo<U>(covariant Object a, U b, int c) {}
+}
+
+class B extends A<int> implements C {}
+
+class C {
+ void foo<U>(Object a, U b, covariant Object c) {}
+}
+''');
+ var member = manager.getMember2(
+ findElement.classOrMixin('B'),
+ Name(null, 'foo'),
+ concrete: true,
+ )!;
+ expect(member.parameters[0].isCovariant, isTrue);
+ expect(member.parameters[1].isCovariant, isFalse);
+ expect(member.parameters[2].isCovariant, isTrue);
+ }
+
test_getMember_method_covariantByDeclaration_inherited() async {
await resolveTestCode('''
abstract class A {