Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 9f810fa

Browse files
author
Dart CI
committed
Version 2.11.0-184.0.dev
Merge commit '3efed861472346c54e571d9bce61c0c791605ded' into 'dev'
2 parents 2eab25e + 3efed86 commit 9f810fa

File tree

14 files changed

+551
-83
lines changed

14 files changed

+551
-83
lines changed

pkg/analyzer/lib/src/dart/element/type_system.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,56 @@ class TypeSystemImpl implements TypeSystem {
755755
return false;
756756
}
757757

758+
/// A dynamic bounded type is either `dynamic` itself, or a type variable
759+
/// whose bound is dynamic bounded, or an intersection (promoted type
760+
/// parameter type) whose second operand is dynamic bounded.
761+
bool isDynamicBounded(DartType type) {
762+
if (identical(type, DynamicTypeImpl.instance)) {
763+
return true;
764+
}
765+
766+
if (type is TypeParameterTypeImpl) {
767+
var bound = type.element.bound;
768+
if (bound != null && isDynamicBounded(bound)) {
769+
return true;
770+
}
771+
772+
var promotedBound = type.promotedBound;
773+
if (promotedBound != null && isDynamicBounded(promotedBound)) {
774+
return true;
775+
}
776+
}
777+
778+
return false;
779+
}
780+
781+
/// A function bounded type is either `Function` itself, or a type variable
782+
/// whose bound is function bounded, or an intersection (promoted type
783+
/// parameter type) whose second operand is function bounded.
784+
bool isFunctionBounded(DartType type) {
785+
if (type is FunctionType) {
786+
return type.nullabilitySuffix != NullabilitySuffix.question;
787+
}
788+
789+
if (type is InterfaceType && type.isDartCoreFunction) {
790+
return type.nullabilitySuffix != NullabilitySuffix.question;
791+
}
792+
793+
if (type is TypeParameterTypeImpl) {
794+
var bound = type.element.bound;
795+
if (bound != null && isFunctionBounded(bound)) {
796+
return true;
797+
}
798+
799+
var promotedBound = type.promotedBound;
800+
if (promotedBound != null && isFunctionBounded(promotedBound)) {
801+
return true;
802+
}
803+
}
804+
805+
return false;
806+
}
807+
758808
/// Defines an (almost) total order on bottom and `Null` types. This does not
759809
/// currently consistently order two different type variables with the same
760810
/// bound.

pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -136,27 +136,14 @@ class MethodInvocationResolver {
136136
}
137137

138138
DartType receiverType = receiver.staticType;
139-
receiverType = _resolveTypeParameter(receiverType);
140139

