Ejemplo n.º 1
0
		//
		// Returns AnonymousMethod container if this anonymous method
		// expression can be implicitly converted to the delegate type `delegate_type'
		//
		public Expression Compatible (ResolveContext ec, TypeSpec type)
		{
			Expression am;
			if (compatibles.TryGetValue (type, out am))
				return am;

			TypeSpec delegate_type = CompatibleChecks (ec, type);
			if (delegate_type == null)
				return null;

			//
			// At this point its the first time we know the return type that is 
			// needed for the anonymous method.  We create the method here.
			//

			var invoke_mb = Delegate.GetInvokeMethod (delegate_type);
			TypeSpec return_type = invoke_mb.ReturnType;

			//
			// Second: the return type of the delegate must be compatible with 
			// the anonymous type.   Instead of doing a pass to examine the block
			// we satisfy the rule by setting the return type on the EmitContext
			// to be the delegate type return type.
			//

			var body = CompatibleMethodBody (ec, null, return_type, delegate_type);
			if (body == null)
				return null;

			bool etree_conversion = delegate_type != type;

			try {
				if (etree_conversion) {
					if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
						//
						// Nested expression tree lambda use same scope as parent
						// lambda, this also means no variable capturing between this
						// and parent scope
						//
						am = body.Compatible (ec, ec.CurrentAnonymousMethod);

						//
						// Quote nested expression tree
						//
						if (am != null)
							am = new Quote (am);
					} else {
						int errors = ec.Report.Errors;

						if (Block.IsAsync) {
							ec.Report.Error (1989, loc, "Async lambda expressions cannot be converted to expression trees");
						}

						using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) {
							am = body.Compatible (ec);
						}

						//
						// Rewrite expressions into expression tree when targeting Expression<T>
						//
						if (am != null && errors == ec.Report.Errors)
							am = CreateExpressionTree (ec, delegate_type);
					}
				} else {
					am = body.Compatible (ec);

					if (body.DirectMethodGroupConversion != null) {
						var errors_printer = new SessionReportPrinter ();
						var old = ec.Report.SetPrinter (errors_printer);
						var expr = new ImplicitDelegateCreation (delegate_type, body.DirectMethodGroupConversion, loc) {
							AllowSpecialMethodsInvocation = true
						}.Resolve (ec);
						ec.Report.SetPrinter (old);
						if (expr != null && errors_printer.ErrorsCount == 0)
							am = expr;
					}
				}
			} catch (CompletionResult) {
				throw;
			} catch (FatalException) {
				throw;
			} catch (Exception e) {
				throw new InternalErrorException (e, loc);
			}

			if (!ec.IsInProbingMode) {
				compatibles.Add (type, am ?? EmptyExpression.Null);
			}

			return am;
		}
Ejemplo n.º 2
0
        public override bool Resolve(BlockContext bc)
        {
            if (bc.CurrentBlock is Linq.QueryBlock)
            {
                bc.Report.Error(1995, loc,
                                "The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause");
                return(false);
            }

            if (!base.Resolve(bc))
            {
                return(false);
            }

            type = expr.Type;
            Arguments args = new Arguments(0);

            //
            // The await expression is of dynamic type
            //
            if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
            {
                result_type = type;
                expr        = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc);
                return(true);
            }

            //
            // Check whether the expression is awaitable
            //
            Expression ama = new AwaitableMemberAccess(expr).Resolve(bc);

            if (ama == null)
            {
                return(false);
            }

            var errors_printer = new SessionReportPrinter();
            var old            = bc.Report.SetPrinter(errors_printer);

            ama = new Invocation(ama, args).Resolve(bc);
            bc.Report.SetPrinter(old);

            if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type))
            {
                bc.Report.Error(1986, expr.Location,
                                "The `await' operand type `{0}' must have suitable GetAwaiter method",
                                expr.Type.GetSignatureForError());

                return(false);
            }

            var awaiter_type = ama.Type;

            awaiter_definition = bc.Module.GetAwaiter(awaiter_type);

            if (!awaiter_definition.IsValidPattern)
            {
                Error_WrongAwaiterPattern(bc, awaiter_type);
                return(false);
            }

            if (!awaiter_definition.INotifyCompletion)
            {
                bc.Report.Error(4027, loc, "The awaiter type `{0}' must implement interface `{1}'",
                                awaiter_type.GetSignatureForError(), bc.Module.PredefinedTypes.INotifyCompletion.GetSignatureForError());
                return(false);
            }

            expr        = ama;
            result_type = awaiter_definition.GetResult.ReturnType;

            return(true);
        }
