Ejemplo n.º 1
0
        // Get the type kind of a symbol, going to candidates if possible.
        internal static TypeKind ExtractNonErrorTypeKind(TypeSymbol oldSymbol)
        {
            if (oldSymbol.TypeKind != TypeKind.Error)
            {
                return(oldSymbol.TypeKind);
            }

            // At this point, we know that oldSymbol is a non-null type symbol with kind error.
            // Hence, it is either an ErrorTypeSymbol or it has an ErrorTypeSymbol as its
            // original definition.  In the former case, it is its own original definition.
            // Thus, if there's a CSErrorTypeSymbol in there somewhere, it's returned by
            // OriginalDefinition.
            ExtendedErrorTypeSymbol oldError = oldSymbol.OriginalDefinition as ExtendedErrorTypeSymbol;

            // If the original definition isn't a CSErrorTypeSymbol, then we don't know how to
            // pull out a non-error type.  If it is, then if there is a unambiguous type inside it,
            // use that.
            TypeKind commonTypeKind = TypeKind.Error;

            if ((object)oldError != null && !oldError._candidateSymbols.IsDefault && oldError._candidateSymbols.Length > 0)
            {
                foreach (Symbol sym in oldError._candidateSymbols)
                {
                    TypeSymbol type = sym as TypeSymbol;
                    if ((object)type != null && type.TypeKind != TypeKind.Error)
                    {
                        if (commonTypeKind == TypeKind.Error)
                        {
                            commonTypeKind = type.TypeKind;
                        }
                        else if (commonTypeKind != type.TypeKind)
                        {
                            return(TypeKind.Error);  // no common kind.
                        }
                    }
                }
            }

            return(commonTypeKind);
        }
