Beispiel #1
0
        OverloadResolutionErrors IsUnambiguousCall(ExpectedTargetDetails expectedTargetDetails, IMethod method,
                                                   ResolveResult target, IType[] typeArguments, IList <TranslatedExpression> arguments,
                                                   string[] argumentNames,
                                                   out IParameterizedMember foundMember)
        {
            foundMember = null;
            var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
            var or     = new OverloadResolution(resolver.Compilation,
                                                arguments.SelectArray(a => a.ResolveResult),
                                                argumentNames: argumentNames,
                                                typeArguments: typeArguments,
                                                conversions: expressionBuilder.resolver.conversions);

            if (expectedTargetDetails.CallOpCode == OpCode.NewObj)
            {
                foreach (IMethod ctor in method.DeclaringType.GetConstructors())
                {
                    if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition))
                    {
                        or.AddCandidate(ctor);
                    }
                }
            }
            else if (target == null)
            {
                var result = resolver.ResolveSimpleName(method.Name, typeArguments, isInvocationTarget: true) as MethodGroupResolveResult;
                if (result == null)
                {
                    return(OverloadResolutionErrors.AmbiguousMatch);
                }
                or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray());
            }
            else
            {
                var result = lookup.Lookup(target, method.Name, EmptyList <IType> .Instance, isInvocation: true) as MethodGroupResolveResult;
                if (result == null)
                {
                    return(OverloadResolutionErrors.AmbiguousMatch);
                }
                or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray());
            }
            if (or.BestCandidateErrors != OverloadResolutionErrors.None)
            {
                return(or.BestCandidateErrors);
            }
            if (or.IsAmbiguous)
            {
                return(OverloadResolutionErrors.AmbiguousMatch);
            }
            foundMember = or.GetBestCandidateWithSubstitutedTypeArguments();
            if (!IsAppropriateCallTarget(expectedTargetDetails, method, foundMember))
            {
                return(OverloadResolutionErrors.AmbiguousMatch);
            }
            return(OverloadResolutionErrors.None);
        }
Beispiel #2
0
        public OverloadResolution PerformOverloadResolution(ICompilation compilation, Expression[] arguments, string[] argumentNames = null,
                                                            bool allowExtensionMethods = true,
                                                            bool allowExpandingParams = true,
                                                            bool allowOptionalParameters = true,
                                                            bool checkForOverflow = false, VSharpConversions conversions = null)
        {

            var typeArgumentArray = this.TypeArguments.ToArray();
            OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, typeArgumentArray, conversions);
            or.AllowExpandingParams = allowExpandingParams;
            or.AllowOptionalParameters = allowOptionalParameters;
            or.CheckForOverflow = checkForOverflow;

            or.AddMethodLists(methodLists);

            if (allowExtensionMethods && !or.FoundApplicableCandidate)
            {
                // No applicable match found, so let's try extension methods.

                var extensionMethods = this.GetExtensionMethods();

                if (extensionMethods.Any())
                {

                    Expression[] extArguments = new Expression[arguments.Length + 1];
                    extArguments[0] = new AST.Expression(this.TargetType);
                    arguments.CopyTo(extArguments, 1);
                    string[] extArgumentNames = null;
                    if (argumentNames != null)
                    {
                        extArgumentNames = new string[argumentNames.Length + 1];
                        argumentNames.CopyTo(extArgumentNames, 1);
                    }
                    var extOr = new OverloadResolution(compilation, extArguments, extArgumentNames, typeArgumentArray, conversions);
                    extOr.AllowExpandingParams = allowExpandingParams;
                    extOr.AllowOptionalParameters = allowOptionalParameters;
                    extOr.IsExtensionMethodInvocation = true;
                    extOr.CheckForOverflow = checkForOverflow;

                    foreach (var g in extensionMethods)
                    {
                        foreach (var method in g)
                            extOr.AddCandidate(method);

                        if (extOr.FoundApplicableCandidate)
                            break;
                    }
                    // For the lack of a better comparison function (the one within OverloadResolution
                    // cannot be used as it depends on the argument set):
                    if (extOr.FoundApplicableCandidate || or.BestCandidate == null)
                    {
                        // Consider an extension method result better than the normal result only
                        // if it's applicable; or if there is no normal result.
                        or = extOr;
                    }
                }
            }

            return or;
        }