Ejemplo n.º 3
0
        public override bool Resolve(BlockContext bc)
        {
            if (bc.CurrentBlock is Linq.QueryBlock)
            {
                bc.Report.Error(1995, loc,
                                "The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause");
                return(false);
            }

            if (!base.Resolve(bc))
            {
                return(false);
            }

            Arguments args = new Arguments(0);

            type = expr.Type;

            //
            // The await expression is of dynamic type
            //
            if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
            {
                result_type = type;
                expr        = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc);
                return(true);
            }

            //
            // Check whether the expression is awaitable
            //
            Expression ama = new AwaitableMemberAccess(expr).Resolve(bc);

            if (ama == null)
            {
                return(false);
            }

            var errors_printer = new SessionReportPrinter();
            var old            = bc.Report.SetPrinter(errors_printer);

            ama = new Invocation(ama, args).Resolve(bc);
            bc.Report.SetPrinter(old);

            if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type))
            {
                bc.Report.Error(1986, expr.Location,
                                "The `await' operand type `{0}' must have suitable GetAwaiter method",
                                expr.Type.GetSignatureForError());

                return(false);
            }

            var awaiter_type = ama.Type;

            expr = ama;

            //
            // Predefined: bool IsCompleted { get; }
            //
            is_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Property("IsCompleted", bc.Module.Compiler.BuiltinTypes.Bool),
                                                  BindingRestriction.InstanceOnly) as PropertySpec;

            if (is_completed == null || !is_completed.HasGet)
            {
                Error_WrongAwaiterPattern(bc, awaiter_type);
                return(false);
            }

            //
            // Predefined: GetResult ()
            //
            // The method return type is also result type of await expression
            //
            get_result = MemberCache.FindMember(awaiter_type, MemberFilter.Method("GetResult", 0,
                                                                                  ParametersCompiled.EmptyReadOnlyParameters, null),
                                                BindingRestriction.InstanceOnly) as MethodSpec;

            if (get_result == null)
            {
                Error_WrongAwaiterPattern(bc, awaiter_type);
                return(false);
            }

            //
            // Predefined: INotifyCompletion.OnCompleted (System.Action)
            //
            var nc = bc.Module.PredefinedTypes.INotifyCompletion;

            if (nc.Define() && !awaiter_type.ImplementsInterface(nc.TypeSpec, false))
            {
                bc.Report.Error(4027, loc, "The awaiter type `{0}' must implement interface `{1}'",
                                awaiter_type.GetSignatureForError(), nc.GetSignatureForError());
                return(false);
            }

            result_type = get_result.ReturnType;

            return(true);
        }
Ejemplo n.º 4
0
		/// <summary>
		///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
		/// </summary>
		void ResolveAttributeType ()
		{
			SessionReportPrinter resolve_printer = new SessionReportPrinter ();
			ReportPrinter prev_recorder = context.Compiler.Report.SetPrinter (resolve_printer);

			bool t1_is_attr = false;
			bool t2_is_attr = false;
			TypeSpec t1, t2;
			ATypeNameExpression expanded = null;

			try {
				t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);

				if (nameEscaped) {
					t2 = null;
				} else {
					expanded = (ATypeNameExpression) expression.Clone (null);
					expanded.Name += "Attribute";

					t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
				}

				resolve_printer.EndSession ();
			} finally {
				context.Compiler.Report.SetPrinter (prev_recorder);
			}

			if (t1_is_attr && t2_is_attr) {
				Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
					GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
				resolve_error = true;
				return;
			}

			if (t1_is_attr) {
				Type = t1;
				return;
			}

			if (t2_is_attr) {
				Type = t2;
				return;
			}

			resolve_printer.Merge (prev_recorder);
			resolve_error = true;
		}
