Skip to content

Commit bd528bf

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Updates and tests for ReplaceTopBottomVisitor, fix hints.
Bug: dart-lang/sdk#42196 Change-Id: If9350ccc4ad2908a2c7cde7281fe9e2f01c52f97 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/156561 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
1 parent 9750492 commit bd528bf

File tree

5 files changed

+156
-41
lines changed

5 files changed

+156
-41
lines changed

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

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,13 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:analyzer/dart/element/nullability_suffix.dart';
65
import 'package:analyzer/dart/element/type.dart';
76
import 'package:analyzer/src/dart/element/replacement_visitor.dart';
87
import 'package:analyzer/src/dart/element/type_system.dart';
98
import 'package:meta/meta.dart';
109

11-
/// Visitor that computes replaces covariant uses of Top with Bottom, and
12-
/// contravariant uses of Bottom with Top.
13-
///
14-
/// Each visitor method returns `null` if there are no `_`s contained in the
15-
/// type, otherwise it returns the result of substituting `_` with [_bottomType]
16-
/// or [_topType], as appropriate.
10+
/// Replace every "top" type in a covariant position with [_bottomType].
11+
/// Replace every "bottom" type in a contravariant position with [_topType].
1712
class ReplaceTopBottomVisitor extends ReplacementVisitor {
1813
final DartType _topType;
1914
final DartType _bottomType;
@@ -34,30 +29,34 @@ class ReplaceTopBottomVisitor extends ReplacementVisitor {
3429
}
3530

3631
@override
37-
DartType visitDynamicType(DynamicType type) =>
38-
_isCovariant ? _bottomType : type;
32+
DartType visitDynamicType(DynamicType type) {
33+
return _isCovariant ? _bottomType : null;
34+
}
3935

4036
@override
4137
DartType visitInterfaceType(InterfaceType type) {
42-
if (_typeSystem.isTop(type)) {
43-
return _isCovariant ? _bottomType : type;
44-
}
45-
if (_typeSystem.isBottom(type) ||
46-
(!_typeSystem.isNonNullableByDefault && type.isDartCoreNull)) {
47-
return _isCovariant ? type : _topType;
38+
if (_isCovariant) {
39+
if (_typeSystem.isTop(type)) {
40+
return _bottomType;
41+
}
42+
} else {
43+
if (!_typeSystem.isNonNullableByDefault && type.isDartCoreNull) {
44+
return _topType;
45+
}
4846
}
4947

5048
return super.visitInterfaceType(type);
5149
}
5250

5351
@override
54-
DartType visitNeverType(NeverType type) =>
55-
_isCovariant && type.nullabilitySuffix != NullabilitySuffix.question
56-
? type
57-
: _topType;
52+
DartType visitNeverType(NeverType type) {
53+
return _isCovariant ? null : _topType;
54+
}
5855

5956
@override
60-
DartType visitVoidType(VoidType type) => _isCovariant ? _bottomType : type;
57+
DartType visitVoidType(VoidType type) {
58+
return _isCovariant ? _bottomType : null;
59+
}
6160

6261
/// Runs an instance of the visitor on the given [type] and returns the
6362
/// resulting type. If the type contains no instances of Top or Bottom, the

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

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import 'package:analyzer/dart/ast/token.dart' show Keyword;
66
import 'package:analyzer/dart/element/nullability_suffix.dart';
77
import 'package:analyzer/dart/element/type.dart';
8-
import 'package:analyzer/dart/element/type_provider.dart';
98
import 'package:analyzer/dart/element/type_visitor.dart';
109
import 'package:analyzer/src/dart/element/display_string_builder.dart';
1110
import 'package:analyzer/src/dart/element/type.dart';
@@ -53,23 +52,6 @@ class UnknownInferredType extends TypeImpl {
5352
builder.writeUnknownInferredType();
5453
}
5554

56-
@override
57-
DartType replaceTopAndBottom(TypeProvider typeProvider,
58-
{bool isCovariant = true}) {
59-
// In theory this should never happen, since we only need to do this
60-
// replacement when checking super-boundedness of explicitly-specified
61-
// types, or types produced by mixin inference or instantiate-to-bounds, and
62-
// the unknown type can't occur in any of those cases.
63-
assert(
64-
false, 'Attempted to check super-boundedness of a type including "_"');
65-
// But just in case it does, behave similar to `dynamic`.
66-
if (isCovariant) {
67-
return typeProvider.nullType;
68-
} else {
69-
return this;
70-
}
71-
}
72-
7355
@override
7456
DartType substitute2(
7557
List<DartType> argumentTypes, List<DartType> parameterTypes) {

pkg/analyzer/lib/src/error/type_arguments_verifier.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import "dart:math" as math;
77
import 'package:analyzer/dart/ast/ast.dart';
88
import 'package:analyzer/dart/element/element.dart';
99
import 'package:analyzer/dart/element/type.dart';
10-
import 'package:analyzer/dart/element/type_provider.dart';
1110
import 'package:analyzer/error/error.dart';
1211
import 'package:analyzer/error/listener.dart';
1312
import 'package:analyzer/src/dart/element/type_algebra.dart';
@@ -28,8 +27,6 @@ class TypeArgumentsVerifier {
2827
this._errorReporter,
2928
);
3029

31-
TypeProvider get _typeProvider => _libraryElement.typeProvider;
32-
3330
TypeSystemImpl get _typeSystem => _libraryElement.typeSystem;
3431

3532
void checkFunctionExpressionInvocation(FunctionExpressionInvocation node) {
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
6+
import 'package:analyzer/dart/element/type.dart';
7+
import 'package:analyzer/src/dart/element/type.dart';
8+
import 'package:test/test.dart';
9+
import 'package:test_reflective_loader/test_reflective_loader.dart';
10+
11+
import '../../../generated/type_system_test.dart';
12+
13+
main() {
14+
defineReflectiveSuite(() {
15+
defineReflectiveTests(ReplaceTopBottomLegacyTest);
16+
defineReflectiveTests(ReplaceTopBottomNullSafetyTest);
17+
});
18+
}
19+
20+
@reflectiveTest
21+
class ReplaceTopBottomLegacyTest extends AbstractTypeSystemTest {
22+
test_contravariant_bottom() {
23+
// Not contravariant.
24+
_check(nullStar, 'Null*');
25+
26+
_check(
27+
functionTypeStar(returnType: intStar, parameters: [
28+
requiredParameter(type: nullStar),
29+
]),
30+
'int* Function(dynamic)*',
31+
);
32+
}
33+
34+
test_covariant_top() {
35+
_check(objectStar, 'Null*');
36+
_check(dynamicNone, 'Null*');
37+
_check(voidNone, 'Null*');
38+
39+
_check(futureOrStar(objectStar), 'Null*');
40+
_check(futureOrStar(dynamicNone), 'Null*');
41+
_check(futureOrStar(voidNone), 'Null*');
42+
_check(futureOrStar(futureOrStar(voidNone)), 'Null*');
43+
44+
_check(
45+
functionTypeStar(returnType: intStar, parameters: [
46+
requiredParameter(
47+
type: functionTypeStar(returnType: intStar, parameters: [
48+
requiredParameter(type: objectStar),
49+
]),
50+
),
51+
]),
52+
'int* Function(int* Function(Null*)*)*',
53+
typeStr: 'int* Function(int* Function(Object*)*)*',
54+
);
55+
56+
_check(listStar(intStar), 'List<int*>*');
57+
}
58+
59+
void _check(DartType type, String expectedStr, {String typeStr}) {
60+
NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
61+
if (typeStr != null) {
62+
expect(_typeString(type), typeStr);
63+
}
64+
65+
var result = typeSystem.replaceTopAndBottom(type);
66+
var resultStr = _typeString(result);
67+
expect(resultStr, expectedStr);
68+
});
69+
}
70+
71+
String _typeString(TypeImpl type) {
72+
return type.getDisplayString(withNullability: true);
73+
}
74+
}
75+
76+
@reflectiveTest
77+
class ReplaceTopBottomNullSafetyTest extends AbstractTypeSystemNullSafetyTest {
78+
test_contravariant_bottom() {
79+
// Not contravariant.
80+
_check(neverNone, 'Never');
81+
82+
_check(
83+
functionTypeNone(returnType: intNone, parameters: [
84+
requiredParameter(type: neverNone),
85+
]),
86+
'int Function(Object?)',
87+
);
88+
}
89+
90+
test_covariant_top() {
91+
_check(objectQuestion, 'Never');
92+
_check(objectStar, 'Never');
93+
_check(dynamicNone, 'Never');
94+
_check(voidNone, 'Never');
95+
96+
_check(futureOrNone(objectQuestion), 'Never');
97+
_check(futureOrNone(objectStar), 'Never');
98+
_check(futureOrNone(dynamicNone), 'Never');
99+
_check(futureOrNone(voidNone), 'Never');
100+
_check(futureOrNone(futureOrNone(voidNone)), 'Never');
101+
102+
_check(
103+
functionTypeNone(returnType: intNone, parameters: [
104+
requiredParameter(
105+
type: functionTypeNone(returnType: intNone, parameters: [
106+
requiredParameter(type: objectQuestion),
107+
]),
108+
),
109+
]),
110+
'int Function(int Function(Never))',
111+
typeStr: 'int Function(int Function(Object?))',
112+
);
113+
114+
_check(listNone(intNone), 'List<int>');
115+
_check(listNone(intQuestion), 'List<int?>');
116+
_check(listQuestion(intNone), 'List<int>?');
117+
_check(listQuestion(intQuestion), 'List<int?>?');
118+
}
119+
120+
void _check(DartType type, String expectedStr, {String typeStr}) {
121+
NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
122+
if (typeStr != null) {
123+
expect(_typeString(type), typeStr);
124+
}
125+
126+
var result = typeSystem.replaceTopAndBottom(type);
127+
var resultStr = _typeString(result);
128+
expect(resultStr, expectedStr);
129+
});
130+
}
131+
132+
String _typeString(TypeImpl type) {
133+
return type.getDisplayString(withNullability: true);
134+
}
135+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'least_upper_bound_helper_test.dart' as least_upper_bound_helper;
1717
import 'normalize_type_test.dart' as normalize_type;
1818
import 'nullability_eliminator_test.dart' as nullability_eliminator;
1919
import 'nullable_test.dart' as nullable;
20+
import 'replace_top_bottom_test.dart' as replace_top_bottom;
2021
import 'runtime_type_equality_test.dart' as runtime_type_equality;
2122
import 'subtype_test.dart' as subtype;
2223
import 'top_merge_test.dart' as top_merge;
@@ -42,6 +43,7 @@ main() {
4243
normalize_type.main();
4344
nullability_eliminator.main();
4445
nullable.main();
46+
replace_top_bottom.main();
4547
runtime_type_equality.main();
4648
subtype.main();
4749
top_merge.main();

0 commit comments

Comments
 (0)