@@ -11300,5 +11300,162 @@ public static void M({{scoped2}} {{modifier}} R r) { }
11300
11300
""" ;
11301
11301
CreateCompilation ( source ) . VerifyDiagnostics ( ) ;
11302
11302
}
11303
+
11304
+ [ Theory , WorkItem ( "https://github.com/dotnet/roslyn/issues/78711" ) ]
11305
+ [ InlineData ( "public void UseSpan(Span<int> span)" , 17 ) ]
11306
+ [ InlineData ( "void I.UseSpan(Span<int> span)" , 12 ) ]
11307
+ public void RefStructInterface_ScopedDifference ( string implSignature , int column )
11308
+ {
11309
+ // This is a case where interface methods need to be treated specially in scoped variance checks.
11310
+ // Because a ref struct can implement the interface, we need to compare the signatures as if the interface has a receiver parameter which is ref-to-ref-struct.
11311
+ var source = $$ """
11312
+ using System;
11313
+
11314
+ interface I
11315
+ {
11316
+ void UseSpan(scoped Span<int> span);
11317
+ }
11318
+
11319
+ ref struct RS : I
11320
+ {
11321
+ public Span<int> Span { get; set; }
11322
+ public RS(Span<int> span) => Span = span;
11323
+
11324
+ {{ implSignature }} // 1
11325
+ {
11326
+ this.Span = span;
11327
+ }
11328
+ }
11329
+ """ ;
11330
+
11331
+ var comp = CreateCompilation ( source , targetFramework : TargetFramework . Net90 ) ;
11332
+ comp . VerifyEmitDiagnostics (
11333
+ // (13,17): error CS8987: The 'scoped' modifier of parameter 'span' doesn't match overridden or implemented member.
11334
+ // public void UseSpan(Span<int> span)
11335
+ Diagnostic ( ErrorCode . ERR_ScopedMismatchInParameterOfOverrideOrImplementation , "UseSpan" ) . WithArguments ( "span" ) . WithLocation ( 13 , column ) ) ;
11336
+ }
11337
+
11338
+ [ Theory , WorkItem ( "https://github.com/dotnet/roslyn/issues/78711" ) ]
11339
+ [ InlineData ( "public readonly void UseSpan(Span<int> span)" ) ]
11340
+ [ InlineData ( "readonly void I.UseSpan(Span<int> span)" ) ]
11341
+ public void RefStructInterface_ScopedDifference_ReadonlyImplementation ( string implSignature )
11342
+ {
11343
+ var source = $$ """
11344
+ using System;
11345
+
11346
+ interface I
11347
+ {
11348
+ void UseSpan(scoped Span<int> span);
11349
+ }
11350
+
11351
+ ref struct RS : I
11352
+ {
11353
+ public Span<int> Span { get; set; }
11354
+ public RS(Span<int> span) => Span = span;
11355
+
11356
+ {{ implSignature }}
11357
+ {
11358
+ Span = span; // 1
11359
+ }
11360
+ }
11361
+ """ ;
11362
+
11363
+ var comp = CreateCompilation ( source , targetFramework : TargetFramework . Net90 ) ;
11364
+ comp . VerifyEmitDiagnostics (
11365
+ // (15,9): error CS1604: Cannot assign to 'Span' because it is read-only
11366
+ // Span = span; // 1
11367
+ Diagnostic ( ErrorCode . ERR_AssgReadonlyLocal , "Span" ) . WithArguments ( "Span" ) . WithLocation ( 15 , 9 ) ) ;
11368
+ }
11369
+
11370
+ [ Fact , WorkItem ( "https://github.com/dotnet/roslyn/issues/78711" ) ]
11371
+ public void SimilarScenarioAs78711InvolvingNonReceiverParameter ( )
11372
+ {
11373
+ // Demonstrate a scenario similar to https://github.com/dotnet/roslyn/issues/78711 involving a non-receiver parameter has consistent behavior
11374
+ // In this case, the interface and implementation parameters cannot differ by type. But it as close as we can get to the receiver parameter case.
11375
+ var source = """
11376
+ using System;
11377
+
11378
+ interface I
11379
+ {
11380
+ void UseSpan1(ref RS rs, scoped Span<int> span);
11381
+ void UseSpan2(ref readonly RS rs, scoped Span<int> span);
11382
+ }
11383
+
11384
+ class C : I
11385
+ {
11386
+ public void UseSpan1(ref RS rs, Span<int> span) // 1
11387
+ {
11388
+ rs.Span = span;
11389
+ }
11390
+
11391
+ public void UseSpan2(ref readonly RS rs, Span<int> span)
11392
+ {
11393
+ rs.Span = span; // 2
11394
+ }
11395
+ }
11396
+
11397
+ ref struct RS
11398
+ {
11399
+ public Span<int> Span { get; set; }
11400
+ public RS(Span<int> span) => Span = span;
11401
+ }
11402
+ """ ;
11403
+
11404
+ var comp = CreateCompilation ( source , targetFramework : TargetFramework . Net90 ) ;
11405
+ comp . VerifyEmitDiagnostics (
11406
+ // (11,17): error CS8987: The 'scoped' modifier of parameter 'span' doesn't match overridden or implemented member.
11407
+ // public void UseSpan1(ref RS rs, Span<int> span) // 1
11408
+ Diagnostic ( ErrorCode . ERR_ScopedMismatchInParameterOfOverrideOrImplementation , "UseSpan1" ) . WithArguments ( "span" ) . WithLocation ( 11 , 17 ) ,
11409
+ // (18,9): error CS8332: Cannot assign to a member of variable 'rs' or use it as the right hand side of a ref assignment because it is a readonly variable
11410
+ // rs.Span = span; // 2
11411
+ Diagnostic ( ErrorCode . ERR_AssignReadonlyNotField2 , "rs.Span" ) . WithArguments ( "variable" , "rs" ) . WithLocation ( 18 , 9 ) ) ;
11412
+ }
11413
+
11414
+ [ Fact , WorkItem ( "https://github.com/dotnet/roslyn/issues/78711" ) ]
11415
+ public void Repro_78711 ( )
11416
+ {
11417
+ var source = """
11418
+ using System;
11419
+
11420
+ public static class Demo
11421
+ {
11422
+ public static void Show()
11423
+ {
11424
+ var stru = new Stru();
11425
+
11426
+ Unsafe(ref stru);
11427
+
11428
+ Console.Out.WriteLine(stru.Span);
11429
+ }
11430
+
11431
+ private static void Unsafe<T>(ref T stru) where T : IStru, allows ref struct
11432
+ {
11433
+ Span<char> span = stackalloc char[10];
11434
+
11435
+ "bug".CopyTo(span);
11436
+
11437
+ stru.UseSpan(span);
11438
+ }
11439
+ }
11440
+
11441
+ internal interface IStru
11442
+ {
11443
+ public void UseSpan(scoped Span<char> span);
11444
+ }
11445
+
11446
+ internal ref struct Stru : IStru
11447
+ {
11448
+ public Span<char> Span;
11449
+
11450
+ public void UseSpan(Span<char> span) => Span = span; // 1
11451
+ }
11452
+ """ ;
11453
+
11454
+ var comp = CreateCompilation ( source , targetFramework : TargetFramework . Net90 ) ;
11455
+ comp . VerifyEmitDiagnostics (
11456
+ // (33,17): error CS8987: The 'scoped' modifier of parameter 'span' doesn't match overridden or implemented member.
11457
+ // public void UseSpan(Span<char> span) => Span = span;
11458
+ Diagnostic ( ErrorCode . ERR_ScopedMismatchInParameterOfOverrideOrImplementation , "UseSpan" ) . WithArguments ( "span" ) . WithLocation ( 33 , 17 ) ) ;
11459
+ }
11303
11460
}
11304
11461
}
0 commit comments