Ejemplo n.º 5
0
        /// <summary>
        ///   Find the Applicable Function Members (7.4.2.1)
        ///
        ///   me: Method Group expression with the members to select.
        ///       it might contain constructors or methods (or anything
        ///       that maps to a method).
        ///
        ///   Arguments: ArrayList containing resolved Argument objects.
        ///
        ///   loc: The location if we want an error to be reported, or a Null
        ///        location for "probing" purposes.
        ///
        ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
        ///            that is the best match of me on Arguments.
        ///
        /// </summary>
        public virtual MethodGroupExpr OverloadResolve(ResolveContext ec, ref Arguments Arguments,
            bool may_fail, Location loc)
        {
            var candidates = new List<MethodSpec> (2);
            List<MethodSpec> params_candidates = null;

            int arg_count = Arguments != null ? Arguments.Count : 0;
            Dictionary<MethodSpec, Arguments> candidates_expanded = null;
            Arguments candidate_args = Arguments;

            if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
                if (!may_fail)
                    ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
                return null;
            }

            //
            // Enable message recording, it's used mainly by lambda expressions
            //
            var msg_recorder = new SessionReportPrinter ();
            var prev_recorder = ec.Report.SetPrinter (msg_recorder);

            do {
                //
                // Methods in a base class are not candidates if any method in a derived
                // class is applicable
                //
                int best_candidate_rate = int.MaxValue;

                foreach (var member in Methods) {
                    var m = member as MethodSpec;
                    if (m == null) {
                        // TODO: It's wrong when non-member is before applicable method
                        // TODO: Should report only when at least 1 from the batch is applicable
                        if (candidates.Count != 0) {
                            ec.Report.SymbolRelatedToPreviousError (candidates [0]);
                            ec.Report.SymbolRelatedToPreviousError (member);
                            ec.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
                                candidates[0].GetSignatureForError (), member.GetSignatureForError ());
                        }
                        continue;
                    }

                    //
                    // Check if candidate is applicable (section 14.4.2.1)
                    //
                    bool params_expanded_form = false;
                    int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref m, ref params_expanded_form);

                    if (candidate_rate < best_candidate_rate) {
                        best_candidate_rate = candidate_rate;
                        best_candidate = m;
                    }

                    if (params_expanded_form) {
                        if (params_candidates == null)
                            params_candidates = new List<MethodSpec> (2);
                        params_candidates.Add (m);
                    }

                    if (candidate_args != Arguments) {
                        if (candidates_expanded == null)
                            candidates_expanded = new Dictionary<MethodSpec, Arguments> (2);

                        candidates_expanded.Add (m, candidate_args);
                        candidate_args = Arguments;
                    }

                    if (candidate_rate != 0 || has_inaccessible_candidates_only) {
                        if (msg_recorder != null)
                            msg_recorder.EndSession ();
                        continue;
                    }

                    msg_recorder = null;
                    candidates.Add (m);
                }
            } while (candidates.Count == 0 && GetBaseTypeMethods (ec));

            ec.Report.SetPrinter (prev_recorder);
            if (msg_recorder != null && !msg_recorder.IsEmpty) {
                if (!may_fail)
                    msg_recorder.Merge (prev_recorder);

                return null;
            }

            int candidate_top = candidates.Count;
            if (candidate_top == 0) {
                //
                // When we found a top level method which does not match and it's
                // not an extension method. We start extension methods lookup from here
                //
                if (InstanceExpression != null) {
                    var first = Methods.First ();
                    var arity = type_arguments == null ? -1 : type_arguments.Count;
                    ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, first.Name, arity, loc);
                    if (ex_method_lookup != null) {
                        ex_method_lookup.ExtensionExpression = InstanceExpression;
                        ex_method_lookup.SetTypeArguments (ec, type_arguments);
                        return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
                    }
                }

                if (may_fail)
                    return null;

                //
                // Okay so we have failed to find exact match so we
                // return error info about the closest match
                //
                if (best_candidate != null) {
                    if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
                        return null;

                    bool params_expanded = params_candidates != null && params_candidates.Contains (best_candidate);
                    if (NoExactMatch (ec, ref Arguments, params_expanded))
                        return null;
                }

                //
                // We failed to find any method with correct argument count
                //
                if (Methods.First ().Kind == MemberKind.Constructor) {
                    ec.Report.SymbolRelatedToPreviousError (queried_type);
                    ec.Report.Error (1729, loc,
                        "The type `{0}' does not contain a constructor that takes `{1}' arguments",
                        TypeManager.CSharpName (queried_type), arg_count.ToString ());
                } else {
                    Error_ArgumentCountWrong (ec, arg_count);
                }

                return null;
            }

            if (arg_count != 0 && Arguments.HasDynamic) {
                best_candidate = null;
                return this;
            }

            //
            // Now we actually find the best method
            //
            best_candidate = candidates [0];
            bool method_params = params_candidates != null && params_candidates.Contains (best_candidate);

            for (int ix = 1; ix < candidate_top; ix++) {
                var candidate = candidates [ix];

                if (candidate == best_candidate)
                    continue;

                bool cand_params = params_candidates != null && params_candidates.Contains (candidate);

                if (candidates_expanded != null && candidates_expanded.ContainsKey (candidate)) {
                    candidate_args = candidates_expanded[candidate];
                    arg_count = candidate_args.Count;
                }

                if (BetterFunction (ec, candidate_args, arg_count,
                    candidate, cand_params,
                    best_candidate, method_params)) {
                    best_candidate = candidate;
                    method_params = cand_params;
                }

                if (candidate_args != Arguments) {
                    candidate_args = Arguments;
                    arg_count = candidate_args != null ? candidate_args.Count : 0;
                }
            }

            if (candidates_expanded != null && candidates_expanded.ContainsKey (best_candidate)) {
                candidate_args = candidates_expanded[best_candidate];
                arg_count = candidate_args.Count;
            }

            //
            // Now check that there are no ambiguities i.e the selected method
            // should be better than all the others
            //
            MethodSpec ambiguous = null;
            for (int ix = 1; ix < candidate_top; ix++) {
                var candidate = candidates [ix];

                if (candidate == best_candidate)
                    continue;

                bool cand_params = params_candidates != null && params_candidates.Contains (candidate);
                if (!BetterFunction (ec, candidate_args, arg_count,
                    best_candidate, method_params,
                    candidate, cand_params))
                {
                    if (!may_fail)
                        ec.Report.SymbolRelatedToPreviousError (candidate);
                    ambiguous = candidate;
                }
            }

            if (ambiguous != null) {
                Error_AmbiguousCall (ec, ambiguous);
                return this;
            }

            //
            // And now check if the arguments are all
            // compatible, perform conversions if
            // necessary etc. and return if everything is
            // all right
            //
            if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
                method_params, may_fail, loc))
                return null;

            if (best_candidate == null)
                return null;

            if (best_candidate.IsGeneric) {
                ConstraintChecker.CheckAll (best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments,
                    best_candidate.Constraints, loc, ec.Report);
            }

            //
            // Check ObsoleteAttribute on the best method
            //
            ObsoleteAttribute oa = best_candidate.GetAttributeObsolete ();
            if (oa != null && !ec.IsObsolete)
                AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);

            best_candidate.MemberDefinition.SetIsUsed ();

            Arguments = candidate_args;
            return this;
        }
