Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support u8 type suffix for UTF8 string literals. #58991

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,9 @@ private BoundExpression BindExpressionInternal(ExpressionSyntax node, BindingDia
case SyntaxKind.NullLiteralExpression:
return BindLiteralConstant((LiteralExpressionSyntax)node, diagnostics);

case SyntaxKind.UTF8StringLiteralExpression:
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Jan 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi, in the raw-string-work we decided to not have a special expression type. it's just a string-literal that consumer can check the token kind on. up to you if you want to do the same. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi, in the raw-string-work we decided to not have a special expression type. it's just a string-literal that consumer can check the token kind on. up to you if you want to do the same.

I will add a PROTOTYPE comment for now and will revisit this once raw-string-work gets into this branch.

return BindUTF8StringLiteral((LiteralExpressionSyntax)node, diagnostics);

case SyntaxKind.DefaultLiteralExpression:
return new BoundDefaultLiteral(node);

Expand Down Expand Up @@ -5897,6 +5900,18 @@ private BoundLiteral BindLiteralConstant(LiteralExpressionSyntax node, BindingDi
return new BoundLiteral(node, cv, type);
}

private BoundUTF8String BindUTF8StringLiteral(LiteralExpressionSyntax node, BindingDiagnosticBag diagnostics)
{
Debug.Assert(node.Kind() == SyntaxKind.UTF8StringLiteralExpression);

CheckFeatureAvailability(node, MessageID.IDS_FeatureUTF8StringLiterals, diagnostics);

var value = (string)node.Token.Value;
var type = ArrayTypeSymbol.CreateSZArray(Compilation.Assembly, TypeWithAnnotations.Create(GetSpecialType(SpecialType.System_Byte, diagnostics, node)));

return new BoundUTF8String(node, value, type);
}

private BoundExpression BindCheckedExpression(CheckedExpressionSyntax node, BindingDiagnosticBag diagnostics)
{
// the binder is not cached since we only cache statement level binders
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ internal static bool CanBeValidAttributeArgument(ExpressionSyntax node, Binder t
// Literals (including the null literal).
case SyntaxKind.NumericLiteralExpression:
case SyntaxKind.StringLiteralExpression:
case SyntaxKind.UTF8StringLiteralExpression:
case SyntaxKind.CharacterLiteralExpression:
case SyntaxKind.TrueLiteralExpression:
case SyntaxKind.FalseLiteralExpression:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ public bool IsConstantExpression
}

/// <summary>
/// Returns true if the conversion is an implicit Utf8 strings literal conversion.
/// Returns true if the conversion is an implicit Utf8 string literal conversion.
/// </summary>
public bool IsUtf8StringLiteral
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1110,10 +1110,10 @@ private Conversion ClassifyImplicitUtf8StringLiteralConversion(BoundExpression s
if (constantValue?.IsString == true && // PROTOTYPE(UTF8StringLiterals) : confirm if we actually want it to work with 'null' constant value.
sourceExpression.Type?.SpecialType == SpecialType.System_String &&
(destination is ArrayTypeSymbol { IsSZArray: true, ElementType.SpecialType: SpecialType.System_Byte } || // byte[]
((destinationOriginalDefinition.Equals(compilation.GetWellKnownType(WellKnownType.System_Span_T), TypeCompareKind.AllIgnoreOptions) || // Span<T>
(destinationOriginalDefinition.TypeKind == TypeKind.Struct && destinationOriginalDefinition.IsRefLikeType &&
(destinationOriginalDefinition.Equals(compilation.GetWellKnownType(WellKnownType.System_Span_T), TypeCompareKind.AllIgnoreOptions) || // Span<T>
destinationOriginalDefinition.Equals(compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions)) && // ReadOnlySpan<T>
destinationOriginalDefinition.TypeKind == TypeKind.Struct && destinationOriginalDefinition.IsRefLikeType &&
((NamedTypeSymbol)destination).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single().SpecialType == SpecialType.System_Byte))) // T is byte
((NamedTypeSymbol)destination).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single().SpecialType == SpecialType.System_Byte))) // T is byte
{
return Conversion.ImplicitUtf8StringLiteral;
}
Expand Down Expand Up @@ -1638,7 +1638,7 @@ internal Conversion GetCallerLineNumberConversion(TypeSymbol destination, ref Co
TypeSymbol expectedAttributeType = corLibrary.GetSpecialType(SpecialType.System_Int32);
BoundLiteral intMaxValueLiteral = new BoundLiteral(syntaxNode, ConstantValue.Create(int.MaxValue), expectedAttributeType);

// Below is a dupliucation of relevant parts of ClassifyStandardImplicitConversion method.
// Below is a duplication of relevant parts of ClassifyStandardImplicitConversion method.
// It needs a compilation instance, but we don't have it and the relevant parts actually do not depend on
// a compilation.
if (HasImplicitEnumerationConversion(intMaxValueLiteral, destination))
Expand Down
6 changes: 6 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,12 @@
<Field Name="ConstantValueOpt" Type="ConstantValue?"/>
</Node>

<Node Name="BoundUTF8String" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Value" Type="string" Null="disallow"/>
</Node>

<Node Name="BoundThisReference" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,11 @@ public override BoundNode VisitLiteral(BoundLiteral node)
return null;
}

public override BoundNode VisitUTF8String(BoundUTF8String node)
{
return null;
}

protected void SplitIfBooleanConstant(BoundExpression node)
{
if (node.ConstantValue is { IsBoolean: true, BooleanValue: bool booleanValue })
Expand Down
8 changes: 8 additions & 0 deletions src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10357,6 +10357,14 @@ private TypeWithState InferResultNullabilityOfBinaryLogicalOperator(BoundExpress
return result;
}

public override BoundNode? VisitUTF8String(BoundUTF8String node)
{
Debug.Assert(!IsConditionalState);
var result = base.VisitUTF8String(node);
SetNotNullResult(node);
return result;
}

public override BoundNode? VisitPreviousSubmissionReference(BoundPreviousSubmissionReference node)
{
var result = base.VisitPreviousSubmissionReference(node);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -36270,6 +36270,7 @@ public LiteralExpressionSyntax LiteralExpression(SyntaxKind kind, SyntaxToken to
case SyntaxKind.ArgListExpression:
case SyntaxKind.NumericLiteralExpression:
case SyntaxKind.StringLiteralExpression:
case SyntaxKind.UTF8StringLiteralExpression:
case SyntaxKind.CharacterLiteralExpression:
case SyntaxKind.TrueLiteralExpression:
case SyntaxKind.FalseLiteralExpression:
Expand All @@ -36284,6 +36285,7 @@ public LiteralExpressionSyntax LiteralExpression(SyntaxKind kind, SyntaxToken to
case SyntaxKind.ArgListKeyword:
case SyntaxKind.NumericLiteralToken:
case SyntaxKind.StringLiteralToken:
case SyntaxKind.UTF8StringLiteralToken:
case SyntaxKind.CharacterLiteralToken:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
Expand Down Expand Up @@ -41284,6 +41286,7 @@ public static LiteralExpressionSyntax LiteralExpression(SyntaxKind kind, SyntaxT
case SyntaxKind.ArgListExpression:
case SyntaxKind.NumericLiteralExpression:
case SyntaxKind.StringLiteralExpression:
case SyntaxKind.UTF8StringLiteralExpression:
case SyntaxKind.CharacterLiteralExpression:
case SyntaxKind.TrueLiteralExpression:
case SyntaxKind.FalseLiteralExpression:
Expand All @@ -41298,6 +41301,7 @@ public static LiteralExpressionSyntax LiteralExpression(SyntaxKind kind, SyntaxT
case SyntaxKind.ArgListKeyword:
case SyntaxKind.NumericLiteralToken:
case SyntaxKind.StringLiteralToken:
case SyntaxKind.UTF8StringLiteralToken:
case SyntaxKind.CharacterLiteralToken:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2836,6 +2836,7 @@ public static LiteralExpressionSyntax LiteralExpression(SyntaxKind kind, SyntaxT
case SyntaxKind.ArgListExpression:
case SyntaxKind.NumericLiteralExpression:
case SyntaxKind.StringLiteralExpression:
case SyntaxKind.UTF8StringLiteralExpression:
case SyntaxKind.CharacterLiteralExpression:
case SyntaxKind.TrueLiteralExpression:
case SyntaxKind.FalseLiteralExpression:
Expand All @@ -2848,6 +2849,7 @@ public static LiteralExpressionSyntax LiteralExpression(SyntaxKind kind, SyntaxT
case SyntaxKind.ArgListKeyword:
case SyntaxKind.NumericLiteralToken:
case SyntaxKind.StringLiteralToken:
case SyntaxKind.UTF8StringLiteralToken:
case SyntaxKind.CharacterLiteralToken:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
Expand All @@ -2868,6 +2870,7 @@ private static SyntaxKind GetLiteralExpressionTokenKind(SyntaxKind kind)
SyntaxKind.ArgListExpression => SyntaxKind.ArgListKeyword,
SyntaxKind.NumericLiteralExpression => SyntaxKind.NumericLiteralToken,
SyntaxKind.StringLiteralExpression => SyntaxKind.StringLiteralToken,
SyntaxKind.UTF8StringLiteralExpression => SyntaxKind.UTF8StringLiteralToken,
SyntaxKind.CharacterLiteralExpression => SyntaxKind.CharacterLiteralToken,
SyntaxKind.TrueLiteralExpression => SyntaxKind.TrueKeyword,
SyntaxKind.FalseLiteralExpression => SyntaxKind.FalseKeyword,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1947,6 +1947,7 @@ public BaseExpressionSyntax Update(SyntaxToken token)
/// <item><description><see cref="SyntaxKind.ArgListExpression"/></description></item>
/// <item><description><see cref="SyntaxKind.NumericLiteralExpression"/></description></item>
/// <item><description><see cref="SyntaxKind.StringLiteralExpression"/></description></item>
/// <item><description><see cref="SyntaxKind.UTF8StringLiteralExpression"/></description></item>
/// <item><description><see cref="SyntaxKind.CharacterLiteralExpression"/></description></item>
/// <item><description><see cref="SyntaxKind.TrueLiteralExpression"/></description></item>
/// <item><description><see cref="SyntaxKind.FalseLiteralExpression"/></description></item>
Expand Down
Loading