|
|
|
@ -2777,8 +2777,14 @@ namespace Mono.CSharp { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO: For now we do it for any hoisted call even if it's needed for
|
|
|
|
//
|
|
|
|
// hoisted stories only but that requires a new expression wrapper
|
|
|
|
// When base access is used inside anonymous method/iterator/etc we need to
|
|
|
|
|
|
|
|
// get back to the context of original type. We do it by emiting proxy
|
|
|
|
|
|
|
|
// method in original class and rewriting base call to this compiler
|
|
|
|
|
|
|
|
// generated method call which does the actual base invocation. This may
|
|
|
|
|
|
|
|
// introduce redundant storey but with `this' only but it's tricky to avoid
|
|
|
|
|
|
|
|
// at this stage as we don't know what expressions follow base
|
|
|
|
|
|
|
|
//
|
|
|
|
if (rc.CurrentAnonymousMethod != null) { |
|
|
|
if (rc.CurrentAnonymousMethod != null) { |
|
|
|
if (targs == null && method.IsGeneric) { |
|
|
|
if (targs == null && method.IsGeneric) { |
|
|
|
targs = method.TypeArguments; |
|
|
|
targs = method.TypeArguments; |
|
|
|
@ -2792,8 +2798,9 @@ namespace Mono.CSharp { |
|
|
|
|
|
|
|
|
|
|
|
// Ideally this should apply to any proxy rewrite but in the case of unary mutators on
|
|
|
|
// Ideally this should apply to any proxy rewrite but in the case of unary mutators on
|
|
|
|
// get/set member expressions second call would fail to proxy because left expression
|
|
|
|
// get/set member expressions second call would fail to proxy because left expression
|
|
|
|
// would be of 'this' and not 'base'
|
|
|
|
// would be of 'this' and not 'base' because we share InstanceExpression for get/set
|
|
|
|
if (rc.CurrentType.IsStruct) |
|
|
|
// FIXME: The async check is another hack but will probably fail with mutators
|
|
|
|
|
|
|
|
if (rc.CurrentType.IsStruct || rc.CurrentAnonymousMethod.Storey is AsyncTaskStorey) |
|
|
|
InstanceExpression = new This (loc).Resolve (rc); |
|
|
|
InstanceExpression = new This (loc).Resolve (rc); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -2993,6 +3000,8 @@ namespace Mono.CSharp { |
|
|
|
if (me != null) { |
|
|
|
if (me != null) { |
|
|
|
me.ResolveInstanceExpression (rc, rhs); |
|
|
|
me.ResolveInstanceExpression (rc, rhs); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Using this check to detect probing instance expression resolve
|
|
|
|
|
|
|
|
if (!rc.OmitStructFlowAnalysis) { |
|
|
|
var fe = me as FieldExpr; |
|
|
|
var fe = me as FieldExpr; |
|
|
|
if (fe != null && fe.IsMarshalByRefAccess (rc)) { |
|
|
|
if (fe != null && fe.IsMarshalByRefAccess (rc)) { |
|
|
|
rc.Report.SymbolRelatedToPreviousError (me.DeclaringType); |
|
|
|
rc.Report.SymbolRelatedToPreviousError (me.DeclaringType); |
|
|
|
@ -3000,6 +3009,7 @@ namespace Mono.CSharp { |
|
|
|
"Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", |
|
|
|
"Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", |
|
|
|
me.GetSignatureForError ()); |
|
|
|
me.GetSignatureForError ()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -3587,7 +3597,6 @@ namespace Mono.CSharp { |
|
|
|
TypeSpec best_candidate_return_type; |
|
|
|
TypeSpec best_candidate_return_type; |
|
|
|
|
|
|
|
|
|
|
|
SessionReportPrinter lambda_conv_msgs; |
|
|
|
SessionReportPrinter lambda_conv_msgs; |
|
|
|
ReportPrinter prev_recorder; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public OverloadResolver (IList<MemberSpec> members, Restrictions restrictions, Location loc) |
|
|
|
public OverloadResolver (IList<MemberSpec> members, Restrictions restrictions, Location loc) |
|
|
|
: this (members, null, restrictions, loc) |
|
|
|
: this (members, null, restrictions, loc) |
|
|
|
@ -4045,6 +4054,7 @@ namespace Mono.CSharp { |
|
|
|
//
|
|
|
|
//
|
|
|
|
// A return value rates candidate method compatibility,
|
|
|
|
// A return value rates candidate method compatibility,
|
|
|
|
// 0 = the best, int.MaxValue = the worst
|
|
|
|
// 0 = the best, int.MaxValue = the worst
|
|
|
|
|
|
|
|
// -1 = fatal error
|
|
|
|
//
|
|
|
|
//
|
|
|
|
int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, IParametersMember pm, ref bool params_expanded_form, ref bool dynamicArgument, ref TypeSpec returnType) |
|
|
|
int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, IParametersMember pm, ref bool params_expanded_form, ref bool dynamicArgument, ref TypeSpec returnType) |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -4166,6 +4176,18 @@ namespace Mono.CSharp { |
|
|
|
arg_count = arguments.Count; |
|
|
|
arg_count = arguments.Count; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Don't do any expensive checks when the candidate cannot succeed
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
if (arg_count != param_count && !cpd.HasParams) |
|
|
|
|
|
|
|
return (param_count - arg_count) * 2 + 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var dep = candidate.GetMissingDependencies (); |
|
|
|
|
|
|
|
if (dep != null) { |
|
|
|
|
|
|
|
ImportedTypeDefinition.Error_MissingDependency (ec, dep, loc); |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// 1. Handle generic method using type arguments when specified or type inference
|
|
|
|
// 1. Handle generic method using type arguments when specified or type inference
|
|
|
|
//
|
|
|
|
//
|
|
|
|
@ -4182,20 +4204,41 @@ namespace Mono.CSharp { |
|
|
|
|
|
|
|
|
|
|
|
ms = ms.MakeGenericMethod (ec, type_arguments.Arguments); |
|
|
|
ms = ms.MakeGenericMethod (ec, type_arguments.Arguments); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// TODO: It should not be here (we don't know yet whether any argument is lambda) but
|
|
|
|
//
|
|
|
|
// for now it simplifies things. I should probably add a callback to ResolveContext
|
|
|
|
// Deploy custom error reporting for infered anonymous expression or lambda methods. When
|
|
|
|
|
|
|
|
// probing lambda methods keep all errors reported in separate set and once we are done and no best
|
|
|
|
|
|
|
|
// candidate was found use the set to report more details about what was wrong with lambda body.
|
|
|
|
|
|
|
|
// The general idea is to distinguish between code errors and errors caused by
|
|
|
|
|
|
|
|
// trial-and-error type inference
|
|
|
|
|
|
|
|
//
|
|
|
|
if (lambda_conv_msgs == null) { |
|
|
|
if (lambda_conv_msgs == null) { |
|
|
|
|
|
|
|
for (int i = 0; i < arg_count; i++) { |
|
|
|
|
|
|
|
Argument a = arguments[i]; |
|
|
|
|
|
|
|
if (a == null) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var am = a.Expr as AnonymousMethodExpression; |
|
|
|
|
|
|
|
if (am != null) { |
|
|
|
|
|
|
|
if (lambda_conv_msgs == null) |
|
|
|
lambda_conv_msgs = new SessionReportPrinter (); |
|
|
|
lambda_conv_msgs = new SessionReportPrinter (); |
|
|
|
prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs); |
|
|
|
|
|
|
|
|
|
|
|
am.TypeInferenceReportPrinter = lambda_conv_msgs; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var ti = new TypeInference (arguments); |
|
|
|
var ti = new TypeInference (arguments); |
|
|
|
TypeSpec[] i_args = ti.InferMethodArguments (ec, ms); |
|
|
|
TypeSpec[] i_args = ti.InferMethodArguments (ec, ms); |
|
|
|
lambda_conv_msgs.EndSession (); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (i_args == null) |
|
|
|
if (i_args == null) |
|
|
|
return ti.InferenceScore - 20000; |
|
|
|
return ti.InferenceScore - 20000; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Clear any error messages when the result was success
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
if (lambda_conv_msgs != null) |
|
|
|
|
|
|
|
lambda_conv_msgs.ClearSession (); |
|
|
|
|
|
|
|
|
|
|
|
if (i_args.Length != 0) { |
|
|
|
if (i_args.Length != 0) { |
|
|
|
ms = ms.MakeGenericMethod (ec, i_args); |
|
|
|
ms = ms.MakeGenericMethod (ec, i_args); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -4403,28 +4446,11 @@ namespace Mono.CSharp { |
|
|
|
if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0) |
|
|
|
if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Deploy custom error reporting for lambda methods. When probing lambda methods
|
|
|
|
|
|
|
|
// keep all errors reported in separate set and once we are done and no best
|
|
|
|
|
|
|
|
// candidate was found, this set is used to report more details about what was wrong
|
|
|
|
|
|
|
|
// with lambda body
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
if (argument.Expr.Type == InternalType.AnonymousMethod) { |
|
|
|
|
|
|
|
if (lambda_conv_msgs == null) { |
|
|
|
|
|
|
|
lambda_conv_msgs = new SessionReportPrinter (); |
|
|
|
|
|
|
|
prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Use implicit conversion in all modes to return same candidates when the expression
|
|
|
|
// Use implicit conversion in all modes to return same candidates when the expression
|
|
|
|
// is used as argument or delegate conversion
|
|
|
|
// is used as argument or delegate conversion
|
|
|
|
//
|
|
|
|
//
|
|
|
|
if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) { |
|
|
|
if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) { |
|
|
|
if (lambda_conv_msgs != null) { |
|
|
|
|
|
|
|
lambda_conv_msgs.EndSession (); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 2; |
|
|
|
return 2; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -4494,14 +4520,11 @@ namespace Mono.CSharp { |
|
|
|
bool error_mode = false; |
|
|
|
bool error_mode = false; |
|
|
|
MemberSpec invocable_member = null; |
|
|
|
MemberSpec invocable_member = null; |
|
|
|
|
|
|
|
|
|
|
|
// Be careful, cannot return until error reporter is restored
|
|
|
|
|
|
|
|
while (true) { |
|
|
|
while (true) { |
|
|
|
best_candidate = null; |
|
|
|
best_candidate = null; |
|
|
|
best_candidate_rate = int.MaxValue; |
|
|
|
best_candidate_rate = int.MaxValue; |
|
|
|
|
|
|
|
|
|
|
|
var type_members = members; |
|
|
|
var type_members = members; |
|
|
|
try { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do { |
|
|
|
do { |
|
|
|
for (int i = 0; i < type_members.Count; ++i) { |
|
|
|
for (int i = 0; i < type_members.Count; ++i) { |
|
|
|
var member = type_members[i]; |
|
|
|
var member = type_members[i]; |
|
|
|
@ -4556,10 +4579,18 @@ namespace Mono.CSharp { |
|
|
|
TypeSpec rt = pm.MemberType; |
|
|
|
TypeSpec rt = pm.MemberType; |
|
|
|
int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt); |
|
|
|
int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lambda_conv_msgs != null) |
|
|
|
|
|
|
|
lambda_conv_msgs.EndSession (); |
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// How does it score compare to others
|
|
|
|
// How does it score compare to others
|
|
|
|
//
|
|
|
|
//
|
|
|
|
if (candidate_rate < best_candidate_rate) { |
|
|
|
if (candidate_rate < best_candidate_rate) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fatal error (missing dependency), cannot continue
|
|
|
|
|
|
|
|
if (candidate_rate < 0) |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
|
|
|
|
best_candidate_rate = candidate_rate; |
|
|
|
best_candidate_rate = candidate_rate; |
|
|
|
best_candidate = member; |
|
|
|
best_candidate = member; |
|
|
|
best_candidate_args = candidate_args; |
|
|
|
best_candidate_args = candidate_args; |
|
|
|
@ -4631,10 +4662,6 @@ namespace Mono.CSharp { |
|
|
|
candidate_args = args; |
|
|
|
candidate_args = args; |
|
|
|
} |
|
|
|
} |
|
|
|
} while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null); |
|
|
|
} while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null); |
|
|
|
} finally { |
|
|
|
|
|
|
|
if (prev_recorder != null) |
|
|
|
|
|
|
|
rc.Report.SetPrinter (prev_recorder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// We've found exact match
|
|
|
|
// We've found exact match
|
|
|
|
@ -4744,11 +4771,6 @@ namespace Mono.CSharp { |
|
|
|
if (oa != null && !rc.IsObsolete) |
|
|
|
if (oa != null && !rc.IsObsolete) |
|
|
|
AttributeTester.Report_ObsoleteMessage (oa, best_candidate.GetSignatureForError (), loc, rc.Report); |
|
|
|
AttributeTester.Report_ObsoleteMessage (oa, best_candidate.GetSignatureForError (), loc, rc.Report); |
|
|
|
|
|
|
|
|
|
|
|
var dep = best_candidate.GetMissingDependencies (); |
|
|
|
|
|
|
|
if (dep != null) { |
|
|
|
|
|
|
|
ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
best_candidate.MemberDefinition.SetIsUsed (); |
|
|
|
best_candidate.MemberDefinition.SetIsUsed (); |
|
|
|
|
|
|
|
|
|
|
|
args = best_candidate_args; |
|
|
|
args = best_candidate_args; |
|
|
|
@ -4825,8 +4847,7 @@ namespace Mono.CSharp { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (lambda_conv_msgs != null) { |
|
|
|
if (lambda_conv_msgs != null && lambda_conv_msgs.Merge (rc.Report.Printer)) { |
|
|
|
if (lambda_conv_msgs.Merge (rc.Report.Printer)) |
|
|
|
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|