Ejemplo n.º 1
0
        public override Conversion GetMethodGroupFunctionPointerConversion(
            BoundMethodGroup source,
            FunctionPointerTypeSymbol destination,
            ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo
            )
        {
            var resolution = ResolveDelegateOrFunctionPointerMethodGroup(
                _binder,
                source,
                destination.Signature,
                isFunctionPointer: true,
                new CallingConventionInfo(
                    destination.Signature.CallingConvention,
                    destination.Signature.GetCallingConventionModifiers()
                    ),
                ref useSiteInfo
                );
            var conversion =
                (resolution.IsEmpty || resolution.HasAnyErrors)
                    ? Conversion.NoConversion
                    : ToConversion(
                    resolution.OverloadResolutionResult,
                    resolution.MethodGroup,
                    destination.Signature.ParameterCount
                    );

            resolution.Free();
            return(conversion);
        }
Ejemplo n.º 2
0
        public override BoundNode VisitMethodGroup(BoundMethodGroup node)
        {
            BoundSpillSequenceBuilder builder = null;
            var receiver = VisitExpression(ref builder, node.ReceiverOpt);

            return(UpdateExpression(builder, node.Update(node.TypeArgumentsOpt, node.Name, node.Methods, node.LookupSymbolOpt, node.LookupError, node.Flags, receiver, node.ResultKind)));
        }
        private void CheckMethodGroup(BoundMethodGroup node, MethodSymbol method, bool parentIsConversion, TypeSymbol convertedToType)
        {
            // Formerly reported ERR_MemGroupInExpressionTree when this occurred, but the expanded
            // ERR_LambdaInIsAs makes this impossible (since the node will always be wrapped in
            // a failed conversion).
            Debug.Assert(!(!parentIsConversion && _inExpressionLambda));

            if (_inExpressionLambda)
            {
                if ((node.LookupSymbolOpt as MethodSymbol)?.MethodKind == MethodKind.LocalFunction)
                {
                    Error(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, node);
                }
                else if (parentIsConversion && convertedToType.IsFunctionPointer())
                {
                    Error(ErrorCode.ERR_AddressOfMethodGroupInExpressionTree, node);
                }
            }

            CheckReceiverIfField(node.ReceiverOpt);
            CheckReferenceToMethodIfLocalFunction(node, method);

            if (method is null || method.RequiresInstanceReceiver)
            {
                Visit(node.ReceiverOpt);
            }
        }
Ejemplo n.º 4
0
 public override Conversion GetMethodGroupFunctionPointerConversion(
     BoundMethodGroup source,
     FunctionPointerTypeSymbol destination,
     ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo
     )
 {
     // Conversions involving method groups require a Binder.
     throw ExceptionUtilities.Unreachable;
 }
        private BoundNode VisitMethodGroup(BoundMethodGroup node, bool parentIsConversion)
        {
            // Formerly reported ERR_MemGroupInExpressionTree when this occurred, but the expanded
            // ERR_LambdaInIsAs makes this impossible (since the node will always be wrapped in
            // a failed conversion).
            Debug.Assert(!(!parentIsConversion && _inExpressionLambda));

            CheckReceiverIfField(node.ReceiverOpt);
            return(base.VisitMethodGroup(node));
        }
Ejemplo n.º 6
0
        public override Conversion GetMethodGroupFunctionPointerConversion(BoundMethodGroup source, FunctionPointerTypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            var resolution = ResolveDelegateOrFunctionPointerMethodGroup(_binder, source, destination.Signature, isFunctionPointer: true, ref useSiteDiagnostics);
            var conversion = (resolution.IsEmpty || resolution.HasAnyErrors) ?
                             Conversion.NoConversion :
                             ToConversion(resolution.OverloadResolutionResult, resolution.MethodGroup, destination.Signature.ParameterCount);

            resolution.Free();
            return(conversion);
        }
Ejemplo n.º 7
0
 public override BoundNode VisitMethodGroup(BoundMethodGroup node)
 {
     if (IsInside &&
         node.Methods.Length == 1 &&
         node.Methods[0].MethodKind == MethodKind.LocalFunction)
     {
         _interactsWithLocalFunction = true;
     }
     return(base.VisitMethodGroup(node));
 }
Ejemplo n.º 8
0
            public override BoundNode VisitMethodGroup(BoundMethodGroup node)
            {
                // We only get here in error cases, as normally the enclosing node is a method group conversion
                // whose visit (below) doesn't call this.  So we don't know which method is to be selected, and
                // therefore don't know if the receiver is used. Assume if the receiver was provided, it is used.
                var receiverOpt = node.ReceiverOpt;

                if (receiverOpt != null)
                {
                    return(VisitSyntaxWithReceiver(node.Syntax, receiverOpt));
                }
                return(null);
            }