Beispiel #3
0
        OverloadResolutionErrors IsUnambiguousCall(ILInstruction inst, TranslatedExpression target, IMethod method, IType[] typeArguments, IList <TranslatedExpression> arguments)
        {
            var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
            var or     = new OverloadResolution(resolver.Compilation, arguments.SelectArray(a => a.ResolveResult), typeArguments: typeArguments);

            if (inst is NewObj newObj)
            {
                foreach (IMethod ctor in newObj.Method.DeclaringType.GetConstructors())
                {
                    if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == newObj.Method.DeclaringTypeDefinition))
                    {
                        or.AddCandidate(ctor);
                    }
                }
            }
            else
            {
                var result = lookup.Lookup(target.ResolveResult, method.Name, EmptyList <IType> .Instance, true) as MethodGroupResolveResult;
                if (result == null)
                {
                    return(OverloadResolutionErrors.AmbiguousMatch);
                }
                or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray());
            }
            if (or.BestCandidateErrors != OverloadResolutionErrors.None)
            {
                return(or.BestCandidateErrors);
            }
            if (!IsAppropriateCallTarget(method, or.GetBestCandidateWithSubstitutedTypeArguments(), inst.OpCode == OpCode.CallVirt))
            {
                return(OverloadResolutionErrors.AmbiguousMatch);
            }
            return(OverloadResolutionErrors.None);
        }
Beispiel #4
0
        TranslatedExpression HandleDelegateConstruction(CallInstruction inst)
        {
            ILInstruction func = inst.Arguments[1];
            IMethod       method;

            switch (func.OpCode)
            {
            case OpCode.LdFtn:
                method = ((LdFtn)func).Method;
                break;

            case OpCode.LdVirtFtn:
                method = ((LdVirtFtn)func).Method;
                break;

            default:
                method = (IMethod)typeSystem.Resolve(((ILFunction)func).Method);
                break;
            }
            var target = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn);
            var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
            var or     = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type)));
            var result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, true) as MethodGroupResolveResult;

            if (result == null)
            {
                target = target.ConvertTo(method.DeclaringType, expressionBuilder);
            }
            else
            {
                or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray());
                if (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(method, or.BestCandidate, func.OpCode == OpCode.LdVirtFtn))
                {
                    target = target.ConvertTo(method.DeclaringType, expressionBuilder);
                }
            }

            var mre = new MemberReferenceExpression(target, method.Name);

            mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
            var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), mre)
                      //				.WithAnnotation(new DelegateConstruction.Annotation(func.OpCode == OpCode.LdVirtFtn, target, method.Name))
                      .WithILInstruction(inst)
                      .WithRR(new ConversionResolveResult(
                                  inst.Method.DeclaringType,
                                  new MemberResolveResult(target.ResolveResult, method),
                                  // TODO handle extension methods capturing the first argument
                                  Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false)));

            if (func is ILFunction)
            {
                return(expressionBuilder.TranslateFunction(oce, target, (ILFunction)func));
            }
            else
            {
                return(oce);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Resolves an indexer access.
        /// </summary>
        /// <param name="target">Target expression.</param>
        /// <param name="arguments">
        /// Arguments passed to the indexer.
        /// The resolver may mutate this array to wrap elements in <see cref="CastExpression"/>s!
        /// </param>
        /// <param name="argumentNames">
        /// The argument names. Pass the null string for positional arguments.
        /// </param>
        /// <returns>ArrayAccessResolveResult, InvocationResolveResult, or ErrorResolveResult</returns>
        public Expression ResolveIndexer(ResolveContext rc, Expression target, Expression[] arguments, string[] argumentNames = null)
        {
            switch (target.Type.Kind)
            {
            case TypeKind.Array:
                // �6.6.1 Array access
                if (argumentNames != null && argumentNames.Length > 0)
                {
                    rc.Report.Error(0, Arguments.args.Where(x => x is NamedArgument).First().loc, "An element access expression cannot use named argument");
                }


                return(new ArrayAccessExpression(((ElementTypeSpec)target.Type).ElementType, target, arguments));

            case TypeKind.Pointer:
                // �.5.3 Pointer element access
                if (argumentNames != null && argumentNames.Length > 0)
                {
                    rc.Report.Error(0, Arguments.args.Where(x => x is NamedArgument).First().loc, "An element access expression cannot use named argument");
                }

                return(new PointerArithmeticExpression(((ElementTypeSpec)target.Type).ElementType, target, arguments));
            }

            // �6.6.2 Indexer access
            MemberLookup lookup   = rc.CreateMemberLookup();
            var          indexers = lookup.LookupIndexers(target);

            OverloadResolution or = rc.CreateOverloadResolution(arguments, argumentNames);

            or.AddMethodLists(indexers);
            if (or.BestCandidate != null)
            {
                return(or.CreateInvocation(target));
            }
            else
            {
                rc.Report.Error(0, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
                                target.Type.ToString());
                return(null);
            }
        }
Beispiel #6
0
        TranslatedExpression HandleDelegateConstruction(CallInstruction inst)
        {
            ILInstruction func = inst.Arguments[1];
            IMethod       method;

            switch (func.OpCode)
            {
            case OpCode.LdFtn:
                method = ((LdFtn)func).Method;
                break;

            case OpCode.LdVirtFtn:
                method = ((LdVirtFtn)func).Method;
                break;

            default:
                throw new ArgumentException($"Unknown instruction type: {func.OpCode}");
            }
            var invokeMethod = inst.Method.DeclaringType.GetDelegateInvokeMethod();
            TranslatedExpression target;
            IType targetType;

            if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count)
            {
                target     = expressionBuilder.Translate(inst.Arguments[0]);
                targetType = method.Parameters[0].Type;
            }
            else
            {
                target     = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn);
                targetType = method.DeclaringType;
            }
            var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
            var or     = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type)));
            var result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);

            bool needsCast = true;

            if (result is MethodGroupResolveResult mgrr)
            {
                or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
                var expectedTargetDetails = new ExpectedTargetDetails {
                    CallOpCode = inst.OpCode
                };
                needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
            }
            if (needsCast)
            {
                target = target.ConvertTo(targetType, expressionBuilder);
                result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
            }

            var mre = new MemberReferenceExpression(target, method.Name);

            mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
            mre.WithRR(result);
            var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), mre)
                      .WithILInstruction(inst)
                      .WithRR(new ConversionResolveResult(
                                  inst.Method.DeclaringType,
                                  new MemberResolveResult(target.ResolveResult, method),
                                  Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false)));

            return(oce);
        }