Ejemplo n.º 6
0
        public override bool Resolve(BlockContext bc)
        {
            if (!base.Resolve(bc))
            {
                return(false);
            }

            Arguments args = new Arguments(0);

            type = expr.Type;

            //
            // The await expression is of dynamic type
            //
            if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
            {
                result_type = type;

                awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(type, loc);

                expr = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc);
                return(true);
            }

            //
            // Check whether the expression is awaitable
            //
            Expression ama = new AwaitableMemberAccess(expr).Resolve(bc);

            if (ama == null)
            {
                return(false);
            }

            var errors_printer = new SessionReportPrinter();
            var old            = bc.Report.SetPrinter(errors_printer);

            ama = new Invocation(ama, args).Resolve(bc);
            bc.Report.SetPrinter(old);

            if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type))
            {
                bc.Report.Error(1986, expr.Location,
                                "The `await' operand type `{0}' must have suitable GetAwaiter method",
                                expr.Type.GetSignatureForError());

                return(false);
            }

            var awaiter_type = ama.Type;

            awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(awaiter_type, loc);

            expr = ama;

            //
            // Predefined: bool IsCompleted { get; }
            //
            is_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Property("IsCompleted", bc.Module.Compiler.BuiltinTypes.Bool),
                                                  BindingRestriction.InstanceOnly) as PropertySpec;

            if (is_completed == null || !is_completed.HasGet)
            {
                Error_WrongAwaiterPattern(bc, awaiter_type);
                return(false);
            }

            //
            // Predefined: OnCompleted (Action)
            //
            if (bc.Module.PredefinedTypes.Action.Define())
            {
                on_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Method("OnCompleted", 0,
                                                                                        ParametersCompiled.CreateFullyResolved(bc.Module.PredefinedTypes.Action.TypeSpec), bc.Module.Compiler.BuiltinTypes.Void),
                                                      BindingRestriction.InstanceOnly) as MethodSpec;

                if (on_completed == null)
                {
                    Error_WrongAwaiterPattern(bc, awaiter_type);
                    return(false);
                }
            }

            //
            // Predefined: GetResult ()
            //
            // The method return type is also result type of await expression
            //
            get_result = MemberCache.FindMember(awaiter_type, MemberFilter.Method("GetResult", 0,
                                                                                  ParametersCompiled.EmptyReadOnlyParameters, null),
                                                BindingRestriction.InstanceOnly) as MethodSpec;

            if (get_result == null)
            {
                Error_WrongAwaiterPattern(bc, awaiter_type);
                return(false);
            }

            result_type = get_result.ReturnType;

            return(true);
        }
Ejemplo n.º 7
0
        /// <summary>
        ///   User-defined conversions
        /// </summary>
        public static Expression UserDefinedConversion(ResolveContext ec, Expression source,
            TypeSpec target, Location loc,
            bool look_for_explicit, bool return_convert)
        {
            TypeSpec source_type = source.Type;
            MethodSpec method = null;
            Expression expr = null;

            object o;
            DoubleHash hash;
            if (look_for_explicit) {
                hash = explicit_conv;
            } else {
                // Implicit user operators cannot convert to interfaces
                if (target.IsInterface)
                    return null;

                hash = implicit_conv;
            }

            if (!(source is Constant) && hash.Lookup (source_type, target, out o)) {
                method = (MethodSpec) o;
            } else {
                if (source_type == InternalType.Dynamic)
                    return null;

                method = GetConversionOperator (ec.Compiler, null, source, target, look_for_explicit);
            }

            if (method != null) {
                TypeSpec most_specific_source = method.Parameters.Types[0];

                //
                // This will do the conversion to the best match that we
                // found.  Now we need to perform an implict standard conversion
                // if the best match was not the type that we were requested
                // by target.
                //
                if (look_for_explicit) {
                    ReportPrinter temp = new SessionReportPrinter ();
                    ReportPrinter prev = ec.Report.SetPrinter (temp);

                    expr = ExplicitConversionStandard (ec, source, most_specific_source, loc);

                    ec.Report.SetPrinter (prev);
                    if (temp.ErrorsCount != 0)
                        expr = null;
                } else {
                    if (ImplicitStandardConversionExists (source, most_specific_source))
                        expr = ImplicitConversionStandard (ec, source, most_specific_source, loc);
                    else
                        expr = null;
                }
            }

            if (expr == null) {
                bool nullable = false;

                if (TypeManager.IsNullableType (source_type)) {
                    source = Nullable.Unwrap.Create (source);
                    nullable = true;
                }

                TypeSpec target_underlying;
                if (TypeManager.IsNullableType (target)) {
                    target_underlying = TypeManager.GetTypeArguments (target)[0];
                    nullable = true;
                } else {
                    // No implicit conversion S? -> T for non-reference type T
                    if (!look_for_explicit && !TypeManager.IsReferenceType (target))
                        nullable = false;

                    target_underlying = target;
                }

                if (nullable) {
                    expr = UserDefinedConversion (ec, source, target_underlying, loc, look_for_explicit, return_convert);

                    // Do result expression lifting only when it's needed
                    if (expr != null && (!look_for_explicit || TypeManager.IsReferenceType (target)))
                        expr = new Nullable.Lifted (expr, source, target).Resolve (ec);

                    return expr;
                }
            } else {
                expr = new UserCast (method, expr, loc).Resolve (ec);

                if (return_convert && !TypeManager.IsEqual (expr.Type, target)) {
                    if (look_for_explicit) {
                        expr = ExplicitConversionStandard (ec, expr, target, loc);
                    } else {
                        expr = ImplicitConversionStandard (ec, expr, target, loc);
                    }
                }
            }

            if (!(source is Constant))
                hash.Insert (source_type, target, method);

            return expr;
        }