Ejemplo n.º 9
0
        private BoundNode VisitMethodGroup(BoundMethodGroup node, bool parentIsConversion)
        {
            // Formerly reported ERR_MemGroupInExpressionTree when this occurred, but the expanded
            // ERR_LambdaInIsAs makes this impossible (since the node will always be wrapped in
            // a failed conversion).
            Debug.Assert(!(!parentIsConversion && _inExpressionLambda));

            if (_inExpressionLambda && (node.LookupSymbolOpt as MethodSymbol)?.MethodKind == MethodKind.LocalFunction)
            {
                Error(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, node);
            }

            CheckReceiverIfField(node.ReceiverOpt);
            return(base.VisitMethodGroup(node));
        }
Ejemplo n.º 10
0
        public override Conversion GetMethodGroupConversion(BoundMethodGroup source, TypeSymbol destination, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            // Must be a bona fide delegate type, not an expression tree type.
            if (!destination.IsDelegateType())
            {
                return Conversion.NoConversion;
            }

            var methodSymbol = GetDelegateInvokeMethodIfAvailable(destination);
            if ((object)methodSymbol == null)
            {
                return Conversion.NoConversion;
            }

            var resolution = ResolveDelegateMethodGroup(_binder, source, methodSymbol, ref useSiteDiagnostics);
            var conversion = (resolution.IsEmpty || resolution.HasAnyErrors) ?
                Conversion.NoConversion :
                ToConversion(resolution.OverloadResolutionResult, resolution.MethodGroup, (NamedTypeSymbol)destination);
            resolution.Free();
            return conversion;
        }
Ejemplo n.º 11
0
        public override Conversion GetMethodGroupDelegateConversion(BoundMethodGroup source, TypeSymbol destination, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo)
        {
            // Must be a bona fide delegate type, not an expression tree type.
            if (!destination.IsDelegateType())
            {
                return(Conversion.NoConversion);
            }

            var(methodSymbol, isFunctionPointer, callingConventionInfo) = GetDelegateInvokeOrFunctionPointerMethodIfAvailable(destination);
            if ((object)methodSymbol == null)
            {
                return(Conversion.NoConversion);
            }

            var resolution = ResolveDelegateOrFunctionPointerMethodGroup(_binder, source, methodSymbol, isFunctionPointer, callingConventionInfo, ref useSiteInfo);
            var conversion = (resolution.IsEmpty || resolution.HasAnyErrors) ?
                             Conversion.NoConversion :
                             ToConversion(resolution.OverloadResolutionResult, resolution.MethodGroup, ((NamedTypeSymbol)destination).DelegateInvokeMethod.ParameterCount);

            resolution.Free();
            return(conversion);
        }