Beispiel #7
0
        TranslatedExpression HandleDelegateConstruction(CallInstruction inst)
        {
            ILInstruction func = inst.Arguments[1];
            IMethod       method;

            switch (func.OpCode)
            {
            case OpCode.LdFtn:
                method = ((LdFtn)func).Method;
                break;

            case OpCode.LdVirtFtn:
                method = ((LdVirtFtn)func).Method;
                break;

            default:
                throw new ArgumentException($"Unknown instruction type: {func.OpCode}");
            }
            var invokeMethod = inst.Method.DeclaringType.GetDelegateInvokeMethod();
            TranslatedExpression target;
            IType targetType;
            bool  requireTarget;

            if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count)
            {
                targetType    = method.Parameters[0].Type;
                target        = expressionBuilder.Translate(inst.Arguments[0], targetType);
                target        = ExpressionBuilder.UnwrapBoxingConversion(target);
                requireTarget = true;
            }
            else
            {
                targetType    = method.DeclaringType;
                target        = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn);
                target        = ExpressionBuilder.UnwrapBoxingConversion(target);
                requireTarget = expressionBuilder.HidesVariableWithName(method.Name) ||
                                (method.IsStatic ? !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression));
            }
            var expectedTargetDetails = new ExpectedTargetDetails {
                CallOpCode = inst.OpCode
            };
            bool          needsCast = false;
            ResolveResult result    = null;
            var           or        = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type)));

            if (!requireTarget)
            {
                result = resolver.ResolveSimpleName(method.Name, method.TypeArguments, isInvocationTarget: false);
                if (result is MethodGroupResolveResult mgrr)
                {
                    or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
                    requireTarget = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
                }
                else
                {
                    requireTarget = true;
                }
            }
            MemberLookup lookup = null;

            if (requireTarget)
            {
                lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
                var rr = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
                needsCast = true;
                result    = rr;
                if (rr is MethodGroupResolveResult mgrr)
                {
                    or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
                    needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
                }
            }
            if (needsCast)
            {
                Debug.Assert(requireTarget);
                target = target.ConvertTo(targetType, expressionBuilder);
                result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
            }
            Expression targetExpression;

            if (requireTarget)
            {
                var mre = new MemberReferenceExpression(target, method.Name);
                mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
                mre.WithRR(result);
                targetExpression = mre;
            }
            else
            {
                var ide = new IdentifierExpression(method.Name)
                          .WithRR(result);
                targetExpression = ide;
            }
            var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), targetExpression)
                      .WithILInstruction(inst)
                      .WithRR(new ConversionResolveResult(
                                  inst.Method.DeclaringType,
                                  new MemberResolveResult(target.ResolveResult, method),
                                  Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false)));

            return(oce);
        }