Ejemplo n.º 8
0
        public override bool Resolve(BlockContext bc)
        {
            if (!base.Resolve(bc))
            {
                return(false);
            }

            type = expr.Type;

            //
            // The task result is of dynamic type
            //
            if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
            {
                throw new NotImplementedException("dynamic await");
            }

            //
            // Check whether the expression is awaitable
            //
            Expression ama = new AwaitableMemberAccess(expr).Resolve(bc);

            if (ama == null)
            {
                return(false);
            }

            Arguments args = new Arguments(0);

            var errors_printer = new SessionReportPrinter();
            var old            = bc.Report.SetPrinter(errors_printer);

            ama = new Invocation(ama, args).Resolve(bc);

            if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type))
            {
                bc.Report.SetPrinter(old);
                Error_WrongGetAwaiter(bc, loc, expr.Type);
                return(false);
            }

            var awaiter_type = ama.Type;

            awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(awaiter_type, loc);
            expr    = ama;

            //
            // Predefined: bool IsCompleted { get; }
            //
            var is_completed_ma = new MemberAccess(expr, "IsCompleted").Resolve(bc);

            if (is_completed_ma != null)
            {
                is_completed = is_completed_ma as PropertyExpr;
                if (is_completed != null && is_completed.Type.BuiltinType == BuiltinTypeSpec.Type.Bool && is_completed.IsInstance && is_completed.Getter != null)
                {
                    // valid
                }
                else
                {
                    bc.Report.SetPrinter(old);
                    Error_WrongAwaiterPattern(bc, awaiter_type);
                    return(false);
                }
            }

            bc.Report.SetPrinter(old);

            if (errors_printer.ErrorsCount > 0)
            {
                Error_WrongAwaiterPattern(bc, awaiter_type);
                return(false);
            }

            //
            // Predefined: OnCompleted (Action)
            //
            if (bc.Module.PredefinedTypes.Action.Define())
            {
                on_completed = MemberCache.FindMember(awaiter_type, MemberFilter.Method("OnCompleted", 0,
                                                                                        ParametersCompiled.CreateFullyResolved(bc.Module.PredefinedTypes.Action.TypeSpec), bc.Module.Compiler.BuiltinTypes.Void),
                                                      BindingRestriction.InstanceOnly) as MethodSpec;

                if (on_completed == null)
                {
                    Error_WrongAwaiterPattern(bc, awaiter_type);
                    return(false);
                }
            }

            //
            // Predefined: GetResult ()
            //
            // The method return type is also result type of await expression
            //
            get_result = MemberCache.FindMember(awaiter_type, MemberFilter.Method("GetResult", 0,
                                                                                  ParametersCompiled.EmptyReadOnlyParameters, null),
                                                BindingRestriction.InstanceOnly) as MethodSpec;

            if (get_result == null)
            {
                Error_WrongAwaiterPattern(bc, awaiter_type);
                return(false);
            }

            return(true);
        }
