From 369809185896d0893698eae139b189469b30b659 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Thu, 1 Oct 2020 22:22:47 +0000 Subject: [PATCH] Use demoteType() on inferred type arguments. Bug: https://github.com/dart-lang/language/issues/1182#issuecomment-702272641 Change-Id: I72d30f51aaf1d2651c1568cd68f37e5c7c03b582 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165683 Reviewed-by: Brian Wilkerson Commit-Queue: Konstantin Shcheglov --- .../src/dart/element/generic_inferrer.dart | 3 ++ .../dart/element/generic_inferrer_test.dart | 21 +++++++++++ .../resolution/instance_creation_test.dart | 37 ++++++++++++++++++- .../resolution/method_invocation_test.dart | 19 ++++++++++ .../test/src/dart/resolution/resolution.dart | 13 ++++++- 5 files changed, 90 insertions(+), 3 deletions(-) diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart index d6dd68a32197..f778aefbe609 100644 --- a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart +++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart @@ -479,6 +479,9 @@ class GenericInferrer { types[i] = _typeSystem.nonNullifyLegacy(types[i]); } } + for (var i = 0; i < types.length; i++) { + types[i] = _typeSystem.demoteType(types[i]); + } } /// If in a legacy library, return the legacy version of the [type]. diff --git a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart index 970191b094ed..428784d3da33 100644 --- a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart +++ b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart @@ -192,6 +192,27 @@ class GenericFunctionInferenceTest extends AbstractTypeSystemNullSafetyTest { ); } + /// https://github.com/dart-lang/language/issues/1182#issuecomment-702272641 + void test_demoteType() { + // (T x) -> void + var T = typeParameter('T'); + var rawType = functionTypeNone( + typeFormals: [T], + parameters: [ + requiredParameter(type: typeParameterTypeNone(T)), + ], + returnType: voidNone, + ); + + var S = typeParameter('S'); + var S_and_int = typeParameterTypeNone(S, promotedBound: intNone); + + var inferredTypes = _inferCall(rawType, [S_and_int]); + var inferredType = inferredTypes[0] as TypeParameterTypeImpl; + expect(inferredType.element, S); + expect(inferredType.promotedBound, isNull); + } + void test_fromLegacy_nonNullableBound() { typeSystem = analysisContext.typeSystemLegacy; diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart index d9eda139c43d..be98561bb266 100644 --- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart @@ -2,6 +2,7 @@ // 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/type.dart'; import 'package:analyzer/src/error/codes.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -9,12 +10,40 @@ import 'context_collection_resolution.dart'; main() { defineReflectiveSuite(() { - defineReflectiveTests(InstanceCreationDriverResolutionTest); + defineReflectiveTests(InstanceCreationTest); + defineReflectiveTests(InstanceCreationWithNullSafetyTest); }); } @reflectiveTest -class InstanceCreationDriverResolutionTest extends PubPackageResolutionTest { +class InstanceCreationTest extends PubPackageResolutionTest + with InstanceCreationTestCases {} + +mixin InstanceCreationTestCases on PubPackageResolutionTest { + test_demoteType() async { + await assertNoErrorsInCode(r''' +class A { + A(T t); +} + +void f(S s) { + if (s is int) { + A(s); + } +} + +'''); + + var creation = findNode.instanceCreation('A(s)'); + var creationType = creation.staticType as InterfaceType; + + assertTypeParameterType( + creationType.typeArguments[0], + element: findElement.typeParameter('S'), + promotedBound: null, + ); + } + test_error_newWithInvalidTypeParameters_implicitNew_inference_top() async { await assertErrorsInCode(r''' final foo = Map(); @@ -147,3 +176,7 @@ main() { ); } } + +@reflectiveTest +class InstanceCreationWithNullSafetyTest extends PubPackageResolutionTest + with WithNullSafetyMixin, InstanceCreationTestCases {} diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart index d83065c072ae..5c49601008e7 100644 --- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart @@ -393,6 +393,25 @@ f(A a, int b, int c) { expectedType: 'String'); } + test_demoteType() async { + await assertNoErrorsInCode(r''' +void test(T t) {} + +void f(S s) { + if (s is int) { + test(s); + } +} + +'''); + + assertTypeParameterType( + findNode.methodInvocation('test(s)').typeArgumentTypes[0], + element: findElement.typeParameter('S'), + promotedBound: null, + ); + } + test_error_ambiguousImport_topFunction() async { newFile('$testPackageLibPath/a.dart', content: r''' void foo(int _) {} diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart index 49dd0da5ae88..011e60fe2171 100644 --- a/pkg/analyzer/test/src/dart/resolution/resolution.dart +++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart @@ -703,7 +703,9 @@ mixin ResolutionTest implements ResourceProviderMixin { void assertType(Object typeOrNode, String expected) { DartType actual; - if (typeOrNode is DartType) { + if (typeOrNode == null) { + actual = typeOrNode; + } else if (typeOrNode is DartType) { actual = typeOrNode; } else if (typeOrNode is Expression) { actual = typeOrNode.staticType; @@ -774,6 +776,15 @@ mixin ResolutionTest implements ResourceProviderMixin { expect(node.staticType, isNull); } + void assertTypeParameterType( + TypeParameterTypeImpl type, { + @required TypeParameterElement element, + @required String promotedBound, + }) { + assertElement(type.element, element); + assertType(type.promotedBound, promotedBound); + } + Matcher elementMatcher( Element declaration, { bool isLegacy = false,