diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
index 6f24e552a0ed7..7c90dfe9cffe2 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
@@ -484,6 +484,18 @@ void checkConstraintLanguageVersionAndRuntimeSupportForConversion(SyntaxNode syn
CheckInlineArrayTypeIsSupported(syntax, source.Type, elementField.Type, diagnostics);
}
+ else if (conversion.IsSpan)
+ {
+ if (destination.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions))
+ {
+ _ = GetWellKnownTypeMember(WellKnownMember.System_ReadOnlySpan_T__ctor_Array, diagnostics, syntax: syntax);
+ }
+ else
+ {
+ Debug.Assert(destination.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_Span_T), TypeCompareKind.AllIgnoreOptions));
+ _ = GetWellKnownTypeMember(WellKnownMember.System_Span_T__ctor_Array, diagnostics, syntax: syntax);
+ }
+ }
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
index 8a32d3821bb6f..572b1e37ed34a 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
@@ -1241,7 +1241,7 @@ private BoundCall BindInvocationExpressionContinued(
ParameterSymbol receiverParameter = method.Parameters.First();
// we will have a different receiver if ReplaceTypeOrValueReceiver has unwrapped TypeOrValue
- if ((object)receiver != receiverArgument)
+ if ((object)receiver != methodGroup.Receiver)
{
// Because the receiver didn't pass through CoerceArguments, we need to apply an appropriate conversion here.
Debug.Assert(argsToParams.IsDefault || argsToParams[0] == 0);
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs
index 96888f4a2ff91..4a298445c97db 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversion.cs
@@ -244,6 +244,7 @@ private static void AssertTrivialConversion(ConversionKind kind)
case ConversionKind.InterpolatedString:
case ConversionKind.InterpolatedStringHandler:
case ConversionKind.InlineArray:
+ case ConversionKind.ImplicitSpan:
isTrivial = true;
break;
@@ -294,6 +295,7 @@ internal static Conversion GetTrivialConversion(ConversionKind kind)
internal static Conversion ImplicitPointer => new Conversion(ConversionKind.ImplicitPointer);
internal static Conversion FunctionType => new Conversion(ConversionKind.FunctionType);
internal static Conversion InlineArray => new Conversion(ConversionKind.InlineArray);
+ internal static Conversion ImplicitSpan => new Conversion(ConversionKind.ImplicitSpan);
// trivial conversions that could be underlying in nullable conversion
// NOTE: tuple conversions can be underlying as well, but they are not trivial
@@ -819,6 +821,20 @@ public bool IsReference
}
}
+ ///
+ /// Returns true if the conversion is a span conversion.
+ ///
+ ///
+ /// Span conversion is available since C# 13 as part of the "first-class Span types" feature.
+ ///
+ internal bool IsSpan // PROTOTYPE: Make part of public API
+ {
+ get
+ {
+ return Kind == ConversionKind.ImplicitSpan;
+ }
+ }
+
///
/// Returns true if the conversion is an implicit user-defined conversion or explicit user-defined conversion.
///
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs
index 69ad0370f5ca2..b72eeca287d21 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKind.cs
@@ -68,5 +68,7 @@ internal enum ConversionKind : byte
InterpolatedStringHandler, // A conversion from an interpolated string literal to a type attributed with InterpolatedStringBuilderAttribute
InlineArray, // A conversion from an inline array to Span/ReadOnlySpan
+
+ ImplicitSpan, // A conversion between array, (ReadOnly)Span, string - part of the "first-class Span types" feature
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKindExtensions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKindExtensions.cs
index e0d3c4578f7b6..10a6f6c44b291 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKindExtensions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionKindExtensions.cs
@@ -53,6 +53,7 @@ public static bool IsImplicitConversion(this ConversionKind conversionKind)
case ObjectCreation:
case InlineArray:
case CollectionExpression:
+ case ImplicitSpan:
return true;
case ExplicitNumeric:
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
index 28c1c79ac1461..58f825feac71a 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
@@ -602,6 +602,7 @@ private static bool IsStandardImplicitConversionFromExpression(ConversionKind ki
case ConversionKind.StackAllocToPointerType:
case ConversionKind.StackAllocToSpanType:
case ConversionKind.InlineArray:
+ case ConversionKind.ImplicitSpan:
return true;
default:
return false;
@@ -906,6 +907,12 @@ private Conversion DeriveStandardExplicitFromOppositeStandardImplicitConversion(
break;
+ case ConversionKind.ImplicitSpan:
+ // Implicit span conversion, unlike other standard implicit conversions,
+ // does not imply opposite standard explicit conversion.
+ impliedExplicitConversion = Conversion.NoConversion;
+ break;
+
default:
throw ExceptionUtilities.UnexpectedValue(oppositeConversion.Kind);
}
@@ -1014,6 +1021,11 @@ private Conversion ClassifyImplicitBuiltInConversionFromExpression(BoundExpressi
return Conversion.ImplicitDynamic;
}
+ if (HasImplicitSpanConversion(source, destination, ref useSiteInfo))
+ {
+ return Conversion.ImplicitSpan;
+ }
+
// The following conversions only exist for certain form of expressions,
// if we have no expression none if them is applicable.
if (sourceExpression == null)
@@ -1916,6 +1928,12 @@ public Conversion ClassifyImplicitExtensionMethodThisArgConversion(BoundExpressi
{
return Conversion.ImplicitReference;
}
+
+ // PROTOTYPE: Investigate callers where Compilation is null.
+ if (Compilation is not null && HasImplicitSpanConversion(sourceType, destination, ref useSiteInfo))
+ {
+ return Conversion.ImplicitSpan;
+ }
}
if (sourceExpressionOpt?.Kind == BoundKind.TupleLiteral)
@@ -1977,6 +1995,7 @@ public static bool IsValidExtensionMethodThisArgConversion(Conversion conversion
case ConversionKind.Identity:
case ConversionKind.Boxing:
case ConversionKind.ImplicitReference:
+ case ConversionKind.ImplicitSpan:
return true;
case ConversionKind.ImplicitTuple:
@@ -3025,7 +3044,7 @@ internal bool HasImplicitConversionToOrImplementsVarianceCompatibleInterface(Bou
// The rules for variant interface and delegate conversions are the same:
//
// An interface/delegate type S is convertible to an interface/delegate type T
- // if and only if T is U and T is U such that for all
+ // if and only if S is U and T is U such that for all
// parameters of U:
//
// * if the ith parameter of U is invariant then Si is exactly equal to Ti.
@@ -3908,5 +3927,45 @@ private static bool IsIntegerTypeSupportingPointerConversions(TypeSymbol type)
return false;
}
+
+ private bool HasImplicitSpanConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo useSiteInfo)
+ {
+ if (!Compilation.IsFeatureEnabled(MessageID.IDS_FeatureFirstClassSpan))
+ {
+ return false;
+ }
+
+ // SPEC: From any single-dimensional `array_type` with element type `Ei`...
+ if (source is ArrayTypeSymbol { IsSZArray: true, ElementTypeWithAnnotations: { } elementType })
+ {
+ // SPEC: ...to `System.Span`.
+ if (destination.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_Span_T), TypeCompareKind.AllIgnoreOptions))
+ {
+ var spanElementType = ((NamedTypeSymbol)destination).TypeArgumentsWithDefinitionUseSiteDiagnostics(ref useSiteInfo)[0];
+ return hasIdentityConversion(elementType, spanElementType);
+ }
+
+ // SPEC: ...to `System.ReadOnlySpan`, provided that `Ei` is covariance-convertible to `Ui`.
+ if (destination.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions))
+ {
+ var spanElementType = ((NamedTypeSymbol)destination).TypeArgumentsWithDefinitionUseSiteDiagnostics(ref useSiteInfo)[0];
+ return hasCovariantConversion(elementType, spanElementType, ref useSiteInfo);
+ }
+ }
+
+ return false;
+
+ bool hasCovariantConversion(TypeWithAnnotations source, TypeWithAnnotations destination, ref CompoundUseSiteInfo useSiteInfo)
+ {
+ return hasIdentityConversion(source, destination) ||
+ HasImplicitReferenceConversion(source, destination, ref useSiteInfo);
+ }
+
+ bool hasIdentityConversion(TypeWithAnnotations source, TypeWithAnnotations destination)
+ {
+ return HasIdentityConversionInternal(source.Type, destination.Type) &&
+ HasTopLevelNullabilityIdentityConversion(source, destination);
+ }
+ }
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs
index 06f7ae0686a9b..d92bc7d996754 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs
@@ -666,6 +666,8 @@ private static bool IsEncompassingImplicitConversionKind(ConversionKind kind)
case ConversionKind.ImplicitPointer:
// Added for C# 12
case ConversionKind.InlineArray:
+ // Added for C# 13
+ case ConversionKind.ImplicitSpan:
return true;
default:
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 4c09a80debc1a..53b2b2adac17b 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -7956,4 +7956,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
foreach statement cannot operate on enumerators of type '{0}' because it is a type parameter that allows ref struct and it is not known at compile time to implement IDisposable.
+
+ first-class Span types
+
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
index 18fa9dbb51d6e..07ec814b1a908 100644
--- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs
+++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
@@ -286,6 +286,8 @@ internal enum MessageID
IDS_FeatureRefUnsafeInIteratorAsync = MessageBase + 12843,
IDS_FeatureRefStructInterfaces = MessageBase + 12844,
+
+ IDS_FeatureFirstClassSpan = MessageBase + 12845,
}
// Message IDs may refer to strings that need to be localized.
@@ -472,6 +474,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
case MessageID.IDS_FeatureParamsCollections:
case MessageID.IDS_FeatureRefUnsafeInIteratorAsync:
case MessageID.IDS_FeatureRefStructInterfaces:
+ case MessageID.IDS_FeatureFirstClassSpan:
return LanguageVersion.Preview;
// C# 12.0 features.
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
index c139e3daf28c4..09bcd2e580f8e 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
@@ -8890,6 +8890,7 @@ private TypeWithState VisitConversion(
break;
case ConversionKind.InlineArray:
+ case ConversionKind.ImplicitSpan:
if (checkConversion)
{
conversion = GenerateConversion(_conversions, conversionOperand, operandType.Type, targetType, fromExplicitCast, extensionMethodThisArgument, isChecked: conversionOpt?.Checked ?? false);
diff --git a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs
index 1f401b2ef6eff..ca544bb53940a 100644
--- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs
@@ -811,6 +811,8 @@ public override BoundNode VisitConversion(BoundConversion node)
}
break;
+ // PROTOTYPE: ImplicitSpan
+
default:
if (_inExpressionLambda && node.Conversion.Method is MethodSymbol method && (method.IsAbstract || method.IsVirtual) && method.IsStatic)
diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
index 4f6b4f96c378d..ec2931a2623d8 100644
--- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
@@ -614,6 +614,32 @@ private BoundExpression MakeConversionNodeCore(
return _factory.Call(null, createSpan, rewrittenOperand, _factory.Literal(length), useStrictArgumentRefKinds: true);
}
+ case ConversionKind.ImplicitSpan:
+ {
+ var spanType = (NamedTypeSymbol)rewrittenType;
+
+ WellKnownMember ctorMember;
+ if (spanType.OriginalDefinition.Equals(_compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions))
+ {
+ ctorMember = WellKnownMember.System_ReadOnlySpan_T__ctor_Array;
+ }
+ else
+ {
+ Debug.Assert(spanType.OriginalDefinition.Equals(_compilation.GetWellKnownType(WellKnownType.System_Span_T), TypeCompareKind.AllIgnoreOptions));
+ ctorMember = WellKnownMember.System_Span_T__ctor_Array;
+ }
+
+ if (!TryGetWellKnownTypeMember(rewrittenOperand.Syntax, ctorMember, out MethodSymbol? ctor))
+ {
+ Debug.Fail("We should have reported an error during binding for missing members for span conversion.");
+ return BadExpression(rewrittenOperand.Syntax, rewrittenType, []);
+ }
+ else
+ {
+ return new BoundObjectCreationExpression(rewrittenOperand.Syntax, ctor.AsMember((NamedTypeSymbol)rewrittenType), rewrittenOperand);
+ }
+ }
+
default:
break;
}
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index 482f74b8c1b7e..43efba95fb988 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -2317,6 +2317,11 @@
typy souborů
+
+
+ first-class Span types
+
+
obecné atributy
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index 458820646f0bd..fa820535f23e7 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -2317,6 +2317,11 @@
Dateitypen
+
+
+ first-class Span types
+
+
Generische Attribute
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index de96942b43ca1..b00d32316581c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -2317,6 +2317,11 @@
tipos de archivo
+
+
+ first-class Span types
+
+
atributos genéricos
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index cd8e3b4571564..b9dcdc4eea745 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -2317,6 +2317,11 @@
types de fichier
+
+
+ first-class Span types
+
+
attributs génériques
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index ee6c972ccf03d..a74a5e663019b 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -2317,6 +2317,11 @@
tipi di file
+
+
+ first-class Span types
+
+
attributi generici
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index 049964d81ce3a..550addc69a38c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -2317,6 +2317,11 @@
ファイルの種類
+
+
+ first-class Span types
+
+
汎用属性
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index dd8ef848b9a66..f7cb69c9bebe7 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -2317,6 +2317,11 @@
파일 형식
+
+
+ first-class Span types
+
+
제네릭 특성
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 871593fc5cad5..52289e76246a0 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -2317,6 +2317,11 @@
typy plików
+
+
+ first-class Span types
+
+
atrybuty ogólne
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index a4f21ff34b491..2d0cff5f73cc6 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -2317,6 +2317,11 @@
tipos de arquivo
+
+
+ first-class Span types
+
+
atributos genéricos
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 7bc750767181d..714d9b412b217 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -2317,6 +2317,11 @@
типы файлов
+
+
+ first-class Span types
+
+
универсальные атрибуты
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index 61a78dded475d..c485c0a4c9ec8 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -2317,6 +2317,11 @@
dosya türleri
+
+
+ first-class Span types
+
+
genel öznitelikler
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index b0175426fa302..6f78c4575cbd3 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -2317,6 +2317,11 @@
文件类型
+
+
+ first-class Span types
+
+
通用属性
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 59932f5945760..f0998b8629821 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -2317,6 +2317,11 @@
檔案類型
+
+
+ first-class Span types
+
+
一般屬性
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
index 999bf6667331d..1a9ce95de49b5 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
@@ -3575,7 +3575,12 @@ public sealed class JsonSerializerOptions
}
}
";
- var v = CompileAndVerify(source, options: TestOptions.DebugExe);
+ CreateCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics(
+ // (12,69): error CS0656: Missing compiler required member 'System.ReadOnlySpan`1..ctor'
+ // System.Text.Json.Serialization.JsonSerializer.Parse(await TestAsync());
+ Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "await TestAsync()").WithArguments("System.ReadOnlySpan`1", ".ctor").WithLocation(12, 69));
+
+ var v = CompileAndVerify(source, parseOptions: TestOptions.Regular12, options: TestOptions.DebugExe);
v.VerifyMethodBody("Program.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
index 73f912f5b7d23..93998dad18434 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
@@ -7167,7 +7167,7 @@ .locals init (delegate*, System.Span> V_0)
IL_0000: ldftn ""System.Span C.ChopSpan(System.Span)""
IL_0006: stloc.0
IL_0007: ldsfld ""char[] C.chars""
- IL_000c: call ""System.Span System.Span.op_Implicit(char[])""
+ IL_000c: newobj ""System.Span..ctor(char[])""
IL_0011: ldloc.0
IL_0012: calli ""delegate*, System.Span>""
IL_0017: call ""System.ReadOnlySpan System.Span.op_Implicit(System.Span)""
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenReadOnlySpanConstructionTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenReadOnlySpanConstructionTest.cs
index 2e808a3d5ec6f..02fcc6af09a6a 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenReadOnlySpanConstructionTest.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenReadOnlySpanConstructionTest.cs
@@ -193,38 +193,33 @@ public static void Main()
expectedOutput: type == "byte" ? "TrueTrue" : null,
verify: type == "byte" ? Verification.Passes : Verification.Skipped).VerifyIL("Test.Main", @$"
{{
- // Code size 77 (0x4d)
+ // Code size 75 (0x4b)
.maxstack 2
.locals init (System.ReadOnlySpan<{type}> V_0, //s1
- System.ReadOnlySpan<{type}> V_1, //s2
- System.ReadOnlySpan<{type}> V_2)
- IL_0000: ldloca.s V_2
+ System.ReadOnlySpan<{type}> V_1) //s2
+ IL_0000: ldloca.s V_0
IL_0002: initobj ""System.ReadOnlySpan<{type}>""
- IL_0008: ldloc.2
- IL_0009: stloc.0
- IL_000a: ldloca.s V_2
- IL_000c: initobj ""System.ReadOnlySpan<{type}>""
- IL_0012: ldloc.2
- IL_0013: stloc.1
- IL_0014: ldloca.s V_0
- IL_0016: call ""int System.ReadOnlySpan<{type}>.Length.get""
- IL_001b: ldloca.s V_1
- IL_001d: call ""int System.ReadOnlySpan<{type}>.Length.get""
- IL_0022: ceq
- IL_0024: call ""void System.Console.Write(bool)""
- IL_0029: ldnull
- IL_002a: call ""System.ReadOnlySpan<{type}> System.ReadOnlySpan<{type}>.op_Implicit({type}[])""
- IL_002f: stloc.0
- IL_0030: ldnull
- IL_0031: call ""System.ReadOnlySpan<{type}> System.ReadOnlySpan<{type}>.op_Implicit({type}[])""
- IL_0036: stloc.1
- IL_0037: ldloca.s V_0
- IL_0039: call ""int System.ReadOnlySpan<{type}>.Length.get""
- IL_003e: ldloca.s V_1
- IL_0040: call ""int System.ReadOnlySpan<{type}>.Length.get""
- IL_0045: ceq
- IL_0047: call ""void System.Console.Write(bool)""
- IL_004c: ret
+ IL_0008: ldloca.s V_1
+ IL_000a: initobj ""System.ReadOnlySpan<{type}>""
+ IL_0010: ldloca.s V_0
+ IL_0012: call ""int System.ReadOnlySpan<{type}>.Length.get""
+ IL_0017: ldloca.s V_1
+ IL_0019: call ""int System.ReadOnlySpan<{type}>.Length.get""
+ IL_001e: ceq
+ IL_0020: call ""void System.Console.Write(bool)""
+ IL_0025: ldloca.s V_0
+ IL_0027: ldnull
+ IL_0028: call ""System.ReadOnlySpan<{type}>..ctor({type}[])""
+ IL_002d: ldloca.s V_1
+ IL_002f: ldnull
+ IL_0030: call ""System.ReadOnlySpan<{type}>..ctor({type}[])""
+ IL_0035: ldloca.s V_0
+ IL_0037: call ""int System.ReadOnlySpan<{type}>.Length.get""
+ IL_003c: ldloca.s V_1
+ IL_003e: call ""int System.ReadOnlySpan<{type}>.Length.get""
+ IL_0043: ceq
+ IL_0045: call ""void System.Console.Write(bool)""
+ IL_004a: ret
}}");
}
@@ -417,40 +412,40 @@ public static void Main()
CompileAndVerify(comp, expectedOutput: "3", verify: Verification.Passes).VerifyIL("Test.Main", @"
{
- // Code size 72 (0x48)
- .maxstack 4
+ // Code size 73 (0x49)
+ .maxstack 5
.locals init (System.ReadOnlySpan