Ejemplo n.º 9
0
		/// <summary>
		///   Find the Applicable Function Members (7.4.2.1)
		///
		///   me: Method Group expression with the members to select.
		///       it might contain constructors or methods (or anything
		///       that maps to a method).
		///
		///   Arguments: ArrayList containing resolved Argument objects.
		///
		///   loc: The location if we want an error to be reported, or a Null
		///        location for "probing" purposes.
		///
		///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
		///            that is the best match of me on Arguments.
		///
		/// </summary>
		public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments Arguments,
			bool may_fail, Location loc)
		{
			bool method_params = false;
			Type applicable_type = null;
			ArrayList candidates = new ArrayList (2);
			ArrayList candidate_overrides = null;

			//
			// Used to keep a map between the candidate
			// and whether it is being considered in its
			// normal or expanded form
			//
			// false is normal form, true is expanded form
			//
			Hashtable candidate_to_form = null;
			Hashtable candidates_expanded = null;
			Arguments candidate_args = Arguments;

			int arg_count = Arguments != null ? Arguments.Count : 0;

			if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
				if (!may_fail)
					ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
				return null;
			}

			int nmethods = Methods.Length;

			if (!IsBase) {
				//
				// Methods marked 'override' don't take part in 'applicable_type'
				// computation, nor in the actual overload resolution.
				// However, they still need to be emitted instead of a base virtual method.
				// So, we salt them away into the 'candidate_overrides' array.
				//
				// In case of reflected methods, we replace each overriding method with
				// its corresponding base virtual method.  This is to improve compatibility
				// with non-C# libraries which change the visibility of overrides (#75636)
				//
				int j = 0;
				for (int i = 0; i < Methods.Length; ++i) {
					MethodBase m = Methods [i];
					if (TypeManager.IsOverride (m)) {
						if (candidate_overrides == null)
							candidate_overrides = new ArrayList ();
						candidate_overrides.Add (m);
						m = TypeManager.TryGetBaseDefinition (m);
					}
					if (m != null)
						Methods [j++] = m;
				}
				nmethods = j;
			}

			//
			// Enable message recording, it's used mainly by lambda expressions
			//
			SessionReportPrinter msg_recorder = new SessionReportPrinter ();
			ReportPrinter prev_recorder = ec.Report.SetPrinter (msg_recorder);

			//
			// First we construct the set of applicable methods
			//
			bool is_sorted = true;
			int best_candidate_rate = int.MaxValue;
			for (int i = 0; i < nmethods; i++) {
				Type decl_type = Methods [i].DeclaringType;

				//
				// If we have already found an applicable method
				// we eliminate all base types (Section 14.5.5.1)
				//
				if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
					continue;

				//
				// Check if candidate is applicable (section 14.4.2.1)
				//
				bool params_expanded_form = false;
				int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref Methods [i], ref params_expanded_form);

				if (candidate_rate < best_candidate_rate) {
					best_candidate_rate = candidate_rate;
					best_candidate = Methods [i];
				}
				
				if (params_expanded_form) {
					if (candidate_to_form == null)
						candidate_to_form = new PtrHashtable ();
					MethodBase candidate = Methods [i];
					candidate_to_form [candidate] = candidate;
				}
				
				if (candidate_args != Arguments) {
					if (candidates_expanded == null)
						candidates_expanded = new Hashtable (2);

					candidates_expanded.Add (Methods [i], candidate_args);
					candidate_args = Arguments;
				}

				if (candidate_rate != 0 || has_inaccessible_candidates_only) {
					if (msg_recorder != null)
						msg_recorder.EndSession ();
					continue;
				}

				msg_recorder = null;
				candidates.Add (Methods [i]);

				if (applicable_type == null)
					applicable_type = decl_type;
				else if (applicable_type != decl_type) {
					is_sorted = false;
					if (IsAncestralType (applicable_type, decl_type))
						applicable_type = decl_type;
				}
			}

			ec.Report.SetPrinter (prev_recorder);
			if (msg_recorder != null && !msg_recorder.IsEmpty) {
				if (!may_fail)
					msg_recorder.Merge (prev_recorder);

				return null;
			}
			
			int candidate_top = candidates.Count;

			if (applicable_type == null) {
				//
				// When we found a top level method which does not match and it's 
				// not an extension method. We start extension methods lookup from here
				//
				if (InstanceExpression != null) {
					ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, Name, loc);
					if (ex_method_lookup != null) {
						ex_method_lookup.ExtensionExpression = InstanceExpression;
						ex_method_lookup.SetTypeArguments (ec, type_arguments);
						return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
					}
				}
				
				if (may_fail)
					return null;

				//
				// Okay so we have failed to find exact match so we
				// return error info about the closest match
				//
				if (best_candidate != null) {
					if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
						return null;

					AParametersCollection pd = TypeManager.GetParameterData (best_candidate);
					bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
					if (arg_count == pd.Count || pd.HasParams) {
						if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
							if (type_arguments == null) {
								ec.Report.Error (411, loc,
									"The type arguments for method `{0}' cannot be inferred from " +
									"the usage. Try specifying the type arguments explicitly",
									TypeManager.CSharpSignature (best_candidate));
								return null;
							}

							Type[] g_args = TypeManager.GetGenericArguments (best_candidate);
							if (type_arguments.Count != g_args.Length) {
								ec.Report.SymbolRelatedToPreviousError (best_candidate);
								ec.Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)",
									TypeManager.CSharpSignature (best_candidate),
									g_args.Length.ToString ());
								return null;
							}
						} else {
							if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
								Namespace.Error_TypeArgumentsCannotBeUsed (best_candidate, loc);
								return null;
							}
						}

						if (has_inaccessible_candidates_only) {
							if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) {
								// Although a derived class can access protected members of
								// its base class it cannot do so through an instance of the
								// base class (CS1540).  If the qualifier_type is a base of the
								// ec.CurrentType and the lookup succeeds with the latter one,
								// then we are in this situation.
								Error_CannotAccessProtected (ec, loc, best_candidate, queried_type, ec.CurrentType);
							} else {
								ec.Report.SymbolRelatedToPreviousError (best_candidate);
								ErrorIsInaccesible (loc, GetSignatureForError (), ec.Report);
							}
						}

						if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
							return null;

						if (has_inaccessible_candidates_only)
							return null;

						throw new InternalErrorException ("VerifyArgumentsCompat didn't find any problem with rejected candidate " + best_candidate);
					}
				}

				//
				// We failed to find any method with correct argument count
				//
				if (Name == ConstructorInfo.ConstructorName) {
					ec.Report.SymbolRelatedToPreviousError (queried_type);
					ec.Report.Error (1729, loc,
						"The type `{0}' does not contain a constructor that takes `{1}' arguments",
						TypeManager.CSharpName (queried_type), arg_count);
				} else {
					Error_ArgumentCountWrong (ec, arg_count);
				}
                                
				return null;
			}

			if (!is_sorted) {
				//
				// At this point, applicable_type is _one_ of the most derived types
				// in the set of types containing the methods in this MethodGroup.
				// Filter the candidates so that they only contain methods from the
				// most derived types.
				//

				int finalized = 0; // Number of finalized candidates

				do {
					// Invariant: applicable_type is a most derived type
					
					// We'll try to complete Section 14.5.5.1 for 'applicable_type' by 
					// eliminating all it's base types.  At the same time, we'll also move
					// every unrelated type to the end of the array, and pick the next
					// 'applicable_type'.

					Type next_applicable_type = null;
					int j = finalized; // where to put the next finalized candidate
					int k = finalized; // where to put the next undiscarded candidate
					for (int i = finalized; i < candidate_top; ++i) {
						MethodBase candidate = (MethodBase) candidates [i];
						Type decl_type = candidate.DeclaringType;

						if (decl_type == applicable_type) {
							candidates [k++] = candidates [j];
							candidates [j++] = candidates [i];
							continue;
						}

						if (IsAncestralType (decl_type, applicable_type))
							continue;

						if (next_applicable_type != null &&
							IsAncestralType (decl_type, next_applicable_type))
							continue;

						candidates [k++] = candidates [i];

						if (next_applicable_type == null ||
							IsAncestralType (next_applicable_type, decl_type))
							next_applicable_type = decl_type;
					}

					applicable_type = next_applicable_type;
					finalized = j;
					candidate_top = k;
				} while (applicable_type != null);
			}

			//
			// Now we actually find the best method
			//

			best_candidate = (MethodBase) candidates [0];
			method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);

			//
			// TODO: Broken inverse order of candidates logic does not work with optional
			// parameters used for method overrides and I am not going to fix it for SRE
			//
			if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) {
				candidate_args = (Arguments) candidates_expanded [best_candidate];
				arg_count = candidate_args.Count;
			}

			for (int ix = 1; ix < candidate_top; ix++) {
				MethodBase candidate = (MethodBase) candidates [ix];

				if (candidate == best_candidate)
					continue;

				bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);

				if (BetterFunction (ec, candidate_args, arg_count, 
					candidate, cand_params,
					best_candidate, method_params)) {
					best_candidate = candidate;
					method_params = cand_params;
				}
			}
			//
			// Now check that there are no ambiguities i.e the selected method
			// should be better than all the others
			//
			MethodBase ambiguous = null;
			for (int ix = 1; ix < candidate_top; ix++) {
				MethodBase candidate = (MethodBase) candidates [ix];

				if (candidate == best_candidate)
					continue;

				bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
				if (!BetterFunction (ec, candidate_args, arg_count,
					best_candidate, method_params,
					candidate, cand_params)) 
				{
					if (!may_fail)
						ec.Report.SymbolRelatedToPreviousError (candidate);
					ambiguous = candidate;
				}
			}

			if (ambiguous != null) {
				Error_AmbiguousCall (ec, ambiguous);
				return this;
			}

			//
			// If the method is a virtual function, pick an override closer to the LHS type.
			//
			if (!IsBase && best_candidate.IsVirtual) {
				if (TypeManager.IsOverride (best_candidate))
					throw new InternalErrorException (
						"Should not happen.  An 'override' method took part in overload resolution: " + best_candidate);

				if (candidate_overrides != null) {
					Type[] gen_args = null;
					bool gen_override = false;
					if (TypeManager.IsGenericMethod (best_candidate))
						gen_args = TypeManager.GetGenericArguments (best_candidate);

					foreach (MethodBase candidate in candidate_overrides) {
						if (TypeManager.IsGenericMethod (candidate)) {
							if (gen_args == null)
								continue;

							if (gen_args.Length != TypeManager.GetGenericArguments (candidate).Length)
								continue;
						} else {
							if (gen_args != null)
								continue;
						}
						
						if (IsOverride (candidate, best_candidate)) {
							gen_override = true;
							best_candidate = candidate;
						}
					}

					if (gen_override && gen_args != null) {
#if GMCS_SOURCE
						best_candidate = ((MethodInfo) best_candidate).MakeGenericMethod (gen_args);
#endif						
					}
				}
			}

			//
			// And now check if the arguments are all
			// compatible, perform conversions if
			// necessary etc. and return if everything is
			// all right
			//
			if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
				method_params, may_fail, loc))
				return null;

			if (best_candidate == null)
				return null;

			MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
			if (TypeManager.IsGenericMethodDefinition (the_method) &&
			    !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
				return null;

			//
			// Check ObsoleteAttribute on the best method
			//
			ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (the_method);
			if (oa != null && !ec.IsObsolete)
				AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);

			IMethodData data = TypeManager.GetMethod (the_method);
			if (data != null)
				data.SetMemberIsUsed ();

			Arguments = candidate_args;
			return this;
		}
