Update display string for promoted type parameter type.
Bug: https://github.com/dart-lang/sdk/issues/49692
Change-Id: I4f61dfe9bb123f000cb253f14a0733063f16acde
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255547
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
index 6cd85f2..b3c4b83 100644
--- a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
@@ -236,14 +236,22 @@
}
void writeTypeParameterType(TypeParameterTypeImpl type) {
- _write(type.element2.displayName);
- _writeNullability(type.nullabilitySuffix);
-
- var promotedBound = type.promotedBound;
+ final promotedBound = type.promotedBound;
if (promotedBound != null) {
+ final hasSuffix = type.nullabilitySuffix != NullabilitySuffix.none;
+ if (hasSuffix) {
+ _write('(');
+ }
+ _write(type.element2.displayName);
_write(' & ');
_writeType(promotedBound);
+ if (hasSuffix) {
+ _write(')');
+ }
+ } else {
+ _write(type.element2.displayName);
}
+ _writeNullability(type.nullabilitySuffix);
}
void writeUnknownInferredType() {
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 67feebe..dcce53d 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -411,12 +411,12 @@
check(tryPromote(numStar, T_none), 'T & num*');
check(tryPromote(numNone, T_question), 'T & num');
- check(tryPromote(numQuestion, T_question), 'T? & num?');
- check(tryPromote(numStar, T_question), 'T* & num*');
+ check(tryPromote(numQuestion, T_question), '(T & num?)?');
+ check(tryPromote(numStar, T_question), '(T & num*)*');
- check(tryPromote(numNone, T_star), 'T* & num');
- check(tryPromote(numQuestion, T_star), 'T* & num?');
- check(tryPromote(numStar, T_star), 'T* & num*');
+ check(tryPromote(numNone, T_star), '(T & num)*');
+ check(tryPromote(numQuestion, T_star), '(T & num?)*');
+ check(tryPromote(numStar, T_star), '(T & num*)*');
}
test_typeParameter_twice() {
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 1d8fc98..ee31ff1e 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -3064,7 +3064,7 @@
isSubtype(
promotedTypeParameterTypeStar(T, intStar),
futureOrStar(numStar),
- strT0: 'T* & int*, T extends Object*',
+ strT0: '(T & int*)*, T extends Object*',
strT1: 'FutureOr<num*>*',
);
@@ -3408,7 +3408,7 @@
typeParameterTypeStar(T),
promotedTypeParameterTypeStar(T, intStar),
strT0: 'T*, T extends int*',
- strT1: 'T* & int*, T extends int*',
+ strT1: '(T & int*)*, T extends int*',
);
T = typeParameter('T', bound: intNone);
@@ -3532,7 +3532,7 @@
neverNone,
promotedTypeParameterTypeStar(T, numStar),
strT0: 'Never',
- strT1: 'T* & num*, T extends Object*',
+ strT1: '(T & num*)*, T extends Object*',
);
}
@@ -3542,7 +3542,7 @@
isNotSubtype(
promotedTypeParameterTypeStar(T, numStar),
neverNone,
- strT0: 'T* & num*, T extends Object*',
+ strT0: '(T & num*)*, T extends Object*',
strT1: 'Never',
);
}
@@ -3824,7 +3824,7 @@
nullQuestion,
promotedTypeParameterTypeStar(T, numStar),
strT0: 'Null?',
- strT1: 'T* & num*, T extends Object*',
+ strT1: '(T & num*)*, T extends Object*',
);
}
@@ -4104,8 +4104,8 @@
isSubtype(
type,
type,
- strT0: 'T? & int?, T extends Object',
- strT1: 'T? & int?, T extends Object',
+ strT0: '(T & int?)?, T extends Object',
+ strT1: '(T & int?)?, T extends Object',
);
}
@@ -4860,7 +4860,7 @@
isSubtype(
promotedTypeParameterTypeStar(T, intStar),
typeParameterTypeStar(T),
- strT0: 'T* & int*, T extends int*',
+ strT0: '(T & int*)*, T extends int*',
strT1: 'T*, T extends int*',
);
}
@@ -4871,7 +4871,7 @@
isSubtype(
promotedTypeParameterTypeStar(T, intStar),
typeParameterTypeStar(T),
- strT0: 'T* & int*, T extends num*',
+ strT0: '(T & int*)*, T extends num*',
strT1: 'T*, T extends num*',
);
}
@@ -4882,7 +4882,7 @@
isSubtype(
promotedTypeParameterTypeStar(T, numStar),
typeParameterTypeStar(T),
- strT0: 'T* & num*, T extends num*',
+ strT0: '(T & num*)*, T extends num*',
strT1: 'T*, T extends num*',
);
}
@@ -4894,7 +4894,7 @@
typeParameterTypeStar(T),
promotedTypeParameterTypeStar(T, intStar),
strT0: 'T*, T extends int*',
- strT1: 'T* & int*, T extends int*',
+ strT1: '(T & int*)*, T extends int*',
);
}
@@ -4905,7 +4905,7 @@
typeParameterTypeStar(T),
promotedTypeParameterTypeStar(T, numStar),
strT0: 'T*, T extends int*',
- strT1: 'T* & num*, T extends int*',
+ strT1: '(T & num*)*, T extends int*',
);
}
@@ -4916,7 +4916,7 @@
typeParameterTypeStar(T),
promotedTypeParameterTypeStar(T, intStar),
strT0: 'T*, T extends num*',
- strT1: 'T* & int*, T extends num*',
+ strT1: '(T & int*)*, T extends num*',
);
}
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 af87e20..8265b92 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -3356,7 +3356,7 @@
base: root::@parameter::t
substitution: {T: S*}
staticElement: self::@function::f::@parameter::s
- staticType: S* & int*
+ staticType: (S & int*)*
rightParenthesis: )
staticInvokeType: void Function(S*)*
staticType: void
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index 4a8fd19..cf819fe 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -338,7 +338,7 @@
operand: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
- staticType: T? & num?
+ staticType: (T & num?)?
operator: !
staticElement: <null>
staticType: T & num
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
index a1531fb..ec7ad17 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_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/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../context_collection_resolution.dart';
@@ -28,6 +29,40 @@
assertInvokeType(findNode.methodInvocation('d)'), 'bool Function()');
}
+ test_issue49692() async {
+ await assertErrorsInCode('''
+T f<T>(T t, bool b) {
+ if (t is int) {
+ final u = b ? t : null;
+ return u;
+ } else {
+ return t;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 79, 1),
+ ]);
+
+ final node = findNode.conditionalExpression('b ?');
+ assertResolvedNodeText(node, r'''
+ConditionalExpression
+ condition: SimpleIdentifier
+ token: b
+ staticElement: self::@function::f::@parameter::b
+ staticType: bool
+ question: ?
+ thenExpression: SimpleIdentifier
+ token: t
+ staticElement: self::@function::f::@parameter::t
+ staticType: T & int
+ colon: :
+ elseExpression: NullLiteral
+ literal: null
+ staticType: Null
+ staticType: (T & int)?
+''');
+ }
+
test_type() async {
await assertNoErrorsInCode('''
void f(bool b) {