// 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);
        }
Beispiel #2
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));
        }
Beispiel #3
0
        private ImmutableArray <ParameterSymbol> MakeParameters(
            CSharpCompilation compilation,
            UnboundLambda unboundLambda,
            ImmutableArray <TypeSymbol> parameterTypes,
            ImmutableArray <RefKind> parameterRefKinds,
            DiagnosticBag diagnostics)
        {
            Debug.Assert(parameterTypes.Length == parameterRefKinds.Length);

            if (!unboundLambda.HasSignature || unboundLambda.ParameterCount == 0)
            {
                // The parameters may be omitted in source, but they are still present on the symbol.
                return(parameterTypes.SelectAsArray((type, ordinal, arg) =>
                                                    SynthesizedParameterSymbol.Create(
                                                        arg.owner,
                                                        type,
                                                        ordinal,
                                                        arg.refKinds[ordinal],
                                                        GeneratedNames.LambdaCopyParameterName(ordinal)),     // Make sure nothing binds to this.
                                                    (owner: this, refKinds: parameterRefKinds)));
            }

            var builder = ArrayBuilder <ParameterSymbol> .GetInstance();

            var hasExplicitlyTypedParameterList = unboundLambda.HasExplicitlyTypedParameterList;
            var numDelegateParameters           = parameterTypes.Length;

            for (int p = 0; p < unboundLambda.ParameterCount; ++p)
            {
                // If there are no types given in the lambda then used the delegate type.
                // If the lambda is typed then the types probably match the delegate types;
                // if they do not, use the lambda types for binding. Either way, if we
                // can, then we use the lambda types. (Whatever you do, do not use the names
                // in the delegate parameters; they are not in scope!)

                TypeSymbol type;
                RefKind    refKind;
                if (hasExplicitlyTypedParameterList)
                {
                    type    = unboundLambda.ParameterType(p);
                    refKind = unboundLambda.RefKind(p);
                }
                else if (p < numDelegateParameters)
                {
                    type    = parameterTypes[p];
                    refKind = parameterRefKinds[p];
                }
                else
                {
                    type    = new ExtendedErrorTypeSymbol(compilation, name: string.Empty, arity: 0, errorInfo: null);
                    refKind = RefKind.None;
                }

                var name      = unboundLambda.ParameterName(p);
                var location  = unboundLambda.ParameterLocation(p);
                var locations = ImmutableArray.Create <Location>(location);
                var parameter = new SourceSimpleParameterSymbol(this, type, p, refKind, name, locations);

                builder.Add(parameter);
            }

            var result = builder.ToImmutableAndFree();

            return(result);
        }
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(result.IsClear);

            if (_container.IsSubmissionClass)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);
                return;
            }

            var imports = GetImports(basesBeingResolved);

            // first lookup members of the namespace
            if ((options & LookupOptions.NamespaceAliasesOnly) == 0)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);

                if (result.IsMultiViable)
                {
                    // symbols cannot conflict with using alias names
                    if (arity == 0 && imports.IsUsingAlias(name, originalBinder.IsSemanticModelBinder))
                    {
                        CSDiagnosticInfo diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_ConflictAliasAndMember, name, _container);
                        var error = new ExtendedErrorTypeSymbol((NamespaceOrTypeSymbol)null, name, arity, diagInfo, unreported: true);
                        result.SetFrom(LookupResult.Good(error)); // force lookup to be done w/ error symbol as result
                    }

                    return;
                }
            }

            // next try using aliases or symbols in imported namespaces
            imports.LookupSymbol(originalBinder, result, name, arity, basesBeingResolved, options, diagnose, ref useSiteDiagnostics);
        }
Beispiel #5
0
        private ImmutableArray<ParameterSymbol> MakeParameters(
            CSharpCompilation compilation,
            UnboundLambda unboundLambda,
            ImmutableArray<ParameterSymbol> delegateParameters)
        {
            if (!unboundLambda.HasSignature || unboundLambda.ParameterCount == 0)
            {
                // The parameters may be omitted in source, but they are still present on the symbol.
                return delegateParameters.SelectAsArray(CopyParameter, this);
            }

            var builder = ArrayBuilder<ParameterSymbol>.GetInstance();
            var hasExplicitlyTypedParameterList = unboundLambda.HasExplicitlyTypedParameterList;
            var numDelegateParameters = delegateParameters.IsDefault ? 0 : delegateParameters.Length;

            for (int p = 0; p < unboundLambda.ParameterCount; ++p)
            {
                // If there are no types given in the lambda then used the delegate type.
                // If the lambda is typed then the types probably match the delegate types;
                // if they do not, use the lambda types for binding. Either way, if we 
                // can, then we use the lambda types. (Whatever you do, do not use the names 
                // in the delegate parameters; they are not in scope!)

                TypeSymbol type;
                RefKind refKind;
                if (hasExplicitlyTypedParameterList)
                {
                    type = unboundLambda.ParameterType(p);
                    refKind = unboundLambda.RefKind(p);
                }
                else if (p < numDelegateParameters)
                {
                    ParameterSymbol delegateParameter = delegateParameters[p];
                    type = delegateParameter.Type;
                    refKind = delegateParameter.RefKind;
                }
                else
                {
                    type = new ExtendedErrorTypeSymbol(compilation, name: string.Empty, arity: 0, errorInfo: null);
                    refKind = RefKind.None;
                }

                var name = unboundLambda.ParameterName(p);
                var location = unboundLambda.ParameterLocation(p);
                var locations = ImmutableArray.Create<Location>(location);
                var parameter = new SourceSimpleParameterSymbol(this, type, p, refKind, name, locations);

                builder.Add(parameter);
            }

            var result = builder.ToImmutableAndFree();

            return result;
        }
