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) {