Ejemplo n.º 2
0
        private void ResolveBases(BaseListSyntax baseList, ConsList <TypeSymbol> newBasesBeingResolved, DiagnosticBag diagnostics, Binder baseBinder, ref NamedTypeSymbol localBase, ArrayBuilder <NamedTypeSymbol> localInterfaces)
        {
            int i = -1;

            var isExtendList    = baseList is ExtendListSyntax;
            var isInterface     = TypeKind == TypeKind.Interface;
            var isClassOrStruct = TypeKind == TypeKind.Class || TypeKind == TypeKind.Struct;

            foreach (var baseTypeSyntax in baseList.Types)
            {
                i++;
                var typeSyntax = baseTypeSyntax.Type;
                if (typeSyntax.Kind() != SyntaxKind.PredefinedType && !SyntaxFacts.IsName(typeSyntax.Kind()))
                {
                    diagnostics.Add(ErrorCode.ERR_BadBaseType, typeSyntax.GetLocation());
                }

                var location = new SourceLocation(typeSyntax);

                TypeSymbol baseType;

                if (i == 0 && isClassOrStruct && isExtendList) // allow class in the first position
                {
                    baseType = baseBinder.BindType(typeSyntax, diagnostics, newBasesBeingResolved).TypeSymbol;


                    if (baseType.TypeKind != TypeKind)
                    {
                        if (TypeKind == TypeKind.Struct)
                        {
                            diagnostics.Add(ErrorCode.ERR_NonStructBaseForStruct, location, baseType, this);
                            continue;
                        }
                        else
                        {
                            diagnostics.Add(ErrorCode.ERR_NonClassBaseForClass, location, baseType, this);
                            continue;
                        }
                    }

                    SpecialType baseSpecialType = baseType.SpecialType;
                    if (IsRestrictedBaseType(baseSpecialType))
                    {
                        // check for one of the specific exceptions required for compiling mscorlib
                        if (this.SpecialType == SpecialType.System_Enum ||
                            this.SpecialType == SpecialType.System_MulticastDelegate && baseSpecialType == SpecialType.System_Delegate)
                        {
                            // allowed
                        }
                        else if (baseSpecialType == SpecialType.System_Array && this.ContainingAssembly.CorLibrary == this.ContainingAssembly)
                        {
                            // Specific exception for System.ArrayContracts, which is only built when CONTRACTS_FULL is defined.
                            // (See InheritanceResolver::CheckForBaseClassErrors).
                        }
                        else
                        {
                            // '{0}' cannot derive from special class '{1}'
                            diagnostics.Add(ErrorCode.ERR_DeriveFromEnumOrValueType, Locations[0], baseType, this);
                            continue;
                        }
                    }

                    if (baseType.IsSealed && !this.IsStatic) // Give precedence to ERR_StaticDerivedFromNonObject
                    {
                        diagnostics.Add(ErrorCode.ERR_CantDeriveFromSealedType, Locations[0], baseType, this);
                        continue;
                    }

                    // TODO: log error if base class is not struct/class

                    bool baseTypeIsErrorWithoutInterfaceGuess = false;

                    // If baseType is an error symbol and our best guess is that the desired symbol
                    // is an interface, then put baseType in the interfaces list, rather than the
                    // base type slot, to avoid the frustrating scenario where an error message
                    // indicates that the symbol being returned as the base type was elsewhere
                    // interpreted as an interface.
                    if (baseType.TypeKind == TypeKind.Error)
                    {
                        baseTypeIsErrorWithoutInterfaceGuess = true;

                        TypeKind guessTypeKind = baseType.GetNonErrorTypeKindGuess();
                        if (guessTypeKind == TypeKind.Interface)
                        {
                            //base type is an error *with* a guessed interface
                            baseTypeIsErrorWithoutInterfaceGuess = false;
                        }
                    }

                    if ((baseType.TypeKind == TypeKind.Class ||
                         baseType.TypeKind == TypeKind.Delegate ||
                         baseType.TypeKind == TypeKind.Struct ||
                         baseTypeIsErrorWithoutInterfaceGuess) &&
                        ((object)localBase == null))
                    {
                        localBase = (NamedTypeSymbol)baseType;
                        Debug.Assert((object)localBase != null);
                        if (this.IsStatic && localBase.SpecialType != SpecialType.System_Object)
                        {
                            // Static class '{0}' cannot derive from type '{1}'. Static classes must derive from object.
                            var info = diagnostics.Add(ErrorCode.ERR_StaticDerivedFromNonObject, location, this, localBase);
                            localBase = new ExtendedErrorTypeSymbol(localBase, LookupResultKind.NotReferencable, info);
                        }

                        continue;
                    }
                }
                else
                {
                    baseType = baseBinder.BindType(typeSyntax, diagnostics, newBasesBeingResolved).TypeSymbol;
                }

                // if we have an interface and we have an implements list, this is invalid
                if (isInterface && !isExtendList)
                {
                    diagnostics.Add(ErrorCode.ERR_InvalidImplementsForInterface, location, this, baseType);
                    continue;
                }

                switch (baseType.TypeKind)
                {
                case TypeKind.Interface:
                    // If we have an interface in a extend list of a class, this is not supported
                    if (isClassOrStruct && isExtendList)
                    {
                        diagnostics.Add(ErrorCode.ERR_InvalidInterfaceInExtendList, location, baseType);
                    }

                    foreach (var t in localInterfaces)
                    {
                        if (TypeSymbol.Equals(t, baseType, TypeCompareKind.ConsiderEverything))
                        {
                            diagnostics.Add(ErrorCode.ERR_DuplicateInterfaceInBaseList, location, baseType);
                        }
                    }

                    if (this.IsStatic)
                    {
                        // '{0}': static classes cannot implement interfaces
                        diagnostics.Add(ErrorCode.ERR_StaticClassInterfaceImpl, location, this, baseType);
                    }

                    if (this.IsRefLikeType)
                    {
                        // '{0}': ref structs cannot implement interfaces
                        diagnostics.Add(ErrorCode.ERR_RefStructInterfaceImpl, location, this, baseType);
                    }

                    if (baseType.ContainsDynamic())
                    {
                        diagnostics.Add(ErrorCode.ERR_DeriveFromConstructedDynamic, location, this, baseType);
                    }

                    localInterfaces.Add((NamedTypeSymbol)baseType);
                    break;

                case TypeKind.Struct:
                    if ((object)localBase != null)
                    {
                        if (isExtendList)
                        {
                            diagnostics.Add(ErrorCode.ERR_NoMultipleInheritance, location, this, localBase, baseType);
                            break;
                        }
                    }
                    diagnostics.Add(ErrorCode.ERR_NonInterfaceInImplementsList, location, baseType);
                    break;

                case TypeKind.Class:
                    if ((object)localBase != null)
                    {
                        if (isExtendList)
                        {
                            diagnostics.Add(ErrorCode.ERR_NoMultipleInheritance, location, this, localBase, baseType);
                            break;
                        }
                    }
                    diagnostics.Add(ErrorCode.ERR_NonInterfaceInImplementsList, location, baseType);
                    break;

                case TypeKind.TypeParameter:
                    diagnostics.Add(ErrorCode.ERR_DerivingFromATyVar, location, baseType);
                    break;

                case TypeKind.Error:
                    // put the error type in the interface list so we don't lose track of it
                    localInterfaces.Add((NamedTypeSymbol)baseType);
                    break;

                case TypeKind.Dynamic:
                    diagnostics.Add(ErrorCode.ERR_DeriveFromDynamic, location, this);
                    break;

                case TypeKind.Submission:
                    throw ExceptionUtilities.UnexpectedValue(baseType.TypeKind);

                default:
                    diagnostics.Add(ErrorCode.ERR_NonInterfaceInImplementsList, location, baseType);
                    break;
                }
            }
        }
