private ImmutableArray <NamedTypeSymbol> MakeDeclaredBases(ConsList <TypeSymbol> basesBeingResolved, DiagnosticBag diagnostics) { Debug.Assert(basesBeingResolved == null || !basesBeingResolved.ContainsReference(this.OriginalDefinition)); var newBasesBeingResolved = basesBeingResolved.Prepend(this.OriginalDefinition); var baseTypes = ArrayBuilder <NamedTypeSymbol> .GetInstance(); var baseTypeLocations = PooledDictionary <NamedTypeSymbol, Location> .GetInstance(); foreach (var decl in this.MergedDeclaration.Declarations) { ImmutableArray <NamedTypeSymbol> partBaseTypes = ResolveBaseTypes(newBasesBeingResolved, decl, diagnostics); if (partBaseTypes.IsEmpty) { continue; } foreach (var t in partBaseTypes) { if (!baseTypeLocations.ContainsKey(t)) { baseTypes.Add(t); baseTypeLocations.Add(t, decl.NameLocation); } } } HashSet <DiagnosticInfo> useSiteDiagnostics = null; var baseTypesRO = baseTypes.ToImmutableAndFree(); this.CheckDeclaredBaseTypes(baseTypesRO, baseTypeLocations, diagnostics, ref useSiteDiagnostics); baseTypeLocations.Free(); diagnostics.Add(Locations[0], useSiteDiagnostics); return(baseTypesRO); }
protected override TypeParameterBounds ResolveBounds( ConsList <TypeParameterSymbol> inProgress, BindingDiagnosticBag diagnostics ) { var typeParameter = this.OverriddenTypeParameter; if ((object)typeParameter == null) { return(null); } var map = _map.TypeMap; Debug.Assert(map != null); var constraintTypes = map.SubstituteTypes( typeParameter.ConstraintTypesNoUseSiteDiagnostics ); return(this.ResolveBounds( this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited: true, this.DeclaringCompilation, diagnostics )); }
static bool isValueType( TypeParameterSymbol thisTypeParameter, ImmutableArray <TypeParameterConstraintClause> constraintClauses, SmallDictionary <TypeParameterSymbol, bool> isValueTypeMap, ConsList <TypeParameterSymbol> inProgress ) { if (inProgress.ContainsReference(thisTypeParameter)) { return(false); } if (isValueTypeMap.TryGetValue(thisTypeParameter, out bool knownIsValueType)) { return(knownIsValueType); } TypeParameterConstraintClause constraintClause = constraintClauses[ thisTypeParameter.Ordinal ]; bool result = false; if ( (constraintClause.Constraints & TypeParameterConstraintKind.AllValueTypeKinds) != 0 ) { result = true; } else { Symbol container = thisTypeParameter.ContainingSymbol; inProgress = inProgress.Prepend(thisTypeParameter); foreach (TypeWithAnnotations constraintType in constraintClause.ConstraintTypes) { TypeSymbol type = constraintType.IsResolved ? constraintType.Type : constraintType.DefaultType; if ( type is TypeParameterSymbol typeParameter && (object)typeParameter.ContainingSymbol == (object)container ) { if ( isValueType( typeParameter, constraintClauses, isValueTypeMap, inProgress ) ) { result = true; break; } }
protected override TypeParameterBounds ResolveBounds(ConsList <TypeParameterSymbol> inProgress, DiagnosticBag diagnostics) { var constraintClauses = _owner.TypeParameterConstraintClauses; var constraintTypes = constraintClauses.IsEmpty ? ImmutableArray <TypeSymbol> .Empty : constraintClauses[Ordinal]?.ConstraintTypes ?? ImmutableArray <TypeSymbol> .Empty; return(this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, false, this.DeclaringCompilation, diagnostics)); }
protected override TypeParameterBounds ResolveBounds(ConsList <TypeParameterSymbol> inProgress, BindingDiagnosticBag diagnostics) { var constraintTypes = _owner.GetTypeParameterConstraintTypes(this.Ordinal); if (constraintTypes.IsEmpty && GetConstraintKinds() == TypeParameterConstraintKind.None) { return(null); } return(this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited: false, this.DeclaringCompilation, diagnostics)); }
private bool UsesIsNullable(TypeSymbol type, ConsList <TypeParameterSymbol> inProgress) { if (type is null) { return(false); } switch (type.TypeKind) { case TypeKind.Class: case TypeKind.Delegate: case TypeKind.Interface: case TypeKind.Struct: case TypeKind.Enum: if (UsesIsNullable(type.ContainingType, inProgress)) { return(true); } break; } switch (type.TypeKind) { case TypeKind.Array: return(UsesIsNullable(((ArrayTypeSymbol)type).ElementType, inProgress)); case TypeKind.Class: case TypeKind.Delegate: case TypeKind.Error: case TypeKind.Interface: case TypeKind.Struct: return(UsesIsNullable(((NamedTypeSymbol)type).TypeArgumentsNoUseSiteDiagnostics, inProgress)); case TypeKind.Dynamic: case TypeKind.Enum: return(false); case TypeKind.Pointer: return(UsesIsNullable(((PointerTypeSymbol)type).PointedAtType, inProgress)); case TypeKind.TypeParameter: var typeParameter = (TypeParameterSymbol)type; if (inProgress?.ContainsReference(typeParameter) == true) { return(false); } inProgress = inProgress ?? ConsList <TypeParameterSymbol> .Empty; inProgress = inProgress.Prepend(typeParameter); return(UsesIsNullable(typeParameter.ConstraintTypesNoUseSiteDiagnostics, inProgress) || typeParameter.ReferenceTypeConstraintIsNullable == true); default: throw ExceptionUtilities.UnexpectedValue(type.TypeKind); } }
protected override TypeParameterBounds ResolveBounds(ConsList <TypeParameterSymbol> inProgress, DiagnosticBag diagnostics) { var constraintClause = GetTypeParameterConstraintClause(); if (constraintClause.IsEmpty) { return(null); } var constraintTypes = constraintClause.ConstraintTypes; return(this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited: false, this.DeclaringCompilation, diagnostics)); }
private bool AnyConstraintTypes( ImmutableArray <TypeWithAnnotations> constraintTypes, Func <TypeParameterSymbol, bool> predicate1, Func <TypeSymbol, bool> predicate2) { if (constraintTypes.IsEmpty) { return(false); } bool result = false; ConsList <TypeParameterSymbol> inProgress = ConsList <TypeParameterSymbol> .Empty.Push(this); var stack = ArrayBuilder <TypeWithAnnotations> .GetInstance(constraintTypes.Length); stack.AddRange(constraintTypes); do { TypeWithAnnotations constraintType = stack.Pop(); TypeSymbol type = constraintType.IsResolved ? constraintType.Type : constraintType.DefaultType; if (type.IsTypeParameter()) { var typeParameter = (TypeParameterSymbol)type; if (inProgress.ContainsReference(typeParameter)) { continue; } if (predicate1(typeParameter)) { result = true; break; } inProgress = inProgress.Prepend(typeParameter); stack.AddRange(typeParameter.GetConstraintTypesNoUseSiteDiagnostics(early: true)); } else if (predicate2(type)) { result = true; break; } }while (stack.Count != 0); stack.Free(); return(result); }
private bool AnyConstraintTypes( ImmutableArray <TypeSymbolWithAnnotations> constraintTypes, ConsList <TypeParameterSymbol> inProgress, Func <TypeSymbolWithAnnotations, ConsList <TypeParameterSymbol>, bool> predicate) { if (constraintTypes.IsEmpty) { return(false); } inProgress = inProgress.Prepend(this); foreach (var constraintType in constraintTypes) { if (predicate(constraintType, inProgress)) { return(true); } } return(false); }
protected override TypeParameterBounds ResolveBounds(ConsList <TypeParameterSymbol> inProgress, bool early, DiagnosticBag diagnostics) { var typeParameter = this.OverriddenTypeParameter; if ((object)typeParameter == null) { return(null); } var map = _map.TypeMap; Debug.Assert(map != null); // Use typeParameter.ConstraintTypesNoUseSiteDiagnostics rather than // typeParameter.GetConstraintTypesNoUseSiteDiagnostics(inProgress) // because the overridden type parameter is from a different container. var constraintTypes = map.SubstituteTypes(typeParameter.ConstraintTypesNoUseSiteDiagnostics); if (early) { return(new TypeParameterBounds(constraintTypes)); } return(this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited: true, this.DeclaringCompilation, diagnostics)); }
private Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > MakeDeclaredBases(ConsList <TypeSymbol> basesBeingResolved, DiagnosticBag diagnostics) { if (this.TypeKind == TypeKind.Enum) { // Handled by GetEnumUnderlyingType(). return(new Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> >(null, ImmutableArray <NamedTypeSymbol> .Empty)); } var reportedPartialConflict = false; Debug.Assert(basesBeingResolved == null || !basesBeingResolved.ContainsReference(this.OriginalDefinition)); var newBasesBeingResolved = basesBeingResolved.Prepend(this.OriginalDefinition); var baseInterfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance(); NamedTypeSymbol baseType = null; SourceLocation baseTypeLocation = null; var interfaceLocations = PooledDictionary <NamedTypeSymbol, SourceLocation> .GetInstance(); foreach (var decl in this.declaration.Declarations) { Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > one = MakeOneDeclaredBases(newBasesBeingResolved, decl, diagnostics); if ((object)one == null) { continue; } var partBase = one.Item1; var partInterfaces = one.Item2; if (!reportedPartialConflict) { if ((object)baseType == null) { baseType = partBase; baseTypeLocation = decl.NameLocation; } else if (baseType.TypeKind == TypeKind.Error && (object)partBase != null) { // if the old base was an error symbol, copy it to the interfaces list so it doesn't get lost partInterfaces = partInterfaces.Add(baseType); baseType = partBase; baseTypeLocation = decl.NameLocation; } else if ((object)partBase != null && !TypeSymbol.Equals(partBase, baseType, TypeCompareKind.ConsiderEverything2) && partBase.TypeKind != TypeKind.Error) { // the parts do not agree var info = diagnostics.Add(ErrorCode.ERR_PartialMultipleBases, Locations[0], this); baseType = new ExtendedErrorTypeSymbol(baseType, LookupResultKind.Ambiguous, info); baseTypeLocation = decl.NameLocation; reportedPartialConflict = true; } } foreach (var t in partInterfaces) { if (!interfaceLocations.ContainsKey(t)) { baseInterfaces.Add(t); interfaceLocations.Add(t, decl.NameLocation); } } } HashSet <DiagnosticInfo> useSiteDiagnostics = null; if ((object)baseType != null) { Debug.Assert(baseTypeLocation != null); if (baseType.IsStatic) { // '{1}': cannot derive from static class '{0}' diagnostics.Add(ErrorCode.ERR_StaticBaseClass, baseTypeLocation, baseType, this); } if (!this.IsNoMoreVisibleThan(baseType, ref useSiteDiagnostics)) { // Inconsistent accessibility: base class '{1}' is less accessible than class '{0}' diagnostics.Add(ErrorCode.ERR_BadVisBaseClass, baseTypeLocation, this, baseType); } } var baseInterfacesRO = baseInterfaces.ToImmutableAndFree(); if (DeclaredAccessibility != Accessibility.Private && IsInterface) { foreach (var i in baseInterfacesRO) { if (!i.IsAtLeastAsVisibleAs(this, ref useSiteDiagnostics)) { // Inconsistent accessibility: base interface '{1}' is less accessible than interface '{0}' diagnostics.Add(ErrorCode.ERR_BadVisBaseInterface, interfaceLocations[i], this, i); } } } interfaceLocations.Free(); diagnostics.Add(Locations[0], useSiteDiagnostics); return(new Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> >(baseType, baseInterfacesRO)); }
private Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > MakeDeclaredBases(ConsList <Symbol> basesBeingResolved, DiagnosticBag diagnostics) { if (this.TypeKind == TypeKind.Enum) { // Handled by GetEnumUnderlyingType(). return(new Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> >(null, ImmutableArray <NamedTypeSymbol> .Empty)); } var reportedPartialConflict = false; Debug.Assert(basesBeingResolved == null || !basesBeingResolved.ContainsReference(this.OriginalDefinition)); var newBasesBeingResolved = basesBeingResolved.Prepend(this.OriginalDefinition); var baseInterfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance(); NamedTypeSymbol baseType = null; foreach (var decl in this.declaration.Declarations) { Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > one = MakeOneDeclaredBases(newBasesBeingResolved, decl, diagnostics); if ((object)one == null) { continue; } var partBase = one.Item1; var partInterfaces = one.Item2; if (!reportedPartialConflict) { if ((object)baseType == null) { baseType = partBase; } else if (baseType.TypeKind == TypeKind.Error && (object)partBase != null) { // if the old base was an error symbol, copy it to the interfaces list so it doesn't get lost partInterfaces = partInterfaces.Add(baseType); baseType = partBase; } else if ((object)partBase != null && partBase != baseType && partBase.TypeKind != TypeKind.Error) { // the parts do not agree var info = diagnostics.Add(ErrorCode.ERR_PartialMultipleBases, Locations[0], this); baseType = new ExtendedErrorTypeSymbol(baseType, LookupResultKind.Ambiguous, info); reportedPartialConflict = true; } } int n = baseInterfaces.Count; foreach (var t in partInterfaces) // this could probably be done more efficiently with a side hash table if it proves necessary { for (int i = 0; i < n; i++) { if (t == baseInterfaces[i]) { goto alreadyInInterfaceList; } } baseInterfaces.Add(t); alreadyInInterfaceList :; } } if ((object)baseType != null && baseType.IsStatic) { // '{1}': cannot derive from static class '{0}' diagnostics.Add(ErrorCode.ERR_StaticBaseClass, Locations[0], baseType, this); } HashSet <DiagnosticInfo> useSiteDiagnostics = null; if ((object)baseType != null && !this.IsNoMoreVisibleThan(baseType, ref useSiteDiagnostics)) { // Inconsistent accessibility: base class '{1}' is less accessible than class '{0}' diagnostics.Add(ErrorCode.ERR_BadVisBaseClass, Locations[0], this, baseType); } var baseInterfacesRO = baseInterfaces.ToImmutableAndFree(); if (DeclaredAccessibility != Accessibility.Private && IsInterface) { foreach (var i in baseInterfacesRO) { if (!i.IsAtLeastAsVisibleAs(this, ref useSiteDiagnostics)) { // Inconsistent accessibility: base interface '{1}' is less accessible than interface '{0}' diagnostics.Add(ErrorCode.ERR_BadVisBaseInterface, Locations[0], this, i); } } } diagnostics.Add(Locations[0], useSiteDiagnostics); return(new Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> >(baseType, baseInterfacesRO)); }
private ImmutableArray <TypeWithAnnotations> GetDeclaredConstraintTypes(ConsList <PETypeParameterSymbol> inProgress) { Debug.Assert(!inProgress.ContainsReference(this)); Debug.Assert(!inProgress.Any() || ReferenceEquals(inProgress.Head.ContainingSymbol, this.ContainingSymbol)); if (_lazyDeclaredConstraintTypes.IsDefault) { ImmutableArray <TypeWithAnnotations> declaredConstraintTypes; var moduleSymbol = ((PEModuleSymbol)this.ContainingModule); PEModule peModule = moduleSymbol.Module; GenericParameterConstraintHandleCollection constraints = GetConstraintHandleCollection(peModule); bool hasUnmanagedModreqPattern = false; if (constraints.Count > 0) { var symbolsBuilder = ArrayBuilder <TypeWithAnnotations> .GetInstance(); MetadataDecoder tokenDecoder = GetDecoder(moduleSymbol); TypeWithAnnotations bestObjectConstraint = default; var metadataReader = peModule.MetadataReader; foreach (var constraintHandle in constraints) { TypeWithAnnotations type = GetConstraintTypeOrDefault(moduleSymbol, metadataReader, tokenDecoder, constraintHandle, ref hasUnmanagedModreqPattern); if (!type.HasType) { // Dropped 'System.ValueType' constraint type when the 'valuetype' constraint was also specified. continue; } // Drop 'System.Object' constraint type. if (ConstraintsHelper.IsObjectConstraint(type, ref bestObjectConstraint)) { continue; } symbolsBuilder.Add(type); } if (bestObjectConstraint.HasType) { // See if we need to put Object! or Object~ back in order to preserve nullability information for the type parameter. if (ConstraintsHelper.IsObjectConstraintSignificant(CalculateIsNotNullableFromNonTypeConstraints(), bestObjectConstraint)) { Debug.Assert(!HasNotNullConstraint && !HasValueTypeConstraint); if (symbolsBuilder.Count == 0) { if (bestObjectConstraint.NullableAnnotation.IsOblivious() && !HasReferenceTypeConstraint) { bestObjectConstraint = default; } } else { inProgress = inProgress.Prepend(this); foreach (TypeWithAnnotations constraintType in symbolsBuilder) { if (!ConstraintsHelper.IsObjectConstraintSignificant(IsNotNullableFromConstraintType(constraintType, inProgress, out _), bestObjectConstraint)) { bestObjectConstraint = default; break; } } } if (bestObjectConstraint.HasType) { symbolsBuilder.Insert(0, bestObjectConstraint); } } } declaredConstraintTypes = symbolsBuilder.ToImmutableAndFree(); } else { declaredConstraintTypes = ImmutableArray <TypeWithAnnotations> .Empty; } // - presence of unmanaged pattern has to be matched with `valuetype` // - IsUnmanagedAttribute is allowed iff there is an unmanaged pattern if (hasUnmanagedModreqPattern && (_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0 || hasUnmanagedModreqPattern != peModule.HasIsUnmanagedAttribute(_handle)) { // we do not recognize these combinations as "unmanaged" hasUnmanagedModreqPattern = false; _lazyCachedConstraintsUseSiteInfo.InterlockedCompareExchange(primaryDependency: null, new UseSiteInfo <AssemblySymbol>(new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this))); } _lazyHasIsUnmanagedConstraint = hasUnmanagedModreqPattern.ToThreeState(); ImmutableInterlocked.InterlockedInitialize(ref _lazyDeclaredConstraintTypes, declaredConstraintTypes); } return(_lazyDeclaredConstraintTypes); }
private Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > MakeDeclaredBases(ConsList <TypeSymbol> basesBeingResolved, BindingDiagnosticBag diagnostics) { if (this.TypeKind == TypeKind.Enum) { // Handled by GetEnumUnderlyingType(). return(new Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> >(null, ImmutableArray <NamedTypeSymbol> .Empty)); } var reportedPartialConflict = false; Debug.Assert(basesBeingResolved == null || !basesBeingResolved.ContainsReference(this.OriginalDefinition)); var newBasesBeingResolved = basesBeingResolved.Prepend(this.OriginalDefinition); var baseInterfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance(); NamedTypeSymbol baseType = null; SourceLocation baseTypeLocation = null; var interfaceLocations = SpecializedSymbolCollections.GetPooledSymbolDictionaryInstance <NamedTypeSymbol, SourceLocation>(); foreach (var decl in this.declaration.Declarations) { Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > one = MakeOneDeclaredBases(newBasesBeingResolved, decl, diagnostics); if ((object)one == null) { continue; } var partBase = one.Item1; var partInterfaces = one.Item2; if (!reportedPartialConflict) { if ((object)baseType == null) { baseType = partBase; baseTypeLocation = decl.NameLocation; } else if (baseType.TypeKind == TypeKind.Error && (object)partBase != null) { // if the old base was an error symbol, copy it to the interfaces list so it doesn't get lost partInterfaces = partInterfaces.Add(baseType); baseType = partBase; baseTypeLocation = decl.NameLocation; } else if ((object)partBase != null && !TypeSymbol.Equals(partBase, baseType, TypeCompareKind.ConsiderEverything) && partBase.TypeKind != TypeKind.Error) { // the parts do not agree if (partBase.Equals(baseType, TypeCompareKind.ObliviousNullableModifierMatchesAny)) { if (containsOnlyOblivious(baseType)) { baseType = partBase; baseTypeLocation = decl.NameLocation; continue; } else if (containsOnlyOblivious(partBase)) { continue; } } var info = diagnostics.Add(ErrorCode.ERR_PartialMultipleBases, Locations[0], this); baseType = new ExtendedErrorTypeSymbol(baseType, LookupResultKind.Ambiguous, info); baseTypeLocation = decl.NameLocation; reportedPartialConflict = true;
private TypeParameterBounds GetBounds(ConsList <TypeParameterSymbol> inProgress, bool early) { // https://github.com/dotnet/roslyn/issues/30081: Re-enable asserts. //Debug.Assert(!inProgress.ContainsReference(this)); //Debug.Assert(!inProgress.Any() || ReferenceEquals(inProgress.Head.ContainingSymbol, this.ContainingSymbol)); var currentBounds = _lazyBounds; if (currentBounds == TypeParameterBounds.Unset) { var constraintTypes = GetDeclaredConstraintTypes(); Debug.Assert(!constraintTypes.IsDefault); var bounds = new TypeParameterBounds(constraintTypes); Interlocked.CompareExchange(ref _lazyBounds, bounds, currentBounds); currentBounds = _lazyBounds; } if (!currentBounds.IsSet(early)) { var constraintTypes = currentBounds.ConstraintTypes; var diagnostics = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance(); ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; bool inherited = (_containingSymbol.Kind == SymbolKind.Method) && ((MethodSymbol)_containingSymbol).IsOverride; var bounds = this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited, currentCompilation: null, diagnosticsBuilder: diagnostics, useSiteDiagnosticsBuilder: ref useSiteDiagnosticsBuilder); DiagnosticInfo errorInfo = null; if (diagnostics.Count > 0) { errorInfo = diagnostics[0].DiagnosticInfo; } else if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0) { foreach (var diag in useSiteDiagnosticsBuilder) { if (diag.DiagnosticInfo.Severity == DiagnosticSeverity.Error) { errorInfo = diag.DiagnosticInfo; break; } else if ((object)errorInfo == null) { errorInfo = diag.DiagnosticInfo; } } } diagnostics.Free(); Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, errorInfo, CSDiagnosticInfo.EmptyErrorInfo); Interlocked.CompareExchange(ref _lazyBounds, bounds, currentBounds); } return(_lazyBounds); }
protected override TypeParameterBounds ResolveBounds(ConsList<TypeParameterSymbol> inProgress, DiagnosticBag diagnostics) { var typeParameter = this.OverriddenTypeParameter; if ((object)typeParameter == null) { return null; } var map = _map.TypeMap; Debug.Assert(map != null); var constraintTypes = map.SubstituteTypesWithoutModifiers(typeParameter.ConstraintTypesNoUseSiteDiagnostics); return this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, true, this.DeclaringCompilation, diagnostics); }
private Tuple<NamedTypeSymbol, ImmutableArray<NamedTypeSymbol>> MakeDeclaredBases(ConsList<Symbol> basesBeingResolved, DiagnosticBag diagnostics) { if (this.TypeKind == TypeKind.Enum) { // Handled by GetEnumUnderlyingType(). return new Tuple<NamedTypeSymbol, ImmutableArray<NamedTypeSymbol>>(null, ImmutableArray<NamedTypeSymbol>.Empty); } var reportedPartialConflict = false; Debug.Assert(basesBeingResolved == null || !basesBeingResolved.ContainsReference(this.OriginalDefinition)); var newBasesBeingResolved = basesBeingResolved.Prepend(this.OriginalDefinition); var baseInterfaces = ArrayBuilder<NamedTypeSymbol>.GetInstance(); NamedTypeSymbol baseType = null; foreach (var decl in this.declaration.Declarations) { Tuple<NamedTypeSymbol, ImmutableArray<NamedTypeSymbol>> one = MakeOneDeclaredBases(newBasesBeingResolved, decl, diagnostics); if ((object)one == null) continue; var partBase = one.Item1; var partInterfaces = one.Item2; if (!reportedPartialConflict) { if ((object)baseType == null) { baseType = partBase; } else if (baseType.TypeKind == TypeKind.Error && (object)partBase != null) { // if the old base was an error symbol, copy it to the interfaces list so it doesn't get lost partInterfaces = partInterfaces.Add(baseType); baseType = partBase; } else if ((object)partBase != null && partBase != baseType && partBase.TypeKind != TypeKind.Error) { // the parts do not agree var info = diagnostics.Add(ErrorCode.ERR_PartialMultipleBases, Locations[0], this); baseType = new ExtendedErrorTypeSymbol(baseType, LookupResultKind.Ambiguous, info); reportedPartialConflict = true; } } int n = baseInterfaces.Count; foreach (var t in partInterfaces) // this could probably be done more efficiently with a side hash table if it proves necessary { for (int i = 0; i < n; i++) { if (t == baseInterfaces[i]) { goto alreadyInInterfaceList; } } baseInterfaces.Add(t); alreadyInInterfaceList:; } } if ((object)baseType != null && baseType.IsStatic) { // '{1}': cannot derive from static class '{0}' diagnostics.Add(ErrorCode.ERR_StaticBaseClass, Locations[0], baseType, this); } HashSet<DiagnosticInfo> useSiteDiagnostics = null; if ((object)baseType != null && !this.IsNoMoreVisibleThan(baseType, ref useSiteDiagnostics)) { // Inconsistent accessibility: base class '{1}' is less accessible than class '{0}' diagnostics.Add(ErrorCode.ERR_BadVisBaseClass, Locations[0], this, baseType); } var baseInterfacesRO = baseInterfaces.ToImmutableAndFree(); if (DeclaredAccessibility != Accessibility.Private && IsInterface) { foreach (var i in baseInterfacesRO) { if (!i.IsAtLeastAsVisibleAs(this, ref useSiteDiagnostics)) { // Inconsistent accessibility: base interface '{1}' is less accessible than interface '{0}' diagnostics.Add(ErrorCode.ERR_BadVisBaseInterface, Locations[0], this, i); } } } diagnostics.Add(Locations[0], useSiteDiagnostics); return new Tuple<NamedTypeSymbol, ImmutableArray<NamedTypeSymbol>>(baseType, baseInterfacesRO); }
protected override TypeParameterBounds ResolveBounds(ConsList<TypeParameterSymbol> inProgress, DiagnosticBag diagnostics) { var constraintTypes = _owner.GetTypeParameterConstraintTypes(this.Ordinal); return this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, false, this.DeclaringCompilation, diagnostics); }
private TypeParameterBounds GetBounds(ConsList<TypeParameterSymbol> inProgress) { Debug.Assert(!inProgress.ContainsReference(this)); Debug.Assert(!inProgress.Any() || ReferenceEquals(inProgress.Head.ContainingSymbol, this.ContainingSymbol)); if (ReferenceEquals(_lazyBounds, TypeParameterBounds.Unset)) { var constraintTypes = GetDeclaredConstraintTypes(); Debug.Assert(!constraintTypes.IsDefault); var diagnostics = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance(); ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; bool inherited = (_containingSymbol.Kind == SymbolKind.Method) && ((MethodSymbol)_containingSymbol).IsOverride; var bounds = this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited, currentCompilation: null, diagnosticsBuilder: diagnostics, useSiteDiagnosticsBuilder: ref useSiteDiagnosticsBuilder); DiagnosticInfo errorInfo = null; if (diagnostics.Count > 0) { errorInfo = diagnostics[0].DiagnosticInfo; } else if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0) { foreach (var diag in useSiteDiagnosticsBuilder) { if (diag.DiagnosticInfo.Severity == DiagnosticSeverity.Error) { errorInfo = diag.DiagnosticInfo; break; } else if ((object)errorInfo == null) { errorInfo = diag.DiagnosticInfo; } } } diagnostics.Free(); Interlocked.CompareExchange(ref _lazyBoundsErrorInfo, errorInfo, CSDiagnosticInfo.EmptyErrorInfo); Interlocked.CompareExchange(ref _lazyBounds, bounds, TypeParameterBounds.Unset); } Debug.Assert(!ReferenceEquals(_lazyBoundsErrorInfo, CSDiagnosticInfo.EmptyErrorInfo)); return _lazyBounds; }
protected override TypeParameterBounds ResolveBounds(ConsList <TypeParameterSymbol> inProgress, DiagnosticBag diagnostics) { var constraintTypes = _owner.GetTypeParameterConstraintTypes(this.Ordinal); return(this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, false, this.DeclaringCompilation, diagnostics)); }
private TypeParameterBounds ResolveBounds(ConsList <TypeParameterSymbol> inProgress, DiagnosticBag diagnostics) => this.ResolveBounds(ContainingAssembly.CorLibrary, inProgress.Prepend(this), _constraintTypes(Ordinal), false, DeclaringCompilation, diagnostics);
private TypeParameterBounds GetBounds(ConsList <TypeParameterSymbol> inProgress) { Debug.Assert(!inProgress.ContainsReference(this)); Debug.Assert(!inProgress.Any() || ReferenceEquals(inProgress.Head.ContainingSymbol, this.ContainingSymbol)); if (ReferenceEquals(_lazyBounds, TypeParameterBounds.Unset)) { var constraintTypes = GetDeclaredConstraintTypes(); Debug.Assert(!constraintTypes.IsDefault); var diagnostics = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance(); ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; bool inherited = (_containingSymbol.Kind == SymbolKind.Method) && ((MethodSymbol)_containingSymbol).IsOverride; var bounds = this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited, currentCompilation: null, diagnosticsBuilder: diagnostics, useSiteDiagnosticsBuilder: ref useSiteDiagnosticsBuilder); DiagnosticInfo errorInfo = null; if (diagnostics.Count > 0) { errorInfo = diagnostics[0].DiagnosticInfo; } else if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0) { foreach (var diag in useSiteDiagnosticsBuilder) { if (diag.DiagnosticInfo.Severity == DiagnosticSeverity.Error) { errorInfo = diag.DiagnosticInfo; break; } else if ((object)errorInfo == null) { errorInfo = diag.DiagnosticInfo; } } } diagnostics.Free(); Interlocked.CompareExchange(ref _lazyBoundsErrorInfo, errorInfo, CSDiagnosticInfo.EmptyErrorInfo); Interlocked.CompareExchange(ref _lazyBounds, bounds, TypeParameterBounds.Unset); } Debug.Assert(!ReferenceEquals(_lazyBoundsErrorInfo, CSDiagnosticInfo.EmptyErrorInfo)); return(_lazyBounds); }