Skip to content

Commit

Permalink
Remove Utf8StringLiteral conversion (#61481)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlekseyTs authored May 26, 2022
1 parent 9f4cf68 commit 235ee5d
Show file tree
Hide file tree
Showing 14 changed files with 125 additions and 1,673 deletions.
5 changes: 0 additions & 5 deletions src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,6 @@ BoundExpression createConversion(
.WithSuppression(source.IsSuppressed);
}

if (conversion.IsUTF8StringLiteral)
{
CheckFeatureAvailability(syntax, MessageID.IDS_FeatureUTF8StringLiterals, diagnostics);
}

reportUseSiteDiagnosticsForUnderlyingConversions(conversion);

return new BoundConversion(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ private static void AssertTrivialConversion(ConversionKind kind)
case ConversionKind.NoConversion:
case ConversionKind.Identity:
case ConversionKind.ImplicitConstant:
case ConversionKind.ImplicitUtf8StringLiteral:
case ConversionKind.ImplicitNumeric:
case ConversionKind.ImplicitReference:
case ConversionKind.ImplicitEnumeration:
Expand Down Expand Up @@ -227,7 +226,6 @@ internal static Conversion GetTrivialConversion(ConversionKind kind)
internal static Conversion NoConversion => new Conversion(ConversionKind.NoConversion);
internal static Conversion Identity => new Conversion(ConversionKind.Identity);
internal static Conversion ImplicitConstant => new Conversion(ConversionKind.ImplicitConstant);
internal static Conversion ImplicitUtf8StringLiteral => new Conversion(ConversionKind.ImplicitUtf8StringLiteral);
internal static Conversion ImplicitNumeric => new Conversion(ConversionKind.ImplicitNumeric);
internal static Conversion ImplicitReference => new Conversion(ConversionKind.ImplicitReference);
internal static Conversion ImplicitEnumeration => new Conversion(ConversionKind.ImplicitEnumeration);
Expand Down Expand Up @@ -827,17 +825,6 @@ public bool IsConstantExpression
}
}

/// <summary>
/// Returns true if the conversion is an implicit Utf8 string literal conversion.
/// </summary>
public bool IsUTF8StringLiteral
{
get
{
return Kind == ConversionKind.ImplicitUtf8StringLiteral;
}
}

