@@ -3702,7 +3702,7 @@ TypeWithState convertCollection(BoundCollectionExpression node, TypeWithAnnotati
37023702
37033703 // Record the final state
37043704 NullableFlowState resultState = getResultState(node, collectionKind);
3705- var resultTypeWithState = TypeWithState.Create(node.Type , resultState);
3705+ var resultTypeWithState = TypeWithState.Create(strippedTargetCollectionType , resultState);
37063706 SetAnalyzedNullability(node, resultTypeWithState);
37073707 return resultTypeWithState;
37083708 }
@@ -4570,7 +4570,7 @@ static TypeSymbol setSpanElementType(NamedTypeSymbol namedType, TypeWithAnnotati
45704570 /// This is done using <see cref="TargetTypedAnalysisCompletion"/>. All registered completions must be processed
45714571 /// (ie. analyzed via some conversion) before the nullable analysis completes.
45724572 /// </summary>
4573- private static bool IsTargetTypedExpression(BoundExpression node)
4573+ internal static bool IsTargetTypedExpression(BoundExpression node)
45744574 {
45754575 return node is BoundConditionalOperator { WasTargetTyped: true } or
45764576 BoundConvertedSwitchExpression { WasTargetTyped: true } or
@@ -5817,6 +5817,14 @@ void makeAndAdjustReceiverSlot(BoundExpression receiver)
58175817 {
58185818 resultType = null;
58195819 }
5820+ else if (IsTargetTypedExpression(consequence))
5821+ {
5822+ resultType = alternativeRValue.Type;
5823+ }
5824+ else if (IsTargetTypedExpression(alternative))
5825+ {
5826+ resultType = consequenceRValue.Type;
5827+ }
58205828 else
58215829 {
58225830 // Determine nested nullability using BestTypeInferrer.
@@ -9305,14 +9313,17 @@ private void TrackAnalyzedNullabilityThroughConversionGroup(TypeWithState result
93059313 while (conversionOpt != null && conversionOpt != convertedNode)
93069314 {
93079315 Debug.Assert(conversionOpt.ConversionGroupOpt == conversionGroup);
9308- visitResult = withType(visitResult, conversionOpt.Type);
9316+
9317+ // https://github.com/dotnet/roslyn/issues/35046
9318+ // SetAnalyzedNullability will drop the type if the visitResult.RValueType.Type differs from conversionOpt.Type.
9319+ // (It will use the top-level nullability from visitResult, though.)
9320+ //
9321+ // Here, the visitResult represents the result of visiting the operand.
9322+ // Ideally, we would use the visitResult to reinfer the types of the containing conversions, and store those results here.
93099323 SetAnalyzedNullability(conversionOpt, visitResult);
9324+
93109325 conversionOpt = conversionOpt.Operand as BoundConversion;
93119326 }
9312-
9313- static VisitResult withType(VisitResult visitResult, TypeSymbol newType) =>
9314- new VisitResult(TypeWithState.Create(newType, visitResult.RValueType.State),
9315- TypeWithAnnotations.Create(newType, visitResult.LValueType.NullableAnnotation));
93169327 }
93179328
93189329 /// <summary>
@@ -11282,8 +11293,6 @@ private TypeWithState InferResultNullabilityOfBinaryLogicalOperator(BoundExpress
1128211293 }
1128311294 }
1128411295
11285- // https://github.com/dotnet/roslyn/issues/33344: this fails to produce an updated tuple type for a default expression
11286- // (should produce nullable element types for those elements that are of reference types)
1128711296 SetResultType(node, TypeWithState.ForType(type));
1128811297 return result;
1128911298 }
0 commit comments