diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
index 5239c3f322a55971e371b9a72f7a2feed55a76eb..d982de2fe6c479eccd68a214e106fd6e223eaf68 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
+++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
@@ -8999,7 +8999,7 @@ internal class CSharpResources {
}
///
- /// Looks up a localized string similar to Type '{0}' is forwarded to multiple assemblies: '{1}' and '{2}'.
+ /// Looks up a localized string similar to Module '{0}' in assembly '{1}' is forwarding the type '{2}' to multiple assemblies: '{3}' and '{4}'..
///
internal static string ERR_TypeForwardedToMultipleAssemblies {
get {
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 4e649deaa2495ff8956285d64c461a2ebebc470f..483d5e4d443141ea85a9825b38444d09b51a3ecb 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -5009,6 +5009,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
Attributes are not allowed on local function parameters or type parameters
- Type '{0}' is forwarded to multiple assemblies: '{1}' and '{2}'
+ Module '{0}' in assembly '{1}' is forwarding the type '{2}' to multiple assemblies: '{3}' and '{4}'.
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs
index bd29e48ab7eb078719bcaa303527ac92aad8a477..88d1858d1769e77b99d250e8037766333f692fe0 100644
--- a/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs
@@ -370,6 +370,12 @@ internal ErrorTypeSymbol CreateCycleInTypeForwarderErrorTypeSymbol(ref MetadataT
return new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(this.Modules[0], ref emittedName, diagnosticInfo);
}
+ internal ErrorTypeSymbol CreateMultipleForwardingErrorTypeSymbol(ref MetadataTypeName emittedName, ModuleSymbol forwardingModule, AssemblySymbol destination1, AssemblySymbol destination2)
+ {
+ var diagnosticInfo = new CSDiagnosticInfo(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, forwardingModule, this, emittedName.FullName, destination1, destination2);
+ return new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(forwardingModule, ref emittedName, diagnosticInfo);
+ }
+
///
/// Lookup declaration for predefined CorLib type in this Assembly.
///
diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEAssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEAssemblySymbol.cs
index 88832a79669546a3904f0a3f5834f35fc8de0087..661b6ed9b8806393afd5fc0d29afeab196525613 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEAssemblySymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEAssemblySymbol.cs
@@ -157,13 +157,8 @@ internal override NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetecti
{
if ((object)secondSymbol != null)
{
- var forwardingErrorInfo = new DiagnosticInfo(
- MessageProvider.Instance,
- (int)ErrorCode.ERR_TypeForwardedToMultipleAssemblies,
- emittedName.FullName,
- firstSymbol.Name,
- secondSymbol.Name);
- return new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(PrimaryModule, ref emittedName, forwardingErrorInfo);
+ // Report the main module as that is the only one checked. clr does not honor type forwarders in non-primary modules.
+ return CreateMultipleForwardingErrorTypeSymbol(ref emittedName, this.PrimaryModule, firstSymbol, secondSymbol);
}
// Don't bother to check the forwarded-to assembly if we've already seen it.
diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs
index a2ec27722fe1b3c46c2c25c4016f7269a094a192..c55e723db6a8f12e08425445b86ca2a71b8d006e 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEModuleSymbol.cs
@@ -653,9 +653,19 @@ internal NamedTypeSymbol LookupTopLevelMetadataType(ref MetadataTypeName emitted
string matchedName;
(int firstIndex, int secondIndex) = this.Module.GetAssemblyRefsForForwardedType(fullName.FullName, ignoreCase: false, matchedName: out matchedName);
- var firstSymbol = firstIndex < 0 ? null : GetReferencedAssemblySymbol(firstIndex);
- var secondSymbol = secondIndex < 0 ? null : GetReferencedAssemblySymbol(secondIndex);
+ if (firstIndex < 0)
+ {
+ return (null, null);
+ }
+
+ AssemblySymbol firstSymbol = GetReferencedAssemblySymbol(firstIndex);
+ if (secondIndex < 0)
+ {
+ return (firstSymbol, null);
+ }
+
+ AssemblySymbol secondSymbol = GetReferencedAssemblySymbol(secondIndex);
return (firstSymbol, secondSymbol);
}
@@ -663,13 +673,9 @@ internal IEnumerable GetForwardedTypes()
{
foreach (KeyValuePair forwarder in Module.GetForwardedTypes())
{
- if (forwarder.Value.FirstIndex < 0)
- {
- continue;
- }
-
var name = MetadataTypeName.FromFullName(forwarder.Key);
+ Debug.Assert(forwarder.Value.FirstIndex >= 0, "First index should never be negative");
AssemblySymbol firstSymbol = this.GetReferencedAssemblySymbol(forwarder.Value.FirstIndex);
Debug.Assert((object)firstSymbol != null, "Invalid indexes (out of bound) are discarded during reading metadata in PEModule.EnsureForwardTypeToAssemblyMap()");
@@ -678,8 +684,7 @@ internal IEnumerable GetForwardedTypes()
var secondSymbol = this.GetReferencedAssemblySymbol(forwarder.Value.SecondIndex);
Debug.Assert((object)secondSymbol != null, "Invalid indexes (out of bound) are discarded during reading metadata in PEModule.EnsureForwardTypeToAssemblyMap()");
- var forwardingErrorInfo = new DiagnosticInfo(MessageProvider.Instance, (int)ErrorCode.ERR_TypeForwardedToMultipleAssemblies, forwarder.Key, firstSymbol.Name, secondSymbol.Name);
- yield return new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(this, ref name, forwardingErrorInfo);
+ yield return ContainingAssembly.CreateMultipleForwardingErrorTypeSymbol(ref name, this, firstSymbol, secondSymbol);
}
else
{
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs
index ca7dc03c93f7398bd792ae6b47b3f5b51a53a90e..4cc0f8a9bea23d9ba604684ef5570a6b11c75dfa 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceAssemblySymbol.cs
@@ -2589,13 +2589,7 @@ internal override NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetecti
{
if ((object)secondSymbol != null)
{
- var forwardingErrorInfo = new DiagnosticInfo(
- MessageProvider.Instance,
- (int)ErrorCode.ERR_TypeForwardedToMultipleAssemblies,
- emittedName.FullName,
- firstSymbol.Name,
- secondSymbol.Name);
- return new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(SourceModule, ref emittedName, forwardingErrorInfo);
+ return CreateMultipleForwardingErrorTypeSymbol(ref emittedName, peModuleSymbol, firstSymbol, secondSymbol);
}
// Don't bother to check the forwarded-to assembly if we've already seen it.
diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs
index a6cfd9473e0bfc4bff5edff5fe72df05100de3ed..ece16dd97c7cef8b587e63b836bfb7d51a386bdc 100644
--- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs
@@ -19508,6 +19508,7 @@ .assembly Forwarder
{
.ver 1:0:0:0
}
+.module ForwarderModule.dll
.class extern forwarder Destination.TestClass
{
.assembly extern Destination1
@@ -19519,9 +19520,9 @@ .assembly Forwarder
var compilation = CreateCompilationWithCustomILSource(userCode, forwardingIL, appendDefaultHeader: false);
compilation.VerifyDiagnostics(
- // (8,29): error CS8206: Type 'Destination.TestClass' is forwarded to multiple assemblies: 'Destination1' and 'Destination2'
+ // (8,29): error CS8206: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Destination.TestClass' to multiple assemblies: 'Destination1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' and 'Destination2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
// new Destination.TestClass();
- Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "TestClass").WithArguments("Destination.TestClass", "Destination1", "Destination2").WithLocation(8, 29),
+ Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "TestClass").WithArguments("ForwarderModule.dll", "Forwarder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Destination.TestClass", "Destination1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Destination2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 29),
// (8,29): error CS0234: The type or namespace name 'TestClass' does not exist in the namespace 'Destination' (are you missing an assembly reference?)
// new Destination.TestClass();
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "TestClass").WithArguments("TestClass", "Destination").WithLocation(8, 29));
@@ -19542,9 +19543,8 @@ public static void Main()
}
}";
var forwardingIL = @"
-.assembly Forwarder
-{
-}
+.assembly Forwarder { }
+.module ForwarderModule.dll
.assembly extern Destination1 { }
.assembly extern Destination2 { }
.assembly extern Destination3 { }
@@ -19573,9 +19573,9 @@ .assembly Forwarder
var compilation = CreateCompilationWithCustomILSource(userCode, forwardingIL, appendDefaultHeader: false);
compilation.VerifyDiagnostics(
- // (8,29): error CS8206: Type 'Destination.TestClass' is forwarded to multiple assemblies: 'Destination1' and 'Destination2'
+ // (8,29): error CS8206: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Destination.TestClass' to multiple assemblies: 'Destination1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'Destination2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// new Destination.TestClass();
- Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "TestClass").WithArguments("Destination.TestClass", "Destination1", "Destination2").WithLocation(8, 29),
+ Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "TestClass").WithArguments("ForwarderModule.dll", "Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Destination.TestClass", "Destination1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Destination2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 29),
// (8,29): error CS0234: The type or namespace name 'TestClass' does not exist in the namespace 'Destination' (are you missing an assembly reference?)
// new Destination.TestClass();
Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "TestClass").WithArguments("TestClass", "Destination").WithLocation(8, 29));
@@ -19631,6 +19631,7 @@ .assembly C
{
.ver 0:0:0:0
}
+.module CModule.dll
.assembly extern D1 { }
.assembly extern D2 { }
.class extern forwarder C.ClassC
@@ -19645,9 +19646,9 @@ .assembly C
var referenceC2 = CompileIL(codeC2, appendDefaultHeader: false);
CreateCompilationWithMscorlib(codeA, references: new MetadataReference[] { referenceB, referenceC2 }, assemblyName: "A").VerifyDiagnostics(
- // (10,13): error CS8206: Type 'C.ClassC' is forwarded to multiple assemblies: 'D1' and 'D2'
+ // (10,13): error CS8206: Module 'CModule.dll' in assembly 'C, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'C.ClassC' to multiple assemblies: 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// ClassB.MethodB(null);
- Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "ClassB.MethodB").WithArguments("C.ClassC", "D1", "D2").WithLocation(10, 13));
+ Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "ClassB.MethodB").WithArguments("CModule.dll", "C, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "C.ClassC", "D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
}
[Fact, WorkItem(16484, "https://github.com/dotnet/roslyn/issues/16484")]
@@ -19718,9 +19719,10 @@ .assembly C
}
[Fact, WorkItem(16484, "https://github.com/dotnet/roslyn/issues/16484")]
- public void AddingReferenceToModuleWithMultipleForwardersToDifferentAssembliesShouldErrorOut()
+ public void CompilingModuleWithMultipleForwardersToDifferentAssembliesShouldErrorOut()
{
var ilSource = @"
+.module ForwarderModule.dll
.assembly extern D1 { }
.assembly extern D2 { }
.class extern forwarder Testspace.TestType
@@ -19732,19 +19734,14 @@ public void AddingReferenceToModuleWithMultipleForwardersToDifferentAssembliesSh
.assembly extern D2
}";
- ImmutableArray ilBytes;
- ImmutableArray pdbBytes;
- EmitILToArray(ilSource, appendDefaultHeader: false, includePdb: false, assemblyBytes: out ilBytes, pdbBytes: out pdbBytes);
-
- var ilModule = ModuleMetadata.CreateFromImage(ilBytes).GetReference();
-
- CreateCompilationWithMscorlib(string.Empty, references: new MetadataReference[] { ilModule }).VerifyDiagnostics(
- // error CS8206: Type 'Testspace.TestType' is forwarded to multiple assemblies: 'D1' and 'D2'
- Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies).WithArguments("Testspace.TestType", "D1", "D2").WithLocation(1, 1));
+ var ilModule = GetILModuleReference(ilSource, appendDefaultHeader: false);
+ CreateCompilationWithMscorlib(string.Empty, references: new MetadataReference[] { ilModule }, assemblyName: "Forwarder").VerifyDiagnostics(
+ // error CS8206: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Testspace.TestType' to multiple assemblies: 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
+ Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies).WithArguments("ForwarderModule.dll", "Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Testspace.TestType", "D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1));
}
[Fact, WorkItem(16484, "https://github.com/dotnet/roslyn/issues/16484")]
- public void AddingReferenceToModuleWithMultipleForwardersToTheSameAssemblyShouldNotProduceMultipleForwardingErrors()
+ public void CompilingModuleWithMultipleForwardersToTheSameAssemblyShouldNotProduceMultipleForwardingErrors()
{
var ilSource = @"
.assembly extern D1 { }
@@ -19757,12 +19754,7 @@ public void AddingReferenceToModuleWithMultipleForwardersToTheSameAssemblyShould
.assembly extern D1
}";
- ImmutableArray ilBytes;
- ImmutableArray pdbBytes;
- EmitILToArray(ilSource, appendDefaultHeader: false, includePdb: false, assemblyBytes: out ilBytes, pdbBytes: out pdbBytes);
-
- var ilModule = ModuleMetadata.CreateFromImage(ilBytes).GetReference();
-
+ var ilModule = GetILModuleReference(ilSource, appendDefaultHeader: false);
CreateCompilationWithMscorlib(string.Empty, references: new MetadataReference[] { ilModule }).VerifyDiagnostics(
// error CS0012: The type 'TestType' is defined in an assembly that is not referenced. You must add a reference to assembly 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
Diagnostic(ErrorCode.ERR_NoTypeDef).WithArguments("Testspace.TestType", "D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1));
diff --git a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs
index 1cc6c4ce22aed4b6743a434e4f8548c03c1b741e..d3335b8bd4b16e5bf98e4470f4c3599386b498c6 100644
--- a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs
+++ b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs
@@ -2901,7 +2901,7 @@ private void EnsureForwardTypeToAssemblyMap()
continue;
}
- if (referencedAssemblyIndex >= this.ReferencedAssemblies.Length)
+ if (referencedAssemblyIndex < 0 || referencedAssemblyIndex >= this.ReferencedAssemblies.Length)
{
continue;
}
@@ -2921,6 +2921,8 @@ private void EnsureForwardTypeToAssemblyMap()
if (typesToAssemblyIndexMap.TryGetValue(name, out indices))
{
+ Debug.Assert(indices.FirstIndex >= 0, "Not allowed to store a negative (non-existent) index in typesToAssemblyIndexMap");
+
// Store it only if it was not a duplicate
if (indices.FirstIndex != referencedAssemblyIndex && indices.SecondIndex < 0)
{
diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Symbols.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Symbols.vb
index 5dc8623c78f28cf82dc60bcae151709c6f5d929d..5bda397b04ce56de1f6a1d6c5c84d3dc48866cb9 100644
--- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Symbols.vb
+++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Symbols.vb
@@ -511,9 +511,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Next
If forwardedType IsNot Nothing Then
- If Not reportedAnError And forwardedType.IsErrorType Then
+ If Not reportedAnError AndAlso forwardedType.IsErrorType Then
Dim errorInfo = DirectCast(forwardedType, ErrorTypeSymbol).ErrorInfo
-
+
If errorInfo.Code = ERRID.ERR_TypeFwdCycle2 Then
Debug.Assert(forwardedType.ContainingAssembly IsNot Nothing, "How did we find a cycle if there is no forwarding?")
Binder.ReportDiagnostic(diagBag, typeSyntax, ERRID.ERR_TypeFwdCycle2, fullName, forwardedType.ContainingAssembly)
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb
index a66ac607e0930d49c11aa5200d3ae10398a8d51f..4e6b582d0230e48a59003c5158c9be991c554345 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb
@@ -301,6 +301,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return New MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(Me.Modules(0), emittedName, diagInfo)
End Function
+ Friend Function CreateMultipleForwardingErrorTypeSymbol(ByRef emittedName As MetadataTypeName, forwardingModule As ModuleSymbol, destination1 As AssemblySymbol, destination2 As AssemblySymbol) As ErrorTypeSymbol
+ Dim diagnosticInfo = New DiagnosticInfo(MessageProvider.Instance, ERRID.ERR_TypeForwardedToMultipleAssemblies, forwardingModule, Me, emittedName.FullName, destination1, destination2)
+ Return New MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(forwardingModule, emittedName, diagnosticInfo)
+ End Function
+
'''
''' Lookup declaration for predefined CorLib type in this Assembly. Only valid if this
''' assembly is the Cor Library
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEAssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEAssemblySymbol.vb
index 541c9b97c711931881cb57c421588f52cae2bf4c..b3bf7c94372365432a67dd49bfb57572ab4d5db3 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEAssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEAssemblySymbol.vb
@@ -166,17 +166,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Dim matchedName As String = Nothing
Dim forwardedToAssemblies = LookupAssembliesForForwardedMetadataType(emittedName, ignoreCase, matchedName)
- If DirectCast(forwardedToAssemblies.FirstSymbol, Object) IsNot Nothing
- If DirectCast(forwardedToAssemblies.SecondSymbol, Object) IsNot Nothing
- Dim forwardingErrorInfo = New DiagnosticInfo(
- MessageProvider.Instance,
- ERRID.ERR_TypeForwardedToMultipleAssemblies,
- emittedName.FullName,
- forwardedToAssemblies.FirstSymbol.Name,
- forwardedToAssemblies.SecondSymbol.Name)
- Return new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(PrimaryModule, emittedName, forwardingErrorInfo)
+ If forwardedToAssemblies.FirstSymbol IsNot Nothing Then
+ If forwardedToAssemblies.SecondSymbol IsNot Nothing Then
+ ' Report the main module as that Is the only one checked. clr does Not honor type forwarders in non-primary modules.
+ Return CreateMultipleForwardingErrorTypeSymbol(emittedName, PrimaryModule, forwardedToAssemblies.FirstSymbol, forwardedToAssemblies.SecondSymbol)
End If
-
+
' Don't bother to check the forwarded-to assembly if we've already seen it.
If visitedAssemblies IsNot Nothing AndAlso visitedAssemblies.Contains(forwardedToAssemblies.FirstSymbol) Then
Return CreateCycleInTypeForwarderErrorTypeSymbol(emittedName)
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEModuleSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEModuleSymbol.vb
index 61b303e5b19e0b2180c4690ecaeaf08de40c2021..8fde0cfa7d82f933c3648165d7137fbc68469c10 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEModuleSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEModuleSymbol.vb
@@ -434,30 +434,34 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
'''
Friend Function GetAssembliesForForwardedType(ByRef fullName As MetadataTypeName, ignoreCase As Boolean, ByRef matchedName As String) As (FirstSymbol As AssemblySymbol, SecondSymbol As AssemblySymbol)
Dim indices = Me.Module.GetAssemblyRefsForForwardedType(fullName.FullName, ignoreCase, matchedName)
-
- Dim firstSymbol = If(indices.FirstIndex < 0, Nothing, GetReferencedAssemblySymbol(indices.FirstIndex))
- Dim secondSymbol = If(indices.SecondIndex < 0, Nothing, GetReferencedAssemblySymbol(indices.SecondIndex))
- return (firstSymbol, secondSymbol)
+ If indices.FirstIndex < 0 Then
+ Return (Nothing, Nothing)
+ End If
+
+ Dim firstSymbol = GetReferencedAssemblySymbol(indices.FirstIndex)
+
+ If indices.SecondIndex < 0 Then
+ Return (firstSymbol, Nothing)
+ End If
+
+ Dim secondSymbol = GetReferencedAssemblySymbol(indices.SecondIndex)
+ Return (firstSymbol, secondSymbol)
End Function
Friend Iterator Function GetForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
For Each forwarder As KeyValuePair(Of String, (FirstIndex As Integer, SecondIndex As Integer)) In Me.Module.GetForwardedTypes()
- If forwarder.Value.FirstIndex < 0 Then
- Continue For
- End If
-
Dim name = MetadataTypeName.FromFullName(forwarder.Key)
+ Debug.Assert(forwarder.Value.FirstIndex >= 0, "First index should never be negative")
Dim firstSymbol = GetReferencedAssemblySymbol(forwarder.Value.FirstIndex)
- Debug.Assert(DirectCast(firstSymbol, Object) IsNot Nothing, "Invalid indexes (out of bound) are discarded during reading metadata in PEModule.EnsureForwardTypeToAssemblyMap()")
+ Debug.Assert(firstSymbol IsNot Nothing, "Invalid indexes (out of bound) are discarded during reading metadata in PEModule.EnsureForwardTypeToAssemblyMap()")
If forwarder.Value.SecondIndex >= 0 Then
Dim secondSymbol = GetReferencedAssemblySymbol(forwarder.Value.SecondIndex)
- Debug.Assert(DirectCast(secondSymbol, Object) IsNot Nothing, "Invalid indexes (out of bound) are discarded during reading metadata in PEModule.EnsureForwardTypeToAssemblyMap()")
+ Debug.Assert(secondSymbol IsNot Nothing, "Invalid indexes (out of bound) are discarded during reading metadata in PEModule.EnsureForwardTypeToAssemblyMap()")
- Dim forwardingErrorInfo = New DiagnosticInfo(MessageProvider.Instance, ERRID.ERR_TypeForwardedToMultipleAssemblies, forwarder.Key, firstSymbol.Name, secondSymbol.Name)
- Yield New MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(Me, name, forwardingErrorInfo)
+ Yield ContainingAssembly.CreateMultipleForwardingErrorTypeSymbol(name, Me, firstSymbol, secondSymbol)
Else
Yield firstSymbol.LookupTopLevelMetadataType(name, digThroughForwardedTypes:= true)
End If
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
index 5da4b34a181f7c54e466fb6a2c64001ef3c70f30..0c84acfd3c7b17dd654b7a24cbab41ff9be8f5eb 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
@@ -1695,10 +1695,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim peModuleSymbol = DirectCast(_modules(i), PEModuleSymbol)
Dim forwardedToAssemblies = peModuleSymbol.GetAssembliesForForwardedType(emittedName, ignoreCase, matchedName)
- If DirectCast(forwardedToAssemblies.FirstSymbol, Object) IsNot Nothing Then
- If DirectCast(forwardedToAssemblies.SecondSymbol, Object) IsNot Nothing Then
- Dim forwardingErrorInfo = New DiagnosticInfo(MessageProvider.Instance, ERRID.ERR_TypeForwardedToMultipleAssemblies, emittedName.FullName, forwardedToAssemblies.FirstSymbol.Name, forwardedToAssemblies.SecondSymbol.Name)
- Return New MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(SourceModule, emittedName, forwardingErrorInfo)
+ If forwardedToAssemblies.FirstSymbol IsNot Nothing Then
+ If forwardedToAssemblies.SecondSymbol IsNot Nothing Then
+ Return CreateMultipleForwardingErrorTypeSymbol(emittedName, peModuleSymbol, forwardedToAssemblies.FirstSymbol, forwardedToAssemblies.SecondSymbol)
End If
' Don't bother to check the forwarded-to assembly if we've already seen it.
diff --git a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb
index 8e87be3612007f447e7c1ad7b4a103c8f93d7291..95e05ace3b068d3e09dbbf8443607ba6ed2a13bc 100644
--- a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb
+++ b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb
@@ -10686,7 +10686,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Property
'''
- ''' Looks up a localized string similar to Type '{0}' is forwarded to multiple assemblies: '{1}' and '{2}'.
+ ''' Looks up a localized string similar to Module '{0}' in assembly '{1}' is forwarding the type '{2}' to multiple assemblies: '{3}' and '{4}'..
'''
Friend ReadOnly Property ERR_TypeForwardedToMultipleAssemblies() As String
Get
diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx
index eec85b18d6fe87a371d9c1574687c527c335028e..feba468a29079e3c69387911bba0965ed31206ad 100644
--- a/src/Compilers/VisualBasic/Portable/VBResources.resx
+++ b/src/Compilers/VisualBasic/Portable/VBResources.resx
@@ -5462,6 +5462,6 @@
Invalid assembly name: {0}
- Type '{0}' is forwarded to multiple assemblies: '{1}' and '{2}'
+ Module '{0}' in assembly '{1}' is forwarding the type '{2}' to multiple assemblies: '{3}' and '{4}'.
-
+
\ No newline at end of file
diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/SymbolErrorTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/SymbolErrorTests.vb
index 52c08f01bd927d0fbf47890bf0e4b24778a5b543..44b48af0a5b1b20c87cda019802a0835a3400b34 100644
--- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/SymbolErrorTests.vb
+++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/SymbolErrorTests.vb
@@ -23844,6 +23844,7 @@ End Namespace
{
.ver 1:0:0:0
}
+.module ForwarderModule.dll
.class extern forwarder Destination.TestClass
{
.assembly extern Destination1
@@ -23853,12 +23854,12 @@ End Namespace
.assembly extern Destination2
}"
Dim compilation = CreateCompilationWithCustomILSource(userCode, forwardingIL, appendDefaultHeader:= False)
-
+
CompilationUtils.AssertTheseDiagnostics(compilation, )
@@ -23885,6 +23886,7 @@ End Namespace
.assembly Forwarder
{
}
+.module ForwarderModule.dll
.assembly extern Destination1 { }
.assembly extern Destination2 { }
.assembly extern Destination3 { }
@@ -23912,12 +23914,12 @@ End Namespace
}"
Dim compilation = CreateCompilationWithCustomILSource(userCode, forwardingIL, appendDefaultHeader:= False)
-
+
CompilationUtils.AssertTheseDiagnostics(compilation, )
@@ -23984,6 +23986,7 @@ End Namespace"
{
.ver 0:0:0:0
}
+.module CModule.dll
.assembly extern D1 { }
.assembly extern D2 { }
.class extern forwarder C.ClassC
@@ -24004,7 +24007,7 @@ End Namespace"
assemblyName:= "A")
CompilationUtils.AssertTheseDiagnostics(compilation, )
@@ -24092,8 +24095,9 @@ BC30652: Reference required to assembly 'D, Version=0.0.0.0, Culture=neutral, Pu
- Public Sub AddingReferenceToModuleWithMultipleForwardersToDifferentAssembliesShouldErrorOut()
+ Public Sub CompilingModuleWithMultipleForwardersToDifferentAssembliesShouldErrorOut()
Dim ilSource = "
+.module ForwarderModule.dll
.assembly extern D1 { }
.assembly extern D2 { }
.class extern forwarder Testspace.TestType
@@ -24105,22 +24109,21 @@ BC30652: Reference required to assembly 'D, Version=0.0.0.0, Culture=neutral, Pu
.assembly extern D2
}"
- Dim ilBytes As ImmutableArray(Of Byte) = Nothing
- Dim pdbBytes As ImmutableArray(Of Byte) = Nothing
- EmitILToArray(ilSource, appendDefaultHeader:=False, includePdb:=False, assemblyBytes:=ilBytes, pdbBytes:=pdbBytes)
-
- Dim ilModule = ModuleMetadata.CreateFromImage(ilBytes).GetReference()
-
- Dim compilation = CreateCompilationWithMscorlib(String.Empty, references:={ilModule}, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
+ Dim ilModule = GetILModuleReference(ilSource, appendDefaultHeader:=False)
+ Dim compilation = CreateCompilationWithMscorlib(
+ source:=String.Empty,
+ references:={ilModule},
+ options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
+ assemblyName:="Forwarder")
CompilationUtils.AssertTheseDiagnostics(compilation, )
End Sub
-
- Public Sub AddingReferenceToModuleWithMultipleForwardersToTheSameAssemblyShouldNotProduceMultipleForwardingErrors()
+
+ Public Sub CompilingModuleWithMultipleForwardersToTheSameAssemblyShouldNotProduceMultipleForwardingErrors()
Dim ilSource = "
.assembly extern D1 { }
.class extern forwarder Testspace.TestType
@@ -24132,12 +24135,7 @@ BC37208: Type 'Testspace.TestType' is forwarded to multiple assemblies: 'D1' and
.assembly extern D1
}"
- Dim ilBytes As ImmutableArray(Of Byte) = Nothing
- Dim pdbBytes As ImmutableArray(Of Byte) = Nothing
- EmitILToArray(ilSource, appendDefaultHeader:=False, includePdb:=False, assemblyBytes:=ilBytes, pdbBytes:=pdbBytes)
-
- Dim ilModule = ModuleMetadata.CreateFromImage(ilBytes).GetReference()
-
+ Dim ilModule = GetILModuleReference(ilSource, appendDefaultHeader:=False)
Dim compilation = CreateCompilationWithMscorlib(String.Empty, references:={ilModule}, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
CompilationUtils.AssertTheseDiagnostics(compilation, assemblyBytes;
+ ImmutableArray pdbBytes;
+ EmitILToArray(ilSource, appendDefaultHeader, includePdb: false, assemblyBytes: out assemblyBytes, pdbBytes: out pdbBytes);
+ return ModuleMetadata.CreateFromImage(assemblyBytes).GetReference();
+ }
+
#endregion
#region Compilation Creation Helpers