From ce7fcff2eae2ca1a7e620a621ade8eefaf8407fb Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Fri, 6 Mar 2020 02:36:21 +0000 Subject: [PATCH] Resolve type parameters to bounds when checking for implementing Iterable / Map. R=brianwilkerson@google.com Change-Id: Ifdb8fe73cbe731bfe5e3ea130f846fabfc1ce07f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138565 Reviewed-by: Brian Wilkerson Commit-Queue: Konstantin Shcheglov --- .../src/error/literal_element_verifier.dart | 4 ++ .../diagnostics/not_iterable_spread_test.dart | 43 +++++++++++++++++++ .../src/diagnostics/not_map_spread_test.dart | 43 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart index d6090cca649..fcf6977fd80 100644 --- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart +++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart @@ -142,6 +142,8 @@ class LiteralElementVerifier { return; } + expressionType = typeSystem.resolveToBound(expressionType); + InterfaceType iterableType; if (expressionType is InterfaceTypeImpl) { iterableType = expressionType.asInstanceOf(typeProvider.iterableElement); @@ -183,6 +185,8 @@ class LiteralElementVerifier { return; } + expressionType = typeSystem.resolveToBound(expressionType); + InterfaceType mapType; if (expressionType is InterfaceTypeImpl) { mapType = expressionType.asInstanceOf(typeProvider.mapElement); diff --git a/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart index 4b774e135cd..06f4f236933 100644 --- a/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart +++ b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart @@ -2,7 +2,9 @@ // 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/analysis/features.dart'; import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer/src/generated/engine.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/driver_resolution.dart'; @@ -10,9 +12,30 @@ import '../dart/resolution/driver_resolution.dart'; main() { defineReflectiveSuite(() { defineReflectiveTests(NotIterableSpreadTest); + defineReflectiveTests(NotIterableSpreadNullSafetyTest); }); } +@reflectiveTest +class NotIterableSpreadNullSafetyTest extends NotIterableSpreadTest { + @override + AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl() + ..contextFeatures = FeatureSet.forTesting( + sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]); + + @override + bool get typeToStringWithNullability => true; + + test_iterable_typeParameter_bound_listQuestion() async { + await assertNoErrorsInCode(''' +void f?>(T a) { + var v = [...?a]; + v; +} +'''); + } +} + @reflectiveTest class NotIterableSpreadTest extends DriverResolutionTest { test_iterable_list() async { @@ -28,6 +51,15 @@ var v = [...?null]; '''); } + test_iterable_typeParameter_bound_list() async { + await assertNoErrorsInCode(''' +void f>(T a) { + var v = [...a]; + v; +} +'''); + } + test_notIterable_direct() async { await assertErrorsInCode(''' var a = 0; @@ -64,4 +96,15 @@ var v = [if (1 > 0) ...a]; error(CompileTimeErrorCode.NOT_ITERABLE_SPREAD, 34, 1), ]); } + + test_notIterable_typeParameter_bound() async { + await assertErrorsInCode(''' +void f(T a) { + var v = [...a]; + v; +} +''', [ + error(CompileTimeErrorCode.NOT_ITERABLE_SPREAD, 43, 1), + ]); + } } diff --git a/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart index 2f7e4153e7c..98ccc0d9ee7 100644 --- a/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart +++ b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart @@ -2,7 +2,9 @@ // 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/analysis/features.dart'; import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer/src/generated/engine.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/driver_resolution.dart'; @@ -10,9 +12,30 @@ import '../dart/resolution/driver_resolution.dart'; main() { defineReflectiveSuite(() { defineReflectiveTests(NotMapSpreadTest); + defineReflectiveTests(NotMapSpreadNullSafetyTest); }); } +@reflectiveTest +class NotMapSpreadNullSafetyTest extends NotMapSpreadTest { + @override + AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl() + ..contextFeatures = FeatureSet.forTesting( + sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]); + + @override + bool get typeToStringWithNullability => true; + + test_map_typeParameter_bound_mapQuestion() async { + await assertNoErrorsInCode(''' +void f?>(T a) { + var v = {...?a}; + v; +} +'''); + } +} + @reflectiveTest class NotMapSpreadTest extends DriverResolutionTest { test_map() async { @@ -28,6 +51,15 @@ var v = {...?null}; '''); } + test_map_typeParameter_bound_map() async { + await assertNoErrorsInCode(''' +void f>(T a) { + var v = {...a}; + v; +} +'''); + } + test_notMap_direct() async { await assertErrorsInCode(''' var a = 0; @@ -64,4 +96,15 @@ var v = {if (1 > 0) ...a}; error(CompileTimeErrorCode.NOT_MAP_SPREAD, 44, 1), ]); } + + test_notMap_typeParameter_bound() async { + await assertErrorsInCode(''' +void f(T a) { + var v = {...a}; + v; +} +''', [ + error(CompileTimeErrorCode.NOT_MAP_SPREAD, 53, 1), + ]); + } }