141-
if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
142-
_typeSystem.isNonNullableByDefault) {
143-
receiverType = _typeSystem.promoteToNonNull(receiverType);
144-
}
145-
146-
if (receiverType is InterfaceType) {
147-
_resolveReceiverInterfaceType(
148-
node, receiver, receiverType, nameNode, name);
149-
return;
150-
}
151-
152-
if (receiverType is DynamicTypeImpl) {
153-
_resolveReceiverDynamic(node);
140+
if (_typeSystem.isDynamicBounded(receiverType)) {
141+
_resolveReceiverDynamicBounded(node);
154142
return;
155143
}
156144

157-
if (receiverType is FunctionType) {
158-
_resolveReceiverFunctionType(
159-
node, receiver, receiverType, nameNode, name);
145+
if (receiverType is NeverTypeImpl) {
146+
_resolveReceiverNever(node, receiver, receiverType);
160147
return;
161148
}
162149

@@ -165,10 +152,25 @@ class MethodInvocationResolver {
165152
return;
166153
}
167154

168-
if (receiverType is NeverTypeImpl) {
169-
_resolveReceiverNever(node, receiver, receiverType);
155+
if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
156+
_typeSystem.isNonNullableByDefault) {
157+
receiverType = _typeSystem.promoteToNonNull(receiverType);
158+
}
159+
160+
if (_typeSystem.isFunctionBounded(receiverType)) {
161+
_resolveReceiverFunctionBounded(
162+
node, receiver, receiverType, nameNode, name);
170163
return;
171164
}
165+
166+
_resolveReceiverType(
167+
node: node,
168+
receiver: receiver,
169+
receiverType: receiverType,
170+
nameNode: nameNode,
171+
name: name,
172+
receiverErrorNode: receiver,
173+
);
172174
}
173175

174176
bool _isCoreFunction(DartType type) {
@@ -382,7 +384,7 @@ class MethodInvocationResolver {
382384
_setResolution(node, member.type);
383385
}
384386

385-
void _resolveReceiverDynamic(MethodInvocationImpl node) {
387+
void _resolveReceiverDynamicBounded(MethodInvocation node) {
386388
var nameNode = node.methodName;
387389

388390
var objectElement = _typeSystem.typeProvider.objectElement;
@@ -411,8 +413,13 @@ class MethodInvocationResolver {
411413
node.argumentList.accept(_resolver);
412414
}
413415

414-
void _resolveReceiverFunctionType(MethodInvocation node, Expression receiver,
415-
FunctionType receiverType, SimpleIdentifier nameNode, String name) {
416+
void _resolveReceiverFunctionBounded(
417+
MethodInvocation node,
418+
Expression receiver,
419+
DartType receiverType,
420+
SimpleIdentifier nameNode,
421+
String name,
422+
) {
416423
if (name == FunctionElement.CALL_METHOD_NAME) {
417424
_setResolution(node, receiverType);
418425
// TODO(scheglov) Replace this with using FunctionType directly.
@@ -432,18 +439,6 @@ class MethodInvocationResolver {
432439
);
433440
}
434441

435-
void _resolveReceiverInterfaceType(MethodInvocation node, Expression receiver,
436-
InterfaceType receiverType, SimpleIdentifier nameNode, String name) {
437-
_resolveReceiverType(
438-
node: node,
439-
receiver: receiver,
440-
receiverType: receiverType,
441-
nameNode: nameNode,
442-
name: name,
443-
receiverErrorNode: receiver,
444-
);
445-
}
446-
447442
void _resolveReceiverNever(
448443
MethodInvocation node,
449444
Expression receiver,

pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,6 @@ class PropertyElementResolver {
328328
}
329329

330330
var targetType = target.staticType;
331-
targetType = _resolveTypeParameter(targetType);
332331

333332
if (targetType.isVoid) {
334333
_errorReporter.reportErrorForNode(

pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import 'package:analyzer/dart/element/element.dart';
88
import 'package:analyzer/dart/element/type.dart';
99
import 'package:analyzer/src/dart/element/element.dart';
1010
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
11-
import 'package:analyzer/src/dart/element/type.dart';
1211
import 'package:analyzer/src/dart/element/type_provider.dart';
1312
import 'package:analyzer/src/dart/element/type_system.dart';
1413
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
@@ -71,9 +70,9 @@ class TypePropertyResolver {
7170
_nameErrorEntity = nameErrorEntity;
7271
_resetResult();
7372

74-
receiverType = _resolveTypeParameter(receiverType);
73+
receiverType = _resolveTypeParameter(receiverType, ifLegacy: true);
7574

76-
if (receiverType is DynamicTypeImpl) {
75+
if (_typeSystem.isDynamicBounded(receiverType)) {
7776
_lookupInterfaceType(_typeProvider.objectType);
7877
_needsGetterError = false;
7978
_needsSetterError = false;
@@ -100,29 +99,33 @@ class TypePropertyResolver {
10099
_reportedSetterError = true;
101100

102101
// Recovery, get some resolution.
102+
receiverType = _resolveTypeParameter(receiverType, ifNullSafe: true);
103103
if (receiverType is InterfaceType) {
104104
_lookupInterfaceType(receiverType);
105105
}
106106

107107
return _toResult();
108108
} else {
109-
if (receiverType is InterfaceType) {
110-
_lookupInterfaceType(receiverType);
109+
var receiverTypeResolved =
110+
_resolveTypeParameter(receiverType, ifNullSafe: true);
111+
112+
if (receiverTypeResolved is InterfaceType) {
113+
_lookupInterfaceType(receiverTypeResolved);
111114
if (_hasGetterOrSetter) {
112115
return _toResult();
113116
}
114-
if (receiverType.isDartCoreFunction && _name == 'call') {
117+
if (receiverTypeResolved.isDartCoreFunction && _name == 'call') {
115118
_needsGetterError = false;
116119
_needsSetterError = false;
117120
return _toResult();
118121
}
119122
}
120123

121-
if (receiverType is FunctionType && _name == 'call') {
124+
if (receiverTypeResolved is FunctionType && _name == 'call') {
122125
return _toResult();
123126
}
124127

125-
if (receiverType is NeverType) {
128+
if (receiverTypeResolved is NeverType) {
126129
_lookupInterfaceType(_typeProvider.objectType);
127130
_needsGetterError = false;
128131
_needsSetterError = false;
@@ -200,8 +203,22 @@ class TypePropertyResolver {
200203

201204
/// If the given [type] is a type parameter, replace it with its bound.
202205
/// Otherwise, return the original type.
203-
DartType _resolveTypeParameter(DartType type) {
204-
return type?.resolveToBound(_typeProvider.objectType);
206+
///
207+
/// See https://github.com/dart-lang/language/issues/1182
208+
/// There was a bug in the analyzer (and CFE) - we were always resolving
209+
/// types to bounds before searching for a property. But extensions should
210+
/// be applied to original types. Fixing this would be a breaking change,
211+
/// so we fix it together with null safety.
212+
DartType _resolveTypeParameter(
213+
DartType type, {
214+
bool ifLegacy = false,
215+
bool ifNullSafe = false,
216+
}) {
217+
if (_typeSystem.isNonNullableByDefault ? ifNullSafe : ifLegacy) {
218+
return type?.resolveToBound(_typeProvider.objectType);
219+
} else {
220+
return type;
221+
}
205222
}
206223

207224
ResolutionResult _toResult() {

pkg/analyzer/test/src/dart/element/test_all.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import 'runtime_type_equality_test.dart' as runtime_type_equality;
2222
import 'subtype_test.dart' as subtype;
2323
import 'top_merge_test.dart' as top_merge;
2424
import 'type_algebra_test.dart' as type_algebra;
25+
import 'type_bounded_test.dart' as type_bounded;
2526
import 'type_constraint_gatherer_test.dart' as type_constraint_gatherer;
2627
import 'type_parameter_element_test.dart' as type_parameter_element;
2728
import 'type_visitor_test.dart' as type_visitor;
@@ -48,6 +49,7 @@ main() {
4849
subtype.main();
4950
top_merge.main();
5051
type_algebra.main();
52+
type_bounded.main();
5153
type_constraint_gatherer.main();
5254
type_parameter_element.main();
5355
type_visitor.main();

0 commit comments

Comments
 (0)