Ejemplo n.º 10
0
		protected override Expression DoResolve (ResolveContext rc)
		{
			var sn = expr as SimpleName;
			const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;

			if (sn != null) {
				var errors_printer = new SessionReportPrinter ();
				var old = rc.Report.SetPrinter (errors_printer);
				try {
					expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
				} finally {
					rc.Report.SetPrinter (old);
				}

				if (errors_printer.ErrorsCount != 0)
					return null;

				//
				// Resolve expression which does have type set as we need expression type
				// with disable flow analysis as we don't know whether left side expression
				// is used as variable or type
				//
				if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
					expr = expr.Resolve (rc);
				} else if (expr is TypeParameterExpr) {
					expr.Error_UnexpectedKind (rc, flags, sn.Location);
					expr = null;
				}
			} else {
				expr = expr.Resolve (rc, flags);
			}

			if (expr == null)
				return null;

			TypeSpec expr_type = expr.Type;
			if (expr_type.IsPointer || expr_type.Kind == MemberKind.Void || expr_type == InternalType.NullLiteral || expr_type == InternalType.AnonymousMethod) {
				expr.Error_OperatorCannotBeApplied (rc, loc, ".", expr_type);
				return null;
			}

			if (targs != null) {
				if (!targs.Resolve (rc, true))
					return null;
			}

			var results = new List<string> ();
			var nexpr = expr as NamespaceExpression;
			if (nexpr != null) {
				string namespaced_partial;

				if (partial_name == null)
					namespaced_partial = nexpr.Namespace.Name;
				else
					namespaced_partial = nexpr.Namespace.Name + "." + partial_name;

				rc.CurrentMemberDefinition.GetCompletionStartingWith (namespaced_partial, results);
				if (partial_name != null)
					results = results.Select (l => l.Substring (partial_name.Length)).ToList ();
			} else {
				var r = MemberCache.GetCompletitionMembers (rc, expr_type, partial_name).Select (l => l.Name);
				AppendResults (results, partial_name, r);
			}

			throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ());
		}