Beispiel #6
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));
        }
        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);
        }
        /// <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];
            var argumentTypes = new TypeSymbol[paramCount];
            for (int i = 0; i < paramCount; i++)
            {
                var argument = (i == 0) ? thisArgumentValue : otherArgumentValue;
                arguments[i] = argument;
                argumentTypes[i] = argument.Type;
            }

            var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument(
                conversions,
                method,
                argumentTypes.AsImmutableOrNull(),
                arguments.AsImmutableOrNull(),
                ref useSiteDiagnostics);

            if (typeArgs.IsDefault)
            {
                return null;
            }

            // Check constraints.
            var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance();
            var typeParams = method.TypeParameters;
            var substitution = new TypeMap(typeParams, typeArgs);
            ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
            var success = method.CheckConstraints(conversions, substitution, method.TypeParameters, typeArgs, compilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);
            diagnosticsBuilder.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;
            }

            return method.Construct(typeArgs);
        }
        /// <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];
            var argumentTypes = new TypeSymbol[paramCount];
            for (int i = 0; i < paramCount; i++)
            {
                var argument = (i == 0) ? thisArgumentValue : otherArgumentValue;
                arguments[i] = argument;
                argumentTypes[i] = argument.Type;
            }

            var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument(
                conversions,
                method,
                argumentTypes.AsImmutableOrNull(),
                arguments.AsImmutableOrNull(),
                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 typeArgsForConstraintsCheck = typeArgs;
            for (int i = 0; i < typeArgsForConstraintsCheck.Length; i++)
            {
                if ((object)typeArgsForConstraintsCheck[i] == null)
                {
                    firstNullInTypeArgs = i;
                    var builder = ArrayBuilder<TypeSymbol>.GetInstance();
                    builder.AddRange(typeArgs, firstNullInTypeArgs);

                    for (; i < typeArgsForConstraintsCheck.Length; i++)
                    {
                        builder.Add(typeArgsForConstraintsCheck[i] ?? ErrorTypeSymbol.UnknownResultType);
                    }

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

            // Check constraints.
            var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance();
            var typeParams = method.TypeParameters;
            var substitution = new TypeMap(typeParams, typeArgsForConstraintsCheck.SelectAsArray(TypeMap.TypeSymbolAsTypeWithModifiers));
            ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
            var success = method.CheckConstraints(conversions, substitution, typeParams, typeArgsForConstraintsCheck, compilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);
            diagnosticsBuilder.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<TypeSymbol>.GetInstance();
                builder.AddRange(typeArgs, firstNullInTypeArgs);

                for (int i = firstNullInTypeArgs; i < typeArgsForConstruct.Length; i++)
                {
                    builder.Add(typeArgsForConstruct[i] ?? typeParams[i]);
                }

                typeArgsForConstruct = builder.ToImmutableAndFree();
            }

            return method.Construct(typeArgsForConstruct);
        }
 /// <summary>
 /// Guess the non-error typekind that the given type was intended to represent,
 /// if possible. If not, return TypeKind.Error.
 /// </summary>
 internal static TypeKind GetNonErrorTypeKindGuess(this TypeSymbol type)
 {
     return(ExtendedErrorTypeSymbol.ExtractNonErrorTypeKind(type));
 }
        /// <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];
            var argumentTypes = new TypeSymbol[paramCount];

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

            var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument(
                conversions,
                method,
                argumentTypes.AsImmutableOrNull(),
                arguments.AsImmutableOrNull(),
                ref useSiteDiagnostics);

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

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

            var typeParams   = method.TypeParameters;
            var substitution = new TypeMap(typeParams, typeArgs);
            ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
            var success = method.CheckConstraints(conversions, substitution, method.TypeParameters, typeArgs, compilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);

            diagnosticsBuilder.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);
            }

            return(method.Construct(typeArgs));
        }
        private ImmutableArray<TypeSymbol> GetResults()
        {
            // Anything we didn't infer a type for, give the error type.
            // Note: the error type will have the same name as the name
            // of the type parameter we were trying to infer.  This will give a
            // nice user experience where by we will show something like
            // the following:
            //
            // user types: customers.Select(
            // we show   : IE<TResult> IE<Customer>.Select<Customer,TResult>(Func<Customer,TResult> selector)
            //
            // Initially we thought we'd just show ?.  i.e.:
            //
            //  IE<?> IE<Customer>.Select<Customer,?>(Func<Customer,?> selector)
            //
            // This is nice and concise.  However, it falls down if there are multiple
            // type params that we have left.

            for (int i = 0; i < _methodTypeParameters.Length; i++)
            {
                if ((object)_fixedResults[i] != null)
                {
                    if (!_fixedResults[i].IsErrorType())
                    {
                        continue;
                    }

                    var errorTypeName = _fixedResults[i].Name;
                    if (errorTypeName != null)
                    {
                        continue;
                    }
                }
                _fixedResults[i] = new ExtendedErrorTypeSymbol(_constructedContainingTypeOfMethod, _methodTypeParameters[i].Name, 0, null, false);
            }
            return ImmutableArray.Create<TypeSymbol>(_fixedResults);
        }
