Skip to content

Commit

Permalink
[element model] fix unsafe ConstructorMember cast
Browse files Browse the repository at this point in the history
See: b/374689139.

https://dart-review.googlesource.com/c/sdk/+/390941 is blocking an SDK roll.

Root cause:


```
Action threw an exception: type 'ConstructorMember' is not a subtype of type 'ConstructorFragment' in type cast
#0      InterfaceTypeImpl.constructors2.<anonymous closure> (package:analyzer/src/dart/element/type.dart:569)
#1      MappedListIterable.elementAt (dart:_internal/iterable.dart:435)
#2      ListIterator.moveNext (dart:_internal/iterable.dart:364)
#3      new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:189)
#4      new _GrowableList.of (dart:core-patch/growable_array.dart:150)
#5      new List.of (dart:core-patch/array_patch.dart:39)
#6      ListIterable.toList (dart:_internal/iterable.dart:224)
#7      InterfaceTypeImpl.constructors2 (package:analyzer/src/dart/element/type.dart:570)
#8      _Visitor._hasConstConstructorInvocation (package:linter/src/rules/prefer_const_constructors_in_immutables.dart:110)
#9      _Visitor.visitConstructorDeclaration (package:linter/src/rules/prefer_const_constructors_in_immutables.dart:58)
```


To verify the fix locally:

```
  solo_test_X() async {
    await assertNoErrorsInCode(r'''
class A<T> {}
''');

    var A = findElement.class_('A').instantiate(
      typeArguments: [intType],
      nullabilitySuffix: NullabilitySuffix.none,
    );
    A.constructors2;
  }
```


Bug: b/374689139
Change-Id: I70034d938d840dc0c3939db27e7116164e4617e9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391483
Reviewed-by: Konstantin Shcheglov <[email protected]>
Commit-Queue: Phil Quitslund <[email protected]>
  • Loading branch information
pq authored and Commit Queue committed Oct 22, 2024
1 parent 98ddead commit f65f719
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
8 changes: 7 additions & 1 deletion pkg/analyzer/lib/src/dart/element/type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,13 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {

@override
List<ConstructorElement2> get constructors2 => constructors
.map((fragment) => (fragment as ConstructorFragment).element)
.map((fragment) => switch (fragment) {
ConstructorFragment(:var element) => element,
ConstructorMember() => fragment,
_ => throw StateError(
'unexpected fragment type: ${fragment.runtimeType}',
)
})
.toList();

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,21 @@ macro class M {
]);
}

test_parameterizedType() async {
// Verify we aren't doing an unsafe cast to a `ConstructorFragment` in type.dart.
// b/374689139
await assertNoDiagnostics(r'''
import 'package:meta/meta.dart';
class A<T> {}
@immutable
class C<U> extends A<U> {
C();
}
''');
}

test_returnOfInvalidType() async {
await assertDiagnostics(r'''
import 'package:meta/meta.dart';
Expand Down

0 comments on commit f65f719

Please sign in to comment.