Ejemplo n.º 11
0
        protected override Expression DoResolve(ResolveContext rc)
        {
            var sn = expr as SimpleName;
            const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;

            if (sn != null)
            {
                var errors_printer = new SessionReportPrinter();
                var old            = rc.Report.SetPrinter(errors_printer);
                try {
                    expr = sn.LookupNameExpression(rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
                } finally {
                    rc.Report.SetPrinter(old);
                }

                if (errors_printer.ErrorsCount != 0)
                {
                    return(null);
                }

                //
                // Resolve expression which does have type set as we need expression type
                // with disable flow analysis as we don't know whether left side expression
                // is used as variable or type
                //
                if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess)
                {
                    expr = expr.Resolve(rc);
                }
                else if (expr is TypeParameterExpr)
                {
                    expr.Error_UnexpectedKind(rc, flags, sn.Location);
                    expr = null;
                }
            }
            else
            {
                expr = expr.Resolve(rc, flags);
            }

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

            TypeSpec expr_type = expr.Type;

            if (expr_type.IsPointer || expr_type.Kind == MemberKind.Void || expr_type == InternalType.NullLiteral || expr_type == InternalType.AnonymousMethod)
            {
                expr.Error_OperatorCannotBeApplied(rc, loc, ".", expr_type);
                return(null);
            }

            if (targs != null)
            {
                if (!targs.Resolve(rc, true))
                {
                    return(null);
                }
            }

            var results = new List <string> ();
            var nexpr   = expr as NamespaceExpression;

            if (nexpr != null)
            {
                string namespaced_partial;

                if (partial_name == null)
                {
                    namespaced_partial = nexpr.Namespace.Name;
                }
                else
                {
                    namespaced_partial = nexpr.Namespace.Name + "." + partial_name;
                }

                rc.CurrentMemberDefinition.GetCompletionStartingWith(namespaced_partial, results);
                if (partial_name != null)
                {
                    results = results.Select(l => l.Substring(partial_name.Length)).ToList();
                }
            }
            else
            {
                var r = MemberCache.GetCompletitionMembers(rc, expr_type, partial_name).Select(l => l.Name);
                AppendResults(results, partial_name, r);
            }

            throw new CompletionResult(partial_name == null ? "" : partial_name, results.Distinct().ToArray());
        }