Beispiel #13
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>
        private static MethodSymbol InferExtensionMethodTypeArguments(MethodSymbol method, TypeSymbol thisType, 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);
            }

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

            if (typeArgs.Any(t => !t.HasType))
            {
                typeArgsForConstruct = typeArgs.ZipAsArray(
                    method.TypeParameters,
                    (t, tp) => t.HasType ? t : TypeWithAnnotations.Create(tp));
            }

            return(method.Construct(typeArgsForConstruct));
        }
        // process the base list for one part of a partial class, or for the only part of any other type declaration.
        private Tuple<NamedTypeSymbol, ImmutableArray<NamedTypeSymbol>> MakeOneDeclaredBases(ConsList<Symbol> newBasesBeingResolved, SingleTypeDeclaration decl, DiagnosticBag diagnostics)
        {
            BaseListSyntax bases = GetBaseListOpt(decl);
            if (bases == null)
            {
                return null;
            }

            NamedTypeSymbol localBase = null;
            var localInterfaces = ArrayBuilder<NamedTypeSymbol>.GetInstance();
            var baseBinder = this.DeclaringCompilation.GetBinder(bases);

            // Wrap base binder in a location-specific binder that will avoid generic constraint checks
            // (to avoid cycles if the constraint types are not bound yet). Instead, constraint checks
            // are handled by the caller.
            baseBinder = baseBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);

            int i = -1;
            foreach (var baseTypeSyntax in bases.Types)
            {
                i++;
                var typeSyntax = baseTypeSyntax.Type;
                var location = new SourceLocation(typeSyntax);

                TypeSymbol baseType;

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

                    SpecialType baseSpecialType = baseType.SpecialType;
                    if (IsRestrictedBaseType(baseSpecialType))
                    {
                        // check for one of the specific exceptions required for compiling mscorlib
                        if (this.SpecialType == SpecialType.System_Enum && baseSpecialType == SpecialType.System_ValueType ||
                            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], this, baseType);
                            continue;
                        }
                    }

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

                    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);
                }

                switch (baseType.TypeKind)
                {
                    case TypeKind.Interface:
                        foreach (var t in localInterfaces)
                        {
                            if (t == baseType)
                            {
                                diagnostics.Add(ErrorCode.ERR_DuplicateInterfaceInBaseList, location, baseType);
                                continue;
                            }
                        }

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

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

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

                    case TypeKind.Class:
                        if (TypeKind == TypeKind.Class)
                        {
                            if ((object)localBase == null)
                            {
                                localBase = (NamedTypeSymbol)baseType;
                                diagnostics.Add(ErrorCode.ERR_BaseClassMustBeFirst, location, baseType);
                                continue;
                            }
                            else
                            {
                                diagnostics.Add(ErrorCode.ERR_NoMultipleInheritance, location, this, localBase, baseType);
                                continue;
                            }
                        }
                        goto default;

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

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

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

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

                    default:
                        diagnostics.Add(ErrorCode.ERR_NonInterfaceInInterfaceList, location, baseType);
                        continue;
                }
            }

            if (this.SpecialType == SpecialType.System_Object && ((object)localBase != null || localInterfaces.Count != 0))
            {
                var name = GetName(bases.Parent);
                diagnostics.Add(ErrorCode.ERR_ObjectCantHaveBases, new SourceLocation(name));
            }

            return new Tuple<NamedTypeSymbol, ImmutableArray<NamedTypeSymbol>>(localBase, localInterfaces.ToImmutableAndFree());
        }
