internal NamedTypeSymbol GetWellKnownType(WellKnownType type) { Debug.Assert(type.IsValid()); int index = (int)type - (int)WellKnownType.First; if (_lazyWellKnownTypes == null || (object)_lazyWellKnownTypes[index] == null) { if (_lazyWellKnownTypes == null) { Interlocked.CompareExchange(ref _lazyWellKnownTypes, new NamedTypeSymbol[(int)WellKnownTypes.Count], null); } string mdName = type.GetMetadataName(); var warnings = DiagnosticBag.GetInstance(); NamedTypeSymbol result; if (IsTypeMissing(type)) { result = null; } else { // well-known types introduced before CSharp7 allow lookup ambiguity and report a warning DiagnosticBag legacyWarnings = (type <= WellKnownType.CSharp7Sentinel) ? warnings : null; result = this.Assembly.GetTypeByMetadataName( mdName, includeReferences: true, useCLSCompliantNameArityEncoding: true, isWellKnownType: true, warnings: legacyWarnings); } if ((object)result == null) { // TODO: should GetTypeByMetadataName rather return a missing symbol? MetadataTypeName emittedName = MetadataTypeName.FromFullName(mdName, useCLSCompliantNameArityEncoding: true); result = new MissingMetadataTypeSymbol.TopLevel(this.Assembly.Modules[0], ref emittedName, type); } if ((object)Interlocked.CompareExchange(ref _lazyWellKnownTypes[index], result, null) != null) { Debug.Assert( result == _lazyWellKnownTypes[index] || (_lazyWellKnownTypes[index].IsErrorType() && result.IsErrorType()) ); } else { AdditionalCodegenWarnings.AddRange(warnings); } warnings.Free(); } return(_lazyWellKnownTypes[index]); }
/// <summary> /// This method handles duplicate types in a few different ways: /// - for types before C# 7, the first candidate is returned with a warning /// - for types after C# 7, the type is considered missing /// - in both cases, when BinderFlags.IgnoreCorLibraryDuplicatedTypes is set, any duplicate coming from corlib will be ignored (ie not count as a duplicate) /// </summary> 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) { if (_lazyWellKnownTypes == null) { Interlocked.CompareExchange(ref _lazyWellKnownTypes, new NamedTypeSymbol[(int)WellKnownTypes.Count], null); } string mdName = type.GetMetadataName(); var warnings = DiagnosticBag.GetInstance(); NamedTypeSymbol result; (AssemblySymbol, AssemblySymbol)conflicts = default; if (IsTypeMissing(type)) { result = null; } else { // well-known types introduced before CSharp7 allow lookup ambiguity and report a warning DiagnosticBag legacyWarnings = (type <= WellKnownType.CSharp7Sentinel) ? warnings : null; result = this.Assembly.GetTypeByMetadataName( mdName, includeReferences: true, useCLSCompliantNameArityEncoding: true, isWellKnownType: true, conflicts: out conflicts, warnings: legacyWarnings, ignoreCorLibraryDuplicatedTypes: ignoreCorLibraryDuplicatedTypes); } if ((object)result == null) { // TODO: should GetTypeByMetadataName rather return a missing symbol? MetadataTypeName emittedName = MetadataTypeName.FromFullName(mdName, useCLSCompliantNameArityEncoding: true); if (type.IsValueTupleType()) { CSDiagnosticInfo errorInfo; if (conflicts.Item1 is null) { Debug.Assert(conflicts.Item2 is null); errorInfo = new CSDiagnosticInfo(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, emittedName.FullName); } else { errorInfo = new CSDiagnosticInfo(ErrorCode.ERR_PredefinedValueTupleTypeAmbiguous3, emittedName.FullName, conflicts.Item1, conflicts.Item2); } result = new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(this.Assembly.Modules[0], ref emittedName, errorInfo, type); } else { result = new MissingMetadataTypeSymbol.TopLevel(this.Assembly.Modules[0], ref emittedName, type); } } if ((object)Interlocked.CompareExchange(ref _lazyWellKnownTypes[index], result, null) != null) { Debug.Assert( result == _lazyWellKnownTypes[index] || (_lazyWellKnownTypes[index].IsErrorType() && result.IsErrorType()) ); } else { AdditionalCodegenWarnings.AddRange(warnings); } warnings.Free(); } return(_lazyWellKnownTypes[index]); }