From 6f6797e74527545e9bdd74950592589cebf47a72 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Fri, 7 Feb 2020 21:38:06 +0000 Subject: [PATCH] Add NullSafetyUnderstandingFlag, update APIs to use it. DartType.== implementations ignore nullability if the flag is not true. TypeSystem APIs eliminate nullability from types before doing anything. Internally analyzer continues using actual nullability for types. Package nnbd_migration opted into NullSafetyUnderstandingFlag. Bug: https://github.com/dart-lang/sdk/issues/40500 Change-Id: Ifeea28c01adf1dc59ed2da675b4a62c6334d529a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134865 Reviewed-by: Paul Berry Commit-Queue: Konstantin Shcheglov --- pkg/analyzer/lib/dart/element/element.dart | 8 ++ .../null_safety_understanding_flag.dart | 44 +++++++ .../lib/src/dart/analysis/driver.dart | 49 +++++--- .../lib/src/dart/constant/evaluation.dart | 12 +- pkg/analyzer/lib/src/dart/constant/value.dart | 4 +- .../lib/src/dart/element/element.dart | 14 +++ .../lib/src/dart/element/top_merge.dart | 4 +- pkg/analyzer/lib/src/dart/element/type.dart | 57 +++++---- .../assignment_expression_resolver.dart | 2 +- .../resolver/extension_member_resolver.dart | 6 +- .../dart/resolver/flow_analysis_visitor.dart | 2 +- .../resolver/postfix_expression_resolver.dart | 2 +- .../resolver/prefix_expression_resolver.dart | 2 +- .../dart/resolver/typed_literal_resolver.dart | 16 +-- .../src/error/best_practices_verifier.dart | 8 +- .../src/error/bool_expression_verifier.dart | 2 +- .../lib/src/error/correct_override.dart | 8 +- .../lib/src/error/dead_code_verifier.dart | 2 +- .../error/getter_setter_types_verifier.dart | 4 +- .../src/error/literal_element_verifier.dart | 12 +- .../src/error/type_arguments_verifier.dart | 6 +- .../lib/src/generated/error_verifier.dart | 24 ++-- .../lib/src/generated/ffi_verifier.dart | 8 +- pkg/analyzer/lib/src/generated/resolver.dart | 2 +- .../src/generated/static_type_analyzer.dart | 4 +- .../lib/src/generated/type_system.dart | 113 +++++++++++------- pkg/analyzer/lib/src/task/strong/checker.dart | 14 +-- .../test/generated/type_system_test.dart | 4 +- .../id_tests/assigned_variables_test.dart | 17 +-- pkg/analyzer/test/id_tests/constant_test.dart | 17 +-- .../id_tests/definite_assignment_test.dart | 17 +-- .../test/id_tests/nullability_test.dart | 17 +-- .../test/id_tests/reachability_test.dart | 17 +-- .../test/id_tests/type_promotion_test.dart | 17 +-- .../test/src/dart/element/subtype_test.dart | 12 +- .../element/type_parameter_element_test.dart | 69 +++++++---- pkg/nnbd_migration/lib/src/edge_builder.dart | 3 +- pkg/nnbd_migration/lib/src/fix_builder.dart | 11 +- 38 files changed, 398 insertions(+), 232 deletions(-) create mode 100644 pkg/analyzer/lib/dart/element/null_safety_understanding_flag.dart diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart index 38c46a8f01bf..76ae5b2002f2 100644 --- a/pkg/analyzer/lib/dart/element/element.dart +++ b/pkg/analyzer/lib/dart/element/element.dart @@ -1374,6 +1374,14 @@ abstract class LibraryElement implements Element { /// Return the class defined in this library that has the given [name], or /// `null` if this library does not define a class with the given name. ClassElement getType(String className); + + /// If a legacy library, return the legacy view on the [element]. + /// Otherwise, return the original element. + T toLegacyElementIfOptOut(T element); + + /// If a legacy library, return the legacy version of the [type]. + /// Otherwise, return the original type. + DartType toLegacyTypeIfOptOut(DartType type); } /// An element that can be (but is not required to be) defined within a method diff --git a/pkg/analyzer/lib/dart/element/null_safety_understanding_flag.dart b/pkg/analyzer/lib/dart/element/null_safety_understanding_flag.dart new file mode 100644 index 000000000000..9ddfd9c43507 --- /dev/null +++ b/pkg/analyzer/lib/dart/element/null_safety_understanding_flag.dart @@ -0,0 +1,44 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/type.dart'; + +/// Every [DartType] has the nullability suffix, elements declared in legacy +/// libraries have types with star suffixes, and types in migrated libraries +/// have none, question mark, or star suffixes. Analyzer itself can handle +/// mixtures of nullabilities with legacy and migrated libraries. +/// +/// However analyzer clients saw only star suffixes so far. Exposing other +/// nullabilities is a breaking change, because types types with different +/// nullabilities are not equal, `null` cannot be used where a non-nullable +/// type is expected, etc. When accessing elements and types that come from +/// migrated libraries, while analyzing a legacy library, nullabilities must +/// be erased, using [LibraryElement.toLegacyElementIfOptOut] and +/// [LibraryElement.toLegacyTypeIfOptOut]. The client must explicitly do +/// this, and explicitly specify that it knows how to handle nullabilities +/// by setting this flag to `true`. +/// +/// When this flag is `false` (by default), all types will return their +/// nullability as star. So, type equality and subtype checks will work +/// as they worked before some libraries migrated. Note, that during +/// analysis (building element models, and resolving ASTs), analyzer will use +/// actual nullabilities, according to the language specification, so report +/// all corresponding errors, and perform necessary type operations. It is +/// only when the client later views on the types, they will look as legacy. +class NullSafetyUnderstandingFlag { + static final _zoneKey = Object(); + + static bool get isEnabled { + return Zone.current[_zoneKey] ?? false; + } + + /// Code that understands nullability should be run using this method, + /// otherwise all type operations will treat all nullabilities as star. + static R enableNullSafetyTypes(R body()) { + return runZoned(body, zoneValues: {_zoneKey: true}); + } +} diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart index d94e3f827c1f..07c0df6957c4 100644 --- a/pkg/analyzer/lib/src/dart/analysis/driver.dart +++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart @@ -11,6 +11,7 @@ import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart' show LibraryElement; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/exception/exception.dart'; @@ -1216,6 +1217,21 @@ class AnalysisDriver implements AnalysisDriverGeneric { {bool withUnit = false, bool asIsIfPartWithoutLibrary = false, bool skipIfSameSignature = false}) { + return NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + return _computeAnalysisResult2( + path, + withUnit: withUnit, + asIsIfPartWithoutLibrary: asIsIfPartWithoutLibrary, + skipIfSameSignature: skipIfSameSignature, + ); + }); + } + + /// Unwrapped implementation of [_computeAnalysisResult]. + AnalysisResult _computeAnalysisResult2(String path, + {bool withUnit = false, + bool asIsIfPartWithoutLibrary = false, + bool skipIfSameSignature = false}) { FileState file = _fsState.getFileForPath(path); // Prepare the library - the file itself, or the known library. @@ -1476,21 +1492,24 @@ class AnalysisDriver implements AnalysisDriverGeneric { } } - if (_libraryContext == null) { - _libraryContext = LibraryContext( - session: currentSession, - logger: _logger, - fsState: fsState, - byteStore: _byteStore, - analysisOptions: _analysisOptions, - declaredVariables: declaredVariables, - sourceFactory: _sourceFactory, - externalSummaries: _externalSummaries, - targetLibrary: library, - ); - } else { - _libraryContext.load2(library); - } + NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + if (_libraryContext == null) { + _libraryContext = LibraryContext( + session: currentSession, + logger: _logger, + fsState: fsState, + byteStore: _byteStore, + analysisOptions: _analysisOptions, + declaredVariables: declaredVariables, + sourceFactory: _sourceFactory, + externalSummaries: _externalSummaries, + targetLibrary: library, + ); + } else { + _libraryContext.load2(library); + } + }); + return _libraryContext; } diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart index f1f8be10fb8b..6512d668b573 100644 --- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart +++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart @@ -67,7 +67,7 @@ class ConstantEvaluationEngine { /// The type system. This is used to guess the types of constants when their /// exact value is unknown. - final TypeSystem typeSystem; + final TypeSystemImpl typeSystem; /// The helper for evaluating variables declared on the command line /// using '-D', and represented as [DeclaredVariables]. @@ -109,7 +109,7 @@ class ConstantEvaluationEngine { } bool get _isNonNullableByDefault { - return (typeSystem as TypeSystemImpl).isNonNullableByDefault; + return typeSystem.isNonNullableByDefault; } DartObjectImpl get _nullObject { @@ -937,7 +937,7 @@ class ConstantEvaluationEngine { return true; } var objType = obj.type; - return typeSystem.isSubtypeOf(objType, type); + return typeSystem.isSubtypeOf2(objType, type); } /// Determine whether the given string is a valid name for a public symbol @@ -1039,7 +1039,7 @@ class ConstantVisitor extends UnifyingAstVisitor { ExperimentStatus get experimentStatus => evaluationEngine.experimentStatus; /// Convenience getter to gain access to the [evaluationEngine]'s type system. - TypeSystem get typeSystem => evaluationEngine.typeSystem; + TypeSystemImpl get typeSystem => evaluationEngine.typeSystem; /// Convenience getter to gain access to the [evaluationEngine]'s type /// provider. @@ -1211,7 +1211,7 @@ class ConstantVisitor extends UnifyingAstVisitor { ParameterizedType elseType = elseResult.type; return DartObjectImpl.validWithUnknownValue( typeSystem, - typeSystem.leastUpperBound(thenType, elseType) as ParameterizedType, + typeSystem.getLeastUpperBound(thenType, elseType) as ParameterizedType, ); } @@ -1672,7 +1672,7 @@ class ConstantVisitor extends UnifyingAstVisitor { // TODO(brianwilkerson) Figure out why the static type is sometimes null. DartType staticType = condition.staticType; if (staticType == null || - typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) { + typeSystem.isAssignableTo2(staticType, _typeProvider.boolType)) { // If the static type is not assignable, then we will have already // reported this error. // TODO(mfairhurst) get the FeatureSet to suppress this for nnbd too. diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart index 726e1eadcf09..c032be14b34b 100644 --- a/pkg/analyzer/lib/src/dart/constant/value.dart +++ b/pkg/analyzer/lib/src/dart/constant/value.dart @@ -262,7 +262,7 @@ class DartObjectImpl implements DartObject { if (isNull) { return this; } - if (!typeSystem.isSubtypeOf(type, (castType._state as TypeState)._type)) { + if (!typeSystem.isSubtypeOf2(type, (castType._state as TypeState)._type)) { throw EvaluationException( CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION); } @@ -478,7 +478,7 @@ class DartObjectImpl implements DartObject { state = BoolState.FALSE_STATE; } } else { - state = BoolState.from(typeSystem.isSubtypeOf(type, typeType)); + state = BoolState.from(typeSystem.isSubtypeOf2(type, typeType)); } return DartObjectImpl(typeSystem, typeSystem.typeProvider.boolType, state); } diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index f17b1bee7e4f..dfb9c924c048 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -16,6 +16,8 @@ import 'package:analyzer/src/dart/constant/compute.dart'; import 'package:analyzer/src/dart/constant/evaluation.dart'; import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/src/dart/element/display_string_builder.dart'; +import 'package:analyzer/src/dart/element/member.dart'; +import 'package:analyzer/src/dart/element/nullability_eliminator.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/element/type_algebra.dart'; import 'package:analyzer/src/dart/element/type_provider.dart'; @@ -5662,6 +5664,18 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { BooleanArray.set(_resolutionCapabilities, capability.index, value); } + @override + T toLegacyElementIfOptOut(T element) { + if (isNonNullableByDefault) return element; + return Member.legacy(element); + } + + @override + DartType toLegacyTypeIfOptOut(DartType type) { + if (isNonNullableByDefault) return type; + return NullabilityEliminator.perform(typeProvider, type); + } + @override void visitChildren(ElementVisitor visitor) { super.visitChildren(visitor); diff --git a/pkg/analyzer/lib/src/dart/element/top_merge.dart b/pkg/analyzer/lib/src/dart/element/top_merge.dart index 147e00b12584..334b6c2139a5 100644 --- a/pkg/analyzer/lib/src/dart/element/top_merge.dart +++ b/pkg/analyzer/lib/src/dart/element/top_merge.dart @@ -236,8 +236,8 @@ class TopMergeHelper { if (R_isCovariant) { var T1 = T_parameter.type; var T2 = S_parameter.type; - var T1_isSubtype = typeSystem.isSubtypeOf(T1, T2); - var T2_isSubtype = typeSystem.isSubtypeOf(T2, T1); + var T1_isSubtype = typeSystem.isSubtypeOf2(T1, T2); + var T2_isSubtype = typeSystem.isSubtypeOf2(T2, T1); if (T1_isSubtype && T2_isSubtype) { // if `T1 <: T2` and `T2 <: T1`, then the result is // `NNBD_TOP_MERGE(T1, T2)`, and it is covariant. diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart index d240f68e5de4..27174ba250e0 100644 --- a/pkg/analyzer/lib/src/dart/element/type.dart +++ b/pkg/analyzer/lib/src/dart/element/type.dart @@ -6,6 +6,7 @@ import 'dart:collection'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type_provider.dart'; @@ -241,9 +242,19 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { List get typeParameters => const [] /*TODO(paulberry)*/; @override - bool operator ==(Object object) { - if (object is FunctionTypeImpl) { - if (typeFormals.length != object.typeFormals.length) { + bool operator ==(Object other) { + if (identical(other, this)) { + return true; + } + + if (other is FunctionTypeImpl) { + if (NullSafetyUnderstandingFlag.isEnabled) { + if (other.nullabilitySuffix != nullabilitySuffix) { + return false; + } + } + + if (other.typeFormals.length != typeFormals.length) { return false; } // `T -> T` should be equal to `U -> U` @@ -251,17 +262,15 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { // variables, and see if the result is equal. if (typeFormals.isNotEmpty) { List freshVariables = FunctionTypeImpl.relateTypeFormals( - this, object, (t, s, _, __) => t == s); + this, other, (t, s, _, __) => t == s); if (freshVariables == null) { return false; } - return instantiate(freshVariables) == - object.instantiate(freshVariables); + return instantiate(freshVariables) == other.instantiate(freshVariables); } - return returnType == object.returnType && - _equalParameters(parameters, object.parameters) && - nullabilitySuffix == object.nullabilitySuffix; + return other.returnType == returnType && + _equalParameters(other.parameters, parameters); } return false; } @@ -930,14 +939,18 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { (element.library.session as AnalysisSessionImpl).inheritanceManager; @override - bool operator ==(Object object) { - if (identical(object, this)) { + bool operator ==(Object other) { + if (identical(other, this)) { return true; } - if (object is InterfaceTypeImpl) { - return element == object.element && - TypeImpl.equalArrays(typeArguments, object.typeArguments) && - nullabilitySuffix == object.nullabilitySuffix; + if (other is InterfaceTypeImpl) { + if (NullSafetyUnderstandingFlag.isEnabled) { + if (other.nullabilitySuffix != nullabilitySuffix) { + return false; + } + } + return other.element == element && + TypeImpl.equalArrays(other.typeArguments, typeArguments); } return false; } @@ -1553,7 +1566,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { for (DartType type in types) { // If any existing type in the bucket is more specific than this type, // then we can ignore this type. - if (bucket.any((DartType t) => typeSystem.isSubtypeOf(t, type))) { + if (bucket.any((DartType t) => typeSystem.isSubtypeOf2(t, type))) { continue; } // Otherwise, we need to add this type to the bucket and remove any types @@ -1561,7 +1574,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { bool added = false; int i = 0; while (i < bucket.length) { - if (typeSystem.isSubtypeOf(type, bucket[i])) { + if (typeSystem.isSubtypeOf2(type, bucket[i])) { if (added) { if (i < bucket.length - 1) { bucket[i] = bucket.removeLast(); @@ -2057,9 +2070,13 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { return true; } - if (other is TypeParameterTypeImpl && - other.nullabilitySuffix == nullabilitySuffix && - other.element == element) { + if (other is TypeParameterTypeImpl && other.element == element) { + if (NullSafetyUnderstandingFlag.isEnabled) { + if (other.nullabilitySuffix != nullabilitySuffix) { + return false; + } + } + // If the same declaration, or the same promoted element. if (identical(other.element, element)) { return true; diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart index 56a67ea63fbb..098854cfff63 100644 --- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart @@ -293,7 +293,7 @@ class AssignmentExpressionResolver { _inferenceHelper.recordStaticType(node, type); var leftWriteType = _getStaticType2(node.leftHandSide); - if (!_typeSystem.isAssignableTo(type, leftWriteType)) { + if (!_typeSystem.isAssignableTo2(type, leftWriteType)) { _resolver.errorReporter.reportErrorForNode( StaticTypeWarningCode.INVALID_ASSIGNMENT, node.rightHandSide, diff --git a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart index a1cc73aa7d96..fd2751188157 100644 --- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart @@ -153,7 +153,7 @@ class ExtensionMemberResolver { if (receiverType.isVoid) { _errorReporter.reportErrorForNode( StaticWarningCode.USE_OF_VOID_RESULT, receiverExpression); - } else if (!_typeSystem.isAssignableTo(receiverType, node.extendedType)) { + } else if (!_typeSystem.isAssignableTo2(receiverType, node.extendedType)) { _errorReporter.reportErrorForNode( CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE, receiverExpression, @@ -212,7 +212,7 @@ class ExtensionMemberResolver { var boundType = typeParameters[i].bound; if (boundType != null) { boundType = substitution.substituteType(boundType); - if (!_typeSystem.isSubtypeOf(argType, boundType)) { + if (!_typeSystem.isSubtypeOf2(argType, boundType)) { _errorReporter.reportErrorForNode( CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, typeArgumentList.arguments[i], @@ -429,7 +429,7 @@ class ExtensionMemberResolver { /// Ask the type system for a subtype check. bool _isSubtypeOf(DartType type1, DartType type2) => - _typeSystem.isSubtypeOf(type1, type2); + _typeSystem.isSubtypeOf2(type1, type2); List _listOfDynamic(List parameters) { return List.filled(parameters.length, _dynamicType); diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart index f68266723c8d..f51e9a18891e 100644 --- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart +++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart @@ -317,7 +317,7 @@ class TypeSystemTypeOperations @override bool isSubtypeOf(DartType leftType, DartType rightType) { - return typeSystem.isSubtypeOf(leftType, rightType); + return typeSystem.isSubtypeOf2(leftType, rightType); } @override diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart index 687889f1851b..0d5cb0031cb8 100644 --- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart @@ -71,7 +71,7 @@ class PostfixExpressionResolver { void _checkForInvalidAssignmentIncDec( AstNode node, Expression operand, DartType type) { var operandWriteType = _getWriteType(operand); - if (!_typeSystem.isAssignableTo(type, operandWriteType)) { + if (!_typeSystem.isAssignableTo2(type, operandWriteType)) { _resolver.errorReporter.reportErrorForNode( StaticTypeWarningCode.INVALID_ASSIGNMENT, node, diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart index d985231bf9f2..46e6e2897efd 100644 --- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart @@ -71,7 +71,7 @@ class PrefixExpressionResolver { void _checkForInvalidAssignmentIncDec( AstNode node, Expression operand, DartType type) { var operandWriteType = _getStaticType(operand); - if (!_typeSystem.isAssignableTo(type, operandWriteType)) { + if (!_typeSystem.isAssignableTo2(type, operandWriteType)) { _resolver.errorReporter.reportErrorForNode( StaticTypeWarningCode.INVALID_ASSIGNMENT, node, diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart index 52817e664367..238602d6677f 100644 --- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart @@ -168,7 +168,7 @@ class TypedLiteralResolver { } var elseType = _computeElementType(elseElement); - return _typeSystem.leastUpperBound(thenType, elseType); + return _typeSystem.getLeastUpperBound(thenType, elseType); } else if (element is MapLiteralEntry) { // This error will be reported elsewhere. return _typeProvider.dynamicType; @@ -271,9 +271,9 @@ class TypedLiteralResolver { DartType unwrappedContextType = unwrap(contextType); // TODO(brianwilkerson) Find out what the "greatest closure" is and use that // where [unwrappedContextType] is used below. - bool isIterable = _typeSystem.isSubtypeOf( + bool isIterable = _typeSystem.isSubtypeOf2( unwrappedContextType, _typeProvider.iterableForSetMapDisambiguation); - bool isMap = _typeSystem.isSubtypeOf( + bool isMap = _typeSystem.isSubtypeOf2( unwrappedContextType, _typeProvider.mapForSetMapDisambiguation); if (isIterable && !isMap) { return _LiteralResolution( @@ -332,7 +332,7 @@ class TypedLiteralResolver { DartType expressionType = element.expression.staticType; bool isNull = expressionType.isDartCoreNull; if (!isNull && expressionType is InterfaceType) { - if (_typeSystem.isSubtypeOf( + if (_typeSystem.isSubtypeOf2( expressionType, _typeProvider.iterableForSetMapDisambiguation)) { InterfaceType iterableType = (expressionType as InterfaceTypeImpl) .asInstanceOf(_typeProvider.iterableElement); @@ -340,7 +340,7 @@ class TypedLiteralResolver { elementType: iterableType.typeArguments[0], keyType: null, valueType: null); - } else if (_typeSystem.isSubtypeOf( + } else if (_typeSystem.isSubtypeOf2( expressionType, _typeProvider.mapForSetMapDisambiguation)) { InterfaceType mapType = (expressionType as InterfaceTypeImpl) .asInstanceOf(_typeProvider.mapElement); @@ -475,10 +475,10 @@ class TypedLiteralResolver { bool contextProvidesAmbiguityResolutionClues = contextType != null && contextType is! UnknownInferredType; bool contextIsIterable = contextProvidesAmbiguityResolutionClues && - _typeSystem.isSubtypeOf( + _typeSystem.isSubtypeOf2( contextType, _typeProvider.iterableForSetMapDisambiguation); bool contextIsMap = contextProvidesAmbiguityResolutionClues && - _typeSystem.isSubtypeOf( + _typeSystem.isSubtypeOf2( contextType, _typeProvider.mapForSetMapDisambiguation); if (contextIsIterable && !contextIsMap) { return _toSetType(literal, contextType, inferredTypes); @@ -830,7 +830,7 @@ class _InferredCollectionElementTypeInformation { } else if (second == null) { return first; } else { - return typeSystem.leastUpperBound(first, second); + return typeSystem.getLeastUpperBound(first, second); } } } diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart index cfd68d6339aa..e568a7fed179 100644 --- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart +++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart @@ -1305,7 +1305,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor { /// /// Returns `true` if and only if an unnecessary cast hint should be generated /// on [node]. See [HintCode.UNNECESSARY_CAST]. - static bool isUnnecessaryCast(AsExpression node, TypeSystem typeSystem) { + static bool isUnnecessaryCast(AsExpression node, TypeSystemImpl typeSystem) { // TODO(jwren) After dartbug.com/13732, revisit this, we should be able to // remove the (x is! TypeParameterType) checks. AstNode parent = node.parent; @@ -1329,8 +1329,8 @@ class BestPracticesVerifier extends RecursiveAstVisitor { elseType != null && !thenType.isDynamic && !elseType.isDynamic && - !typeSystem.isSubtypeOf(thenType, elseType) && - !typeSystem.isSubtypeOf(elseType, thenType)) { + !typeSystem.isSubtypeOf2(thenType, elseType) && + !typeSystem.isSubtypeOf2(elseType, thenType)) { return false; } } @@ -1340,7 +1340,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor { rhsType != null && !lhsType.isDynamic && !rhsType.isDynamic && - typeSystem.isSubtypeOf(lhsType, rhsType)) { + typeSystem.isSubtypeOf2(lhsType, rhsType)) { return true; } return false; diff --git a/pkg/analyzer/lib/src/error/bool_expression_verifier.dart b/pkg/analyzer/lib/src/error/bool_expression_verifier.dart index 3f626bdba889..0acc357e7386 100644 --- a/pkg/analyzer/lib/src/error/bool_expression_verifier.dart +++ b/pkg/analyzer/lib/src/error/bool_expression_verifier.dart @@ -49,7 +49,7 @@ class BoolExpressionVerifier { {@required ErrorCode errorCode, List arguments}) { var type = expression.staticType; if (!_checkForUseOfVoidResult(expression) && - !_typeSystem.isAssignableTo(type, _boolType)) { + !_typeSystem.isAssignableTo2(type, _boolType)) { if (type.element == _boolElement) { _nullableDereferenceVerifier.report(expression, type); } else { diff --git a/pkg/analyzer/lib/src/error/correct_override.dart b/pkg/analyzer/lib/src/error/correct_override.dart index 7e0a016ec55b..f88bc43aad7f 100644 --- a/pkg/analyzer/lib/src/error/correct_override.dart +++ b/pkg/analyzer/lib/src/error/correct_override.dart @@ -38,7 +38,7 @@ class CorrectOverrideHelper { @required ExecutableElement superMember, }) { var superType = superMember.type; - if (!_typeSystem.isSubtypeOf(_thisTypeForSubtype, superType)) { + if (!_typeSystem.isSubtypeOf2(_thisTypeForSubtype, superType)) { return false; } @@ -71,8 +71,10 @@ class CorrectOverrideHelper { ); } - if (!_typeSystem.isSubtypeOf(superParameterType, thisParameterType) && - !_typeSystem.isSubtypeOf(thisParameterType, superParameterType)) { + if (!_typeSystem.isSubtypeOf2( + superParameterType, thisParameterType) && + !_typeSystem.isSubtypeOf2( + thisParameterType, superParameterType)) { return false; } } diff --git a/pkg/analyzer/lib/src/error/dead_code_verifier.dart b/pkg/analyzer/lib/src/error/dead_code_verifier.dart index 98834a125751..40d859f7f36b 100644 --- a/pkg/analyzer/lib/src/error/dead_code_verifier.dart +++ b/pkg/analyzer/lib/src/error/dead_code_verifier.dart @@ -315,7 +315,7 @@ class DeadCodeVerifier extends RecursiveAstVisitor { int length = visitedTypes.length; for (int j = 0; j < length; j++) { DartType type = visitedTypes[j]; - if (_typeSystem.isSubtypeOf(currentType, type)) { + if (_typeSystem.isSubtypeOf2(currentType, type)) { CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; int offset = catchClause.offset; int length = lastCatchClause.end - offset; diff --git a/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart b/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart index c9287f40bd7b..c21040b6da0d 100644 --- a/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart +++ b/pkg/analyzer/lib/src/error/getter_setter_types_verifier.dart @@ -115,8 +115,8 @@ class GetterSetterTypesVerifier { bool _match(DartType getterType, DartType setterType) { return _isNonNullableByDefault - ? _typeSystem.isSubtypeOf(getterType, setterType) - : _typeSystem.isAssignableTo(getterType, setterType); + ? _typeSystem.isSubtypeOf2(getterType, setterType) + : _typeSystem.isAssignableTo2(getterType, setterType); } /// Return the return type of the [getter]. diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart index 96f1ba6785d2..d6090cca6497 100644 --- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart +++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart @@ -48,7 +48,7 @@ class LiteralElementVerifier { /// Check that the given [type] is assignable to the [elementType], otherwise /// report the list or set error on the [errorNode]. void _checkAssignableToElementType(DartType type, AstNode errorNode) { - if (!typeSystem.isAssignableTo(type, elementType)) { + if (!typeSystem.isAssignableTo2(type, elementType)) { var errorCode = forList ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE; @@ -108,7 +108,7 @@ class LiteralElementVerifier { } var keyType = entry.key.staticType; - if (!typeSystem.isAssignableTo(keyType, mapKeyType)) { + if (!typeSystem.isAssignableTo2(keyType, mapKeyType)) { errorReporter.reportErrorForNode( StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, entry.key, @@ -117,7 +117,7 @@ class LiteralElementVerifier { } var valueType = entry.value.staticType; - if (!typeSystem.isAssignableTo(valueType, mapValueType)) { + if (!typeSystem.isAssignableTo2(valueType, mapValueType)) { errorReporter.reportErrorForNode( StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, entry.value, @@ -155,7 +155,7 @@ class LiteralElementVerifier { } var iterableElementType = iterableType.typeArguments[0]; - if (!typeSystem.isAssignableTo(iterableElementType, elementType)) { + if (!typeSystem.isAssignableTo2(iterableElementType, elementType)) { var errorCode = forList ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE; @@ -196,7 +196,7 @@ class LiteralElementVerifier { } var keyType = mapType.typeArguments[0]; - if (!typeSystem.isAssignableTo(keyType, mapKeyType)) { + if (!typeSystem.isAssignableTo2(keyType, mapKeyType)) { errorReporter.reportErrorForNode( StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, expression, @@ -205,7 +205,7 @@ class LiteralElementVerifier { } var valueType = mapType.typeArguments[1]; - if (!typeSystem.isAssignableTo(valueType, mapValueType)) { + if (!typeSystem.isAssignableTo2(valueType, mapValueType)) { errorReporter.reportErrorForNode( StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, expression, diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart index dd84cbeedd5a..f9c86d9bf15b 100644 --- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart +++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart @@ -228,12 +228,12 @@ class TypeArgumentsVerifier { .substituteType(boundType); } - if (!_typeSystem.isSubtypeOf(argType, boundType)) { + if (!_typeSystem.isSubtypeOf2(argType, boundType)) { if (_shouldAllowSuperBoundedTypes(typeName)) { var replacedType = (argType as TypeImpl).replaceTopAndBottom(_typeProvider); if (!identical(replacedType, argType) && - _typeSystem.isSubtypeOf(replacedType, boundType)) { + _typeSystem.isSubtypeOf2(replacedType, boundType)) { // Bound is satisfied under super-bounded rules, so we're ok. continue; } @@ -329,7 +329,7 @@ class TypeArgumentsVerifier { var substitution = Substitution.fromPairs(fnTypeParams, typeArgs); var bound = substitution.substituteType(rawBound); - if (!_typeSystem.isSubtypeOf(argType, bound)) { + if (!_typeSystem.isSubtypeOf2(argType, bound)) { _errorReporter.reportErrorForNode( CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, typeArgumentList[i], diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 96a296512cd4..d5cfa1951879 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart @@ -1485,14 +1485,14 @@ class ErrorVerifier extends RecursiveAstVisitor { // Report specific problem when return type is incompatible FunctionType constructorType = declaration.declaredElement.type; DartType constructorReturnType = constructorType.returnType; - if (!_typeSystem.isAssignableTo( + if (!_typeSystem.isAssignableTo2( redirectedReturnType, constructorReturnType)) { _errorReporter.reportErrorForNode( StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE, redirectedConstructor, [redirectedReturnType, constructorReturnType]); return; - } else if (!_typeSystem.isSubtypeOf(redirectedType, constructorType)) { + } else if (!_typeSystem.isSubtypeOf2(redirectedType, constructorType)) { // Check parameters. _errorReporter.reportErrorForNode( StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE, @@ -1702,7 +1702,7 @@ class ErrorVerifier extends RecursiveAstVisitor { DartType actualStaticType, DartType expectedStaticType, ErrorCode errorCode) { - if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) { + if (!_typeSystem.isAssignableTo2(actualStaticType, expectedStaticType)) { _errorReporter.reportErrorForNode( errorCode, expression, [actualStaticType, expectedStaticType]); return false; @@ -2448,7 +2448,7 @@ class ErrorVerifier extends RecursiveAstVisitor { StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, node.iterable, [iterableType, loopTypeName]); - } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) { + } else if (!_typeSystem.isAssignableTo2(bestIterableType, variableType)) { _errorReporter.reportErrorForNode( StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, node.iterable, @@ -2666,7 +2666,7 @@ class ErrorVerifier extends RecursiveAstVisitor { if (staticType == null) { return; } - if (_typeSystem.isAssignableTo(staticType, fieldType)) { + if (_typeSystem.isAssignableTo2(staticType, fieldType)) { return; } // report problem @@ -2881,7 +2881,7 @@ class ErrorVerifier extends RecursiveAstVisitor { typeArguments: [NeverTypeImpl.instance], nullabilitySuffix: NullabilitySuffix.star, ); - if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) { + if (!_typeSystem.isSubtypeOf2(lowerBound, returnType)) { _errorReporter.reportErrorForNode(errorCode, returnTypeName); } } @@ -3522,11 +3522,11 @@ class ErrorVerifier extends RecursiveAstVisitor { superType = superType.withNullability(NullabilitySuffix.none); } - bool isSatisfied = _typeSystem.isSubtypeOf(superType, constraint); + bool isSatisfied = _typeSystem.isSubtypeOf2(superType, constraint); if (!isSatisfied) { for (int i = 0; i < mixinIndex && !isSatisfied; i++) { isSatisfied = - _typeSystem.isSubtypeOf(_enclosingClass.mixins[i], constraint); + _typeSystem.isSubtypeOf2(_enclosingClass.mixins[i], constraint); } } if (!isSatisfied) { @@ -4375,7 +4375,7 @@ class ErrorVerifier extends RecursiveAstVisitor { if (!expectedType.isVoid && !fromType.isVoid) { var checkWithType = !_inAsync ? fromType : _typeProvider.futureType2(fromType); - if (_typeSystem.isAssignableTo(checkWithType, expectedType)) { + if (_typeSystem.isAssignableTo2(checkWithType, expectedType)) { return; } } @@ -4480,7 +4480,7 @@ class ErrorVerifier extends RecursiveAstVisitor { DartType caseType = getStaticType(caseExpression); // check types - if (!_typeSystem.isAssignableTo(expressionType, caseType)) { + if (!_typeSystem.isAssignableTo2(expressionType, caseType)) { _errorReporter.reportErrorForNode( StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE, expression, @@ -4779,7 +4779,7 @@ class ErrorVerifier extends RecursiveAstVisitor { [parameter.identifier.name]); } else if (declaredType != null && fieldType != null && - !_typeSystem.isAssignableTo(declaredType, fieldType)) { + !_typeSystem.isAssignableTo2(declaredType, fieldType)) { _errorReporter.reportErrorForNode( StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, parameter, @@ -5075,7 +5075,7 @@ class ErrorVerifier extends RecursiveAstVisitor { } else { requiredReturnType = _typeProvider.iterableDynamicType; } - if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType)) { + if (!_typeSystem.isAssignableTo2(impliedReturnType, requiredReturnType)) { _errorReporter.reportErrorForNode( StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, yieldExpression, diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart index 92686aa6c1f9..70b6e5af3551 100644 --- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart +++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart @@ -6,9 +6,9 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/dart/element/type_system.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/dart/error/ffi_code.dart'; +import 'package:analyzer/src/generated/type_system.dart'; /// A visitor used to find problems with the way the `dart:ffi` APIs are being /// used. See 'pkg/vm/lib/transformations/ffi_checks.md' for the specification @@ -32,7 +32,7 @@ class FfiVerifier extends RecursiveAstVisitor { ]; /// The type system used to check types. - final TypeSystem typeSystem; + final TypeSystemImpl typeSystem; /// The error reporter used to report errors. final ErrorReporter _errorReporter; @@ -441,8 +441,8 @@ class FfiVerifier extends RecursiveAstVisitor { return dartType.isVoid; } else if (dartType is InterfaceType && nativeType is InterfaceType) { return checkCovariance - ? typeSystem.isSubtypeOf(dartType, nativeType) - : typeSystem.isSubtypeOf(nativeType, dartType); + ? typeSystem.isSubtypeOf2(dartType, nativeType) + : typeSystem.isSubtypeOf2(nativeType, dartType); } else { // If the [nativeType] is not a primitive int/double type then it has to // be a Pointer type atm. diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index f2b05286a059..418996fe7188 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart @@ -137,7 +137,7 @@ class InferenceContext { context ??= DynamicTypeImpl.instance; inferred ??= DynamicTypeImpl.instance; - if (_typeSystem.isSubtypeOf(inferred, context)) { + if (_typeSystem.isSubtypeOf2(inferred, context)) { setType(node, inferred); } } else { diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart index d9047b946a73..6e8f2ab01cac 100644 --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart @@ -403,8 +403,8 @@ class StaticTypeAnalyzer extends SimpleAstVisitor { var context = InferenceContext.getContext( (node as IntegerLiteralImpl).immediatelyNegated ? node.parent : node); if (context == null || - _typeSystem.isAssignableTo(_typeProvider.intType, context) || - !_typeSystem.isAssignableTo(_typeProvider.doubleType, context)) { + _typeSystem.isAssignableTo2(_typeProvider.intType, context) || + !_typeSystem.isAssignableTo2(_typeProvider.doubleType, context)) { _recordStaticType(node, _nonNullable(_typeProvider.intType)); } else { _recordStaticType(node, _nonNullable(_typeProvider.doubleType)); diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart index 96177bd67c35..1179f06f4220 100644 --- a/pkg/analyzer/lib/src/generated/type_system.dart +++ b/pkg/analyzer/lib/src/generated/type_system.dart @@ -8,6 +8,7 @@ import 'dart:math' as math; import 'package:analyzer/dart/ast/ast.dart' show AstNode, ConstructorName; import 'package:analyzer/dart/ast/token.dart' show Keyword, TokenType; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type_provider.dart'; @@ -272,7 +273,7 @@ class Dart2TypeSystem extends TypeSystem { if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull) { // * Null if Null <: T2 // * Never otherwise - if (isSubtypeOf(nullNone, T2)) { + if (isSubtypeOf2(nullNone, T2)) { return nullNone; } else { return NeverTypeImpl.instance; @@ -283,7 +284,7 @@ class Dart2TypeSystem extends TypeSystem { if (T2_nullability == NullabilitySuffix.none && T2.isDartCoreNull) { // * Null if Null <: T1 // * Never otherwise - if (isSubtypeOf(nullNone, T1)) { + if (isSubtypeOf2(nullNone, T1)) { return nullNone; } else { return NeverTypeImpl.instance; @@ -371,12 +372,12 @@ class Dart2TypeSystem extends TypeSystem { } // DOWN(T1, T2) = T1 if T1 <: T2 - if (isSubtypeOf(T1, T2)) { + if (isSubtypeOf2(T1, T2)) { return T1; } // DOWN(T1, T2) = T2 if T2 <: T1 - if (isSubtypeOf(T2, T1)) { + if (isSubtypeOf2(T2, T1)) { return T2; } @@ -570,11 +571,11 @@ class Dart2TypeSystem extends TypeSystem { // UP(X1 & B1, T2) if (T1 is TypeParameterType) { // T2 if X1 <: T2 - if (isSubtypeOf(T1, T2)) { + if (isSubtypeOf2(T1, T2)) { return T2; } // otherwise X1 if T2 <: X1 - if (isSubtypeOf(T2, T1)) { + if (isSubtypeOf2(T2, T1)) { return T1; } // otherwise UP(B1[Object/X1], T2) @@ -586,12 +587,12 @@ class Dart2TypeSystem extends TypeSystem { // UP(T1, X2 & B2) if (T2 is TypeParameterType) { // X2 if T1 <: X2 - if (isSubtypeOf(T1, T2)) { + if (isSubtypeOf2(T1, T2)) { // TODO(scheglov) How to get here? return T2; } // otherwise T1 if X2 <: T1 - if (isSubtypeOf(T2, T1)) { + if (isSubtypeOf2(T2, T1)) { return T1; } // otherwise UP(T1, B2[Object/X2]) @@ -899,8 +900,16 @@ class Dart2TypeSystem extends TypeSystem { @override bool isAssignableTo(DartType fromType, DartType toType) { + if (!NullSafetyUnderstandingFlag.isEnabled) { + fromType = NullabilityEliminator.perform(typeProvider, fromType); + toType = NullabilityEliminator.perform(typeProvider, toType); + } + return isAssignableTo2(fromType, toType); + } + + bool isAssignableTo2(DartType fromType, DartType toType) { // An actual subtype - if (isSubtypeOf(fromType, toType)) { + if (isSubtypeOf2(fromType, toType)) { return true; } @@ -909,7 +918,7 @@ class Dart2TypeSystem extends TypeSystem { !isNullable(fromType) && acceptsFunctionType(toType)) { var callMethodType = getCallMethodType(fromType); - if (callMethodType != null && isAssignableTo(callMethodType, toType)) { + if (callMethodType != null && isAssignableTo2(callMethodType, toType)) { return true; } } @@ -944,7 +953,7 @@ class Dart2TypeSystem extends TypeSystem { } // If the subtype relation goes the other way, allow the implicit downcast. - if (isSubtypeOf(toType, fromType)) { + if (isSubtypeOf2(toType, fromType)) { // TODO(leafp,jmesserly): we emit warnings/hints for these in // src/task/strong/checker.dart, which is a bit inconsistent. That // code should be handled into places that use isAssignableTo, such as @@ -1078,7 +1087,7 @@ class Dart2TypeSystem extends TypeSystem { } @override - bool isMoreSpecificThan(DartType t1, DartType t2) => isSubtypeOf(t1, t2); + bool isMoreSpecificThan(DartType t1, DartType t2) => isSubtypeOf2(t1, t2); /// Defines a total order on top and Object types. bool isMoreTop(DartType T, DartType S) { @@ -1221,6 +1230,14 @@ class Dart2TypeSystem extends TypeSystem { /// https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md#rules @override bool isSubtypeOf(DartType _T0, DartType _T1) { + if (!NullSafetyUnderstandingFlag.isEnabled) { + _T0 = NullabilityEliminator.perform(typeProvider, _T0); + _T1 = NullabilityEliminator.perform(typeProvider, _T1); + } + return isSubtypeOf2(_T0, _T1); + } + + bool isSubtypeOf2(DartType _T0, DartType _T1) { // Reflexivity: if `T0` and `T1` are the same type then `T0 <: T1`. if (identical(_T0, _T1)) { return true; @@ -1248,7 +1265,7 @@ class Dart2TypeSystem extends TypeSystem { // then `T0 <: T1` if `Object? <: T1`. if (identical(T0, DynamicTypeImpl.instance) || identical(T0, VoidTypeImpl.instance)) { - if (isSubtypeOf(objectQuestion, T1)) { + if (isSubtypeOf2(objectQuestion, T1)) { return true; } } @@ -1269,18 +1286,18 @@ class Dart2TypeSystem extends TypeSystem { if (T0_nullability == NullabilitySuffix.none && T0 is TypeParameterTypeImpl) { var bound = T0.element.bound ?? objectQuestion; - return isSubtypeOf(bound, objectNone); + return isSubtypeOf2(bound, objectNone); } // * if `T0` is `FutureOr` for some `S`, // then `T0 <: T1` iff `S <: Object` if (T0_nullability == NullabilitySuffix.none && T0 is InterfaceTypeImpl && T0.isDartAsyncFutureOr) { - return isSubtypeOf(T0.typeArguments[0], T1); + return isSubtypeOf2(T0.typeArguments[0], T1); } // * if `T0` is `S*` for any `S`, then `T0 <: T1` iff `S <: T1` if (T0_nullability == NullabilitySuffix.star) { - return isSubtypeOf( + return isSubtypeOf2( T0.withNullability(NullabilitySuffix.none), T1, ); @@ -1306,7 +1323,7 @@ class Dart2TypeSystem extends TypeSystem { T1 is InterfaceTypeImpl && T1.isDartAsyncFutureOr) { var S = T1.typeArguments[0]; - return isSubtypeOf(nullNone, S); + return isSubtypeOf2(nullNone, S); } // If `T1` is `Null`, `S?` or `S*` for some `S`, then the query is true. if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull || @@ -1326,14 +1343,14 @@ class Dart2TypeSystem extends TypeSystem { if (T0_nullability == NullabilitySuffix.star) { // * `T0 <: T1` iff `S0 <: T1`. var S0 = T0.withNullability(NullabilitySuffix.none); - return isSubtypeOf(S0, T1); + return isSubtypeOf2(S0, T1); } // Right Legacy `T1` is `S1*` then: // * `T0 <: T1` iff `T0 <: S1?`. if (T1_nullability == NullabilitySuffix.star) { var S1 = T1.withNullability(NullabilitySuffix.question); - return isSubtypeOf(T0, S1); + return isSubtypeOf2(T0, S1); } // Left FutureOr: if `T0` is `FutureOr` then: @@ -1342,12 +1359,12 @@ class Dart2TypeSystem extends TypeSystem { T0.isDartAsyncFutureOr) { var S0 = T0.typeArguments[0]; // * `T0 <: T1` iff `Future <: T1` and `S0 <: T1` - if (isSubtypeOf(S0, T1)) { + if (isSubtypeOf2(S0, T1)) { var FutureS0 = typeProvider.futureElement.instantiate( typeArguments: [S0], nullabilitySuffix: NullabilitySuffix.none, ); - return isSubtypeOf(FutureS0, T1); + return isSubtypeOf2(FutureS0, T1); } return false; } @@ -1356,7 +1373,7 @@ class Dart2TypeSystem extends TypeSystem { // * `T0 <: T1` iff `S0 <: T1` and `Null <: T1`. if (T0_nullability == NullabilitySuffix.question) { var S0 = T0.withNullability(NullabilitySuffix.none); - return isSubtypeOf(S0, T1) && isSubtypeOf(nullNone, T1); + return isSubtypeOf2(S0, T1) && isSubtypeOf2(nullNone, T1); } // Right Promoted Variable: if `T1` is a promoted type variable `X1 & S1`: @@ -1365,14 +1382,14 @@ class Dart2TypeSystem extends TypeSystem { if (T1 is TypeParameterTypeImpl && T0.definition == T1.definition) { var S0 = T0.element.bound ?? objectQuestion; var S1 = T1.element.bound ?? objectQuestion; - if (isSubtypeOf(S0, S1)) { + if (isSubtypeOf2(S0, S1)) { return true; } } var T0_element = T0.element; if (T0_element is TypeParameterMember) { - return isSubtypeOf(T0_element.bound, T1); + return isSubtypeOf2(T0_element.bound, T1); } } @@ -1387,18 +1404,18 @@ class Dart2TypeSystem extends TypeSystem { typeArguments: [S1], nullabilitySuffix: NullabilitySuffix.none, ); - if (isSubtypeOf(T0, FutureS1)) { + if (isSubtypeOf2(T0, FutureS1)) { return true; } // * or `T0 <: S1` - if (isSubtypeOf(T0, S1)) { + if (isSubtypeOf2(T0, S1)) { return true; } // * or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1` // * or `T0` is `X0 & S0` and `S0 <: T1` if (T0 is TypeParameterTypeImpl) { var S0 = T0.element.bound ?? objectQuestion; - if (isSubtypeOf(S0, T1)) { + if (isSubtypeOf2(S0, T1)) { return true; } } @@ -1411,18 +1428,18 @@ class Dart2TypeSystem extends TypeSystem { var S1 = T1.withNullability(NullabilitySuffix.none); // `T0 <: T1` iff any of the following hold: // * either `T0 <: S1` - if (isSubtypeOf(T0, S1)) { + if (isSubtypeOf2(T0, S1)) { return true; } // * or `T0 <: Null` - if (isSubtypeOf(T0, nullNone)) { + if (isSubtypeOf2(T0, nullNone)) { return true; } // or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1` // or `T0` is `X0 & S0` and `S0 <: T1` if (T0 is TypeParameterTypeImpl) { var S0 = T0.element.bound ?? objectQuestion; - return isSubtypeOf(S0, T1); + return isSubtypeOf2(S0, T1); } // iff return false; @@ -1441,7 +1458,7 @@ class Dart2TypeSystem extends TypeSystem { // * and `B0 <: T1` if (T0 is TypeParameterTypeImpl) { var S0 = T0.element.bound ?? objectQuestion; - if (isSubtypeOf(S0, T1)) { + if (isSubtypeOf2(S0, T1)) { return true; } } @@ -1579,13 +1596,13 @@ class Dart2TypeSystem extends TypeSystem { // // This allows the variable to be used wherever the supertype (here `Base`) // is expected, while gaining a more precise type. - if (isSubtypeOf(to, from)) { + if (isSubtypeOf2(to, from)) { return to; } // For a type parameter `T extends U`, allow promoting the upper bound // `U` to `S` where `S <: U`, yielding a type parameter `T extends S`. if (from is TypeParameterType) { - if (isSubtypeOf(to, from.bound ?? DynamicTypeImpl.instance)) { + if (isSubtypeOf2(to, from.bound ?? DynamicTypeImpl.instance)) { var declaration = from.element.declaration; var newElement = TypeParameterMember(declaration, null, to); return newElement.instantiate( @@ -1901,7 +1918,7 @@ class Dart2TypeSystem extends TypeSystem { FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) { // Type parameter bounds are invariant. // TODO(scheglov) We do this for top types, but the spec says explicitly. - return isSubtypeOf(t, s) && isSubtypeOf(s, t); + return isSubtypeOf2(t, s) && isSubtypeOf2(s, t); }); if (freshTypeFormalTypes == null) { return false; @@ -1910,7 +1927,7 @@ class Dart2TypeSystem extends TypeSystem { f = f.instantiate(freshTypeFormalTypes); g = g.instantiate(freshTypeFormalTypes); - if (!isSubtypeOf(f.returnType, g.returnType)) { + if (!isSubtypeOf2(f.returnType, g.returnType)) { return false; } @@ -1924,7 +1941,7 @@ class Dart2TypeSystem extends TypeSystem { var gParameter = gParameters[gIndex]; if (fParameter.isRequiredPositional) { if (gParameter.isRequiredPositional) { - if (isSubtypeOf(gParameter.type, fParameter.type)) { + if (isSubtypeOf2(gParameter.type, fParameter.type)) { fIndex++; gIndex++; } else { @@ -1935,7 +1952,7 @@ class Dart2TypeSystem extends TypeSystem { } } else if (fParameter.isOptionalPositional) { if (gParameter.isPositional) { - if (isSubtypeOf(gParameter.type, fParameter.type)) { + if (isSubtypeOf2(gParameter.type, fParameter.type)) { fIndex++; gIndex++; } else { @@ -1950,7 +1967,7 @@ class Dart2TypeSystem extends TypeSystem { if (compareNames == 0) { if (fParameter.isRequiredNamed && !gParameter.isRequiredNamed) { return false; - } else if (isSubtypeOf(gParameter.type, fParameter.type)) { + } else if (isSubtypeOf2(gParameter.type, fParameter.type)) { fIndex++; gIndex++; } else { @@ -2020,15 +2037,15 @@ class Dart2TypeSystem extends TypeSystem { // variance is added to the interface. Variance variance = (tParams[i] as TypeParameterElementImpl).variance; if (variance.isCovariant) { - if (!isSubtypeOf(t1, t2)) { + if (!isSubtypeOf2(t1, t2)) { return false; } } else if (variance.isContravariant) { - if (!isSubtypeOf(t2, t1)) { + if (!isSubtypeOf2(t2, t1)) { return false; } } else if (variance.isInvariant) { - if (!isSubtypeOf(t1, t2) || !isSubtypeOf(t2, t1)) { + if (!isSubtypeOf2(t1, t2) || !isSubtypeOf2(t2, t1)) { return false; } } else { @@ -3016,10 +3033,10 @@ class InterfaceLeastUpperBoundHelper { type1 = type1.withNullability(NullabilitySuffix.none); type2 = type2.withNullability(NullabilitySuffix.none); - if (typeSystem.isSubtypeOf(type1, type2)) { + if (typeSystem.isSubtypeOf2(type1, type2)) { return type2.withNullability(nullability); } - if (typeSystem.isSubtypeOf(type2, type1)) { + if (typeSystem.isSubtypeOf2(type2, type1)) { return type1.withNullability(nullability); } @@ -3045,8 +3062,8 @@ class InterfaceLeastUpperBoundHelper { args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]); } } else if (parameterVariance.isInvariant) { - if (!typeSystem.isSubtypeOf(args1[i], args2[i]) || - !typeSystem.isSubtypeOf(args2[i], args1[i])) { + if (!typeSystem.isSubtypeOf2(args1[i], args2[i]) || + !typeSystem.isSubtypeOf2(args2[i], args1[i])) { // No bound will be valid, find bound at the interface level. return _computeLeastUpperBound( InstantiatedClass.of(type1), @@ -3471,6 +3488,10 @@ abstract class TypeSystem implements public.TypeSystem { @override DartType leastUpperBound(DartType leftType, DartType rightType) { + if (!NullSafetyUnderstandingFlag.isEnabled) { + leftType = NullabilityEliminator.perform(typeProvider, leftType); + rightType = NullabilityEliminator.perform(typeProvider, rightType); + } return getLeastUpperBound(leftType, rightType); } @@ -3921,7 +3942,7 @@ class _TypeConstraint extends _TypeRange { bool get isDownwards => origin is! _TypeConstraintFromArgument; bool isSatisifedBy(TypeSystemImpl ts, DartType type) => - ts.isSubtypeOf(lowerBound, type) && ts.isSubtypeOf(type, upperBound); + ts.isSubtypeOf2(lowerBound, type) && ts.isSubtypeOf2(type, upperBound); /// Converts this constraint to a message suitable for a type inference error. @override diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart index cf73b01f6364..20a05bf599e6 100644 --- a/pkg/analyzer/lib/src/task/strong/checker.dart +++ b/pkg/analyzer/lib/src/task/strong/checker.dart @@ -354,7 +354,7 @@ class CodeChecker extends RecursiveAstVisitor { var fieldElement = node.identifier.staticElement as FieldFormalParameterElement; var fieldType = _elementType(fieldElement.field); - if (!rules.isSubtypeOf(type, fieldType)) { + if (!rules.isSubtypeOf2(type, fieldType)) { _recordMessage(node, StrongModeCode.INVALID_PARAMETER_DECLARATION, [node, fieldType]); } @@ -682,13 +682,13 @@ class CodeChecker extends RecursiveAstVisitor { return null; // unrelated } - if (rules.isSubtypeOf(from, to)) { + if (rules.isSubtypeOf2(from, to)) { // Sound subtype. // However we may still need cast if we have a call tearoff. return callTearoff; } - if (rules.isSubtypeOf(to, from)) { + if (rules.isSubtypeOf2(to, from)) { // Assignable, but needs cast. return true; } @@ -878,12 +878,12 @@ class CodeChecker extends RecursiveAstVisitor { } // fromT <: toT, no coercion needed. - if (rules.isSubtypeOf(from, to)) { + if (rules.isSubtypeOf2(from, to)) { return false; } // Down cast or legal sideways cast, coercion needed. - if (rules.isAssignableTo(from, to)) { + if (rules.isAssignableTo2(from, to)) { return true; } @@ -916,7 +916,7 @@ class CodeChecker extends RecursiveAstVisitor { // want to warn if it's a legal subtype. if (from is InterfaceType && rules.acceptsFunctionType(to)) { var type = rules.getCallMethodType(from); - if (type != null && rules.isSubtypeOf(type, to)) { + if (type != null && rules.isSubtypeOf2(type, to)) { return; } } @@ -1038,7 +1038,7 @@ class CodeChecker extends RecursiveAstVisitor { nullabilitySuffix: _noneOrStarSuffix, ); - if (rules.isSubtypeOf(sequenceType, iterableType)) { + if (rules.isSubtypeOf2(sequenceType, iterableType)) { _recordImplicitCast(node.iterable, sequenceType, from: iterableType); elementType = DynamicTypeImpl.instance; } diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart index 2901cdde1308..028da1edab3b 100644 --- a/pkg/analyzer/test/generated/type_system_test.dart +++ b/pkg/analyzer/test/generated/type_system_test.dart @@ -384,11 +384,11 @@ class AssignabilityTest extends AbstractTypeSystemTest { } void _checkIsAssignableTo(DartType type1, DartType type2) { - expect(typeSystem.isAssignableTo(type1, type2), true); + expect(typeSystem.isAssignableTo2(type1, type2), true); } void _checkIsNotAssignableTo(DartType type1, DartType type2) { - expect(typeSystem.isAssignableTo(type1, type2), false); + expect(typeSystem.isAssignableTo2(type1, type2), false); } void _checkIsStrictAssignableTo(DartType type1, DartType type2) { diff --git a/pkg/analyzer/test/id_tests/assigned_variables_test.dart b/pkg/analyzer/test/id_tests/assigned_variables_test.dart index 5cdd76bc095f..a46ec06d17c1 100644 --- a/pkg/analyzer/test/id_tests/assigned_variables_test.dart +++ b/pkg/analyzer/test/id_tests/assigned_variables_test.dart @@ -9,6 +9,7 @@ import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id; import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/src/dart/analysis/testing_data.dart'; import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart'; import 'package:analyzer/src/util/ast_data_extractor.dart'; @@ -19,13 +20,15 @@ main(List args) async { Directory dataDir = Directory.fromUri(Platform.script.resolve( '../../../_fe_analyzer_shared/test/flow_analysis/assigned_variables/' 'data')); - await runTests<_Data>(dataDir, - args: args, - supportedMarkers: cfeAnalyzerMarkers, - createUriForFileName: createUriForFileName, - onFailure: onFailure, - runTest: runTestFor( - const _AssignedVariablesDataComputer(), [analyzerNnbdConfig])); + await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + return runTests<_Data>(dataDir, + args: args, + supportedMarkers: cfeAnalyzerMarkers, + createUriForFileName: createUriForFileName, + onFailure: onFailure, + runTest: runTestFor( + const _AssignedVariablesDataComputer(), [analyzerNnbdConfig])); + }); } class _AssignedVariablesDataComputer extends DataComputer<_Data> { diff --git a/pkg/analyzer/test/id_tests/constant_test.dart b/pkg/analyzer/test/id_tests/constant_test.dart index 8e1bf64b75ab..5ea6df504496 100644 --- a/pkg/analyzer/test/id_tests/constant_test.dart +++ b/pkg/analyzer/test/id_tests/constant_test.dart @@ -9,6 +9,7 @@ import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/analysis/testing_data.dart'; import 'package:analyzer/src/util/ast_data_extractor.dart'; @@ -18,13 +19,15 @@ import '../util/id_testing_helper.dart'; main(List args) async { Directory dataDir = Directory.fromUri(Platform.script .resolve('../../../_fe_analyzer_shared/test/constants/data')); - await runTests(dataDir, - args: args, - supportedMarkers: sharedMarkers, - createUriForFileName: createUriForFileName, - onFailure: onFailure, - runTest: runTestFor( - const ConstantsDataComputer(), [analyzerConstantUpdate2018Config])); + await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + return runTests(dataDir, + args: args, + supportedMarkers: sharedMarkers, + createUriForFileName: createUriForFileName, + onFailure: onFailure, + runTest: runTestFor( + const ConstantsDataComputer(), [analyzerConstantUpdate2018Config])); + }); } class ConstantsDataComputer extends DataComputer { diff --git a/pkg/analyzer/test/id_tests/definite_assignment_test.dart b/pkg/analyzer/test/id_tests/definite_assignment_test.dart index a879acf3a80e..999e039070fa 100644 --- a/pkg/analyzer/test/id_tests/definite_assignment_test.dart +++ b/pkg/analyzer/test/id_tests/definite_assignment_test.dart @@ -8,6 +8,7 @@ import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id; import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/src/dart/analysis/testing_data.dart'; import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart'; import 'package:analyzer/src/util/ast_data_extractor.dart'; @@ -18,13 +19,15 @@ main(List args) async { Directory dataDir = Directory.fromUri(Platform.script.resolve( '../../../_fe_analyzer_shared/test/flow_analysis/definite_assignment/' 'data')); - await runTests(dataDir, - args: args, - supportedMarkers: cfeAnalyzerMarkers, - createUriForFileName: createUriForFileName, - onFailure: onFailure, - runTest: runTestFor( - const _DefiniteAssignmentDataComputer(), [analyzerNnbdConfig])); + await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + return runTests(dataDir, + args: args, + supportedMarkers: cfeAnalyzerMarkers, + createUriForFileName: createUriForFileName, + onFailure: onFailure, + runTest: runTestFor( + const _DefiniteAssignmentDataComputer(), [analyzerNnbdConfig])); + }); } class _DefiniteAssignmentDataComputer extends DataComputer { diff --git a/pkg/analyzer/test/id_tests/nullability_test.dart b/pkg/analyzer/test/id_tests/nullability_test.dart index 283e16e19dd7..e15edc8c84a0 100644 --- a/pkg/analyzer/test/id_tests/nullability_test.dart +++ b/pkg/analyzer/test/id_tests/nullability_test.dart @@ -9,6 +9,7 @@ import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'; import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/dart/element/type_system.dart'; import 'package:analyzer/src/dart/analysis/testing_data.dart'; import 'package:analyzer/src/dart/element/type.dart'; @@ -21,13 +22,15 @@ import '../util/id_testing_helper.dart'; main(List args) async { Directory dataDir = Directory.fromUri(Platform.script.resolve( '../../../_fe_analyzer_shared/test/flow_analysis/nullability/data')); - await runTests(dataDir, - args: args, - supportedMarkers: cfeAnalyzerMarkers, - createUriForFileName: createUriForFileName, - onFailure: onFailure, - runTest: - runTestFor(const _NullabilityDataComputer(), [analyzerNnbdConfig])); + await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + return runTests(dataDir, + args: args, + supportedMarkers: cfeAnalyzerMarkers, + createUriForFileName: createUriForFileName, + onFailure: onFailure, + runTest: + runTestFor(const _NullabilityDataComputer(), [analyzerNnbdConfig])); + }); } class FlowTestBase { diff --git a/pkg/analyzer/test/id_tests/reachability_test.dart b/pkg/analyzer/test/id_tests/reachability_test.dart index abe5cef5e623..6b85af8d199a 100644 --- a/pkg/analyzer/test/id_tests/reachability_test.dart +++ b/pkg/analyzer/test/id_tests/reachability_test.dart @@ -8,6 +8,7 @@ import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id; import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'; import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/src/dart/analysis/testing_data.dart'; import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart'; import 'package:analyzer/src/util/ast_data_extractor.dart'; @@ -18,13 +19,15 @@ import '../util/id_testing_helper.dart'; main(List args) async { Directory dataDir = Directory.fromUri(Platform.script.resolve( '../../../_fe_analyzer_shared/test/flow_analysis/reachability/data')); - await runTests>(dataDir, - args: args, - supportedMarkers: cfeAnalyzerMarkers, - createUriForFileName: createUriForFileName, - onFailure: onFailure, - runTest: - runTestFor(const _ReachabilityDataComputer(), [analyzerNnbdConfig])); + await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + return runTests>(dataDir, + args: args, + supportedMarkers: cfeAnalyzerMarkers, + createUriForFileName: createUriForFileName, + onFailure: onFailure, + runTest: runTestFor( + const _ReachabilityDataComputer(), [analyzerNnbdConfig])); + }); } class FlowTestBase { diff --git a/pkg/analyzer/test/id_tests/type_promotion_test.dart b/pkg/analyzer/test/id_tests/type_promotion_test.dart index e0779a316b40..874f4293ab4c 100644 --- a/pkg/analyzer/test/id_tests/type_promotion_test.dart +++ b/pkg/analyzer/test/id_tests/type_promotion_test.dart @@ -8,6 +8,7 @@ import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id; import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/analysis/testing_data.dart'; import 'package:analyzer/src/dart/element/member.dart'; @@ -20,13 +21,15 @@ main(List args) async { Directory dataDir = Directory.fromUri(Platform.script .resolve('../../../_fe_analyzer_shared/test/flow_analysis/type_promotion/' 'data')); - await runTests(dataDir, - args: args, - supportedMarkers: sharedMarkers, - createUriForFileName: createUriForFileName, - onFailure: onFailure, - runTest: - runTestFor(const _TypePromotionDataComputer(), [analyzerNnbdConfig])); + await NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + return runTests(dataDir, + args: args, + supportedMarkers: sharedMarkers, + createUriForFileName: createUriForFileName, + onFailure: onFailure, + runTest: runTestFor( + const _TypePromotionDataComputer(), [analyzerNnbdConfig])); + }); } class _TypePromotionDataComputer extends DataComputer { diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart index 994933717b8a..5ec53eeeec99 100644 --- a/pkg/analyzer/test/src/dart/element/subtype_test.dart +++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart @@ -292,7 +292,7 @@ class SubtypeTest extends _SubtypingTestBase { }) { assertExpectedString(T0, strT0); assertExpectedString(T1, strT1); - expect(typeSystem.isSubtypeOf(T0, T1), isFalse); + expect(typeSystem.isSubtypeOf2(T0, T1), isFalse); } void isNotSubtype2( @@ -301,7 +301,7 @@ class SubtypeTest extends _SubtypingTestBase { ) { var T0 = _getTypeByStr(strT0); var T1 = _getTypeByStr(strT1); - expect(typeSystem.isSubtypeOf(T0, T1), isFalse); + expect(typeSystem.isSubtypeOf2(T0, T1), isFalse); } void isNotSubtype3({ @@ -319,7 +319,7 @@ class SubtypeTest extends _SubtypingTestBase { }) { assertExpectedString(T0, strT0); assertExpectedString(T1, strT1); - expect(typeSystem.isSubtypeOf(T0, T1), isTrue); + expect(typeSystem.isSubtypeOf2(T0, T1), isTrue); } void isSubtype2( @@ -328,7 +328,7 @@ class SubtypeTest extends _SubtypingTestBase { ) { var T0 = _getTypeByStr(strT0); var T1 = _getTypeByStr(strT1); - expect(typeSystem.isSubtypeOf(T0, T1), isTrue); + expect(typeSystem.isSubtypeOf2(T0, T1), isTrue); } @override @@ -6086,7 +6086,7 @@ class _SubtypingCompoundTestBase extends _SubtypingTestBase { void _checkIsNotSubtypeOf(DartType type1, DartType type2) { var strType1 = _typeStr(type1); var strType2 = _typeStr(type2); - expect(typeSystem.isSubtypeOf(type1, type2), false, + expect(typeSystem.isSubtypeOf2(type1, type2), false, reason: '$strType1 was not supposed to be a subtype of $strType2'); } @@ -6098,7 +6098,7 @@ class _SubtypingCompoundTestBase extends _SubtypingTestBase { void _checkIsSubtypeOf(DartType type1, DartType type2) { var strType1 = _typeStr(type1); var strType2 = _typeStr(type2); - expect(typeSystem.isSubtypeOf(type1, type2), true, + expect(typeSystem.isSubtypeOf2(type1, type2), true, reason: '$strType1 is not a subtype of $strType2'); } diff --git a/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart b/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart index a732006cda88..73fd51ed65e0 100644 --- a/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart +++ b/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart @@ -2,6 +2,8 @@ // 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. +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; +import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart'; import 'package:test/test.dart'; @@ -146,11 +148,11 @@ class TypeParameterTypeTest extends _TypeParameterElementBase { _setEnclosingElement(T1); _setEnclosingElement(T2); - expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T2), isTrue); - expect(typeParameterTypeNone(T2) == typeParameterTypeNone(T1), isTrue); + _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T2), isTrue); + _assertEqual(typeParameterTypeNone(T2), typeParameterTypeNone(T1), isTrue); - expect(typeParameterTypeNone(T1) == typeParameterTypeStar(T2), isFalse); - expect(typeParameterTypeStar(T1) == typeParameterTypeNone(T2), isFalse); + _assertEqual(typeParameterTypeNone(T1), typeParameterTypeStar(T2), isFalse); + _assertEqual(typeParameterTypeStar(T1), typeParameterTypeNone(T2), isFalse); } test_equal_equalElements_withRecursiveBounds() { @@ -169,11 +171,11 @@ class TypeParameterTypeTest extends _TypeParameterElementBase { _setEnclosingElement(T1); _setEnclosingElement(T2); - expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T2), isTrue); - expect(typeParameterTypeNone(T2) == typeParameterTypeNone(T1), isTrue); + _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T2), isTrue); + _assertEqual(typeParameterTypeNone(T2), typeParameterTypeNone(T1), isTrue); - expect(typeParameterTypeNone(T1) == typeParameterTypeStar(T2), isFalse); - expect(typeParameterTypeStar(T1) == typeParameterTypeNone(T2), isFalse); + _assertEqual(typeParameterTypeNone(T1), typeParameterTypeStar(T2), isFalse); + _assertEqual(typeParameterTypeStar(T1), typeParameterTypeNone(T2), isFalse); } test_equal_sameElement_differentBounds() { @@ -183,39 +185,56 @@ class TypeParameterTypeTest extends _TypeParameterElementBase { var T1 = TypeParameterMember(T, null, typeProvider.intType); var T2 = TypeParameterMember(T, null, typeProvider.doubleType); - expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T1), isTrue); + _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T1), isTrue); - expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T2), isFalse); - expect(typeParameterTypeNone(T2) == typeParameterTypeNone(T1), isFalse); + _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T2), isFalse); + _assertEqual(typeParameterTypeNone(T2), typeParameterTypeNone(T1), isFalse); - expect(typeParameterTypeNone(T1) == typeParameterTypeNone(T), isFalse); - expect(typeParameterTypeNone(T) == typeParameterTypeNone(T1), isFalse); + _assertEqual(typeParameterTypeNone(T1), typeParameterTypeNone(T), isFalse); + _assertEqual(typeParameterTypeNone(T), typeParameterTypeNone(T1), isFalse); } test_equal_sameElements() { var T = typeParameter('T'); - expect(typeParameterTypeNone(T) == typeParameterTypeNone(T), isTrue); - expect(typeParameterTypeNone(T) == typeParameterTypeStar(T), isFalse); - expect(typeParameterTypeNone(T) == typeParameterTypeQuestion(T), isFalse); + _assertEqual(typeParameterTypeNone(T), typeParameterTypeNone(T), isTrue); + _assertEqual(typeParameterTypeNone(T), typeParameterTypeStar(T), isFalse); + _assertEqual( + typeParameterTypeNone(T), + typeParameterTypeQuestion(T), + isFalse, + ); - expect(typeParameterTypeStar(T) == typeParameterTypeNone(T), isFalse); - expect(typeParameterTypeStar(T) == typeParameterTypeStar(T), isTrue); - expect(typeParameterTypeNone(T) == typeParameterTypeQuestion(T), isFalse); + _assertEqual(typeParameterTypeStar(T), typeParameterTypeNone(T), isFalse); + _assertEqual(typeParameterTypeStar(T), typeParameterTypeStar(T), isTrue); + _assertEqual( + typeParameterTypeNone(T), + typeParameterTypeQuestion(T), + isFalse, + ); - expect( - typeParameterTypeQuestion(T) == typeParameterTypeNone(T), + _assertEqual( + typeParameterTypeQuestion(T), + typeParameterTypeNone(T), isFalse, ); - expect( - typeParameterTypeQuestion(T) == typeParameterTypeStar(T), + _assertEqual( + typeParameterTypeQuestion(T), + typeParameterTypeStar(T), isFalse, ); - expect( - typeParameterTypeQuestion(T) == typeParameterTypeQuestion(T), + _assertEqual( + typeParameterTypeQuestion(T), + typeParameterTypeQuestion(T), isTrue, ); } + + void _assertEqual(DartType T1, DartType T2, matcher) { + NullSafetyUnderstandingFlag.enableNullSafetyTypes(() async { + expect(T1 == T2, matcher); + }); + } } class _TypeParameterElementBase extends AbstractTypeTest { diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart index 133fa67862d6..734e78216709 100644 --- a/pkg/nnbd_migration/lib/src/edge_builder.dart +++ b/pkg/nnbd_migration/lib/src/edge_builder.dart @@ -266,7 +266,8 @@ class EdgeBuilder extends GeneralizingAstVisitor @override DecoratedType visitAsExpression(AsExpression node) { - if (BestPracticesVerifier.isUnnecessaryCast(node, _typeSystem)) { + if (BestPracticesVerifier.isUnnecessaryCast( + node, _typeSystem as TypeSystemImpl)) { _variables.recordUnnecessaryCast(source, node); } node.type.accept(this); diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart index 8c603ae6c868..6d09133fd7e5 100644 --- a/pkg/nnbd_migration/lib/src/fix_builder.dart +++ b/pkg/nnbd_migration/lib/src/fix_builder.dart @@ -8,6 +8,7 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/null_safety_understanding_flag.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type_provider.dart'; @@ -153,10 +154,12 @@ class FixBuilder { /// makes note of changes that need to be made. void visitAll() { try { - ElementTypeProvider.current = migrationResolutionHooks; - unit.accept(_FixBuilderPreVisitor(this)); - unit.accept(_resolver); - unit.accept(_FixBuilderPostVisitor(this)); + NullSafetyUnderstandingFlag.enableNullSafetyTypes(() { + ElementTypeProvider.current = migrationResolutionHooks; + unit.accept(_FixBuilderPreVisitor(this)); + unit.accept(_resolver); + unit.accept(_FixBuilderPostVisitor(this)); + }); } catch (exception, stackTrace) { if (listener != null) { listener.reportException(source, unit, exception, stackTrace);