Beispiel #15
0
        // process the base list for one part of a partial class, or for the only part of any other type declaration.
        private Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > MakeOneDeclaredBases(ConsList <Symbol> newBasesBeingResolved, SingleTypeDeclaration decl, DiagnosticBag diagnostics)
        {
            BaseListSyntax bases = GetBaseListOpt(decl);

            if (bases == null)
            {
                return(null);
            }

            NamedTypeSymbol localBase       = null;
            var             localInterfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            var baseBinder = this.DeclaringCompilation.GetBinder(bases);

            // Wrap base binder in a location-specific binder that will avoid generic constraint checks
            // (to avoid cycles if the constraint types are not bound yet). Instead, constraint checks
            // are handled by the caller.
            baseBinder = baseBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);

            int i = -1;

            foreach (var baseTypeSyntax in bases.Types)
            {
                i++;
                var typeSyntax = baseTypeSyntax.Type;
                var location   = new SourceLocation(typeSyntax);

                TypeSymbol baseType;

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

                    SpecialType baseSpecialType = baseType.SpecialType;
                    if (IsRestrictedBaseType(baseSpecialType))
                    {
                        // check for one of the specific exceptions required for compiling mscorlib
                        if (this.SpecialType == SpecialType.System_Enum && baseSpecialType == SpecialType.System_ValueType ||
                            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], this, baseType);
                            continue;
                        }
                    }

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

                    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);
                }

                switch (baseType.TypeKind)
                {
                case TypeKind.Interface:
                    foreach (var t in localInterfaces)
                    {
                        if (t == baseType)
                        {
                            diagnostics.Add(ErrorCode.ERR_DuplicateInterfaceInBaseList, location, baseType);
                            continue;
                        }
                    }

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

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

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

                case TypeKind.Class:
                    if (TypeKind == TypeKind.Class)
                    {
                        if ((object)localBase == null)
                        {
                            localBase = (NamedTypeSymbol)baseType;
                            diagnostics.Add(ErrorCode.ERR_BaseClassMustBeFirst, location, baseType);
                            continue;
                        }
                        else
                        {
                            diagnostics.Add(ErrorCode.ERR_NoMultipleInheritance, location, this, localBase, baseType);
                            continue;
                        }
                    }
                    goto default;

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

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

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

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

                default:
                    diagnostics.Add(ErrorCode.ERR_NonInterfaceInInterfaceList, location, baseType);
                    continue;
                }
            }

            if (this.SpecialType == SpecialType.System_Object && ((object)localBase != null || localInterfaces.Count != 0))
            {
                var name = GetName(bases.Parent);
                diagnostics.Add(ErrorCode.ERR_ObjectCantHaveBases, new SourceLocation(name));
            }

            return(new Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> >(localBase, localInterfaces.ToImmutableAndFree()));
        }
        private static MethodSymbol InferExtensionMethodTypeArguments(MethodSymbol method, TypeSymbol thisType, CSharpCompilation 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);
            }

            // 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.
            int firstNullInTypeArgs       = -1;
            var notInferredTypeParameters = PooledHashSet <TypeParameterSymbol> .GetInstance();

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

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

                    builder.AddRange(typeArgsForConstraintsCheck, firstNullInTypeArgs);

                    for (; i < typeArgsForConstraintsCheck.Length; i++)
                    {
                        var typeArg = typeArgsForConstraintsCheck[i];
                        if (!typeArg.HasType)
                        {
                            notInferredTypeParameters.Add(typeParams[i]);
                            builder.Add(TypeWithAnnotations.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, nullabilityDiagnosticsBuilderOpt: 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.
            ImmutableArray <TypeWithAnnotations> typeArgsForConstruct = typeArgs;

            if (typeArgs.Any(t => !t.HasType))
            {
                typeArgsForConstruct = typeArgs.ZipAsArray(
                    method.TypeParameters,
                    (t, tp) => t.HasType ? t : TypeWithAnnotations.Create(tp));
            }

            return(method.Construct(typeArgsForConstruct));
        }
        internal TypeSymbol GetTypeByReflectionType(Type type, DiagnosticBag diagnostics)
        {
            var result = Assembly.GetTypeByReflectionType(type, includeReferences: true);
            if ((object)result == null)
            {
                var errorType = new ExtendedErrorTypeSymbol(this, type.Name, 0, CreateReflectionTypeNotFoundError(type));
                diagnostics.Add(errorType.ErrorInfo, NoLocation.Singleton);
                result = errorType;
            }

            return result;
        }
Beispiel #18
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;