|
|
|
|
@ -2777,8 +2777,14 @@ namespace Mono.CSharp {
@@ -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 (targs == null && method.IsGeneric) { |
|
|
|
|
targs = method.TypeArguments; |
|
|
|
|
@ -2792,8 +2798,9 @@ namespace Mono.CSharp {
@@ -2792,8 +2798,9 @@ namespace Mono.CSharp {
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
// would be of 'this' and not 'base'
|
|
|
|
|
if (rc.CurrentType.IsStruct) |
|
|
|
|
// would be of 'this' and not 'base' because we share InstanceExpression for get/set
|
|
|
|
|
// 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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -2993,12 +3000,15 @@ namespace Mono.CSharp {
@@ -2993,12 +3000,15 @@ namespace Mono.CSharp {
|
|
|
|
|
if (me != null) { |
|
|
|
|
me.ResolveInstanceExpression (rc, rhs); |
|
|
|
|
|
|
|
|
|
var fe = me as FieldExpr; |
|
|
|
|
if (fe != null && fe.IsMarshalByRefAccess (rc)) { |
|
|
|
|
rc.Report.SymbolRelatedToPreviousError (me.DeclaringType); |
|
|
|
|
rc.Report.Warning (1690, 1, loc, |
|
|
|
|
"Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", |
|
|
|
|
me.GetSignatureForError ()); |
|
|
|
|
// Using this check to detect probing instance expression resolve
|
|
|
|
|
if (!rc.OmitStructFlowAnalysis) { |
|
|
|
|
var fe = me as FieldExpr; |
|
|
|
|
if (fe != null && fe.IsMarshalByRefAccess (rc)) { |
|
|
|
|
rc.Report.SymbolRelatedToPreviousError (me.DeclaringType); |
|
|
|
|
rc.Report.Warning (1690, 1, loc, |
|
|
|
|
"Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", |
|
|
|
|
me.GetSignatureForError ()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
@ -3587,7 +3597,6 @@ namespace Mono.CSharp {
@@ -3587,7 +3597,6 @@ namespace Mono.CSharp {
|
|
|
|
|
TypeSpec best_candidate_return_type; |
|
|
|
|
|
|
|
|
|
SessionReportPrinter lambda_conv_msgs; |
|
|
|
|
ReportPrinter prev_recorder; |
|
|
|
|
|
|
|
|
|
public OverloadResolver (IList<MemberSpec> members, Restrictions restrictions, Location loc) |
|
|
|
|
: this (members, null, restrictions, loc) |
|
|
|
|
@ -4045,6 +4054,7 @@ namespace Mono.CSharp {
@@ -4045,6 +4054,7 @@ namespace Mono.CSharp {
|
|
|
|
|
//
|
|
|
|
|
// A return value rates candidate method compatibility,
|
|
|
|
|
// 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) |
|
|
|
|
{ |
|
|
|
|
@ -4166,6 +4176,18 @@ namespace Mono.CSharp {
@@ -4166,6 +4176,18 @@ namespace Mono.CSharp {
|
|
|
|
|
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
|
|
|
|
|
//
|
|
|
|
|
@ -4182,20 +4204,41 @@ namespace Mono.CSharp {
@@ -4182,20 +4204,41 @@ namespace Mono.CSharp {
|
|
|
|
|
|
|
|
|
|
ms = ms.MakeGenericMethod (ec, type_arguments.Arguments); |
|
|
|
|
} 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) { |
|
|
|
|
lambda_conv_msgs = new SessionReportPrinter (); |
|
|
|
|
prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs); |
|
|
|
|
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 (); |
|
|
|
|
|
|
|
|
|
am.TypeInferenceReportPrinter = lambda_conv_msgs; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ti = new TypeInference (arguments); |
|
|
|
|
TypeSpec[] i_args = ti.InferMethodArguments (ec, ms); |
|
|
|
|
lambda_conv_msgs.EndSession (); |
|
|
|
|
|
|
|
|
|
if (i_args == null) |
|
|
|
|
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) { |
|
|
|
|
ms = ms.MakeGenericMethod (ec, i_args); |
|
|
|
|
} |
|
|
|
|
@ -4403,28 +4446,11 @@ namespace Mono.CSharp {
@@ -4403,28 +4446,11 @@ namespace Mono.CSharp {
|
|
|
|
|
if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0) |
|
|
|
|
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
|
|
|
|
|
// is used as argument or delegate conversion
|
|
|
|
|
//
|
|
|
|
|
if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) { |
|
|
|
|
if (lambda_conv_msgs != null) { |
|
|
|
|
lambda_conv_msgs.EndSession (); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 2; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -4494,147 +4520,148 @@ namespace Mono.CSharp {
@@ -4494,147 +4520,148 @@ namespace Mono.CSharp {
|
|
|
|
|
bool error_mode = false; |
|
|
|
|
MemberSpec invocable_member = null; |
|
|
|
|
|
|
|
|
|
// Be careful, cannot return until error reporter is restored
|
|
|
|
|
while (true) { |
|
|
|
|
best_candidate = null; |
|
|
|
|
best_candidate_rate = int.MaxValue; |
|
|
|
|
|
|
|
|
|
var type_members = members; |
|
|
|
|
try { |
|
|
|
|
do { |
|
|
|
|
for (int i = 0; i < type_members.Count; ++i) { |
|
|
|
|
var member = type_members[i]; |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Methods in a base class are not candidates if any method in a derived
|
|
|
|
|
// class is applicable
|
|
|
|
|
//
|
|
|
|
|
if ((member.Modifiers & Modifiers.OVERRIDE) != 0) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (!error_mode) { |
|
|
|
|
if (!member.IsAccessible (rc)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
for (int i = 0; i < type_members.Count; ++i) { |
|
|
|
|
var member = type_members[i]; |
|
|
|
|
if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if ((member.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED && |
|
|
|
|
instance_qualifier != null && !instance_qualifier.CheckProtectedMemberAccess (rc, member)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IParametersMember pm = member as IParametersMember; |
|
|
|
|
if (pm == null) { |
|
|
|
|
//
|
|
|
|
|
// Methods in a base class are not candidates if any method in a derived
|
|
|
|
|
// class is applicable
|
|
|
|
|
// Will use it later to report ambiguity between best method and invocable member
|
|
|
|
|
//
|
|
|
|
|
if ((member.Modifiers & Modifiers.OVERRIDE) != 0) |
|
|
|
|
continue; |
|
|
|
|
if (Invocation.IsMemberInvocable (member)) |
|
|
|
|
invocable_member = member; |
|
|
|
|
|
|
|
|
|
if (!error_mode) { |
|
|
|
|
if (!member.IsAccessible (rc)) |
|
|
|
|
continue; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc)) |
|
|
|
|
continue; |
|
|
|
|
//
|
|
|
|
|
// Overload resolution is looking for base member but using parameter names
|
|
|
|
|
// and default values from the closest member. That means to do expensive lookup
|
|
|
|
|
// for the closest override for virtual or abstract members
|
|
|
|
|
//
|
|
|
|
|
if ((member.Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) { |
|
|
|
|
var override_params = base_provider.GetOverrideMemberParameters (member); |
|
|
|
|
if (override_params != null) |
|
|
|
|
pm = override_params; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((member.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED && |
|
|
|
|
instance_qualifier != null && !instance_qualifier.CheckProtectedMemberAccess (rc, member)) { |
|
|
|
|
//
|
|
|
|
|
// Check if the member candidate is applicable
|
|
|
|
|
//
|
|
|
|
|
bool params_expanded_form = false; |
|
|
|
|
bool dynamic_argument = false; |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
if (lambda_conv_msgs != null) |
|
|
|
|
lambda_conv_msgs.EndSession (); |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// How does it score compare to others
|
|
|
|
|
//
|
|
|
|
|
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 = member; |
|
|
|
|
best_candidate_args = candidate_args; |
|
|
|
|
best_candidate_params = params_expanded_form; |
|
|
|
|
best_candidate_dynamic = dynamic_argument; |
|
|
|
|
best_parameter_member = pm; |
|
|
|
|
best_candidate_return_type = rt; |
|
|
|
|
} else if (candidate_rate == 0) { |
|
|
|
|
//
|
|
|
|
|
// The member look is done per type for most operations but sometimes
|
|
|
|
|
// it's not possible like for binary operators overload because they
|
|
|
|
|
// are unioned between 2 sides
|
|
|
|
|
//
|
|
|
|
|
if ((restrictions & Restrictions.BaseMembersIncluded) != 0) { |
|
|
|
|
if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true)) |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IParametersMember pm = member as IParametersMember; |
|
|
|
|
if (pm == null) { |
|
|
|
|
bool is_better; |
|
|
|
|
if (best_candidate.DeclaringType.IsInterface && member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { |
|
|
|
|
//
|
|
|
|
|
// Will use it later to report ambiguity between best method and invocable member
|
|
|
|
|
// We pack all interface members into top level type which makes the overload resolution
|
|
|
|
|
// more complicated for interfaces. We compensate it by removing methods with same
|
|
|
|
|
// signature when building the cache hence this path should not really be hit often
|
|
|
|
|
//
|
|
|
|
|
if (Invocation.IsMemberInvocable (member)) |
|
|
|
|
invocable_member = member; |
|
|
|
|
// Example:
|
|
|
|
|
// interface IA { void Foo (int arg); }
|
|
|
|
|
// interface IB : IA { void Foo (params int[] args); }
|
|
|
|
|
//
|
|
|
|
|
// IB::Foo is the best overload when calling IB.Foo (1)
|
|
|
|
|
//
|
|
|
|
|
is_better = true; |
|
|
|
|
if (ambiguous_candidates != null) { |
|
|
|
|
foreach (var amb_cand in ambiguous_candidates) { |
|
|
|
|
if (member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
is_better = false; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Overload resolution is looking for base member but using parameter names
|
|
|
|
|
// and default values from the closest member. That means to do expensive lookup
|
|
|
|
|
// for the closest override for virtual or abstract members
|
|
|
|
|
//
|
|
|
|
|
if ((member.Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) { |
|
|
|
|
var override_params = base_provider.GetOverrideMemberParameters (member); |
|
|
|
|
if (override_params != null) |
|
|
|
|
pm = override_params; |
|
|
|
|
if (is_better) |
|
|
|
|
ambiguous_candidates = null; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Is the new candidate better
|
|
|
|
|
is_better = BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Check if the member candidate is applicable
|
|
|
|
|
//
|
|
|
|
|
bool params_expanded_form = false; |
|
|
|
|
bool dynamic_argument = false; |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// How does it score compare to others
|
|
|
|
|
//
|
|
|
|
|
if (candidate_rate < best_candidate_rate) { |
|
|
|
|
best_candidate_rate = candidate_rate; |
|
|
|
|
if (is_better) { |
|
|
|
|
best_candidate = member; |
|
|
|
|
best_candidate_args = candidate_args; |
|
|
|
|
best_candidate_params = params_expanded_form; |
|
|
|
|
best_candidate_dynamic = dynamic_argument; |
|
|
|
|
best_parameter_member = pm; |
|
|
|
|
best_candidate_return_type = rt; |
|
|
|
|
} else if (candidate_rate == 0) { |
|
|
|
|
//
|
|
|
|
|
// The member look is done per type for most operations but sometimes
|
|
|
|
|
// it's not possible like for binary operators overload because they
|
|
|
|
|
// are unioned between 2 sides
|
|
|
|
|
//
|
|
|
|
|
if ((restrictions & Restrictions.BaseMembersIncluded) != 0) { |
|
|
|
|
if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true)) |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool is_better; |
|
|
|
|
if (best_candidate.DeclaringType.IsInterface && member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { |
|
|
|
|
//
|
|
|
|
|
// We pack all interface members into top level type which makes the overload resolution
|
|
|
|
|
// more complicated for interfaces. We compensate it by removing methods with same
|
|
|
|
|
// signature when building the cache hence this path should not really be hit often
|
|
|
|
|
//
|
|
|
|
|
// Example:
|
|
|
|
|
// interface IA { void Foo (int arg); }
|
|
|
|
|
// interface IB : IA { void Foo (params int[] args); }
|
|
|
|
|
//
|
|
|
|
|
// IB::Foo is the best overload when calling IB.Foo (1)
|
|
|
|
|
//
|
|
|
|
|
is_better = true; |
|
|
|
|
if (ambiguous_candidates != null) { |
|
|
|
|
foreach (var amb_cand in ambiguous_candidates) { |
|
|
|
|
if (member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
is_better = false; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (is_better) |
|
|
|
|
ambiguous_candidates = null; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Is the new candidate better
|
|
|
|
|
is_better = BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// It's not better but any other found later could be but we are not sure yet
|
|
|
|
|
if (ambiguous_candidates == null) |
|
|
|
|
ambiguous_candidates = new List<AmbiguousCandidate> (); |
|
|
|
|
|
|
|
|
|
if (is_better) { |
|
|
|
|
best_candidate = member; |
|
|
|
|
best_candidate_args = candidate_args; |
|
|
|
|
best_candidate_params = params_expanded_form; |
|
|
|
|
best_candidate_dynamic = dynamic_argument; |
|
|
|
|
best_parameter_member = pm; |
|
|
|
|
best_candidate_return_type = rt; |
|
|
|
|
} else { |
|
|
|
|
// It's not better but any other found later could be but we are not sure yet
|
|
|
|
|
if (ambiguous_candidates == null) |
|
|
|
|
ambiguous_candidates = new List<AmbiguousCandidate> (); |
|
|
|
|
|
|
|
|
|
ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form)); |
|
|
|
|
} |
|
|
|
|
ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Restore expanded arguments
|
|
|
|
|
if (candidate_args != args) |
|
|
|
|
candidate_args = args; |
|
|
|
|
} |
|
|
|
|
} 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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Restore expanded arguments
|
|
|
|
|
if (candidate_args != args) |
|
|
|
|
candidate_args = args; |
|
|
|
|
} |
|
|
|
|
} while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null); |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// We've found exact match
|
|
|
|
|
@ -4744,11 +4771,6 @@ namespace Mono.CSharp {
@@ -4744,11 +4771,6 @@ namespace Mono.CSharp {
|
|
|
|
|
if (oa != null && !rc.IsObsolete) |
|
|
|
|
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 (); |
|
|
|
|
|
|
|
|
|
args = best_candidate_args; |
|
|
|
|
@ -4825,9 +4847,8 @@ namespace Mono.CSharp {
@@ -4825,9 +4847,8 @@ namespace Mono.CSharp {
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (lambda_conv_msgs != null) { |
|
|
|
|
if (lambda_conv_msgs.Merge (rc.Report.Printer)) |
|
|
|
|
return; |
|
|
|
|
if (lambda_conv_msgs != null && lambda_conv_msgs.Merge (rc.Report.Printer)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -5279,7 +5300,7 @@ namespace Mono.CSharp {
@@ -5279,7 +5300,7 @@ namespace Mono.CSharp {
|
|
|
|
|
if (lvalue_instance && var != null && var.VariableInfo != null) { |
|
|
|
|
var.VariableInfo.SetStructFieldAssigned (ec, Name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fb != null) { |
|
|
|
|
IFixedExpression fe = InstanceExpression as IFixedExpression; |
|
|
|
|
if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) { |
|
|
|
|
|