提交 238db4f7 编写于 作者: A AlekseyTs

Add support for custom modifiers referencing generic types.

Fixes #5725.
上级 a4e375b9
......@@ -15,7 +15,6 @@ bool Cci.ICustomModifier.IsOptional
Cci.ITypeReference Cci.ICustomModifier.GetModifier(EmitContext context)
{
Debug.Assert(this.Modifier.IsDefinition);
return ((PEModuleBuilder)context.Module).Translate(this.Modifier, (CSharpSyntaxNode)context.SyntaxNodeOpt, context.Diagnostics);
}
}
......
......@@ -145,9 +145,50 @@ internal ImmutableArray<CustomModifier> SubstituteCustomModifiers(TypeSymbol typ
return new TypeWithModifiers(type, customModifiers).SubstituteType(this).CustomModifiers;
}
return customModifiers;
return SubstituteCustomModifiers(customModifiers);
}
internal ImmutableArray<CustomModifier> SubstituteCustomModifiers(ImmutableArray<CustomModifier> customModifiers)
{
if (customModifiers.IsDefaultOrEmpty)
{
return customModifiers;
}
for (int i = 0; i < customModifiers.Length; i++)
{
var modifier = (NamedTypeSymbol)customModifiers[i].Modifier;
var substituted = SubstituteNamedType(modifier);
if (modifier != substituted)
{
var builder = ArrayBuilder<CustomModifier>.GetInstance(customModifiers.Length);
builder.AddRange(customModifiers, i);
builder.Add(customModifiers[i].IsOptional ? CSharpCustomModifier.CreateOptional(substituted) : CSharpCustomModifier.CreateRequired(substituted));
for (i++; i < customModifiers.Length; i++)
{
modifier = (NamedTypeSymbol)customModifiers[i].Modifier;
substituted = SubstituteNamedType(modifier);
if (modifier != substituted)
{
builder.Add(customModifiers[i].IsOptional ? CSharpCustomModifier.CreateOptional(substituted) : CSharpCustomModifier.CreateRequired(substituted));
}
else
{
builder.Add(customModifiers[i]);
}
}
Debug.Assert(builder.Count == customModifiers.Length);
return builder.ToImmutableAndFree();
}
}
return customModifiers;
}
protected virtual TypeSymbol SubstituteDynamicType()
{
return DynamicTypeSymbol.Instance;
......
......@@ -934,7 +934,15 @@ internal bool DeriveUseSiteDiagnosticFromCustomModifiers(ref DiagnosticInfo resu
{
foreach (CustomModifier modifier in customModifiers)
{
if (DeriveUseSiteDiagnosticFromType(ref result, (TypeSymbol)modifier.Modifier))
var modifierType = (NamedTypeSymbol)modifier.Modifier;
// Unbound generic type is valid as a modifier, let's not report any use site diagnostics because of that.
if (modifierType.IsUnboundGenericType )
{
modifierType = modifierType.OriginalDefinition;
}
if (DeriveUseSiteDiagnosticFromType(ref result, modifierType))
{
return true;
}
......
......@@ -86,14 +86,15 @@ public TypeSymbol AsTypeSymbolOnly()
public TypeWithModifiers SubstituteType(AbstractTypeMap typeMap)
{
var newCustomModifiers = typeMap.SubstituteCustomModifiers(this.CustomModifiers);
var newTypeWithModifiers = typeMap.SubstituteType(this.Type);
if (!newTypeWithModifiers.Is(this.Type))
if (!newTypeWithModifiers.Is(this.Type) || newCustomModifiers != this.CustomModifiers)
{
return new TypeWithModifiers(newTypeWithModifiers.Type, this.CustomModifiers.Concat(newTypeWithModifiers.CustomModifiers));
return new TypeWithModifiers(newTypeWithModifiers.Type, newCustomModifiers.Concat(newTypeWithModifiers.CustomModifiers));
}
else
{
return this; // substitution had no effect on the type
return this; // substitution had no effect on the type or modifiers
}
}
}
......
......@@ -1370,5 +1370,214 @@ public override void Test(int [,] c)
CompileAndVerify(compilation, expectedOutput: @"Test
Overriden");
}
[ClrOnlyFact(ClrOnlyReason.Ilasm), WorkItem(5725, "https://github.com/dotnet/roslyn/issues/5725")]
public void ModifiersWithConstructedType_01()
{
var ilSource = @"
.class public auto ansi beforefieldinit CL1`1<valuetype .ctor ([mscorlib]System.ValueType) T1>
extends[mscorlib] System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void[mscorlib] System.Object::.ctor()
IL_0006:
ret
} // end of method CL1`1::.ctor
.method public hidebysig newslot virtual
instance void Test(!T1 modopt(valuetype [mscorlib]System.Nullable`1<!T1>) t1) cil managed
{
// Code size 1 (0x1)
.maxstack 1
IL_0000: ldstr ""Test""
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method CL1`1::Test
} // end of class CL1`1
.class public auto ansi beforefieldinit CL2
extends class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>::.ctor()
IL_0006: ret
} // end of method CL2::.ctor
} // end of class CL2
";
var source = @"
class Test
{
static void Main()
{
var x = new CL2();
x.Test(1);
x = new CL3();
x.Test(1);
}
}
class CL3 : CL2
{
public override void Test(int c)
{
System.Console.WriteLine(""Overriden"");
}
}";
var compilation = CreateCompilationWithCustomILSource(source, ilSource, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"Test
Overriden");
}
[ClrOnlyFact(ClrOnlyReason.Ilasm), WorkItem(5725, "https://github.com/dotnet/roslyn/issues/5725")]
public void ModifiersWithConstructedType_02()
{
var ilSource = @"
.class public auto ansi beforefieldinit CL1`1<valuetype .ctor ([mscorlib]System.ValueType) T1>
extends[mscorlib] System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void[mscorlib] System.Object::.ctor()
IL_0006:
ret
} // end of method CL1`1::.ctor
.method public hidebysig newslot virtual
instance void Test(!T1 modopt(valuetype [mscorlib]System.Nullable`1) t1) cil managed
{
// Code size 1 (0x1)
.maxstack 1
IL_0000: ldstr ""Test""
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method CL1`1::Test
} // end of class CL1`1
.class public auto ansi beforefieldinit CL2
extends class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>::.ctor()
IL_0006: ret
} // end of method CL2::.ctor
} // end of class CL2
";
var source = @"
class Test
{
static void Main()
{
var x = new CL2();
x.Test(1);
x = new CL3();
x.Test(1);
}
}
class CL3 : CL2
{
public override void Test(int c)
{
System.Console.WriteLine(""Overriden"");
}
}";
var compilation = CreateCompilationWithCustomILSource(source, ilSource, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"Test
Overriden");
}
[ClrOnlyFact(ClrOnlyReason.Ilasm), WorkItem(5725, "https://github.com/dotnet/roslyn/issues/5725")]
public void ModifiersWithConstructedType_03()
{
var ilSource = @"
.class public auto ansi beforefieldinit CL1`1<valuetype .ctor ([mscorlib]System.ValueType) T1>
extends[mscorlib] System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void[mscorlib] System.Object::.ctor()
IL_0006:
ret
} // end of method CL1`1::.ctor
.method public hidebysig newslot virtual
instance int32 modopt(CL2) modopt(valuetype [mscorlib]System.Nullable`1<!T1>) modopt(valuetype [mscorlib]System.Nullable`1<!T1>) modopt(CL2) [] Test(!T1 t1) cil managed
{
// Code size 1 (0x1)
.maxstack 1
IL_0000: ldstr ""Test""
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_0006: ldnull
IL_000a: ret
} // end of method CL1`1::Test
} // end of class CL1`1
.class public auto ansi beforefieldinit CL2
extends class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>::.ctor()
IL_0006: ret
} // end of method CL2::.ctor
} // end of class CL2
";
var source = @"
class Test
{
static void Main()
{
var x = new CL2();
x.Test(1);
x = new CL3();
x.Test(1);
}
}
class CL3 : CL2
{
public override int[] Test(int c)
{
System.Console.WriteLine(""Overriden"");
return null;
}
}";
var compilation = CreateCompilationWithCustomILSource(source, ilSource, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"Test
Overriden");
}
}
}
\ No newline at end of file
......@@ -309,56 +309,63 @@ private TypeSymbol DecodeTypeOrThrow(ref BlobReader ppSig, SignatureTypeCode typ
break;
case SignatureTypeCode.GenericTypeInstance:
SignatureTypeCode elementTypeCode = ppSig.ReadSignatureTypeCode();
if (elementTypeCode != SignatureTypeCode.TypeHandle)
{
throw new UnsupportedSignatureContent();
}
typeSymbol = DecodeGenericTypeInstanceOrThrow(ref ppSig, out refersToNoPiaLocalType);
break;
EntityHandle tokenGeneric = ppSig.ReadTypeHandle();
int argumentCount;
if (!ppSig.TryReadCompressedInteger(out argumentCount))
{
throw new UnsupportedSignatureContent();
}
default:
throw new UnsupportedSignatureContent();
}
TypeSymbol generic = GetTypeOfToken(tokenGeneric, out refersToNoPiaLocalType);
Debug.Assert(!refersToNoPiaLocalType || generic.TypeKind == TypeKind.Error);
return typeSymbol;
}
var argumentsBuilder = ArrayBuilder<KeyValuePair<TypeSymbol, ImmutableArray<ModifierInfo<TypeSymbol>>>>.GetInstance(argumentCount);
var argumentRefersToNoPiaLocalTypeBuilder = ArrayBuilder<bool>.GetInstance(argumentCount);
private TypeSymbol DecodeGenericTypeInstanceOrThrow(ref BlobReader ppSig, out bool refersToNoPiaLocalType)
{
SignatureTypeCode elementTypeCode = ppSig.ReadSignatureTypeCode();
if (elementTypeCode != SignatureTypeCode.TypeHandle)
{
throw new UnsupportedSignatureContent();
}
for (int argumentIndex = 0; argumentIndex < argumentCount; argumentIndex++)
{
bool argumentRefersToNoPia;
modifiers = DecodeModifiersOrThrow(ref ppSig, out typeCode);
argumentsBuilder.Add(KeyValuePair.Create(DecodeTypeOrThrow(ref ppSig, typeCode, out argumentRefersToNoPia), modifiers));
argumentRefersToNoPiaLocalTypeBuilder.Add(argumentRefersToNoPia);
}
EntityHandle tokenGeneric = ppSig.ReadTypeHandle();
int argumentCount;
if (!ppSig.TryReadCompressedInteger(out argumentCount))
{
throw new UnsupportedSignatureContent();
}
// The instantiated type might have a generic parent, in which case some or all of the type
// arguments might actually be for the parent.
TypeSymbol generic = GetTypeOfToken(tokenGeneric, out refersToNoPiaLocalType);
Debug.Assert(!refersToNoPiaLocalType || generic.TypeKind == TypeKind.Error);
var arguments = argumentsBuilder.ToImmutableAndFree();
var argumentRefersToNoPiaLocalType = argumentRefersToNoPiaLocalTypeBuilder.ToImmutableAndFree();
typeSymbol = SubstituteTypeParameters(generic, arguments, argumentRefersToNoPiaLocalType);
var argumentsBuilder = ArrayBuilder<KeyValuePair<TypeSymbol, ImmutableArray<ModifierInfo<TypeSymbol>>>>.GetInstance(argumentCount);
var argumentRefersToNoPiaLocalTypeBuilder = ArrayBuilder<bool>.GetInstance(argumentCount);
foreach (bool flag in argumentRefersToNoPiaLocalType)
{
if (flag)
{
refersToNoPiaLocalType = true;
break;
}
}
for (int argumentIndex = 0; argumentIndex < argumentCount; argumentIndex++)
{
bool argumentRefersToNoPia;
SignatureTypeCode typeCode;
ImmutableArray<ModifierInfo<TypeSymbol>> modifiers = DecodeModifiersOrThrow(ref ppSig, out typeCode);
argumentsBuilder.Add(KeyValuePair.Create(DecodeTypeOrThrow(ref ppSig, typeCode, out argumentRefersToNoPia), modifiers));
argumentRefersToNoPiaLocalTypeBuilder.Add(argumentRefersToNoPia);
}
break;
// The instantiated type might have a generic parent, in which case some or all of the type
// arguments might actually be for the parent.
default:
throw new UnsupportedSignatureContent();
var arguments = argumentsBuilder.ToImmutableAndFree();
var argumentRefersToNoPiaLocalType = argumentRefersToNoPiaLocalTypeBuilder.ToImmutableAndFree();
TypeSymbol typeSymbol = SubstituteTypeParameters(generic, arguments, argumentRefersToNoPiaLocalType);
foreach (bool flag in argumentRefersToNoPiaLocalType)
{
if (flag)
{
refersToNoPiaLocalType = true;
break;
}
}
return typeSymbol;
return typeSymbol;
}
/// <exception cref="UnsupportedSignatureContent">If the encoded type is invalid.</exception>
......@@ -653,13 +660,7 @@ private ImmutableArray<ModifierInfo<TypeSymbol>> DecodeModifiersOrThrow(ref Blob
if (typeCode == SignatureTypeCode.OptionalModifier)
{
EntityHandle token = signatureReader.ReadTypeHandle();
ModifierInfo<TypeSymbol> modifier = new ModifierInfo<TypeSymbol>(true, GetTypeOfToken(token));
if (!IsAcceptableModOptModifier(token, modifier.Modifier))
{
throw new UnsupportedSignatureContent();
}
ModifierInfo<TypeSymbol> modifier = new ModifierInfo<TypeSymbol>(true, DecodeModifierTypeOrThrow(ref signatureReader));
if (modifiers == null)
{
......@@ -676,48 +677,83 @@ private ImmutableArray<ModifierInfo<TypeSymbol>> DecodeModifiersOrThrow(ref Blob
return modifiers?.ToImmutableAndFree() ?? default(ImmutableArray<ModifierInfo<TypeSymbol>>);
}
/// <summary>
/// According to ECMA spec:
/// The CMOD_OPT or CMOD_REQD is followed by a metadata token that
/// indexes a row in the TypeDef table or the TypeRef table.
/// i.e. No modopt in DecodeType (though it still works in DecodeModifier).
/// </summary>
private static bool IsAcceptableModOptModifier(EntityHandle token, TypeSymbol modifier)
private TypeSymbol DecodeModifierTypeOrThrow(ref BlobReader signatureReader)
{
EntityHandle token = signatureReader.ReadTypeHandle();
TypeSymbol type;
bool isNoPiaLocalType;
// According to ECMA spec:
// The CMOD_OPT or CMOD_REQD is followed by a metadata token that
// indexes a row in the TypeDef table or the TypeRef table.
tryAgain:
switch (token.Kind)
{
case HandleKind.TypeDefinition:
type = GetTypeOfTypeDef((TypeDefinitionHandle)token, out isNoPiaLocalType, isContainingType: false);
// it is valid for a modifier to refer to an unconstructed type, we need to preserve this fact
type = SubstituteWithUnboundIfGeneric(type);
break;
case HandleKind.TypeReference:
return true;
type = GetTypeOfTypeRef((TypeReferenceHandle)token, out isNoPiaLocalType);
// it is valid for a modifier to refer to an unconstructed type, we need to preserve this fact
type = SubstituteWithUnboundIfGeneric(type);
break;
case HandleKind.TypeSpecification:
// Section 23.2.7 of the CLI spec specifically says that this is not allowed (see comment on method),
// but, apparently, ilasm turns modopt(int32) into a TypeSpec.
if (modifier != null)
// In addition, managed C++ compiler can use constructed generic types as modifiers, for example Nullable<bool>, etc.
// We will support only cases like these even though it looks like CLR allows any types that can be encoded through a TypeSpec.
BlobReader memoryReader = this.Module.GetTypeSpecificationSignatureReaderOrThrow((TypeSpecificationHandle)token);
SignatureTypeCode typeCode = memoryReader.ReadSignatureTypeCode();
bool refersToNoPiaLocalType;
switch (typeCode)
{
switch (modifier.SpecialType)
{
case SpecialType.System_Void:
case SpecialType.System_Boolean:
case SpecialType.System_SByte:
case SpecialType.System_Byte:
case SpecialType.System_Int16:
case SpecialType.System_UInt16:
case SpecialType.System_Int32:
case SpecialType.System_UInt32:
case SpecialType.System_Int64:
case SpecialType.System_UInt64:
case SpecialType.System_Single:
case SpecialType.System_Double:
case SpecialType.System_Char:
case SpecialType.System_String:
case SpecialType.System_Object:
return true;
}
case SignatureTypeCode.Void:
case SignatureTypeCode.Boolean:
case SignatureTypeCode.SByte:
case SignatureTypeCode.Byte:
case SignatureTypeCode.Int16:
case SignatureTypeCode.UInt16:
case SignatureTypeCode.Int32:
case SignatureTypeCode.UInt32:
case SignatureTypeCode.Int64:
case SignatureTypeCode.UInt64:
case SignatureTypeCode.Single:
case SignatureTypeCode.Double:
case SignatureTypeCode.Char:
case SignatureTypeCode.String:
case SignatureTypeCode.IntPtr:
case SignatureTypeCode.UIntPtr:
case SignatureTypeCode.Object:
case SignatureTypeCode.TypedReference:
type = GetSpecialType(typeCode.ToSpecialType());
break;
case SignatureTypeCode.TypeHandle:
token = memoryReader.ReadTypeHandle();
goto tryAgain;
case SignatureTypeCode.GenericTypeInstance:
type = DecodeGenericTypeInstanceOrThrow(ref memoryReader, out refersToNoPiaLocalType);
break;
default:
throw new UnsupportedSignatureContent();
}
return false;
break;
default:
return false;
throw new UnsupportedSignatureContent();
}
return type;
}
/// <exception cref="UnsupportedSignatureContent">If the encoded local variable type is invalid.</exception>
......@@ -1645,14 +1681,23 @@ protected TypeSymbol DecodeFieldSignature(ref BlobReader signatureReader, out bo
if (typeCode == SignatureTypeCode.OptionalModifier ||
typeCode == SignatureTypeCode.RequiredModifier)
{
EntityHandle token = signatureReader.ReadTypeHandle();
ModifierInfo<TypeSymbol> modifier = new ModifierInfo<TypeSymbol>((typeCode == SignatureTypeCode.OptionalModifier), GetTypeOfToken(token));
TypeSymbol type;
if (!IsAcceptableModOptModifier(token, modifier.Modifier))
try
{
type = DecodeModifierTypeOrThrow(ref signatureReader);
}
catch (BadImageFormatException mrEx)
{
return GetUnsupportedMetadataTypeSymbol(mrEx); // an exception from metadata reader.
}
catch (UnsupportedSignatureContent)
{
return GetUnsupportedMetadataTypeSymbol(); // unsupported signature content
}
ModifierInfo<TypeSymbol> modifier = new ModifierInfo<TypeSymbol>((typeCode == SignatureTypeCode.OptionalModifier), type);
if (IsVolatileModifierType(modifier.Modifier))
{
isVolatile = true;
......
......@@ -15,7 +15,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Property
Private Function CciGetModifier(context As EmitContext) As Cci.ITypeReference Implements Cci.ICustomModifier.GetModifier
Debug.Assert(Me.Modifier Is Me.Modifier.OriginalDefinition)
Return DirectCast(context.Module, PEModuleBuilder).Translate(Me.Modifier, DirectCast(context.SyntaxNodeOpt, VisualBasicSyntaxNode), context.Diagnostics)
End Function
End Class
......
......@@ -866,6 +866,40 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return New TypeWithModifiers(type, customModifiers).InternalSubstituteTypeParameters(Me).CustomModifiers
End If
Return SubstituteCustomModifiers(customModifiers)
End Function
Function SubstituteCustomModifiers(customModifiers As ImmutableArray(Of CustomModifier)) As ImmutableArray(Of CustomModifier)
If customModifiers.IsDefaultOrEmpty Then
Return customModifiers
End If
For i As Integer = 0 To customModifiers.Length - 1
Dim modifier = DirectCast(customModifiers(i).Modifier, NamedTypeSymbol)
Dim substituted = DirectCast(modifier.InternalSubstituteTypeParameters(Me).AsTypeSymbolOnly(), NamedTypeSymbol)
If modifier <> substituted Then
Dim builder = ArrayBuilder(Of CustomModifier).GetInstance(customModifiers.Length)
builder.AddRange(customModifiers, i)
builder.Add(If(customModifiers(i).IsOptional, VisualBasicCustomModifier.CreateOptional(substituted), VisualBasicCustomModifier.CreateRequired(substituted)))
For j As Integer = i + 1 To customModifiers.Length - 1
modifier = DirectCast(customModifiers(j).Modifier, NamedTypeSymbol)
substituted = DirectCast(modifier.InternalSubstituteTypeParameters(Me).AsTypeSymbolOnly(), NamedTypeSymbol)
If modifier <> substituted Then
builder.Add(If(customModifiers(j).IsOptional, VisualBasicCustomModifier.CreateOptional(substituted), VisualBasicCustomModifier.CreateRequired(substituted)))
Else
builder.Add(customModifiers(j))
End If
Next
Debug.Assert(builder.Count = customModifiers.Length)
Return builder.ToImmutableAndFree()
End If
Next
Return customModifiers
End Function
......
......@@ -66,11 +66,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Function
Function InternalSubstituteTypeParameters(substitution As TypeSubstitution) As TypeWithModifiers
Dim newCustomModifiers = If(substitution IsNot Nothing, substitution.SubstituteCustomModifiers(Me.CustomModifiers), Me.CustomModifiers)
Dim newTypeWithModifiers As TypeWithModifiers = Me.Type.InternalSubstituteTypeParameters(substitution)
If Not newTypeWithModifiers.Is(Me.Type) Then
Return New TypeWithModifiers(newTypeWithModifiers.Type, Me.CustomModifiers.Concat(newTypeWithModifiers.CustomModifiers))
If Not newTypeWithModifiers.Is(Me.Type) OrElse newCustomModifiers <> Me.CustomModifiers Then
Return New TypeWithModifiers(newTypeWithModifiers.Type, newCustomModifiers.Concat(newTypeWithModifiers.CustomModifiers))
Else
Return Me ' substitution had no effect on the type
Return Me ' substitution had no effect on the type or modifiers
End If
End Function
End Structure
......
......@@ -1318,5 +1318,220 @@ End Class
Overriden")
End Sub
<Fact, WorkItem(5725, "https://github.com/dotnet/roslyn/issues/5725")>
Public Sub ModifiersWithConstructedType_01()
Dim ilSource = <![CDATA[
.class public auto ansi beforefieldinit CL1`1<valuetype .ctor ([mscorlib]System.ValueType) T1>
extends[mscorlib] System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void[mscorlib] System.Object::.ctor()
IL_0006:
ret
} // end of method CL1`1::.ctor
.method public hidebysig newslot virtual
instance void Test(!T1 modopt(valuetype [mscorlib]System.Nullable`1<!T1>) t1) cil managed
{
// Code size 1 (0x1)
.maxstack 1
IL_0000: ldstr "Test"
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method CL1`1::Test
} // end of class CL1`1
.class public auto ansi beforefieldinit CL2
extends class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>::.ctor()
IL_0006: ret
} // end of method CL2::.ctor
} // end of class CL2
]]>.Value
Dim vbSource =
<compilation>
<file name="c.vb"><![CDATA[
Class Module1
Shared Sub Main()
Dim x = new CL2()
x.Test(1)
x = new CL3()
x.Test(1)
End Sub
End Class
class CL3
Inherits CL2
public overrides Sub Test(c As Integer)
System.Console.WriteLine("Overriden")
end Sub
End Class
]]>
</file>
</compilation>
Dim compilation = CreateCompilationWithCustomILSource(vbSource, ilSource, options:=TestOptions.ReleaseExe)
CompileAndVerify(compilation, expectedOutput:="Test
Overriden")
End Sub
<Fact, WorkItem(5725, "https://github.com/dotnet/roslyn/issues/5725")>
Public Sub ModifiersWithConstructedType_02()
Dim ilSource = <![CDATA[
.class public auto ansi beforefieldinit CL1`1<valuetype .ctor ([mscorlib]System.ValueType) T1>
extends[mscorlib] System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void[mscorlib] System.Object::.ctor()
IL_0006:
ret
} // end of method CL1`1::.ctor
.method public hidebysig newslot virtual
instance void Test(!T1 modopt(valuetype [mscorlib]System.Nullable`1) t1) cil managed
{
// Code size 1 (0x1)
.maxstack 1
IL_0000: ldstr "Test"
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method CL1`1::Test
} // end of class CL1`1
.class public auto ansi beforefieldinit CL2
extends class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>::.ctor()
IL_0006: ret
} // end of method CL2::.ctor
} // end of class CL2
]]>.Value
Dim vbSource =
<compilation>
<file name="c.vb"><![CDATA[
Class Module1
Shared Sub Main()
Dim x = new CL2()
x.Test(1)
x = new CL3()
x.Test(1)
End Sub
End Class
class CL3
Inherits CL2
public overrides Sub Test(c As Integer)
System.Console.WriteLine("Overriden")
end Sub
End Class
]]>
</file>
</compilation>
Dim compilation = CreateCompilationWithCustomILSource(vbSource, ilSource, options:=TestOptions.ReleaseExe)
CompileAndVerify(compilation, expectedOutput:="Test
Overriden")
End Sub
<Fact, WorkItem(5725, "https://github.com/dotnet/roslyn/issues/5725")>
Public Sub ModifiersWithConstructedType_03()
Dim ilSource = <![CDATA[
.class public auto ansi beforefieldinit CL1`1<valuetype .ctor ([mscorlib]System.ValueType) T1>
extends[mscorlib] System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void[mscorlib] System.Object::.ctor()
IL_0006:
ret
} // end of method CL1`1::.ctor
.method public hidebysig newslot virtual
instance int32 modopt(CL2) modopt(valuetype [mscorlib]System.Nullable`1<!T1>) modopt(valuetype [mscorlib]System.Nullable`1<!T1>) modopt(CL2) [] Test(!T1 t1) cil managed
{
// Code size 1 (0x1)
.maxstack 1
IL_0000: ldstr "Test"
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_0006: ldnull
IL_000a: ret
} // end of method CL1`1::Test
} // end of class CL1`1
.class public auto ansi beforefieldinit CL2
extends class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void class CL1`1<int32 modopt([mscorlib]System.Runtime.CompilerServices.IsLong)>::.ctor()
IL_0006: ret
} // end of method CL2::.ctor
} // end of class CL2
]]>.Value
Dim vbSource =
<compilation>
<file name="c.vb"><![CDATA[
Class Module1
Shared Sub Main()
Dim x = new CL2()
x.Test(1)
x = new CL3()
x.Test(1)
End Sub
End Class
class CL3
Inherits CL2
public overrides Function Test(c As Integer) As Integer()
System.Console.WriteLine("Overriden")
return Nothing
end Function
End Class
]]>
</file>
</compilation>
Dim compilation = CreateCompilationWithCustomILSource(vbSource, ilSource, options:=TestOptions.ReleaseExe)
CompileAndVerify(compilation, expectedOutput:="Test
Overriden")
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册