Skip to content

Commit f5e3e61

Browse files
srawlinsCommit Queue
authored and
Commit Queue
committed
Fix COULD_NOT_INFER on top-level elements
Fixes #49308 Change-Id: I303ac7dda326504e73c6b612625d5eec57fe539b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262540 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent d315721 commit f5e3e61

16 files changed

+468
-127
lines changed

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

Lines changed: 18 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,9 @@
44

55
import 'dart:math' as math;
66

7-
import 'package:analyzer/dart/ast/ast.dart'
8-
show
9-
Annotation,
10-
AsExpression,
11-
AstNode,
12-
ConstructorName,
13-
Expression,
14-
InvocationExpression,
15-
SimpleIdentifier;
7+
import 'package:analyzer/dart/ast/ast.dart' show AstNode;
168
import 'package:analyzer/dart/element/element.dart';
179
import 'package:analyzer/dart/element/type.dart';
18-
import 'package:analyzer/error/listener.dart' show ErrorReporter;
1910
import 'package:analyzer/src/dart/element/element.dart';
2011
import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
2112
import 'package:analyzer/src/dart/element/type.dart';
@@ -24,8 +15,7 @@ import 'package:analyzer/src/dart/element/type_constraint_gatherer.dart';
2415
import 'package:analyzer/src/dart/element/type_provider.dart';
2516
import 'package:analyzer/src/dart/element/type_schema.dart';
2617
import 'package:analyzer/src/dart/element/type_system.dart';
27-
import 'package:analyzer/src/error/codes.dart'
28-
show CompileTimeErrorCode, HintCode;
18+
import 'package:analyzer/src/dart/error/inference_error_listener.dart';
2919
import 'package:meta/meta.dart';
3020

