예제 #1
0
        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);
        }
예제 #2
0
        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
                       ));
        }
예제 #3
0
            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;
                            }
                        }
예제 #4
0
        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));
        }
예제 #5
0
        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));
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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));
        }
예제 #8
0
        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);
        }
예제 #9
0
 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);
 }
예제 #10
0
        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));
        }
예제 #11
0
        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));
        }
예제 #12
0
        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);
        }
예제 #14
0
        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;
예제 #15
0
        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);
        }
예제 #16
0
        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);
        }
예제 #18
0
 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);
 }
예제 #19
0
        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;
        }
예제 #20
0
        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);
예제 #22
0
        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);
        }