Ejemplo n.º 3
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));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// If the extension method is applicable based on the "this" argument type, return
        /// the method constructed with the inferred type arguments. If the method is not an
        /// unconstructed generic method, type inference is skipped. If the method is not
        /// applicable, or if constraints when inferring type parameters from the "this" type
        /// are not satisfied, the return value is null.
        /// </summary>
        public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol method, TypeSymbol thisType, Compilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(method.IsExtensionMethod);
            Debug.Assert((object)thisType != null);

            if (!method.IsGenericMethod || method != method.ConstructedFrom)
            {
                return(method);
            }

            // We never resolve extension methods on a dynamic receiver.
            if (thisType.IsDynamic())
            {
                return(null);
            }

            var containingAssembly = method.ContainingAssembly;
            var errorNamespace     = containingAssembly.GlobalNamespace;
            var conversions        = new TypeConversions(containingAssembly.CorLibrary);

            // There is absolutely no plausible syntax/tree that we could use for these
            // synthesized literals.  We could be speculatively binding a call to a PE method.
            var syntaxTree = CSharpSyntaxTree.Dummy;
            var syntax     = (CSharpSyntaxNode)syntaxTree.GetRoot();

            // Create an argument value for the "this" argument of specific type,
            // and pass the same bad argument value for all other arguments.
            var thisArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, thisType)
            {
                WasCompilerGenerated = true
            };
            var otherArgumentType  = new ExtendedErrorTypeSymbol(errorNamespace, name: string.Empty, arity: 0, errorInfo: null, unreported: false);
            var otherArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, otherArgumentType)
            {
                WasCompilerGenerated = true
            };

            var paramCount = method.ParameterCount;
            var arguments  = new BoundExpression[paramCount];

            for (int i = 0; i < paramCount; i++)
            {
                var argument = (i == 0) ? thisArgumentValue : otherArgumentValue;
                arguments[i] = argument;
            }

            var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument(
                conversions,
                method,
                arguments.AsImmutable(),
                useSiteDiagnostics: ref useSiteDiagnostics);

            if (typeArgs.IsDefault)
            {
                return(null);
            }

            int firstNullInTypeArgs = -1;

            // For the purpose of constraint checks we use error type symbol in place of type arguments that we couldn't infer from the first argument.
            // This prevents constraint checking from failing for corresponding type parameters.
            var notInferredTypeParameters = PooledHashSet <TypeParameterSymbol> .GetInstance();

            var typeParams = method.TypeParameters;
            var typeArgsForConstraintsCheck = typeArgs;

            for (int i = 0; i < typeArgsForConstraintsCheck.Length; i++)
            {
                if (typeArgsForConstraintsCheck[i].IsNull)
                {
                    firstNullInTypeArgs = i;
                    var builder = ArrayBuilder <TypeSymbolWithAnnotations> .GetInstance();

                    builder.AddRange(typeArgsForConstraintsCheck, firstNullInTypeArgs);

                    for (; i < typeArgsForConstraintsCheck.Length; i++)
                    {
                        var typeArg = typeArgsForConstraintsCheck[i];
                        if (typeArg.IsNull)
                        {
                            notInferredTypeParameters.Add(typeParams[i]);
                            builder.Add(TypeSymbolWithAnnotations.Create(ErrorTypeSymbol.UnknownResultType));
                        }
                        else
                        {
                            builder.Add(typeArg);
                        }
                    }

                    typeArgsForConstraintsCheck = builder.ToImmutableAndFree();
                    break;
                }
            }

            // Check constraints.
            var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance();

            var substitution = new TypeMap(typeParams, typeArgsForConstraintsCheck);
            ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
            var success = method.CheckConstraints(conversions, substitution, typeParams, typeArgsForConstraintsCheck, compilation, diagnosticsBuilder, warningsBuilderOpt: null, ref useSiteDiagnosticsBuilder,
                                                  ignoreTypeConstraintsDependentOnTypeParametersOpt: notInferredTypeParameters.Count > 0 ? notInferredTypeParameters : null);

            diagnosticsBuilder.Free();
            notInferredTypeParameters.Free();

            if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0)
            {
                if (useSiteDiagnostics == null)
                {
                    useSiteDiagnostics = new HashSet <DiagnosticInfo>();
                }

                foreach (var diag in useSiteDiagnosticsBuilder)
                {
                    useSiteDiagnostics.Add(diag.DiagnosticInfo);
                }
            }

            if (!success)
            {
                return(null);
            }

            // For the purpose of construction we use original type parameters in place of type arguments that we couldn't infer from the first argument.
            var typeArgsForConstruct = typeArgs;

            if (firstNullInTypeArgs != -1)
            {
                var builder = ArrayBuilder <TypeSymbolWithAnnotations> .GetInstance();

                builder.AddRange(typeArgs, firstNullInTypeArgs);

                for (int i = firstNullInTypeArgs; i < typeArgsForConstruct.Length; i++)
                {
                    var typeArgForConstruct = typeArgsForConstruct[i];
                    builder.Add(!typeArgForConstruct.IsNull ? typeArgForConstruct : TypeSymbolWithAnnotations.Create(typeParams[i]));
                }

                typeArgsForConstruct = builder.ToImmutableAndFree();
            }

            return(method.Construct(typeArgsForConstruct));
        }