@@ -22,6 +22,13 @@ private static ExpressionSyntax GetSpanLength(ExpressionSyntax span, bool isRefT
2222 ConditionalAccessExpression ( span , IdentifierName ( nameof ( Span < int > . Length ) ) ) ,
2323 LiteralExpression ( SyntaxKind . NumericLiteralExpression , Literal ( 0 ) ) ) ) : MemberAccessExpression ( SyntaxKind . SimpleMemberAccessExpression , span , IdentifierName ( nameof ( Span < int > . Length ) ) ) ;
2424
25+ private static ExpressionSyntax GetIsSpanEmpty ( ExpressionSyntax span , bool isRefType ) => isRefType ?
26+ ParenthesizedExpression ( BinaryExpression (
27+ SyntaxKind . EqualsExpression ,
28+ span ,
29+ LiteralExpression ( SyntaxKind . NullLiteralExpression ) ) ) :
30+ MemberAccessExpression ( SyntaxKind . SimpleMemberAccessExpression , span , IdentifierName ( nameof ( Span < int > . IsEmpty ) ) ) ;
31+
2532 private ExpressionSyntax GetIntPtrFromTypeDef ( ExpressionSyntax typedefValue , TypeHandleInfo typeDefTypeInfo )
2633 {
2734 ExpressionSyntax intPtrValue = typedefValue ;
@@ -1017,31 +1024,54 @@ bool TryHandleCountParam(TypeSyntax elementType, bool nullableSource)
10171024 }
10181025 }
10191026
1027+ ExpressionSyntax sizeArgExpression ;
10201028 if ( lengthParamUsedBy . TryGetValue ( countParamIndex . Value , out int userIndex ) )
10211029 {
1030+ bool origNameIsRefType = remainsRefType ;
1031+ bool otherUserNameIsRefType = parameters [ userIndex ] . Type is ArrayTypeSyntax ;
1032+
10221033 // Multiple array parameters share a common 'length' parameter.
10231034 // Since we're making this a little less obvious, add a quick if check in the helper method
10241035 // that enforces that all such parameters have a common span length.
10251036 ExpressionSyntax otherUserName = IdentifierName ( parameters [ userIndex ] . Identifier . ValueText ) ;
1037+
1038+ // Only enforce length equality when both spans are non-empty.
1039+ ExpressionSyntax otherNotEmpty = PrefixUnaryExpression ( SyntaxKind . LogicalNotExpression , GetIsSpanEmpty ( otherUserName , otherUserNameIsRefType ) ) ;
1040+ ExpressionSyntax origNotEmpty = PrefixUnaryExpression ( SyntaxKind . LogicalNotExpression , GetIsSpanEmpty ( origName , origNameIsRefType ) ) ;
1041+ ExpressionSyntax lengthsNotEqual = BinaryExpression (
1042+ SyntaxKind . NotEqualsExpression ,
1043+ GetSpanLength ( otherUserName , otherUserNameIsRefType ) ,
1044+ GetSpanLength ( origName , origNameIsRefType ) ) ;
1045+ ExpressionSyntax condition = BinaryExpression ( SyntaxKind . LogicalAndExpression , BinaryExpression ( SyntaxKind . LogicalAndExpression , otherNotEmpty , origNotEmpty ) , lengthsNotEqual ) ;
10261046 leadingStatements . Add ( IfStatement (
1027- BinaryExpression (
1028- SyntaxKind . NotEqualsExpression ,
1029- GetSpanLength ( otherUserName , parameters [ userIndex ] . Type is ArrayTypeSyntax ) ,
1030- GetSpanLength ( origName , remainsRefType ) ) ,
1047+ condition ,
10311048 ThrowStatement ( ObjectCreationExpression ( IdentifierName ( nameof ( ArgumentException ) ) ) . WithArgumentList ( ArgumentList ( ) ) ) ) ) ;
1049+
1050+ // Also we need to compound the size argument so that if one of the spans was empty, we pass the non-zero one.
1051+ sizeArgExpression = arguments [ countParamIndex . Value ] . Expression ;
1052+ if ( sizeArgExpression is CastExpressionSyntax { Expression : ExpressionSyntax castedExpression } )
1053+ {
1054+ // Unwrap the cast so we can simplify the logic
1055+ sizeArgExpression = castedExpression ;
1056+ }
1057+
1058+ sizeArgExpression = ParenthesizedExpression ( ConditionalExpression ( GetIsSpanEmpty ( origName , origNameIsRefType ) , sizeArgExpression , GetSpanLength ( origName , origNameIsRefType ) ) ) ;
10321059 }
10331060 else
10341061 {
10351062 lengthParamUsedBy . Add ( countParamIndex . Value , paramIndex ) ;
1063+
1064+ sizeArgExpression = GetSpanLength ( origName , remainsRefType ) ;
10361065 }
10371066
1038- ExpressionSyntax sizeArgExpression = GetSpanLength ( origName , remainsRefType ) ;
1067+ // Always wrap the sizeArgExpression in CastExpression if needed.
10391068 if ( ! ( parameters [ countParamIndex . Value ] . Type is PredefinedTypeSyntax { Keyword : { RawKind : ( int ) SyntaxKind . IntKeyword } } ) )
10401069 {
10411070 sizeArgExpression = CastExpression ( parameters [ countParamIndex . Value ] . Type ! , sizeArgExpression ) ;
10421071 }
10431072
10441073 arguments [ countParamIndex . Value ] = Argument ( sizeArgExpression ) ;
1074+
10451075 return true ;
10461076 }
10471077
0 commit comments