Ejemplo n.º 12
0
        public override Conversion GetMethodGroupConversion(BoundMethodGroup source, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            // Must be a bona fide delegate type, not an expression tree type.
            if (!destination.IsDelegateType())
            {
                return(Conversion.NoConversion);
            }

            var methodSymbol = GetDelegateInvokeMethodIfAvailable(destination);

            if ((object)methodSymbol == null)
            {
                return(Conversion.NoConversion);
            }

            var resolution = ResolveDelegateMethodGroup(_binder, source, methodSymbol, ref useSiteDiagnostics);
            var conversion = (resolution.IsEmpty || resolution.HasAnyErrors) ?
                             Conversion.NoConversion :
                             ToConversion(resolution.OverloadResolutionResult, resolution.MethodGroup, (NamedTypeSymbol)destination);

            resolution.Free();
            return(conversion);
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Resolve method group based on the optional delegate invoke method.
 /// If the invoke method is null, ignore arguments in resolution.
 /// </summary>
 private static MethodGroupResolution ResolveDelegateOrFunctionPointerMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, bool isFunctionPointer, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
 {
     if ((object)delegateInvokeMethodOpt != null)
     {
         var analyzedArguments = AnalyzedArguments.GetInstance();
         GetDelegateArguments(source.Syntax, analyzedArguments, delegateInvokeMethodOpt.Parameters, binder.Compilation);
         var resolution = binder.ResolveMethodGroup(source, analyzedArguments, useSiteDiagnostics: ref useSiteDiagnostics, inferWithDynamic: true,
                                                    isMethodGroupConversion: true, returnRefKind: delegateInvokeMethodOpt.RefKind, returnType: delegateInvokeMethodOpt.ReturnType,
                                                    isFunctionPointerResolution: isFunctionPointer, callingConvention: delegateInvokeMethodOpt.CallingConvention);
         analyzedArguments.Free();
         return(resolution);
     }
     else
     {
         return(binder.ResolveMethodGroup(source, analyzedArguments: null, isMethodGroupConversion: true, ref useSiteDiagnostics));
     }
 }
Ejemplo n.º 14
0
 public static bool MethodGroupReceiverIsDynamic(this BoundMethodGroup node)
 {
     return(node.InstanceOpt != null && node.InstanceOpt.HasDynamicType());
 }
        private static BoundMethodGroup FixMethodGroupWithTypeOrValue(BoundMethodGroup group, Conversion conversion, DiagnosticBag diagnostics)
        {

            if (!IsMethodGroupWithTypeOrValueReceiver(group))
            {
                return group;
            }

            BoundExpression receiverOpt = group.ReceiverOpt;
            Debug.Assert(receiverOpt != null);
            Debug.Assert((object)conversion.Method != null);
            receiverOpt = ReplaceTypeOrValueReceiver(receiverOpt, conversion.Method.IsStatic && !conversion.IsExtensionMethod, diagnostics);
            return group.Update(
                group.TypeArgumentsOpt,
                group.Name,
                group.Methods,
                group.LookupSymbolOpt,
                group.LookupError,
                group.Flags,
                receiverOpt, //only change
                group.ResultKind);
        }
        /// <summary>
        /// This method is a wrapper around MethodGroupConversionHasErrors.  As a preliminary step,
        /// it checks whether a conversion exists.
        /// </summary>
        private bool MethodGroupConversionDoesNotExistOrHasErrors(
            BoundMethodGroup boundMethodGroup,
            NamedTypeSymbol delegateType,
            Location delegateMismatchLocation,
            DiagnosticBag diagnostics,
            out Conversion conversion)
        {
            if (ReportDelegateInvokeUseSiteDiagnostic(diagnostics, delegateType, delegateMismatchLocation))
            {
                conversion = Conversion.NoConversion;
                return true;
            }

            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            conversion = Conversions.GetMethodGroupConversion(boundMethodGroup, delegateType, ref useSiteDiagnostics);
            diagnostics.Add(delegateMismatchLocation, useSiteDiagnostics);
            if (!conversion.Exists)
            {
                // No overload for '{0}' matches delegate '{1}'
                diagnostics.Add(ErrorCode.ERR_MethDelegateMismatch, delegateMismatchLocation, boundMethodGroup.Name, delegateType);
                return true;
            }
            else
            {
                Debug.Assert(conversion.IsValid); // i.e. if it exists, then it is valid.
                // Only cares about nullness and type of receiver, so no need to worry about BoundTypeOrValueExpression.
                return this.MethodGroupConversionHasErrors(boundMethodGroup.Syntax, conversion, boundMethodGroup.ReceiverOpt, conversion.IsExtensionMethod, delegateType, diagnostics);
            }
        }
 public override BoundNode VisitMethodGroup(BoundMethodGroup node)
 {
     CheckMethodGroup(node, method: null, parentIsConversion: false, convertedToType: null);
     return(null);
 }
Ejemplo n.º 18
0
 public override BoundNode VisitMethodGroup(BoundMethodGroup node)
 {
     // We only get here in error cases, as normally the enclosing node is a method group conversion
     // whose visit (below) doesn't call this.  So we don't know which method is to be selected, and
     // therefore don't know if the receiver is used. Assume if the receiver was provided, it is used.
     var receiverOpt = node.ReceiverOpt;
     if (receiverOpt != null)
     {
         return VisitSyntaxWithReceiver(node.Syntax, receiverOpt);
     }
     return null;
 }
Ejemplo n.º 19
0
 public override Conversion GetMethodGroupConversion(BoundMethodGroup source, TypeSymbol destination, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
 {
     // Conversions involving method groups require a Binder.
     throw ExceptionUtilities.Unreachable;
 }
Ejemplo n.º 20
0
 public override BoundNode VisitMethodGroup(BoundMethodGroup node)
 {
     throw ExceptionUtilities.Unreachable;
 }
Ejemplo n.º 21
0
        public BoundExpression VisitDynamicInvocation(BoundDynamicInvocation node, bool resultDiscarded)
        {
            var loweredArguments = VisitList(node.Arguments);

            bool                        hasImplicitReceiver;
            BoundExpression             loweredReceiver;
            ImmutableArray <TypeSymbol> typeArguments;
            string                      name;

            switch (node.Expression.Kind)
            {
            case BoundKind.MethodGroup:
                // method invocation
                BoundMethodGroup methodGroup = (BoundMethodGroup)node.Expression;
                typeArguments       = methodGroup.TypeArgumentsOpt;
                name                = methodGroup.Name;
                hasImplicitReceiver = (methodGroup.Flags & BoundMethodGroupFlags.HasImplicitReceiver) != 0;

                // Should have been eliminated during binding of dynamic invocation:
                Debug.Assert(methodGroup.ReceiverOpt == null || methodGroup.ReceiverOpt.Kind != BoundKind.TypeOrValueExpression);

                if (methodGroup.ReceiverOpt == null)
                {
                    // Calling a static method defined on an outer class via its simple name.
                    NamedTypeSymbol firstContainer = node.ApplicableMethods.First().ContainingType;
                    Debug.Assert(node.ApplicableMethods.All(m => m.IsStatic && m.ContainingType == firstContainer));

                    loweredReceiver = new BoundTypeExpression(node.Syntax, null, firstContainer);
                }
                else if (hasImplicitReceiver && factory.TopLevelMethod.IsStatic)
                {
                    // Calling a static method defined on the current class via its simple name.
                    loweredReceiver = new BoundTypeExpression(node.Syntax, null, factory.CurrentClass);
                }
                else
                {
                    loweredReceiver = VisitExpression(methodGroup.ReceiverOpt);
                }

                // If we are calling a method on a NoPIA type, we need to embed all methods/properties
                // with the matching name of this dynamic invocation.
                EmbedIfNeedTo(loweredReceiver, methodGroup.Methods, node.Syntax);

                break;

            case BoundKind.DynamicMemberAccess:
                // method invocation
                var memberAccess = (BoundDynamicMemberAccess)node.Expression;
                name                = memberAccess.Name;
                typeArguments       = memberAccess.TypeArgumentsOpt;
                loweredReceiver     = VisitExpression(memberAccess.Receiver);
                hasImplicitReceiver = false;
                break;

            default:
                // delegate invocation
                var loweredExpression = VisitExpression(node.Expression);
                return(dynamicFactory.MakeDynamicInvocation(loweredExpression, loweredArguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, resultDiscarded).ToExpression());
            }

            Debug.Assert(loweredReceiver != null);
            return(dynamicFactory.MakeDynamicMemberInvocation(
                       name,
                       loweredReceiver,
                       typeArguments,
                       loweredArguments,
                       node.ArgumentNamesOpt,
                       node.ArgumentRefKindsOpt,
                       hasImplicitReceiver,
                       resultDiscarded).ToExpression());
        }
Ejemplo n.º 22
0
        internal static ImmutableArray<MethodSymbol> GetReducedAndFilteredMethodGroupSymbols(Binder binder, BoundMethodGroup node)
        {
            var methods = ArrayBuilder<MethodSymbol>.GetInstance();
            var filteredMethods = ArrayBuilder<MethodSymbol>.GetInstance();
            var resultKind = LookupResultKind.Empty;
            var typeArguments = node.TypeArgumentsOpt;

            // Non-extension methods.
            if (node.Methods.Any())
            {
                // This is the only place we care about overridden/hidden methods.  If there aren't methods
                // in the method group, there's only one fallback candidate and extension methods never override
                // or hide instance methods or other extension methods.
                ImmutableArray<MethodSymbol> nonHiddenMethods = FilterOverriddenOrHiddenMethods(node.Methods);
                Debug.Assert(nonHiddenMethods.Any()); // Something must be hiding, so can't all be hidden.

                foreach (var method in nonHiddenMethods)
                {
                    MergeReducedAndFilteredMethodGroupSymbol(
                        methods,
                        filteredMethods,
                        new SingleLookupResult(node.ResultKind, method, node.LookupError),
                        typeArguments,
                        null,
                        ref resultKind);
                }
            }
            else
            {
                var otherSymbol = node.LookupSymbolOpt;
                if (((object)otherSymbol != null) && (otherSymbol.Kind == SymbolKind.Method))
                {
                    MergeReducedAndFilteredMethodGroupSymbol(
                        methods,
                        filteredMethods,
                        new SingleLookupResult(node.ResultKind, otherSymbol, node.LookupError),
                        typeArguments,
                        null,
                        ref resultKind);
                }
            }

            var receiver = node.ReceiverOpt;
            var name = node.Name;

            // Extension methods, all scopes.
            if (node.SearchExtensionMethods)
            {
                Debug.Assert(receiver != null);
                int arity;
                LookupOptions options;
                if (typeArguments.IsDefault)
                {
                    arity = 0;
                    options = LookupOptions.AllMethodsOnArityZero;
                }
                else
                {
                    arity = typeArguments.Length;
                    options = LookupOptions.Default;
                }

                binder = binder.WithAdditionalFlags(BinderFlags.SemanticModel);
                foreach (var scope in new ExtensionMethodScopes(binder))
                {
                    var extensionMethods = ArrayBuilder<MethodSymbol>.GetInstance();
                    var otherBinder = scope.Binder;
                    otherBinder.GetCandidateExtensionMethods(scope.SearchUsingsNotNamespace,
                                                             extensionMethods,
                                                             name,
                                                             arity,
                                                             options,
                                                             originalBinder: binder);

                    foreach (var method in extensionMethods)
                    {
                        HashSet<DiagnosticInfo> useSiteDiagnostics = null;
                        MergeReducedAndFilteredMethodGroupSymbol(
                            methods,
                            filteredMethods,
                            binder.CheckViability(method, arity, options, accessThroughType: null, diagnose: false, useSiteDiagnostics: ref useSiteDiagnostics),
                            typeArguments,
                            receiver.Type,
                            ref resultKind);
                    }

                    extensionMethods.Free();
                }
            }

            methods.Free();
            return filteredMethods.ToImmutableAndFree();
        }
 /// <summary>
 /// Resolve method group based on the optional delegate invoke method.
 /// If the invoke method is null, ignore arguments in resolution.
 /// </summary>
 private static MethodGroupResolution ResolveDelegateMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
 {
     if ((object)delegateInvokeMethodOpt != null)
     {
         var analyzedArguments = new AnalyzedArguments();
         GetDelegateArguments(source.Syntax, analyzedArguments, delegateInvokeMethodOpt.Parameters, binder.Compilation);
         var resolution = binder.ResolveMethodGroup(source, analyzedArguments, isMethodGroupConversion: true, inferWithDynamic: true, useSiteDiagnostics: ref useSiteDiagnostics);
         return resolution;
     }
     else
     {
         return binder.ResolveMethodGroup(source, null, isMethodGroupConversion: true, useSiteDiagnostics: ref useSiteDiagnostics);
     }
 }
Ejemplo n.º 24
0
 /// <summary>
 /// Resolve method group based on the optional delegate invoke method.
 /// If the invoke method is null, ignore arguments in resolution.
 /// </summary>
 private static MethodGroupResolution ResolveDelegateMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
 {
     if ((object)delegateInvokeMethodOpt != null)
     {
         var analyzedArguments = new AnalyzedArguments();
         GetDelegateArguments(source.Syntax, analyzedArguments, delegateInvokeMethodOpt.Parameters, binder.Compilation);
         var resolution = binder.ResolveMethodGroup(source, analyzedArguments, isMethodGroupConversion: true, inferWithDynamic: true, useSiteDiagnostics: ref useSiteDiagnostics);
         return(resolution);
     }
     else
     {
         return(binder.ResolveMethodGroup(source, null, isMethodGroupConversion: true, useSiteDiagnostics: ref useSiteDiagnostics));
     }
 }
Ejemplo n.º 25
0
        private static TypeSymbol MethodGroupReturnType(Binder binder, BoundMethodGroup source, ImmutableArray<ParameterSymbol> delegateParameters, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            var analyzedArguments = AnalyzedArguments.GetInstance();
            Conversions.GetDelegateArguments(source.Syntax, analyzedArguments, delegateParameters, binder.Compilation);

            var resolution = binder.ResolveMethodGroup(source, analyzedArguments, isMethodGroupConversion: true, useSiteDiagnostics: ref useSiteDiagnostics);

            TypeSymbol type = null;

            // The resolution could be empty (e.g. if there are no methods in the BoundMethodGroup).
            if (!resolution.IsEmpty)
            {
                var result = resolution.OverloadResolutionResult;
                if (result.Succeeded)
                {
                    type = result.BestResult.Member.ReturnType;
                }
            }

            analyzedArguments.Free();
            resolution.Free();
            return type;
        }
Ejemplo n.º 26
0
 public override BoundNode VisitMethodGroup(BoundMethodGroup node)
 {
     return(VisitMethodGroup(node, parentIsConversion: false));
 }
        private BoundNode VisitMethodGroup(BoundMethodGroup node, bool parentIsConversion)
        {
            // Formerly reported ERR_MemGroupInExpressionTree when this occurred, but the expanded 
            // ERR_LambdaInIsAs makes this impossible (since the node will always be wrapped in
            // a failed conversion).
            Debug.Assert(!(!parentIsConversion && _inExpressionLambda));

            CheckReceiverIfField(node.ReceiverOpt);
            return base.VisitMethodGroup(node);
        }
Ejemplo n.º 28
0
 private static MethodGroupResolution ResolveDelegateOrFunctionPointerMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, bool isFunctionPointer, in CallingConventionInfo callingConventionInfo, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
Ejemplo n.º 29
0
 private static MethodGroupResolution ResolveDelegateOrFunctionPointerMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, bool isFunctionPointer, in CallingConventionInfo callingConventionInfo, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo)
Ejemplo n.º 30
0
 public override BoundNode VisitMethodGroup(BoundMethodGroup node)
 {
     return VisitMethodGroup(node, parentIsConversion: false);
 }
Ejemplo n.º 31
0
 public override Conversion GetMethodGroupConversion(BoundMethodGroup source, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
 {
     // Conversions involving method groups require a Binder.
     throw ExceptionUtilities.Unreachable;
 }
Ejemplo n.º 32
0
        public static bool ReportDelegateMethodGroupDiagnostics(Binder binder, BoundMethodGroup expr, TypeSymbol targetType, DiagnosticBag diagnostics)
        {
            var invokeMethodOpt = GetDelegateInvokeMethodIfAvailable(targetType);
            HashSet <DiagnosticInfo> useSiteDiagnostics = null;
            var resolution = ResolveDelegateMethodGroup(binder, expr, invokeMethodOpt, ref useSiteDiagnostics);

            diagnostics.Add(expr.Syntax, useSiteDiagnostics);

            bool hasErrors = resolution.HasAnyErrors;

            diagnostics.AddRange(resolution.Diagnostics);

            // SPEC VIOLATION: Unfortunately, we cannot exactly implement the specification for
            // the scenario in which an extension method that extends a value type is converted
            // to a delegate. The code we generate that captures a delegate to a static method
            // that is "partially evaluated" with the bound-to-the-delegate first argument
            // requires that the first argument be of reference type.
            //
            // SPEC VIOLATION: Similarly, we cannot capture a method of Nullable<T>, because
            // boxing a Nullable<T> gives a T, not a boxed Nullable<T>.
            //
            // We give special error messages in these situations.

            if (resolution.MethodGroup != null)
            {
                var result = resolution.OverloadResolutionResult;
                if (result != null)
                {
                    if (result.Succeeded)
                    {
                        var method = result.BestResult.Member;
                        Debug.Assert((object)method != null);
                        if (resolution.MethodGroup.IsExtensionMethodGroup)
                        {
                            Debug.Assert(method.IsExtensionMethod);

                            var thisParameter = method.Parameters[0];
                            if (!thisParameter.Type.IsReferenceType)
                            {
                                // Extension method '{0}' defined on value type '{1}' cannot be used to create delegates
                                diagnostics.Add(
                                    ErrorCode.ERR_ValueTypeExtDelegate,
                                    expr.Syntax.Location,
                                    method,
                                    thisParameter.Type);
                                hasErrors = true;
                            }
                        }
                        else if (method.OriginalDefinition.ContainingType.SpecialType == SpecialType.System_Nullable_T && !method.IsOverride)
                        {
                            // CS1728: Cannot bind delegate to '{0}' because it is a member of 'System.Nullable<T>'
                            diagnostics.Add(
                                ErrorCode.ERR_DelegateOnNullable,
                                expr.Syntax.Location,
                                method);
                            hasErrors = true;
                        }
                    }
                    else if (!hasErrors &&
                             !resolution.IsEmpty &&
                             resolution.ResultKind == LookupResultKind.Viable)
                    {
                        var overloadDiagnostics = DiagnosticBag.GetInstance();

                        result.ReportDiagnostics(binder, expr.Syntax.Location, overloadDiagnostics,
                                                 expr.Name,
                                                 resolution.MethodGroup.Receiver, resolution.AnalyzedArguments, resolution.MethodGroup.Methods.ToImmutable(),
                                                 typeContainingConstructor: null, delegateTypeBeingInvoked: null, isMethodGroupConversion: true);

                        if (!overloadDiagnostics.IsEmptyWithoutResolution)
                        {
                            hasErrors = overloadDiagnostics.HasAnyErrors();
                            diagnostics.AddRange(overloadDiagnostics);
                        }

                        overloadDiagnostics.Free();
                    }
                }
            }

            resolution.Free();
            return(hasErrors);
        }
Ejemplo n.º 33
0
        private BoundNode VisitMethodGroup(BoundMethodGroup node, bool parentIsConversion)
        {
            // Formerly reported ERR_MemGroupInExpressionTree when this occurred, but the expanded 
            // ERR_LambdaInIsAs makes this impossible (since the node will always be wrapped in
            // a failed conversion).
            Debug.Assert(!(!parentIsConversion && _inExpressionLambda));

            if (_inExpressionLambda && (node.LookupSymbolOpt as MethodSymbol)?.MethodKind == MethodKind.LocalFunction)
            {
                Error(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, node);
            }

            CheckReceiverIfField(node.ReceiverOpt);
            return base.VisitMethodGroup(node);
        }
        public static bool ReportDelegateMethodGroupDiagnostics(Binder binder, BoundMethodGroup expr, TypeSymbol targetType, DiagnosticBag diagnostics)
        {
            var invokeMethodOpt = GetDelegateInvokeMethodIfAvailable(targetType);
            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            var resolution = ResolveDelegateMethodGroup(binder, expr, invokeMethodOpt, ref useSiteDiagnostics);
            diagnostics.Add(expr.Syntax, useSiteDiagnostics);

            bool hasErrors = resolution.HasAnyErrors;

            diagnostics.AddRange(resolution.Diagnostics);

            // SPEC VIOLATION: Unfortunately, we cannot exactly implement the specification for
            // the scenario in which an extension method that extends a value type is converted
            // to a delegate. The code we generate that captures a delegate to a static method
            // that is "partially evaluated" with the bound-to-the-delegate first argument
            // requires that the first argument be of reference type.
            //
            // SPEC VIOLATION: Similarly, we cannot capture a method of Nullable<T>, because
            // boxing a Nullable<T> gives a T, not a boxed Nullable<T>.
            //
            // We give special error messages in these situations.

            if (resolution.MethodGroup != null)
            {
                var result = resolution.OverloadResolutionResult;
                if (result != null)
                {
                    if (result.Succeeded)
                    {
                        var method = result.BestResult.Member;
                        Debug.Assert((object)method != null);
                        if (resolution.MethodGroup.IsExtensionMethodGroup)
                        {
                            Debug.Assert(method.IsExtensionMethod);

                            var thisParameter = method.Parameters[0];
                            if (!thisParameter.Type.IsReferenceType)
                            {
                                // Extension method '{0}' defined on value type '{1}' cannot be used to create delegates
                                diagnostics.Add(
                                    ErrorCode.ERR_ValueTypeExtDelegate,
                                    expr.Syntax.Location,
                                    method,
                                    thisParameter.Type);
                                hasErrors = true;
                            }
                        }
                        else if (method.OriginalDefinition.ContainingType.SpecialType == SpecialType.System_Nullable_T && !method.IsOverride)
                        {
                            // CS1728: Cannot bind delegate to '{0}' because it is a member of 'System.Nullable<T>'
                            diagnostics.Add(
                                ErrorCode.ERR_DelegateOnNullable,
                                expr.Syntax.Location,
                                method);
                            hasErrors = true;
                        }
                    }
                    else if (!hasErrors &&
                            !resolution.IsEmpty &&
                            resolution.ResultKind == LookupResultKind.Viable)
                    {
                        var overloadDiagnostics = DiagnosticBag.GetInstance();

                        result.ReportDiagnostics(binder, expr.Syntax.Location, overloadDiagnostics,
                            expr.Name,
                            resolution.MethodGroup.Receiver, resolution.AnalyzedArguments, resolution.MethodGroup.Methods.ToImmutable(),
                            typeContainingConstructor: null, delegateTypeBeingInvoked: null, isMethodGroupConversion: true);

                        if (!overloadDiagnostics.IsEmptyWithoutResolution)
                        {
                            hasErrors = overloadDiagnostics.HasAnyErrors();
                            diagnostics.AddRange(overloadDiagnostics);
                        }

                        overloadDiagnostics.Free();
                    }
                }
            }

            resolution.Free();
            return hasErrors;
        }
Ejemplo n.º 35
0
        // Get the symbols and possible method group associated with a method group bound node, as
        // they should be exposed through GetSemanticInfo.
        // NB: It is not safe to pass a null binderOpt during speculative binding.
        // 
        // If the parent node of the method group syntax node provides information (such as arguments) 
        // that allows us to return more specific symbols (a specific overload or applicable candidates)
        // we return these. The complete set of symbols of the method group is then returned in methodGroup parameter.
        private ImmutableArray<Symbol> GetMethodGroupSemanticSymbols(
            BoundMethodGroup boundNode,
            BoundNode boundNodeForSyntacticParent,
            Binder binderOpt,
            out LookupResultKind resultKind,
            out bool isDynamic,
            out ImmutableArray<Symbol> methodGroup)
        {
            Debug.Assert(binderOpt != null || IsInTree(boundNode.Syntax));

            ImmutableArray<Symbol> symbols = ImmutableArray<Symbol>.Empty;

            resultKind = boundNode.ResultKind;
            if (resultKind == LookupResultKind.Empty)
            {
                resultKind = LookupResultKind.Viable;
            }

            isDynamic = false;

            // The method group needs filtering.
            Binder binder = binderOpt ?? GetEnclosingBinder(GetAdjustedNodePosition(boundNode.Syntax));
            methodGroup = GetReducedAndFilteredMethodGroupSymbols(binder, boundNode).Cast<MethodSymbol, Symbol>();

            // We want to get the actual node chosen by overload resolution, if possible. 
            if (boundNodeForSyntacticParent != null)
            {
                switch (boundNodeForSyntacticParent.Kind)
                {
                    case BoundKind.Call:
                        // If we are looking for info on M in M(args), we want the symbol that overload resolution
                        // chose for M.
                        var call = (BoundCall)boundNodeForSyntacticParent;
                        InvocationExpressionSyntax invocation = call.Syntax as InvocationExpressionSyntax;
                        if (invocation != null && invocation.Expression.SkipParens() == boundNode.Syntax.SkipParens() && (object)call.Method != null)
                        {
                            if (call.OriginalMethodsOpt.IsDefault)
                            {
                                // Overload resolution succeeded.
                                symbols = CreateReducedExtensionMethodIfPossible(call);
                                resultKind = LookupResultKind.Viable;
                            }
                            else
                            {
                                resultKind = call.ResultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
                                symbols = StaticCast<Symbol>.From(CreateReducedExtensionMethodsFromOriginalsIfNecessary(call));
                            }
                        }
                        break;

                    case BoundKind.DelegateCreationExpression:
                        // If we are looking for info on "M" in "new Action(M)" 
                        // we want to get the symbol that overload resolution chose for M, not the whole method group M.
                        var delegateCreation = (BoundDelegateCreationExpression)boundNodeForSyntacticParent;
                        if (delegateCreation.Argument == boundNode && (object)delegateCreation.MethodOpt != null)
                        {
                            symbols = CreateReducedExtensionMethodIfPossible(delegateCreation, boundNode.ReceiverOpt);
                        }
                        break;

                    case BoundKind.Conversion:
                        // If we are looking for info on "M" in "(Action)M" 
                        // we want to get the symbol that overload resolution chose for M, not the whole method group M.
                        var conversion = (BoundConversion)boundNodeForSyntacticParent;

                        var method = conversion.SymbolOpt;
                        if ((object)method != null)
                        {
                            Debug.Assert(conversion.ConversionKind == ConversionKind.MethodGroup);

                            if (conversion.IsExtensionMethod)
                            {
                                method = ReducedExtensionMethodSymbol.Create(method);
                            }

                            symbols = ImmutableArray.Create((Symbol)method);
                            resultKind = conversion.ResultKind;
                        }
                        else
                        {
                            goto default;
                        }

                        break;

                    case BoundKind.DynamicInvocation:
                        var dynamicInvocation = (BoundDynamicInvocation)boundNodeForSyntacticParent;
                        symbols = dynamicInvocation.ApplicableMethods.Cast<MethodSymbol, Symbol>();
                        isDynamic = true;
                        break;

                    case BoundKind.BadExpression:
                        // If the bad expression has symbol(s) from this method group, it better indicates any problems.
                        ImmutableArray<Symbol> myMethodGroup = methodGroup;

                        symbols = ((BoundBadExpression)boundNodeForSyntacticParent).Symbols.WhereAsArray(sym => myMethodGroup.Contains(sym));
                        if (symbols.Any())
                        {
                            resultKind = ((BoundBadExpression)boundNodeForSyntacticParent).ResultKind;
                        }
                        break;

                    case BoundKind.NameOfOperator:
                        symbols = methodGroup;
                        resultKind = resultKind.WorseResultKind(LookupResultKind.MemberGroup);
                        break;

                    default:
                        symbols = methodGroup;
                        if (symbols.Length > 0)
                        {
                            resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
                        }
                        break;
                }
            }
            else if (methodGroup.Length == 1 && !boundNode.HasAnyErrors)
            {
                // During speculative binding, there won't be a parent bound node. The parent bound
                // node may also be absent if the syntactic parent has errors or if one is simply
                // not specified (see SemanticModel.GetSymbolInfoForNode). However, if there's exactly
                // one candidate, then we should probably succeed.

                symbols = methodGroup;
                if (symbols.Length > 0)
                {
                    resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
                }
            }

            if (!symbols.Any())
            {
                // If we didn't find a better set of symbols, then assume this is a method group that didn't
                // get resolved. Return all members of the method group, with a resultKind of OverloadResolutionFailure
                // (unless the method group already has a worse result kind).
                symbols = methodGroup;
                if (!isDynamic && resultKind > LookupResultKind.OverloadResolutionFailure)
                {
                    resultKind = LookupResultKind.OverloadResolutionFailure;
                }
            }

            return symbols;
        }