diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs index 0862816254c050ad1f02bd79deec8a04c8001e3a..920d1d1557716a1754010ec65a5b9167f91c8091 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs @@ -32,7 +32,6 @@ public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstruct /// - the assignment phase /// private BoundExpression RewriteDeconstruction(BoundTupleExpression left, Conversion conversion, BoundExpression right) - { var temps = ArrayBuilder.GetInstance(); var effects = DeconstructionSideEffects.GetInstance(); diff --git a/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs index 88d1858d1769e77b99d250e8037766333f692fe0..17d923be7b05a7af2b820aa0ad86f72d8df978ba 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs @@ -543,13 +543,18 @@ public NamedTypeSymbol GetTypeByMetadataName(string fullyQualifiedMetadataName) /// /// A diagnostic bag to receive warnings if we should allow multiple definitions and pick one. /// + /// + /// In case duplicate types are found, ignore the one from corlib. This is useful for any kind of compilation at runtime + /// (EE/scripting/Powershell) using a type that is being migrated to corlib. + /// /// Null if the type can't be found. internal NamedTypeSymbol GetTypeByMetadataName( string metadataName, bool includeReferences, bool isWellKnownType, bool useCLSCompliantNameArityEncoding = false, - DiagnosticBag warnings = null) + DiagnosticBag warnings = null, + bool ignoreCorLibraryDuplicatedTypes = false) { NamedTypeSymbol type; MetadataTypeName mdName; @@ -559,7 +564,9 @@ public NamedTypeSymbol GetTypeByMetadataName(string fullyQualifiedMetadataName) var parts = metadataName.Split(s_nestedTypeNameSeparators); Debug.Assert(parts.Length > 0); mdName = MetadataTypeName.FromFullName(parts[0], useCLSCompliantNameArityEncoding); - type = GetTopLevelTypeByMetadataName(ref mdName, assemblyOpt: null, includeReferences: includeReferences, isWellKnownType: isWellKnownType, warnings: warnings); + type = GetTopLevelTypeByMetadataName(ref mdName, assemblyOpt: null, includeReferences: includeReferences, isWellKnownType: isWellKnownType, + warnings: warnings, ignoreCorLibraryDuplicatedTypes: ignoreCorLibraryDuplicatedTypes); + for (int i = 1; (object)type != null && !type.IsErrorType() && i < parts.Length; i++) { mdName = MetadataTypeName.FromTypeName(parts[i]); @@ -570,7 +577,8 @@ public NamedTypeSymbol GetTypeByMetadataName(string fullyQualifiedMetadataName) else { mdName = MetadataTypeName.FromFullName(metadataName, useCLSCompliantNameArityEncoding); - type = GetTopLevelTypeByMetadataName(ref mdName, assemblyOpt: null, includeReferences: includeReferences, isWellKnownType: isWellKnownType, warnings: warnings); + type = GetTopLevelTypeByMetadataName(ref mdName, assemblyOpt: null, includeReferences: includeReferences, isWellKnownType: isWellKnownType, + warnings: warnings, ignoreCorLibraryDuplicatedTypes: ignoreCorLibraryDuplicatedTypes); } return ((object)type == null || type.IsErrorType()) ? null : type; @@ -723,7 +731,8 @@ private NamedTypeSymbol ApplyGenericArguments(NamedTypeSymbol symbol, Type[] typ AssemblyIdentity assemblyOpt, bool includeReferences, bool isWellKnownType, - DiagnosticBag warnings = null) + DiagnosticBag warnings = null, + bool ignoreCorLibraryDuplicatedTypes = false) { NamedTypeSymbol result; @@ -778,6 +787,21 @@ private NamedTypeSymbol ApplyGenericArguments(NamedTypeSymbol symbol, Type[] typ if ((object)result != null) { // duplicate + if (ignoreCorLibraryDuplicatedTypes) + { + if (IsInCorLib(candidate)) + { + // ignore candidate + continue; + } + if (IsInCorLib(result)) + { + // drop previous result + result = candidate; + continue; + } + } + if (warnings == null) { result = null; @@ -798,6 +822,11 @@ private NamedTypeSymbol ApplyGenericArguments(NamedTypeSymbol symbol, Type[] typ return result; } + private static bool IsInCorLib(NamedTypeSymbol type) + { + return type.ContainingAssembly == type.ContainingAssembly.CorLibrary; + } + private bool IsValidWellKnownType(NamedTypeSymbol result) { if ((object)result == null || result.TypeKind == TypeKind.Error) diff --git a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs index 07beacf47901570d06756d6acc43dfb6e67fbf92..4331b23c913e0480a1f2210fbb2c3d3c7ec809c6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs @@ -79,6 +79,8 @@ internal NamedTypeSymbol GetWellKnownType(WellKnownType type) { Debug.Assert(type.IsValid()); + bool ignoreCorLibraryDuplicatedTypes = this.Options.TopLevelBinderFlags.Includes(BinderFlags.IgnoreCorLibraryDuplicatedTypes); + int index = (int)type - (int)WellKnownType.First; if (_lazyWellKnownTypes == null || (object)_lazyWellKnownTypes[index] == null) { @@ -101,7 +103,8 @@ internal NamedTypeSymbol GetWellKnownType(WellKnownType type) DiagnosticBag legacyWarnings = (type <= WellKnownType.CSharp7Sentinel) ? warnings : null; result = this.Assembly.GetTypeByMetadataName( - mdName, includeReferences: true, useCLSCompliantNameArityEncoding: true, isWellKnownType: true, warnings: legacyWarnings); + mdName, includeReferences: true, useCLSCompliantNameArityEncoding: true, isWellKnownType: true, + warnings: legacyWarnings, ignoreCorLibraryDuplicatedTypes: ignoreCorLibraryDuplicatedTypes); } if ((object)result == null) diff --git a/src/Compilers/VisualBasic/Portable/Binding/LookupOptions.vb b/src/Compilers/VisualBasic/Portable/Binding/LookupOptions.vb index 6628475ddbd636e34c3fb6a6ed56e2b9fc2c16f5..171a80ba2ca9d5eb9ffebfb7879cfa902a4df71b 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/LookupOptions.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/LookupOptions.vb @@ -138,16 +138,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' NoSystemObjectLookupForInterfaces = 1 << 16 - ''' - ''' Ignore duplicate types from the cor library. - ''' - IgnoreCorLibraryDuplicatedTypes = 1 << 17 - ''' ''' Handle a case of being able to refer to System.Int32 through System.Integer. ''' Same for other intrinsic types with intrinsic name different from emitted name. ''' - AllowIntrinsicAliases = 1 << 18 + AllowIntrinsicAliases = 1 << 17 End Enum Friend Module LookupOptionExtensions diff --git a/src/Compilers/VisualBasic/Portable/Binding/LookupResult.vb b/src/Compilers/VisualBasic/Portable/Binding/LookupResult.vb index 2572565cf2d81ce4c223a3d9fe670a45b40c311f..b577283478cf7373cd0b50eaa07b35bef4650c1d 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/LookupResult.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/LookupResult.vb @@ -876,7 +876,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return SymbolLocation.FromSourceModule End If - If (options And LookupOptions.IgnoreCorLibraryDuplicatedTypes) <> 0 Then + If sourceModule.DeclaringCompilation.Options.IgnoreCorLibraryDuplicatedTypes Then ' Ignore duplicate types from the cor library if necessary. ' (Specifically the framework assemblies loaded at runtime in ' the EE may contain types also available from mscorlib.dll.) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb index 4e6b582d0230e48a59003c5158c9be991c554345..69fa1bcf744ace564d458c5623a5da7c729f4d0a 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/AssemblySymbol.vb @@ -444,7 +444,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ''' I.e. arity is inferred from the name and matching type must have the same emitted name and arity. ''' ''' - Friend Function GetTypeByMetadataName(metadataName As String, includeReferences As Boolean, isWellKnownType As Boolean, Optional useCLSCompliantNameArityEncoding As Boolean = False) As NamedTypeSymbol + Friend Function GetTypeByMetadataName(metadataName As String, includeReferences As Boolean, isWellKnownType As Boolean, + Optional useCLSCompliantNameArityEncoding As Boolean = False, Optional ignoreCorLibraryDuplicatedTypes As Boolean = False) As NamedTypeSymbol If metadataName Is Nothing Then Throw New ArgumentNullException(NameOf(metadataName)) @@ -470,7 +471,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End While Else mdName = MetadataTypeName.FromFullName(metadataName, useCLSCompliantNameArityEncoding) - type = GetTopLevelTypeByMetadataName(mdName, includeReferences, isWellKnownType) + type = GetTopLevelTypeByMetadataName(mdName, includeReferences, isWellKnownType, + ignoreCorLibraryDuplicatedTypes:=ignoreCorLibraryDuplicatedTypes) End If Return If(type Is Nothing OrElse type.IsErrorType(), Nothing, type) @@ -485,7 +487,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ''' ''' Symbol for the type or Nothing if type cannot be found or ambiguous. ''' - Friend Function GetTopLevelTypeByMetadataName(ByRef metadataName As MetadataTypeName, includeReferences As Boolean, isWellKnownType As Boolean) As NamedTypeSymbol + Friend Function GetTopLevelTypeByMetadataName(ByRef metadataName As MetadataTypeName, includeReferences As Boolean, isWellKnownType As Boolean, + Optional ignoreCorLibraryDuplicatedTypes As Boolean = False) As NamedTypeSymbol Dim result As NamedTypeSymbol ' First try this assembly @@ -516,6 +519,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols If IsAcceptableMatchForGetTypeByNameAndArity(candidate) AndAlso Not candidate.IsHiddenByEmbeddedAttribute() AndAlso candidate <> result Then If (result IsNot Nothing) Then ' Ambiguity + If ignoreCorLibraryDuplicatedTypes Then + If IsInCorLib(candidate) Then + ' ignore candidate + Continue For + End If + If IsInCorLib(result) Then + ' drop previous result + result = candidate + Continue For + End If + End If Return Nothing End If @@ -527,6 +541,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return result End Function + Private Shared Function IsInCorLib(type As NamedTypeSymbol) As Boolean + Return type.ContainingAssembly = type.ContainingAssembly.CorLibrary + End Function + Friend Shared Function IsAcceptableMatchForGetTypeByNameAndArity(candidate As NamedTypeSymbol) As Boolean Return candidate IsNot Nothing AndAlso (candidate.Kind <> SymbolKind.ErrorType OrElse Not (TypeOf candidate Is MissingMetadataTypeSymbol)) End Function diff --git a/src/Compilers/VisualBasic/Portable/Symbols/WellKnownMembers.vb b/src/Compilers/VisualBasic/Portable/Symbols/WellKnownMembers.vb index 533cb48ae04bd16342f7848db8eb96c40d834dc7..04de540c5e1a488795532e8127feae627df746d5 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/WellKnownMembers.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/WellKnownMembers.vb @@ -361,7 +361,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If IsTypeMissing(type) Then result = Nothing Else - result = Me.Assembly.GetTypeByMetadataName(mdName, includeReferences:=True, isWellKnownType:=True, useCLSCompliantNameArityEncoding:=True) + result = Me.Assembly.GetTypeByMetadataName(mdName, includeReferences:=True, isWellKnownType:=True, useCLSCompliantNameArityEncoding:=True, + ignoreCorLibraryDuplicatedTypes:=Me.Options.IgnoreCorLibraryDuplicatedTypes) End If If result Is Nothing Then diff --git a/src/Compilers/VisualBasic/Portable/VisualBasicCompilationOptions.vb b/src/Compilers/VisualBasic/Portable/VisualBasicCompilationOptions.vb index 46a52983c7e1c21a5050491cbb6722475f6c83f0..36efbf8e2e1d5ab9032c96d292b4022f0ed945ad 100644 --- a/src/Compilers/VisualBasic/Portable/VisualBasicCompilationOptions.vb +++ b/src/Compilers/VisualBasic/Portable/VisualBasicCompilationOptions.vb @@ -24,6 +24,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' those should come from the user's code. Private _suppressEmbeddedDeclarations As Boolean + Private _ignoreCorLibraryDuplicatedTypes As Boolean + ''' ''' Initializes a new instance of the VisualBasicCompilationOptions type with various options. ''' @@ -202,6 +204,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic _embedVbCoreRuntime = embedVbCoreRuntime _suppressEmbeddedDeclarations = suppressEmbeddedDeclarations _parseOptions = parseOptions + _ignoreCorLibraryDuplicatedTypes = False Debug.Assert(Not (_embedVbCoreRuntime AndAlso _suppressEmbeddedDeclarations), "_embedVbCoreRuntime and _suppressEmbeddedDeclarations are mutually exclusive") @@ -359,6 +362,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + ''' + ''' Gets the setting to ignore corlib types when duplicates are found. + ''' + Friend ReadOnly Property IgnoreCorLibraryDuplicatedTypes As Boolean + Get + Return _ignoreCorLibraryDuplicatedTypes + End Get + End Property + ''' ''' Gets the Parse Options setting. ''' Compilation level parse options. Used when compiling synthetic embedded code such as My template @@ -605,6 +617,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return New VisualBasicCompilationOptions(Me) With {._suppressEmbeddedDeclarations = suppressEmbeddedDeclarations} End Function + ''' + ''' Creates a new VisualBasicCompilationOptions instance with different ignoreCorLibraryDuplicatedTypes setting specified. + ''' + ''' The ignoreCorLibraryDuplicatedTypes setting. + ''' Only expected to be called from the expression compiler and interactive. + Friend Function WithIgnoreCorLibraryDuplicatedTypes(ignoreCorLibraryDuplicatedTypes As Boolean) As VisualBasicCompilationOptions + If ignoreCorLibraryDuplicatedTypes = _ignoreCorLibraryDuplicatedTypes Then + Return Me + End If + + Return New VisualBasicCompilationOptions(Me) With {._ignoreCorLibraryDuplicatedTypes = ignoreCorLibraryDuplicatedTypes} + End Function + ''' ''' Creates a new VisualBasicCompilationOptions instance with a different cryptography key container specified ''' diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/VisualBasicCompilationOptionsTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/VisualBasicCompilationOptionsTests.vb index 79182d69975ec793ec643c2b4e1d2f7b10b519f1..b07046dd0259efa98045e30b3a6a5d29cc56b5c1 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/VisualBasicCompilationOptionsTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/VisualBasicCompilationOptionsTests.vb @@ -535,7 +535,8 @@ BC2042: The options /vbruntime* and /target:module cannot be combined. "OptionCompareText", "EmbedVbCoreRuntime", "SuppressEmbeddedDeclarations", - "ParseOptions") + "ParseOptions", + "IgnoreCorLibraryDuplicatedTypes") End Sub diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/TupleTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/TupleTests.cs index 8ff61b913e22098a8755ed32d8afdf632c975633..d3cbea65c3dd7fad386eb6d432a3e33ede67c28f 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/TupleTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/TupleTests.cs @@ -1,18 +1,20 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Collections.Immutable; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.ExpressionEvaluator; using Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests; +using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.Debugger.Clr; using Microsoft.VisualStudio.Debugger.Evaluation; using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation; using Roslyn.Test.Utilities; -using System; -using System.Collections.Immutable; -using System.Collections.ObjectModel; -using System.Linq; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.UnitTests @@ -61,6 +63,83 @@ .maxstack 2 }); } + [Fact] + public void DuplicateValueTupleBetweenMscorlibAndLibrary() + { + var versionTemplate = @"[assembly: System.Reflection.AssemblyVersion(""{0}.0.0.0"")]"; + + var corlib_cs = @" +namespace System +{ + public class Object { } + public struct Int32 { } + public struct Boolean { } + public class String { } + public class ValueType { } + public struct Void { } + public class Attribute { } +} + +namespace System.Reflection +{ + public class AssemblyVersionAttribute : Attribute + { + public AssemblyVersionAttribute(String version) { } + } +}"; + string valuetuple_cs = @" +namespace System +{ + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + public ValueTuple(T1 item1, T2 item2) => (Item1, Item2) = (item1, item2); + } +}"; + var corlibWithoutVT = CreateCompilation(new[] { Parse(String.Format(versionTemplate, "1") + corlib_cs) }, assemblyName: "corlib"); + corlibWithoutVT.VerifyDiagnostics(); + var corlibWithoutVTRef = corlibWithoutVT.EmitToImageReference(); + + var corlibWithVT = CreateCompilation(new[] { Parse(String.Format(versionTemplate, "2") + corlib_cs + valuetuple_cs) }, assemblyName: "corlib"); + corlibWithVT.VerifyDiagnostics(); + + var source = +@"class C +{ + static (int, int) M() + { + (int, int) t = (1, 2); + return t; + } +} +"; + var app = CreateCompilation(source + valuetuple_cs, references: new[] { corlibWithoutVTRef }, options: TestOptions.DebugDll); + app.VerifyDiagnostics(); + + // Create EE context with app assembly (including ValueTuple) and a more recent corlib (also including ValueTuple) + var runtime = CreateRuntimeInstance(new[] { app.ToModuleInstance(), corlibWithVT.ToModuleInstance() }); + var evalContext = CreateMethodContext(runtime, "C.M"); + string error; + var testData = new CompilationTestData(); + var compileResult = evalContext.CompileExpression("(1, 2)", out error, testData); + Assert.Null(error); + + using (ModuleMetadata block = ModuleMetadata.CreateFromStream(new MemoryStream(compileResult.Assembly))) + { + var reader = block.MetadataReader; + + var appRef = app.Assembly.Identity.Name; + AssertEx.SetEqual(new[] { "corlib 2.0", appRef + " 0.0" }, reader.DumpAssemblyReferences()); + + AssertEx.SetEqual(new[] { + "Object, System, AssemblyRef:corlib", + "ValueTuple`2, System, AssemblyRef:" + appRef, // ValueTuple comes from app, not corlib + ", System, AssemblyRef:" + appRef }, + reader.DumpTypeReferences()); + } + } + [Fact] public void TupleElementNamesAttribute_NotAvailable() { diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrRuntimeInstance.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrRuntimeInstance.cs index 7007adfa3562fd21dfc95ad0608b1fcdf6e7a861..b84a90cdb8c56ed3601df9b7a0bc9918842f1d50 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrRuntimeInstance.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrRuntimeInstance.cs @@ -4,12 +4,14 @@ #endregion -using Microsoft.CodeAnalysis.ExpressionEvaluator; -using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation; -using Microsoft.VisualStudio.Debugger.Symbols; using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; +using Microsoft.CodeAnalysis.ExpressionEvaluator; +using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation; +using Microsoft.VisualStudio.Debugger.Symbols; using Type = Microsoft.VisualStudio.Debugger.Metadata.Type; namespace Microsoft.VisualStudio.Debugger.Clr @@ -72,7 +74,7 @@ internal DkmClrType GetType(System.Type type) internal DkmClrType GetType(string typeName, params System.Type[] typeArguments) { - foreach (var module in this.Modules) + foreach (var module in WithMscorlibLast(this.Modules)) { var assembly = module.Assembly; var type = assembly.GetType(typeName); @@ -89,6 +91,27 @@ internal DkmClrType GetType(string typeName, params System.Type[] typeArguments) return null; } + private static IEnumerable WithMscorlibLast(DkmClrModuleInstance[] list) + { + DkmClrModuleInstance mscorlib = null; + foreach (var module in list) + { + if (module.Assembly.GetReferencedAssemblies().Length == 0) + { + Debug.Assert(mscorlib == null); + mscorlib = module; + } + else + { + yield return module; + } + } + if (mscorlib != null) + { + yield return mscorlib; + } + } + internal DkmClrModuleInstance FindClrModuleInstance(Guid mvid) { return this.Modules.FirstOrDefault(m => m.Mvid == mvid) ?? _defaultModule; diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Binders/SuppressDiagnosticsBinder.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Binders/SuppressDiagnosticsBinder.vb index fc590ceea1469e967f30ecfb731cf10e80a67639..978299e9d0e54ecdf90b9463f2200cea2c4c651f 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Binders/SuppressDiagnosticsBinder.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/Binders/SuppressDiagnosticsBinder.vb @@ -21,10 +21,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator Return True End Get End Property - - Friend Overrides Function BinderSpecificLookupOptions(options As LookupOptions) As LookupOptions - Return options Or LookupOptions.IgnoreCorLibraryDuplicatedTypes - End Function End Class End Namespace \ No newline at end of file diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/CompilationExtensions.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/CompilationExtensions.vb index f1e07b7f589f41f28fe6bb7b5b3ab2ba0b4b5e9d..ce1bf43d7ec92a1be8ade6a672d780aae3382d0b 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/CompilationExtensions.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/CompilationExtensions.vb @@ -115,7 +115,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator assemblyIdentityComparer:=IdentityComparer). WithMetadataImportOptions(MetadataImportOptions.All). WithReferencesSupersedeLowerVersions(True). - WithSuppressEmbeddedDeclarations(True) + WithSuppressEmbeddedDeclarations(True). + WithIgnoreCorLibraryDuplicatedTypes(True) End Module diff --git a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/TupleTests.vb b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/TupleTests.vb index b0ef3623559c995cd3516f3ae4dee725c6e4aad2..300405b68fd127966a3887bca66ce562c8c02b9f 100644 --- a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/TupleTests.vb +++ b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/TupleTests.vb @@ -2,9 +2,11 @@ Imports System.Collections.Immutable Imports System.Collections.ObjectModel +Imports System.IO Imports Microsoft.CodeAnalysis.CodeGen Imports Microsoft.CodeAnalysis.ExpressionEvaluator Imports Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests +Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests Imports Microsoft.VisualStudio.Debugger.Clr @@ -63,6 +65,90 @@ End Class" End Sub) End Sub + + Public Sub DuplicateValueTupleBetweenMscorlibAndLibrary() + Const versionTemplate = "" + + Const corlib_vb = " +Namespace System + Public Class [Object] + End Class + Public Structure Void + End Structure + Public Class ValueType + End Class + Public Structure IntPtr + End Structure + Public Structure Int32 + End Structure + Public Class [String] + End Class + Public Class Attribute + End Class +End Namespace + +Namespace System.Reflection + Public Class AssemblyVersionAttribute + Inherits Attribute + + Public Sub New(version As String) + End Sub + End Class +End Namespace +" + + Dim corlibWithoutVT = CreateCompilation({String.Format(versionTemplate, "1") + corlib_vb}, options:=TestOptions.DebugDll, assemblyName:="corlib") + corlibWithoutVT.AssertTheseDiagnostics() + Dim corlibWithoutVTRef = corlibWithoutVT.EmitToImageReference() + + Const valuetuple_vb As String = " +Namespace System + Public Structure ValueTuple(Of T1, T2) + Public Dim Item1 As T1 + Public Dim Item2 As T2 + + Public Sub New(item1 As T1, item2 As T2) + End Sub + End Structure +End Namespace +" + + Dim corlibWithVT = CreateCompilation({String.Format(versionTemplate, "2") + corlib_vb + valuetuple_vb}, options:=TestOptions.DebugDll, assemblyName:="corlib") + corlibWithVT.AssertTheseDiagnostics() + + Const source As String = +"Class C + Shared Function M() As (Integer, Integer) + Dim o = (1, 2) + Return o + End Function +End Class" + + Dim app = CreateCompilation(source + valuetuple_vb, references:={corlibWithoutVTRef}, options:=TestOptions.DebugDll) + app.AssertTheseDiagnostics() + + Dim runtime = CreateRuntimeInstance({app.ToModuleInstance(), corlibWithVT.ToModuleInstance()}) + ' Create EE context with app assembly (including ValueTuple) and a more recent corlib (also including ValueTuple) + Dim evalContext = CreateMethodContext(runtime, "C.M") + Dim errorMessage As String = Nothing + Dim testData = New CompilationTestData() + + Dim compileResult = evalContext.CompileExpression("(1, 2)", errorMessage, testData) + Assert.Null(errorMessage) + + Using block As ModuleMetadata = ModuleMetadata.CreateFromStream(New MemoryStream(compileResult.Assembly)) + Dim reader = block.MetadataReader + + Dim appRef = app.Assembly.Identity.Name + AssertEx.SetEqual({"corlib 2.0", appRef + " 0.0"}, reader.DumpAssemblyReferences()) + + AssertEx.SetEqual({"Object, System, AssemblyRef:corlib", + "ValueTuple`2, System, AssemblyRef:" + appRef, ' ValueTuple comes from app, not corlib + ", System, AssemblyRef:" + appRef}, + reader.DumpTypeReferences()) + End Using + End Sub + Public Sub TupleElementNamesAttribute_NotAvailable() Const source = @@ -295,25 +381,25 @@ End Class" End Class" Dim comp = CreateCompilationWithMscorlib({source}, references:={ValueTupleRef, SystemRuntimeFacadeRef}, options:=TestOptions.DebugDll) WithRuntimeInstance(comp, references:={MscorlibRef, ValueTupleRef, SystemRuntimeFacadeRef}, - validator:= Sub(runtime) - Dim context = CreateMethodContext(runtime, "C.M") - Dim errorMessage As String = Nothing - Dim testData = New CompilationTestData() - Dim result = context.CompileExpression( - "y = DirectCast(x, (A As Integer, B As Integer))", - DkmEvaluationFlags.None, - NoAliases, - errorMessage, - testData) - Assert.Null(errorMessage) - Dim typeInfo As ReadOnlyCollection(Of Byte) = Nothing - Dim typeInfoId = result.GetCustomTypeInfo(typeInfo) - Assert.Null(typeInfo) - Dim methodData = testData.GetMethodData("<>x.<>m0") - Dim method = methodData.Method - Assert.Null(GetTupleElementNamesAttributeIfAny(method)) - methodData.VerifyIL( -"{ + validator:=Sub(runtime) + Dim context = CreateMethodContext(runtime, "C.M") + Dim errorMessage As String = Nothing + Dim testData = New CompilationTestData() + Dim result = context.CompileExpression( + "y = DirectCast(x, (A As Integer, B As Integer))", + DkmEvaluationFlags.None, + NoAliases, + errorMessage, + testData) + Assert.Null(errorMessage) + Dim typeInfo As ReadOnlyCollection(Of Byte) = Nothing + Dim typeInfoId = result.GetCustomTypeInfo(typeInfo) + Assert.Null(typeInfo) + Dim methodData = testData.GetMethodData("<>x.<>m0") + Dim method = methodData.Method + Assert.Null(GetTupleElementNamesAttributeIfAny(method)) + methodData.VerifyIL( + "{ // Code size 48 (0x30) .maxstack 4 .locals init ((Integer, Integer) V_0, //x @@ -333,7 +419,7 @@ End Class" IL_002e: stind.ref IL_002f: ret }") - End Sub) + End Sub) End Sub diff --git a/src/Scripting/VisualBasic/VisualBasicScriptCompiler.vb b/src/Scripting/VisualBasic/VisualBasicScriptCompiler.vb index 98d01f5aacaf3af448f82e839f585843a8945194..7bcd2666efa1a3f30d3ae1f872afc34802308655 100644 --- a/src/Scripting/VisualBasic/VisualBasicScriptCompiler.vb +++ b/src/Scripting/VisualBasic/VisualBasicScriptCompiler.vb @@ -86,7 +86,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Scripting xmlReferenceResolver:=Nothing, ' don't support XML file references in interactive (permissions & doc comment includes) sourceReferenceResolver:=SourceFileResolver.Default, metadataReferenceResolver:=script.Options.MetadataResolver, - assemblyIdentityComparer:=DesktopAssemblyIdentityComparer.Default), + assemblyIdentityComparer:=DesktopAssemblyIdentityComparer.Default). + WithIgnoreCorLibraryDuplicatedTypes(True), previousSubmission, script.ReturnType, script.GlobalsType)