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

Default Interface Implementation: Unexpected behavior at runtime #8314

Closed
AlekseyTs opened this issue Jun 7, 2017 · 2 comments
Closed

Default Interface Implementation: Unexpected behavior at runtime #8314

AlekseyTs opened this issue Jun 7, 2017 · 2 comments

Comments

@AlekseyTs
Copy link
Contributor

CC @yizhang82

Compile and run the following code:

public interface I1<T>
{
    void M1()
    {
        System.Console.WriteLine("I1.M1");
    }
    void M2<S>()
    {
        System.Console.WriteLine("I1.M2");
    }
}

public interface I2<T> : I1<T>
{
    void I1<T>.M1() 
    {
        System.Console.WriteLine("I2.I1.M1");
    }
    void I1<T>.M2<S>() 
    {
        System.Console.WriteLine("I2.I1.M2");
    }
}

public interface I3<T> : I1<T>
{}

class Test1 : I1<int>
{
    static void Main()
    {
        I1<int> i1Int = new Test1();
        i1Int.M1();
        i1Int.M2<int>();
        I1<long> i1Long = new Test2();
        i1Long.M1();
        i1Long.M2<int>();
    }
}
class Test2 : I2<long>
{}

Observed:

I1.M1
I1.M2
I1.M1
I1.M2

Expected:

I1.M1
I1.M2
I2.I1.M1
I2.I1.M2

Here is the IL for the assembly:


//  Microsoft (R) .NET Framework IL Disassembler.  Version 4.6.1055.0
//  Copyright (c) Microsoft Corporation.  All rights reserved.



// Metadata version: v4.0.30319
.assembly extern System.Runtime
{
  .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )                         // .?_....:
  .ver 4:1:0:0
}
.assembly extern System.Console
{
  .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )                         // .?_....:
  .ver 4:0:0:0
}
.assembly debug7
{
  .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
  .custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                                   63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.

  // --- The following custom attribute is added automatically, do not uncomment -------
  //  .custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) 

  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module debug7.exe
// MVID: {2D9B8221-4878-4FA1-AEA5-814FD96D8095}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x01210000


// =============== CLASS MEMBERS DECLARATION ===================

.class interface public abstract auto ansi I1`1<T>
{
  .method public hidebysig newslot virtual 
          instance void  M1() cil managed
  {
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "I1.M1"
    IL_0006:  call       void [System.Console]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
  } // end of method I1`1::M1

  .method public hidebysig newslot virtual 
          instance void  M2<S>() cil managed
  {
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "I1.M2"
    IL_0006:  call       void [System.Console]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
  } // end of method I1`1::M2

} // end of class I1`1

.class interface public abstract auto ansi I2`1<T>
       implements class I1`1<!T>
{
  .method private hidebysig virtual final 
          instance void  'I1<T>.M1'() cil managed
  {
    .override  method instance void class I1`1<!T>::M1()
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "I2.I1.M1"
    IL_0006:  call       void [System.Console]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
  } // end of method I2`1::'I1<T>.M1'

  .method private hidebysig virtual final 
          instance void  'I1<T>.M2'<S>() cil managed
  {
    .override  method instance void class I1`1<!T>::M2<[1]>()
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "I2.I1.M2"
    IL_0006:  call       void [System.Console]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
  } // end of method I2`1::'I1<T>.M2'

} // end of class I2`1

.class interface public abstract auto ansi I3`1<T>
       implements class I1`1<!T>
{
} // end of class I3`1

.class private auto ansi beforefieldinit Test1
       extends [System.Runtime]System.Object
       implements class I1`1<int32>
{
  .method private hidebysig static void  Main() cil managed
  {
    .entrypoint
    // Code size       42 (0x2a)
    .maxstack  1
    .locals init (class I1`1<int32> V_0,
             class I1`1<int64> V_1)
    IL_0000:  nop
    IL_0001:  newobj     instance void Test1::.ctor()
    IL_0006:  stloc.0
    IL_0007:  ldloc.0
    IL_0008:  callvirt   instance void class I1`1<int32>::M1()
    IL_000d:  nop
    IL_000e:  ldloc.0
    IL_000f:  callvirt   instance void class I1`1<int32>::M2<int32>()
    IL_0014:  nop
    IL_0015:  newobj     instance void Test2::.ctor()
    IL_001a:  stloc.1
    IL_001b:  ldloc.1
    IL_001c:  callvirt   instance void class I1`1<int64>::M1()
    IL_0021:  nop
    IL_0022:  ldloc.1
    IL_0023:  callvirt   instance void class I1`1<int64>::M2<int32>()
    IL_0028:  nop
    IL_0029:  ret
  } // end of method Test1::Main

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       8 (0x8)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [System.Runtime]System.Object::.ctor()
    IL_0006:  nop
    IL_0007:  ret
  } // end of method Test1::.ctor

} // end of class Test1

.class private auto ansi beforefieldinit Test2
       extends [System.Runtime]System.Object
       implements class I2`1<int64>,
                  class I1`1<int64>
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       8 (0x8)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [System.Runtime]System.Object::.ctor()
    IL_0006:  nop
    IL_0007:  ret
  } // end of method Test2::.ctor

} // end of class Test2


// =============================================================
@yizhang82 yizhang82 self-assigned this Jun 7, 2017
@yizhang82
Copy link
Contributor

@AlekseyTs Thanks for reporting this. Most likely GVMs are not handled correctly today...

@yizhang82
Copy link
Contributor

This is addressed by dotnet/coreclr#12753

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the Future milestone Jan 31, 2020
MichalStrehovsky pushed a commit to MichalStrehovsky/runtime that referenced this issue Oct 12, 2020
* ARM64: PAL_GetCpuCapabilityFlags for Windows host

Use IsProcessorFeaturePresent to check for supported intrinsics
Moves intrinsic constants to seperate header as PalReadhackMinWin cannot include PalReadhawk.h

* ARM64: move constant values
@ghost ghost locked as resolved and limited conversation to collaborators Dec 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants