未验证 提交 745c0094 编写于 作者: M msftbot[bot] 提交者: GitHub

Merge pull request #45248 from dotnet/merges/master-to-master-vs-deps

Merge master to master-vs-deps
......@@ -399,10 +399,15 @@ private BoundPattern BindDiscardPattern(DiscardPatternSyntax node, TypeSymbol in
diagnostics.Add(ErrorCode.ERR_PointerTypeInPatternMatching, typeSyntax.Location);
return true;
}
else if (patternType.IsNullableType() || typeSyntax is NullableTypeSyntax)
else if (patternType.IsNullableType())
{
// It is an error to use pattern-matching with a nullable type, because you'll never get null. Use the underlying type.
Error(diagnostics, ErrorCode.ERR_PatternNullableType, typeSyntax, patternType, patternType.GetNullableUnderlyingType());
Error(diagnostics, ErrorCode.ERR_PatternNullableType, typeSyntax, patternType.GetNullableUnderlyingType());
return true;
}
else if (typeSyntax is NullableTypeSyntax)
{
Error(diagnostics, ErrorCode.ERR_PatternNullableType, typeSyntax, patternType);
return true;
}
else if (patternType.IsStatic)
......
......@@ -5060,7 +5060,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<value>Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals.</value>
</data>
<data name="ERR_PatternNullableType" xml:space="preserve">
<value>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</value>
<value>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</value>
</data>
<data name="ERR_IsNullableType" xml:space="preserve">
<value>It is not legal to use nullable reference type '{0}?' in an is-type expression; use the underlying type '{0}' instead.</value>
......
......@@ -58,19 +58,46 @@ internal override void GenerateMethodBodyStatements(SyntheticBoundNodeFactory F,
internal static MethodSymbol? FindCopyConstructor(NamedTypeSymbol containingType, NamedTypeSymbol within, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
// We should handle ambiguities once we consider custom modifiers, as we do in overload resolution
// https://github.com/dotnet/roslyn/issues/45077
MethodSymbol? bestCandidate = null;
int bestModifierCountSoFar = -1; // stays as -1 unless we hit an ambiguity
foreach (var member in containingType.InstanceConstructors)
{
if (HasCopyConstructorSignature(member) &&
!member.HasUnsupportedMetadata &&
AccessCheck.IsSymbolAccessible(member, within, ref useSiteDiagnostics))
{
return member;
// If one has fewer custom modifiers, that is better
// (see OverloadResolution.BetterFunctionMember)
if (bestCandidate is null && bestModifierCountSoFar < 0)
{
bestCandidate = member;
continue;
}
if (bestModifierCountSoFar < 0)
{
bestModifierCountSoFar = bestCandidate.CustomModifierCount();
}
var memberModCount = member.CustomModifierCount();
if (memberModCount > bestModifierCountSoFar)
{
continue;
}
if (memberModCount == bestModifierCountSoFar)
{
bestCandidate = null;
continue;
}
bestCandidate = member;
bestModifierCountSoFar = memberModCount;
}
}
return null;
return bestCandidate;
}
internal static bool IsCopyConstructor(Symbol member)
......@@ -86,10 +113,8 @@ internal static bool IsCopyConstructor(Symbol member)
internal static bool HasCopyConstructorSignature(MethodSymbol member)
{
NamedTypeSymbol containingType = member.ContainingType;
// We should relax the comparison to AllIgnoreOptions, so that a copy constructor with a custom modifier is recognized
// https://github.com/dotnet/roslyn/issues/45077
return member is MethodSymbol { IsStatic: false, ParameterCount: 1, Arity: 0 } method &&
method.Parameters[0].Type.Equals(containingType, TypeCompareKind.CLRSignatureCompareOptions) &&
method.Parameters[0].Type.Equals(containingType, TypeCompareKind.AllIgnoreOptions) &&
method.Parameters[0].RefKind == RefKind.None;
}
}
......
......@@ -9766,8 +9766,8 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">Ve vzoru se nepovoluje použití typu s možnou hodnotou null {0}; místo toho použijte základní typ {1}.</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">Es ist unzulässig, den Nullable-Typ "{0}" in einem Muster zu verwenden. Verwenden Sie stattdessen den zugrunde liegenden Typ "{1}".</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">No se puede usar el tipo '{0}' que acepta valores NULL en un patrón; utilice el tipo '{1}' subyacente.</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">Il n'est pas correct d'utiliser le type Nullable '{0}' dans un modèle. Utilisez le type sous-jacent '{1}' à la place.</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">Non è consentito usare il tipo nullable '{0}' in un criterio. Usare il tipo sottostante '{1}'.</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">パターンで Null 許容型 '{0}' を使用することはできません。代わりに基になる型 '{1}' をご使用ください。</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">패턴에 nullable 형식 '{0}'을(를) 사용하는 것은 올바르지 않습니다. 대신 기본 형식 '{1}'을(를) 사용하세요.</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">Użycie typu dopuszczającego wartość null „{0}” jest niedozwolone we wzorcu. Użyj zamiast tego bazowego typu „{1}”.</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9764,8 +9764,8 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">É ilegal usar o tipo que permite valor nulo '{0}' em um padrão; em vez disso, use o tipo subjacente '{1}'.</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">Запрещено использовать тип "{0}", допускающий значение NULL, в шаблоне. Используйте вместо него базовый тип "{1}".</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">Boş değer atanabilir '{0}' türünün bir desende kullanılması yasaktır; bunun yerine temel alınan '{1}' türünü kullanın.</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">在模式中使用可以为 null 的类型“{0}”是非法的;请改用基础类型“{1}”。</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -9766,8 +9766,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_PatternNullableType">
<source>It is not legal to use nullable type '{0}' in a pattern; use the underlying type '{1}' instead.</source>
<target state="translated">在模式中使用可為 Null 的型別 '{0}' 不合法; 請改用基礎類型 '{1}'。</target>
<source>It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</source>
<target state="new">It is not legal to use nullable type '{0}?' in a pattern; use the underlying type '{0}' instead.</target>
<note />
</trans-unit>
<trans-unit id="ERR_PeWritingFailure">
......
......@@ -145,7 +145,7 @@ public static void T(object x)
compilation.VerifyDiagnostics(
// (11,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
// if (x is Nullable<int> y) Console.WriteLine($"expression {x} is Nullable<int> y");
Diagnostic(ErrorCode.ERR_PatternNullableType, "Nullable<int>").WithArguments("int?", "int").WithLocation(11, 18)
Diagnostic(ErrorCode.ERR_PatternNullableType, "Nullable<int>").WithArguments("int").WithLocation(11, 18)
);
}
......@@ -219,7 +219,7 @@ public static void Main()
Diagnostic(ErrorCode.ERR_BadPatternExpression, "null").WithArguments("<null>").WithLocation(10, 13),
// (11,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
// if (s is NullableInt x) { } // error: cannot use nullable type
Diagnostic(ErrorCode.ERR_PatternNullableType, "NullableInt").WithArguments("int?", "int").WithLocation(11, 18),
Diagnostic(ErrorCode.ERR_PatternNullableType, "NullableInt").WithArguments("int").WithLocation(11, 18),
// (12,18): error CS8121: An expression of type 'string' cannot be handled by a pattern of type 'long'.
// if (s is long l) { } // error: cannot convert string to long
Diagnostic(ErrorCode.ERR_PatternWrongType, "long").WithArguments("string", "long").WithLocation(12, 18),
......
......@@ -2573,6 +2573,65 @@ public void M(string s)
);
}
[Fact]
public void IsNullableReferenceType_01()
{
var source =
@"#nullable enable
public class C {
public void M1(object o) {
var t = o is string? { };
}
public void M2(object o) {
var t = o is (string? { });
}
public void M3(object o) {
var t = o is string?;
}
public void M4(object o) {
var t = o is string? _;
}
public void M5(object o) {
var t = o is (string? _);
}
}";
CreateCompilation(source, parseOptions: TestOptions.RegularWithPatternCombinators).VerifyDiagnostics(
// (4,22): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
// var t = o is string? { };
Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(4, 22),
// (7,22): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'object', with 2 out parameters and a void return type.
// var t = o is (string? { });
Diagnostic(ErrorCode.ERR_MissingDeconstruct, "(string? { })").WithArguments("object", "2").WithLocation(7, 22),
// (7,29): error CS1003: Syntax error, ',' expected
// var t = o is (string? { });
Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(",", "?").WithLocation(7, 29),
// (7,31): error CS1003: Syntax error, ',' expected
// var t = o is (string? { });
Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments(",", "{").WithLocation(7, 31),
// (10,22): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead.
// var t = o is string?;
Diagnostic(ErrorCode.ERR_IsNullableType, "string?").WithArguments("string").WithLocation(10, 22),
// (13,30): error CS0103: The name '_' does not exist in the current context
// var t = o is string? _;
Diagnostic(ErrorCode.ERR_NameNotInContext, "_").WithArguments("_").WithLocation(13, 30),
// (13,31): error CS1003: Syntax error, ':' expected
// var t = o is string? _;
Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(":", ";").WithLocation(13, 31),
// (13,31): error CS1525: Invalid expression term ';'
// var t = o is string? _;
Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(13, 31),
// (16,22): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'object', with 2 out parameters and a void return type.
// var t = o is (string? _);
Diagnostic(ErrorCode.ERR_MissingDeconstruct, "(string? _)").WithArguments("object", "2").WithLocation(16, 22),
// (16,29): error CS1003: Syntax error, ',' expected
// var t = o is (string? _);
Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(",", "?").WithLocation(16, 29),
// (16,31): error CS1003: Syntax error, ',' expected
// var t = o is (string? _);
Diagnostic(ErrorCode.ERR_SyntaxError, "_").WithArguments(",", "").WithLocation(16, 31)
);
}
[Fact]
public void IsAlwaysPatternKinds()
{
......
......@@ -4330,6 +4330,57 @@ .maxstack 2
}");
}
[Fact, WorkItem(44902, "https://github.com/dotnet/roslyn/issues/44902")]
public void CopyCtor_NotInRecordType()
{
var source =
@"public class C
{
public object Property { get; set; }
public int field = 42;
public C(C c)
{
}
}
public class D : C
{
public int field2 = 43;
public D(D d) : base(d)
{
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var verifier = CompileAndVerify(comp);
verifier.VerifyIL("C..ctor(C)", @"
{
// Code size 15 (0xf)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.s 42
IL_0003: stfld ""int C.field""
IL_0008: ldarg.0
IL_0009: call ""object..ctor()""
IL_000e: ret
}");
verifier.VerifyIL("D..ctor(D)", @"
{
// Code size 16 (0x10)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.s 43
IL_0003: stfld ""int D.field2""
IL_0008: ldarg.0
IL_0009: ldarg.1
IL_000a: call ""C..ctor(C)""
IL_000f: ret
}");
}
[Fact, WorkItem(44902, "https://github.com/dotnet/roslyn/issues/44902")]
public void CopyCtor_UserDefinedButDoesNotDelegateToBaseCopyCtor()
{
......@@ -5111,6 +5162,227 @@ public void CopyCtor_InaccessibleInMetadata()
);
}
[Fact, WorkItem(45077, "https://github.com/dotnet/roslyn/issues/45077")]
public void CopyCtor_AmbiguitiesInMetadata()
{
// IL for a minimal `public record B { }` with injected copy constructors
var ilSource_template = @"
.class public auto ansi beforefieldinit B extends [mscorlib]System.Object
{
INJECT
.method public hidebysig specialname newslot virtual instance class B '<>Clone' () cil managed
{
IL_0000: ldarg.0
IL_0001: newobj instance void B::.ctor(class B)
IL_0006: ret
}
.method public hidebysig specialname rtspecialname instance void .ctor () cil managed
{
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
}
}
";
var source = @"
public record C : B
{
public static void Main()
{
var c = new C();
_ = c with { };
}
}";
// We're going to inject various copy constructors into record B (at INJECT marker), and check which one is used
// by derived record C
// The RAN and THROW markers are shorthands for method bodies that print "RAN" and throw, respectively.
// .ctor(B) vs. .ctor(modopt B)
verifyBoth(@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B '' ) cil managed
RAN
",
@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int64) '' ) cil managed
THROW
");
// .ctor(modopt B) alone
verify(@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int64) '' ) cil managed
RAN
");
// .ctor(B) vs. .ctor(modreq B)
verifyBoth(@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B '' ) cil managed
RAN
",
@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modreq(int64) '' ) cil managed
THROW
");
// .ctor(modopt B) vs. .ctor(modreq B)
verifyBoth(@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int64) '' ) cil managed
RAN
",
@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modreq(int64) '' ) cil managed
THROW
");
// .ctor(B) vs. .ctor(modopt1 B) and .ctor(modopt2 B)
verifyBoth(@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B '' ) cil managed
RAN
",
@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int64) '' ) cil managed
THROW
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int32) '' ) cil managed
THROW
");
// .ctor(B) vs. .ctor(modopt1 B) and .ctor(modreq B)
verifyBoth(@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B '' ) cil managed
RAN
",
@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int64) '' ) cil managed
THROW
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modreq(int32) '' ) cil managed
THROW
");
// .ctor(modeopt1 B) vs. .ctor(modopt2 B)
verifyBoth(@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int64) '' ) cil managed
THROW
",
@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int32) '' ) cil managed
THROW
", isError: true);
// private .ctor(B) vs. .ctor(modopt1 B) and .ctor(modopt B)
verifyBoth(@"
.method private hidebysig specialname rtspecialname instance void .ctor ( class B '' ) cil managed
RAN
",
@"
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int64) '' ) cil managed
THROW
.method public hidebysig specialname rtspecialname instance void .ctor ( class B modopt(int32) '' ) cil managed
THROW
", isError: true);
void verifyBoth(string inject1, string inject2, bool isError = false)
{
verify(inject1 + inject2, isError);
verify(inject2 + inject1, isError);
}
void verify(string inject, bool isError = false)
{
var ranBody = @"
{
IL_0000: ldstr ""RAN""
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
}
";
var throwBody = @"
{
IL_0000: ldnull
IL_0001: throw
}
";
var comp = CreateCompilationWithIL(new[] { source, IsExternalInitTypeDefinition },
ilSource: ilSource_template.Replace("INJECT", inject).Replace("RAN", ranBody).Replace("THROW", throwBody),
parseOptions: TestOptions.RegularPreview, options: TestOptions.DebugExe);
var expectedDiagnostics = isError ? new[] {
// (2,15): error CS8867: No accessible copy constructor found in base type 'B'.
// public record C : B
Diagnostic(ErrorCode.ERR_NoCopyConstructorInBaseType, "C").WithArguments("B").WithLocation(2, 15)
} : new DiagnosticDescription[] { };
comp.VerifyDiagnostics(expectedDiagnostics);
if (expectedDiagnostics is null)
{
CompileAndVerify(comp, expectedOutput: "RAN");
}
}
}
[Fact, WorkItem(45077, "https://github.com/dotnet/roslyn/issues/45077")]
public void CopyCtor_AmbiguitiesInMetadata_GenericType()
{
// IL for a minimal `public record B<T> { }` with modopt in nested position of parameter type
var ilSource = @"
.class public auto ansi beforefieldinit B`1<T> extends [mscorlib]System.Object implements class [mscorlib]System.IEquatable`1<class B`1<!T>>
{
.method family hidebysig specialname rtspecialname instance void .ctor ( class B`1<!T modopt(int64)> '' ) cil managed
{
IL_0000: ldstr ""RAN""
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
}
.method public hidebysig specialname newslot virtual instance class B`1<!T> '<>Clone' () cil managed
{
IL_0000: ldarg.0
IL_0001: newobj instance void class B`1<!T>::.ctor(class B`1<!0>)
IL_0006: ret
}
.method public hidebysig specialname rtspecialname instance void .ctor () cil managed
{
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
}
.method public newslot virtual instance bool Equals ( class B`1<!T> '' ) cil managed
{
IL_0000: ldnull
IL_0001: throw
}
}
";
var source = @"
public record C<T> : B<T> { }
public class Program
{
public static void Main()
{
var c = new C<string>();
_ = c with { };
}
}";
var comp = CreateCompilationWithIL(new[] { source, IsExternalInitTypeDefinition },
ilSource: ilSource,
parseOptions: TestOptions.RegularPreview, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "RAN");
}
[Fact]
public void Deconstruct_Simple()
{
......
......@@ -211,7 +211,7 @@ public sealed class NotNullIfNotNullAttribute : Attribute
protected const string IsExternalInitTypeDefinition = @"
namespace System.Runtime.CompilerServices
{
public sealed class IsExternalInit
public static class IsExternalInit
{
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册