/// <summary>
/// Returns true if the conversion is an implicit anonymous function conversion.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ internal enum ConversionKind : byte
ImplicitDynamic,
ExplicitDynamic,
ImplicitConstant,
ImplicitUtf8StringLiteral,
ImplicitUserDefined,
AnonymousFunction,
MethodGroup,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public static bool IsImplicitConversion(this ConversionKind conversionKind)
case Boxing:
case ImplicitDynamic:
case ImplicitConstant:
case ImplicitUtf8StringLiteral:
case ImplicitUserDefined:
case AnonymousFunction:
case ConversionKind.MethodGroup:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,6 @@ private static bool IsStandardImplicitConversionFromType(ConversionKind kind)
case ConversionKind.ImplicitReference:
case ConversionKind.Boxing:
case ConversionKind.ImplicitConstant:
case ConversionKind.ImplicitUtf8StringLiteral:
case ConversionKind.ImplicitPointer:
case ConversionKind.ImplicitPointerToVoid:
case ConversionKind.ImplicitTuple:
Expand Down Expand Up @@ -657,8 +656,7 @@ private Conversion ClassifyStandardImplicitConversion(BoundExpression sourceExpr

Conversion conversion = ClassifyImplicitBuiltInConversionFromExpression(sourceExpression, source, destination, ref useSiteInfo);
if (conversion.Exists &&
!conversion.IsInterpolatedStringHandler &&
!conversion.IsUTF8StringLiteral) // UTF-8 string conversion is not a standard conversion.
!conversion.IsInterpolatedStringHandler)
{
Debug.Assert(IsStandardImplicitConversionFromExpression(conversion.Kind));
return conversion;
Expand Down Expand Up @@ -1021,12 +1019,6 @@ private Conversion ClassifyImplicitBuiltInConversionFromExpression(BoundExpressi
return constantConversion;
}

constantConversion = ClassifyImplicitUtf8StringLiteralConversion(sourceExpression, destination);
if (constantConversion.Exists)
{
return constantConversion;
}

switch (sourceExpression.Kind)
{
case BoundKind.Literal:
Expand Down Expand Up @@ -1107,35 +1099,6 @@ private Conversion ClassifyImplicitBuiltInConversionFromExpression(BoundExpressi
return Conversion.NoConversion;
}

#nullable enable
private Conversion ClassifyImplicitUtf8StringLiteralConversion(BoundExpression sourceExpression, TypeSymbol destination)
{
var compilation = Compilation;

// The language will allow conversions between string constants and byte sequences
// where the text is converted into the equivalent UTF8 byte representation.
// Specifically the compiler will allow for implicit conversions from string constants to
// byte[], Span<byte>, and ReadOnlySpan<byte>.
ConstantValue? constantValue = sourceExpression.ConstantValue;

TypeSymbol destinationOriginalDefinition = destination.OriginalDefinition;
if (constantValue is ({ IsString: true } or { IsNull: true }) &&
sourceExpression.Type?.SpecialType == SpecialType.System_String &&
(destination is ArrayTypeSymbol { IsSZArray: true, ElementType.SpecialType: SpecialType.System_Byte } || // byte[]
(destinationOriginalDefinition.TypeKind == TypeKind.Struct && destinationOriginalDefinition.IsRefLikeType &&
compilation is not null &&
(destinationOriginalDefinition.Equals(compilation.GetWellKnownType(WellKnownType.System_Span_T), TypeCompareKind.AllIgnoreOptions) || // Span<T>
destinationOriginalDefinition.Equals(compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions)) && // ReadOnlySpan<T>
((NamedTypeSymbol)destination).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single().SpecialType == SpecialType.System_Byte))) // T is byte
{
return Conversion.ImplicitUtf8StringLiteral;
}

Debug.Assert(compilation is not null);
return Conversion.NoConversion;
}
#nullable disable

private Conversion GetSwitchExpressionConversion(BoundExpression source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
{
Debug.Assert(Compilation is not null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,6 @@ private static bool IsEncompassingImplicitConversionKind(ConversionKind kind)
case ConversionKind.StackAllocToPointerType:
case ConversionKind.StackAllocToSpanType:
case ConversionKind.InterpolatedStringHandler:
case ConversionKind.ImplicitUtf8StringLiteral:

// Not "standard".
case ConversionKind.ImplicitUserDefined:
Expand Down
11 changes: 0 additions & 11 deletions src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7775,17 +7775,6 @@ private TypeWithState VisitConversion(
resultState = NullableFlowState.NotNull;
break;

case ConversionKind.ImplicitUtf8StringLiteral:
if (targetType.IsReferenceType)
{
resultState = getConversionResultState(operandType);
}
else
{
resultState = NullableFlowState.NotNull;
}
break;

case ConversionKind.ObjectCreation:
case ConversionKind.SwitchExpression:
case ConversionKind.ConditionalExpression:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -761,13 +761,6 @@ public override BoundNode VisitConversion(BoundConversion node)
}
break;

case ConversionKind.ImplicitUtf8StringLiteral:
if (_inExpressionLambda)
{
Error(ErrorCode.ERR_ExpressionTreeContainsUTF8StringLiterals, node);
}
break;

default:

if (_inExpressionLambda && node.Conversion.Method is MethodSymbol method && (method.IsAbstract || method.IsVirtual) && method.IsStatic)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ public override BoundNode VisitConversion(BoundConversion node)
InterpolationHandlerResult interpolationResult = RewriteToInterpolatedStringHandlerPattern(data, parts, node.Operand.Syntax);
return interpolationResult.WithFinalResult(interpolationResult.HandlerTemp);

case ConversionKind.ImplicitUtf8StringLiteral:
return RewriteUtf8StringLiteralConversion(node);

case ConversionKind.SwitchExpression:
// Skip through target-typed switches
Debug.Assert(node.Operand is BoundConvertedSwitchExpression { WasTargetTyped: true });
Expand Down Expand Up @@ -76,62 +73,6 @@ public override BoundNode VisitConversion(BoundConversion node)
return result;
}

private BoundNode RewriteUtf8StringLiteralConversion(BoundConversion node)
{
string? value = node.Operand.ConstantValue?.StringValue;

if (value == null)
{
return new BoundDefaultExpression(node.Syntax, node.Type);
}

ArrayTypeSymbol byteArray;

if (node.Type is ArrayTypeSymbol array)
{
Debug.Assert(array.IsSZArray);
Debug.Assert(array.ElementType.SpecialType == SpecialType.System_Byte);
byteArray = array;
}
else
{
Debug.Assert(node.Type.OriginalDefinition.Equals(_compilation.GetWellKnownType(WellKnownType.System_Span_T), TypeCompareKind.AllIgnoreOptions) ||
node.Type.OriginalDefinition.Equals(_compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions));
Debug.Assert(node.Type.OriginalDefinition.TypeKind == TypeKind.Struct && node.Type.OriginalDefinition.IsRefLikeType);

var byteType = ((NamedTypeSymbol)node.Type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single().Type;
Debug.Assert(byteType.SpecialType == SpecialType.System_Byte);

byteArray = ArrayTypeSymbol.CreateSZArray(_compilation.Assembly, TypeWithAnnotations.Create(byteType));
}

BoundExpression utf8Bytes = CreateUTF8ByteRepresentation(node.Syntax, node.Operand.Syntax, value, byteArray);

if ((object)node.Type == byteArray)
{
return utf8Bytes;
}

WellKnownMember wellKnownCtor;

if (node.Type.Name == "Span")
{
wellKnownCtor = WellKnownMember.System_Span_T__ctor_Array;
}
else
{
Debug.Assert(node.Type.Name == "ReadOnlySpan");
wellKnownCtor = WellKnownMember.System_ReadOnlySpan_T__ctor_Array;
}

if (!TryGetWellKnownTypeMember<MethodSymbol>(node.Syntax, wellKnownCtor, out MethodSymbol ctor))
{
return BadExpression(node.Syntax, node.Type, ImmutableArray<BoundExpression>.Empty);
}

return new BoundObjectCreationExpression(node.Syntax, ctor.AsMember((NamedTypeSymbol)node.Type), utf8Bytes);
}

private BoundExpression CreateUTF8ByteRepresentation(SyntaxNode resultSyntax, SyntaxNode valueSyntax, string value, ArrayTypeSymbol byteArray)
{
Debug.Assert(byteArray.IsSZArray);
Expand Down
1 change: 0 additions & 1 deletion src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ConversionOperatorDeclaration
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.OperatorMemberCref(Microsoft.CodeAnalysis.SyntaxToken operatorKeyword, Microsoft.CodeAnalysis.SyntaxToken checkedKeyword, Microsoft.CodeAnalysis.SyntaxToken operatorToken, Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax? parameters) -> Microsoft.CodeAnalysis.CSharp.Syntax.OperatorMemberCrefSyntax!
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ConversionOperatorMemberCref(Microsoft.CodeAnalysis.SyntaxToken implicitOrExplicitKeyword, Microsoft.CodeAnalysis.SyntaxToken operatorKeyword, Microsoft.CodeAnalysis.SyntaxToken checkedKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax! type, Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterListSyntax? parameters) -> Microsoft.CodeAnalysis.CSharp.Syntax.ConversionOperatorMemberCrefSyntax!
static Microsoft.CodeAnalysis.CSharp.SyntaxFacts.IsCheckedOperator(string! operatorMetadataName) -> bool
Microsoft.CodeAnalysis.CSharp.Conversion.IsUTF8StringLiteral.get -> bool
*REMOVED*Microsoft.CodeAnalysis.CSharp.SyntaxKind.ExclamationExclamationToken = 8285 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.UTF8StringLiteralExpression = 8756 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.UTF8StringLiteralToken = 8520 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ internal static bool ReportDefaultParameterErrors(
}
}
else if (!defaultExpression.HasAnyErrors &&
!IsValidDefaultValue(defaultExpression.IsImplicitObjectCreation() || convertedExpression is BoundConversion { Conversion.IsUTF8StringLiteral: true } ?
!IsValidDefaultValue(defaultExpression.IsImplicitObjectCreation() ?
convertedExpression : defaultExpression))
{
// error CS1736: Default parameter value for '{0}' must be a compile-time constant
Expand Down
Loading

0 comments on commit 235ee5d

Please sign in to comment.