3121
/// Tracks upper and lower type bounds for a set of type parameters.
@@ -59,12 +49,13 @@ class GenericInferrer {
5949
/// The list of type parameters being inferred.
6050
final List<TypeParameterElement> _typeFormals;
6151

62-
/// The [ErrorReporter] to which inference errors should be reported, or
63-
/// `null` if errors shouldn't be reported.
64-
final ErrorReporter? errorReporter;
52+
/// The [InferenceErrorListener] to which inference errors should be reported,
53+
/// or `null` if errors shouldn't be reported.
54+
final InferenceErrorListener? _inferenceErrorListener;
6555

6656
/// The [AstNode] to which errors should be attached. May be `null` if errors
67-
/// are not being reported (that is, if [errorReporter] is also `null`).
57+
/// are not being reported (that is, if [_inferenceErrorListener] is also
58+
/// `null`).
6859
final AstNode? errorNode;
6960

7061
/// Indicates whether the "generic metadata" feature is enabled. When it is,
@@ -96,12 +87,10 @@ class GenericInferrer {
9687
final Map<TypeParameterElement, DartType> _typesInferredSoFar = {};
9788

9889
GenericInferrer(this._typeSystem, this._typeFormals,
99-
{this.errorReporter,
90+
{InferenceErrorListener? inferenceErrorListener,
10091
this.errorNode,
101-
required this.genericMetadataIsEnabled}) {
102-
if (errorReporter != null) {
103-
assert(errorNode != null);
104-
}
92+
required this.genericMetadataIsEnabled})
93+
: _inferenceErrorListener = inferenceErrorListener {
10594
_typeParameters.addAll(_typeFormals);
10695
for (var formal in _typeFormals) {
10796
_constraints[formal] = [];
@@ -219,9 +208,7 @@ class GenericInferrer {
219208
if (!success) {
220209
if (failAtError) return null;
221210
hasErrorReported = true;
222-
errorReporter?.reportErrorForNode(
223-
CompileTimeErrorCode.COULD_NOT_INFER,
224-
errorNode!,
211+
_inferenceErrorListener?.addCouldNotInferError(errorNode!,
225212
[parameter.name, _formatError(parameter, inferred, constraints)]);
226213

227214
// Heuristic: even if we failed, keep the erroneous type.
@@ -233,13 +220,12 @@ class GenericInferrer {
233220
if (inferred is FunctionType &&
234221
inferred.typeFormals.isNotEmpty &&
235222
!genericMetadataIsEnabled &&
236-
errorReporter != null) {
223+
_inferenceErrorListener != null) {
237224
if (failAtError) return null;
238225
hasErrorReported = true;
239226
var typeFormals = inferred.typeFormals;
240227
var typeFormalsStr = typeFormals.map(_elementStr).join(', ');
241-
errorReporter!.reportErrorForNode(
242-
CompileTimeErrorCode.COULD_NOT_INFER, errorNode!, [
228+
_inferenceErrorListener?.addCouldNotInferError(errorNode!, [
243229
parameter.name,
244230
' Inferred candidate type ${_typeStr(inferred)} has type parameters'
245231
' [$typeFormalsStr], but a function with'
@@ -249,16 +235,13 @@ class GenericInferrer {
249235

250236
if (UnknownInferredType.isKnown(inferred)) {
251237
knownTypes[parameter] = inferred;
252-
} else if (_typeSystem.strictInference) {
238+
} else if (!hasErrorReported && _typeSystem.strictInference) {
253239
// [typeParam] could not be inferred. A result will still be returned
254240
// by [infer], with [typeParam] filled in as its bounds. This is
255241
// considered a failure of inference, under the "strict-inference"
256242
// mode.
257-
_reportInferenceFailure(
258-
errorReporter: errorReporter,
259-
errorNode: errorNode,
260-
genericMetadataIsEnabled: genericMetadataIsEnabled,
261-
);
243+
hasErrorReported = true;
244+
_inferenceErrorListener?.reportInferenceFailure(errorNode!);
262245
}
263246
}
264247

@@ -276,8 +259,7 @@ class GenericInferrer {
276259
var typeParamBound = Substitution.fromPairs(_typeFormals, inferredTypes)
277260
.substituteType(typeParam.bound ?? typeProvider.objectType);
278261
// TODO(jmesserly): improve this error message.
279-
errorReporter?.reportErrorForNode(
280-
CompileTimeErrorCode.COULD_NOT_INFER, errorNode!, [
262+
_inferenceErrorListener?.addCouldNotInferError(errorNode!, [
281263
typeParam.name,
282264
"\nRecursive bound cannot be instantiated: '$typeParamBound'."
283265
"\nConsider passing explicit type argument(s) "
@@ -288,8 +270,6 @@ class GenericInferrer {
288270

289271
if (!hasErrorReported) {
290272
_checkArgumentsNotMatchingBounds(
291-
errorNode: errorNode,
292-
errorReporter: errorReporter,
293273
typeArguments: result,
294274
);
295275
}
@@ -304,8 +284,6 @@ class GenericInferrer {
304284

305285
/// Check that inferred [typeArguments] satisfy the [typeParameters] bounds.
306286
void _checkArgumentsNotMatchingBounds({
307-
required AstNode? errorNode,
308-
required ErrorReporter? errorReporter,
309287
required List<DartType> typeArguments,
310288
}) {
311289
for (int i = 0; i < _typeFormals.length; i++) {
@@ -321,8 +299,7 @@ class GenericInferrer {
321299
var substitution = Substitution.fromPairs(_typeFormals, typeArguments);
322300
var bound = substitution.substituteType(rawBound);
323301
if (!_typeSystem.isSubtypeOf(argument, bound)) {
324-
errorReporter?.reportErrorForNode(
325-
CompileTimeErrorCode.COULD_NOT_INFER,
302+
_inferenceErrorListener?.addCouldNotInferError(
326303
errorNode!,
327304
[
328305
parameter.name,
@@ -547,83 +524,6 @@ class GenericInferrer {
547524
}
548525
}
549526

550-
/// Reports an inference failure on [errorNode] according to its type.
551-
void _reportInferenceFailure({
552-
ErrorReporter? errorReporter,
553-
AstNode? errorNode,
554-
required bool genericMetadataIsEnabled,
555-
}) {
556-
if (errorReporter == null || errorNode == null) {
557-
return;
558-
}
559-
if (errorNode.parent is InvocationExpression &&
560-
errorNode.parent?.parent is AsExpression) {
561-
// Casts via `as` do not play a part in downward inference. We allow an
562-
// exception when inference has "failed" but the return value is
563-
// immediately cast with `as`.
564-
return;
565-
}
566-
if (errorNode is ConstructorName &&
567-
!(errorNode.type.type as InterfaceType).element.hasOptionalTypeArgs) {
568-
String constructorName = errorNode.name == null
569-
? errorNode.type.name.name
570-
: '${errorNode.type}.${errorNode.name}';
571-
errorReporter.reportErrorForNode(
572-
HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION,
573-
errorNode,
574-
[constructorName]);
575-
} else if (errorNode is Annotation) {
576-
if (genericMetadataIsEnabled) {
577-
// Only report an error if generic metadata is valid syntax.
578-
var element = errorNode.name.staticElement;
579-
if (element != null && !element.hasOptionalTypeArgs) {
580-
String constructorName = errorNode.constructorName == null
581-
? errorNode.name.name
582-
: '${errorNode.name.name}.${errorNode.constructorName}';
583-
errorReporter.reportErrorForNode(
584-
HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION,
585-
errorNode,
586-
[constructorName]);
587-
}
588-
}
589-
} else if (errorNode is SimpleIdentifier) {
590-
var element = errorNode.staticElement;
591-
if (element != null) {
592-
if (element is VariableElement) {
593-
// For variable elements, we check their type and possible alias type.
594-
var type = element.type;
595-
final typeElement = type is InterfaceType ? type.element : null;
596-
if (typeElement != null && typeElement.hasOptionalTypeArgs) {
597-
return;
598-
}
599-
var typeAliasElement = type.alias?.element;
600-
if (typeAliasElement != null &&
601-
typeAliasElement.hasOptionalTypeArgs) {
602-
return;
603-
}
604-
}
605-
if (!element.hasOptionalTypeArgs) {
606-
errorReporter.reportErrorForNode(
607-
HintCode.INFERENCE_FAILURE_ON_FUNCTION_INVOCATION,
608-
errorNode,
609-
[errorNode.name]);
610-
return;
611-
}
612-
}
613-
} else if (errorNode is Expression) {
614-
var type = errorNode.staticType;
615-
if (type != null) {
616-
var typeDisplayString = type.getDisplayString(
617-
withNullability: _typeSystem.isNonNullableByDefault);
618-
errorReporter.reportErrorForNode(
619-
HintCode.INFERENCE_FAILURE_ON_GENERIC_INVOCATION,
620-
errorNode,
621-
[typeDisplayString]);
622-
return;
623-
}
624-
}
625-
}
626-
627527
/// If in a legacy library, return the legacy version of the [type].
628528
/// Otherwise, return the original type.
629529
DartType _toLegacyElementIfOptOut(DartType type) {

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import 'package:analyzer/src/dart/element/type_provider.dart';
3131
import 'package:analyzer/src/dart/element/type_schema.dart';
3232
import 'package:analyzer/src/dart/element/type_schema_elimination.dart';
3333
import 'package:analyzer/src/dart/element/well_bounded.dart';
34+
import 'package:analyzer/src/dart/error/inference_error_listener.dart';
3435

3536
/// Fresh type parameters created to unify two lists of type parameters.
3637
class RelatedTypeParameters {
@@ -493,7 +494,13 @@ class TypeSystemImpl implements TypeSystem {
493494
// subtypes (or supertypes) as necessary, and track the constraints that
494495
// are implied by this.
495496
var inferrer = GenericInferrer(this, fnType.typeFormals,
496-
errorReporter: errorReporter,
497+
inferenceErrorListener: errorReporter == null
498+
? null
499+
: InferenceErrorReporter(
500+
errorReporter,
501+
isNonNullableByDefault: isNonNullableByDefault,
502+
isGenericMetadataEnabled: genericMetadataIsEnabled,
503+
),
497504
errorNode: errorNode,
498505
genericMetadataIsEnabled: genericMetadataIsEnabled);
499506
inferrer.constrainGenericFunctionInContext(fnType, contextType);
@@ -1533,15 +1540,23 @@ class TypeSystemImpl implements TypeSystem {
15331540
required DartType declaredReturnType,
15341541
required DartType? contextReturnType,
15351542
ErrorReporter? errorReporter,
1543+
InferenceErrorListener? inferenceErrorListener,
15361544
AstNode? errorNode,
15371545
required bool genericMetadataIsEnabled,
15381546
bool isConst = false}) {
15391547
// Create a GenericInferrer that will allow certain type parameters to be
15401548
// inferred. It will optimistically assume these type parameters can be
15411549
// subtypes (or supertypes) as necessary, and track the constraints that
15421550
// are implied by this.
1551+
if (errorReporter != null) {
1552+
inferenceErrorListener ??= InferenceErrorReporter(
1553+
errorReporter,
1554+
isNonNullableByDefault: isNonNullableByDefault,
1555+
isGenericMetadataEnabled: genericMetadataIsEnabled,
1556+
);
1557+
}
15431558
var inferrer = GenericInferrer(this, typeParameters,
1544-
errorReporter: errorReporter,
1559+
inferenceErrorListener: inferenceErrorListener,
15451560
errorNode: errorNode,
15461561
genericMetadataIsEnabled: genericMetadataIsEnabled);
15471562

0 commit comments

Comments
 (0)