public override Expression DoResolve(ResolveContext ec) { // Field initializer can be resolved (fail) many times if (source == null) { return(null); } if (resolved == null) { // // Field initializers are tricky for partial classes. They have to // share same costructor (block) but they have they own resolve scope. // IMemberContext old = ec.MemberContext; ec.MemberContext = rc; using (ec.Set(ResolveContext.Options.FieldInitializerScope)) { resolved = base.DoResolve(ec) as ExpressionStatement; } ec.MemberContext = old; } return(resolved); }
protected override Expression DoResolve(ResolveContext ec) { constructor_method = Delegate.GetConstructor(type); var invoke_method = Delegate.GetInvokeMethod(type); if (!ec.HasSet(ResolveContext.Options.ConditionalAccessReceiver)) { if (method_group.HasConditionalAccess()) { conditional_access_receiver = true; ec.Set(ResolveContext.Options.ConditionalAccessReceiver); } } Arguments arguments = CreateDelegateMethodArguments(ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc); method_group = method_group.OverloadResolve(ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate); if (conditional_access_receiver) { ec.With(ResolveContext.Options.ConditionalAccessReceiver, false); } if (method_group == null) { return(null); } var delegate_method = method_group.BestCandidate; if (delegate_method.DeclaringType.IsNullableType) { ec.Report.Error(1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type", delegate_method.GetSignatureForError()); return(null); } if (!AllowSpecialMethodsInvocation) { Invocation.IsSpecialMethodInvocation(ec, delegate_method, loc); } ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; if (emg != null) { method_group.InstanceExpression = emg.ExtensionExpression; TypeSpec e_type = emg.ExtensionExpression.Type; if (TypeSpec.IsValueType(e_type)) { ec.Report.Error(1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates", delegate_method.GetSignatureForError(), e_type.GetSignatureForError()); } } TypeSpec rt = method_group.BestCandidateReturnType; if (rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { rt = ec.BuiltinTypes.Object; } if (!Delegate.IsTypeCovariant(ec, rt, invoke_method.ReturnType)) { Expression ret_expr = new TypeExpression(delegate_method.ReturnType, loc); Error_ConversionFailed(ec, delegate_method, ret_expr); } if (method_group.IsConditionallyExcluded) { ec.Report.SymbolRelatedToPreviousError(delegate_method); MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator; if (m != null && m.IsPartialDefinition) { ec.Report.Error(762, loc, "Cannot create delegate from partial method declaration `{0}'", delegate_method.GetSignatureForError()); } else { ec.Report.Error(1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature(delegate_method)); } } var expr = method_group.InstanceExpression; if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType(expr.Type))) { method_group.InstanceExpression = new BoxedCast(expr, ec.BuiltinTypes.Object); } eclass = ExprClass.Value; return(this); }
public override Expression DoResolve(ResolveContext ec) { right = right.Resolve(ec); if (right == null) { return(null); } MemberAccess ma = target as MemberAccess; using (ec.Set(ResolveContext.Options.CompoundAssignmentScope)) { target = target.Resolve(ec); } if (target == null) { return(null); } if (target is MethodGroupExpr) { ec.Report.Error(1656, loc, "Cannot assign to `{0}' because it is a `{1}'", ((MethodGroupExpr)target).Name, target.ExprClassName); return(null); } if (target is EventExpr) { return(new EventAddOrRemove(target, op, right, loc).DoResolve(ec)); } // // Only now we can decouple the original source/target // into a tree, to guarantee that we do not have side // effects. // if (left == null) { left = new TargetExpression(target); } source = new Binary(op, left, right, true); // TODO: TargetExpression breaks MemberAccess composition if (target is DynamicMemberBinder) { Arguments targs = ((DynamicMemberBinder)target).Arguments; source = source.Resolve(ec); Arguments args = new Arguments(2); args.AddRange(targs); args.Add(new Argument(source)); source = new DynamicMemberBinder(true, ma.Name, args, loc).Resolve(ec); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments(2); args.AddRange(targs); args.Add(new Argument(right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; Expression invoke = new DynamicInvocation( new MemberAccess(right, method_prefix + ma.Name, loc), args, loc).Resolve(ec); args = new Arguments(1); args.AddRange(targs); source = new DynamicEventCompoundAssign(ma.Name, args, (ExpressionStatement)source, (ExpressionStatement)invoke, loc).Resolve(ec); } return(source); } return(base.DoResolve(ec)); }
// // 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); } } 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; }
protected override Expression DoResolve (ResolveContext ec) { eclass = ExprClass.Value; // FIXME: Hack var caller_builder = (Constructor) ec.MemberContext; // // Spec mandates that constructor initializer will not have `this' access // using (ec.Set (ResolveContext.Options.BaseInitializer)) { if (argument_list != null) { bool dynamic; argument_list.Resolve (ec, out dynamic); // If actionscript, convert dynamic constructor arguments to type System.Object. if (dynamic && ec.FileType == SourceFileType.PlayScript) { var ctors = MemberCache.FindMembers (ec.CurrentType.BaseType, Constructor.ConstructorName, true); if (ctors != null) { if (argument_list.AsTryResolveDynamicArgs(ec, ctors)) { dynamic = false; } } } if (dynamic) { ec.Report.Error (1975, loc, "The constructor call cannot be dynamically dispatched within constructor initializer"); return null; } } type = ec.CurrentType; if (this is ConstructorBaseInitializer) { if (ec.CurrentType.BaseType == null) return this; type = ec.CurrentType.BaseType; if (ec.CurrentType.IsStruct) { ec.Report.Error (522, loc, "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ()); return this; } } else { // // It is legal to have "this" initializers that take no arguments // in structs, they are just no-ops. // // struct D { public D (int a) : this () {} // if (ec.CurrentType.IsStruct && argument_list == null) return this; } base_ctor = ConstructorLookup (ec, type, ref argument_list, loc); } if (base_ctor != null && base_ctor.MemberDefinition == caller_builder.Spec.MemberDefinition) { ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", caller_builder.GetSignatureForError ()); } return this; }
protected override Expression DoResolve (ResolveContext ec) { right = right.Resolve (ec); if (right == null) return null; MemberAccess ma = target as MemberAccess; using (ec.Set (ResolveContext.Options.CompoundAssignmentScope)) { target = target.Resolve (ec); } if (target == null) return null; if (target is MethodGroupExpr){ ec.Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'", ((MethodGroupExpr)target).Name, target.ExprClassName); return null; } var event_expr = target as EventExpr; if (event_expr != null) { source = Convert.ImplicitConversionRequired (ec, right, target.Type, loc); if (source == null) return null; Expression rside; if (op == Binary.Operator.Addition) rside = EmptyExpression.EventAddition; else if (op == Binary.Operator.Subtraction) rside = EmptyExpression.EventSubtraction; else rside = null; target = target.ResolveLValue (ec, rside); if (target == null) return null; eclass = ExprClass.Value; type = event_expr.Operator.ReturnType; return this; } // // Only now we can decouple the original source/target // into a tree, to guarantee that we do not have side // effects. // if (left == null) left = new TargetExpression (target); source = new Binary (op, left, right, true); if (target is DynamicMemberAssignable) { Arguments targs = ((DynamicMemberAssignable) target).Arguments; source = source.Resolve (ec); Arguments args = new Arguments (targs.Count + 1); args.AddRange (targs); args.Add (new Argument (source)); var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment; // // Compound assignment does target conversion using additional method // call, set checked context as the binary operation can overflow // if (ec.HasSet (ResolveContext.Options.CheckedScope)) binder_flags |= CSharpBinderFlags.CheckedContext; if (target is DynamicMemberBinder) { source = new DynamicMemberBinder (ma.Name, binder_flags, args, loc).Resolve (ec); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments (targs.Count + 1); args.AddRange (targs); args.Add (new Argument (right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; var invoke = DynamicInvocation.CreateSpecialNameInvoke ( new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec); args = new Arguments (targs.Count); args.AddRange (targs); source = new DynamicEventCompoundAssign (ma.Name, args, (ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec); } } else { source = new DynamicIndexBinder (binder_flags, args, loc).Resolve (ec); } return source; } return base.DoResolve (ec); }
// // Returns true if the body of lambda expression can be implicitly // converted to the delegate of type `delegate_type' // public bool ImplicitStandardConversionExists (ResolveContext ec, TypeSpec delegate_type) { using (ec.With (ResolveContext.Options.InferReturnType, false)) { using (ec.Set (ResolveContext.Options.ProbingMode)) { return Compatible (ec, delegate_type) != null; } } }
public TypeSpec InferReturnType (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) { Expression expr; AnonymousExpression am; if (compatibles.TryGetValue (delegate_type, out expr)) { am = expr as AnonymousExpression; return am == null ? null : am.ReturnType; } using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type); if (body != null) { if (Block.IsAsync) { AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc); } am = body.Compatible (ec, body); } else { am = null; } } if (am == null) return null; // compatibles.Add (delegate_type, am); return am.ReturnType; }
bool ResolveArgumentExpression (ResolveContext rc, Expression expr) { var sn = expr as SimpleName; if (sn != null) { Value = sn.Name; if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6) rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator"); var res = sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity | MemberLookupRestrictions.NameOfExcluded); var me = res as MemberExpr; if (me != null) me.ResolveNameOf (rc, sn); return true; } var ma = expr as MemberAccess; if (ma != null) { var lexpr = ma.LeftExpression; Expression res; using (rc.Set (ResolveContext.Options.NameOfScope)) { res = ma.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity); } if (res == null) { return false; } if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6) rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator"); if (ma is QualifiedAliasMember) { rc.Report.Error (8083, loc, "An alias-qualified name is not an expression"); return false; } var me = res as MemberExpr; if (me != null) { me.ResolveNameOf (rc, ma); } // // LAMESPEC: Why is conditional access not allowed? // if (!IsLeftResolvedExpressionValid (ma.LeftExpression) || ma.HasConditionalAccess ()) { rc.Report.Error (8082, lexpr.Location, "An argument to nameof operator cannot include sub-expression"); return false; } Value = ma.Name; return true; } rc.Report.Error (8081, loc, "Expression does not have a name"); return false; }
public Type InferReturnType (ResolveContext ec, TypeInferenceContext tic, Type delegate_type) { AnonymousMethodBody am; using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { am = CompatibleMethod (ec, tic, InternalType.Arglist, delegate_type); } if (am == null) return null; return am.ReturnType; }
protected override Expression DoResolve(ResolveContext rc) { var sn = expr as SimpleName; const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type; // // Resolve the expression with flow analysis turned off, we'll do the definite // assignment checks later. This is because we don't know yet what the expression // will resolve to - it may resolve to a FieldExpr and in this case we must do the // definite assignment check on the actual field and not on the whole struct. // using (rc.Set(ResolveContext.Options.OmitStructFlowAnalysis)) { if (sn != null) { expr = sn.LookupNameExpression(rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity); // // 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) { using (rc.With(ResolveContext.Options.DoFlowAnalysis, false)) { 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)) { return(null); } } var results = new List <string> (); if (expr is Namespace) { Namespace nexpr = expr as Namespace; string namespaced_partial; if (partial_name == null) { namespaced_partial = nexpr.Name; } else { namespaced_partial = nexpr.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()); }
// // 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; if (type == InternalType.ErrorType) return null; 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. // HashSet<LocalVariable> undeclaredVariables = null; var body = CompatibleMethodBody (ec, null, return_type, delegate_type, ref undeclaredVariables); 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); } finally { // // LocalVariable is not stateless and it's not easy to clone because it's // cached in toplevel block. Unsetting any initialized variables should // be enough // if (undeclaredVariables != null) { body.Block.TopBlock.SetUndeclaredVariables (undeclaredVariables); } } if (!ec.IsInProbingMode && !etree_conversion) { compatibles.Add (type, am ?? EmptyExpression.Null); } return am; }
public override Expression DoResolve (ResolveContext ec) { eclass = ExprClass.Value; // TODO: ec.GetSignatureForError () ConstructorBuilder caller_builder = ((Constructor) ec.MemberContext).ConstructorBuilder; if (argument_list != null) { bool dynamic; // // Spec mandates that constructor initializer will not have `this' access // using (ec.Set (ResolveContext.Options.BaseInitializer)) { argument_list.Resolve (ec, out dynamic); } if (dynamic) { SimpleName ctor = new SimpleName (ConstructorBuilder.ConstructorName, loc); return new DynamicInvocation (ctor, argument_list, loc).Resolve (ec) as ExpressionStatement; } } type = ec.CurrentType; if (this is ConstructorBaseInitializer) { if (ec.CurrentType.BaseType == null) return this; type = ec.CurrentType.BaseType; if (TypeManager.IsStruct (ec.CurrentType)) { ec.Report.Error (522, loc, "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder)); return this; } } else { // // It is legal to have "this" initializers that take no arguments // in structs, they are just no-ops. // // struct D { public D (int a) : this () {} // if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null) return this; } base_constructor_group = MemberLookupFinal ( ec, null, type, ConstructorBuilder.ConstructorName, MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, loc) as MethodGroupExpr; if (base_constructor_group == null) return this; base_constructor_group = base_constructor_group.OverloadResolve ( ec, ref argument_list, false, loc); if (base_constructor_group == null) return this; if (!ec.IsStatic) base_constructor_group.InstanceExpression = ec.GetThis (loc); ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group; if (base_ctor == caller_builder){ ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder)); } return this; }
bool ResolveArgumentExpression (ResolveContext rc, Expression expr) { var sn = expr as SimpleName; if (sn != null) { Value = sn.Name; if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6) rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator"); var res = sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity | MemberLookupRestrictions.NameOfExcluded); if (sn.HasTypeArguments && res is MethodGroupExpr) { Error_MethodGroupWithTypeArguments (rc, expr.Location); } return true; } var ma = expr as MemberAccess; if (ma != null) { var lexpr = ma.LeftExpression; Expression res; using (rc.Set (ResolveContext.Options.NameOfScope)) { res = ma.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity); } if (res == null) { return false; } if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6) rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator"); if (ma is QualifiedAliasMember) { rc.Report.Error (8083, loc, "An alias-qualified name is not an expression"); return false; } var mg = res as MethodGroupExpr; if (mg != null) { var emg = res as ExtensionMethodGroupExpr; if (emg != null && !emg.ResolveNameOf (rc, ma)) { return true; } if (!mg.HasAccessibleCandidate (rc)) { ErrorIsInaccesible (rc, ma.GetSignatureForError (), loc); } if (ma.HasTypeArguments) { Error_MethodGroupWithTypeArguments (rc, ma.Location); } } // // LAMESPEC: Why is conditional access not allowed? // if (!IsLeftResolvedExpressionValid (ma.LeftExpression) || ma.HasConditionalAccess ()) { rc.Report.Error (8082, lexpr.Location, "An argument to nameof operator cannot include sub-expression"); return false; } Value = ma.Name; return true; } rc.Report.Error (8081, loc, "Expression does not have a name"); return false; }
public TypeSpec InferReturnType (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) { Expression expr; AnonymousExpression am; if (compatibles.TryGetValue (delegate_type, out expr)) { am = expr as AnonymousExpression; return am == null ? null : am.ReturnType; } using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { am = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type); if (am != null) am = am.Compatible (ec); } if (am == null) return null; // compatibles.Add (delegate_type, am); return am.ReturnType; }
protected override Expression DoResolve(ResolveContext ec) { right = right.Resolve(ec); if (right == null) { return(null); } MemberAccess ma = target as MemberAccess; using (ec.Set(ResolveContext.Options.CompoundAssignmentScope)) { target = target.Resolve(ec); } if (target == null) { return(null); } if (target is MethodGroupExpr) { ec.Report.Error(1656, loc, "Cannot assign to `{0}' because it is a `{1}'", ((MethodGroupExpr)target).Name, target.ExprClassName); return(null); } var event_expr = target as EventExpr; if (event_expr != null) { source = Convert.ImplicitConversionRequired(ec, right, target.Type, loc); if (source == null) { return(null); } Expression rside; if (op == Binary.Operator.Addition) { rside = EmptyExpression.EventAddition; } else if (op == Binary.Operator.Subtraction) { rside = EmptyExpression.EventSubtraction; } else { rside = null; } target = target.ResolveLValue(ec, rside); if (target == null) { return(null); } eclass = ExprClass.Value; type = event_expr.Operator.ReturnType; return(this); } // // Only now we can decouple the original source/target // into a tree, to guarantee that we do not have side // effects. // if (left == null) { left = new TargetExpression(target); } source = new Binary(op, left, right, true, loc); if (target is DynamicMemberAssignable) { Arguments targs = ((DynamicMemberAssignable)target).Arguments; source = source.Resolve(ec); Arguments args = new Arguments(targs.Count + 1); args.AddRange(targs); args.Add(new Argument(source)); var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment; // // Compound assignment does target conversion using additional method // call, set checked context as the binary operation can overflow // if (ec.HasSet(ResolveContext.Options.CheckedScope)) { binder_flags |= CSharpBinderFlags.CheckedContext; } if (target is DynamicMemberBinder) { source = new DynamicMemberBinder(ma.Name, binder_flags, args, loc).Resolve(ec); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments(targs.Count + 1); args.AddRange(targs); args.Add(new Argument(right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; var invoke = DynamicInvocation.CreateSpecialNameInvoke( new MemberAccess(right, method_prefix + ma.Name, loc), args, loc).Resolve(ec); args = new Arguments(targs.Count); args.AddRange(targs); source = new DynamicEventCompoundAssign(ma.Name, args, (ExpressionStatement)source, (ExpressionStatement)invoke, loc).Resolve(ec); } } else { source = new DynamicIndexBinder(binder_flags, args, loc).Resolve(ec); } return(source); } return(base.DoResolve(ec)); }
// // Converts `source' to an int, uint, long or ulong. // protected Expression ConvertExpressionToArrayIndex(ResolveContext ec, Expression source) { if (source.type == InternalType.Dynamic) { Arguments args = new Arguments (1); args.Add (new Argument (source)); return new DynamicConversion (TypeManager.int32_type, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec); } Expression converted; using (ec.Set (ResolveContext.Options.CheckedScope)) { converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, source.loc); if (converted == null) { source.Error_ValueCannotBeConverted (ec, source.loc, TypeManager.int32_type, false); return null; } } // // Only positive constants are allowed at compile time // Constant c = converted as Constant; if (c != null && c.IsNegative) Error_NegativeArrayIndex (ec, source.loc); // No conversion needed to array index if (converted.Type == TypeManager.int32_type) return converted; return new ArrayIndexCast (converted).Resolve (ec); }
// // 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; 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 { if (Block.IsAsync) { var rt = body.ReturnType; if (rt.Kind != MemberKind.Void && rt != ec.Module.PredefinedTypes.Task.TypeSpec && !rt.IsGenericTask) { ec.Report.Error (4010, loc, "Cannot convert async {0} to delegate type `{1}'", GetSignatureForError (), type.GetSignatureForError ()); } AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, rt, loc); } am = body.Compatible (ec); } } catch (CompletionResult) { throw; } catch (Exception e) { throw new InternalErrorException (e, loc); } if (!ec.IsInProbingMode) { compatibles.Add (type, am ?? EmptyExpression.Null); } return am; }
Expression DoResolve(ResolveContext ec, bool lvalue_instance, bool out_access) { if (!IsStatic){ if (InstanceExpression == null){ // // This can happen when referencing an instance field using // a fully qualified type expression: TypeName.InstanceField = xxx // SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return null; } // Resolve the field's instance expression while flow analysis is turned // off: when accessing a field "a.b", we must check whether the field // "a.b" is initialized, not whether the whole struct "a" is initialized. if (lvalue_instance) { using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { Expression right_side = out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; if (InstanceExpression != EmptyExpression.Null) InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side); } } else { if (InstanceExpression != EmptyExpression.Null) { using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue); } } } if (InstanceExpression == null) return null; using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { InstanceExpression.CheckMarshalByRefAccess (ec); } } if (!ec.IsObsolete) { ObsoleteAttribute oa = spec.GetAttributeObsolete (); if (oa != null) AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (spec), loc, ec.Report); } var fb = spec as FixedFieldSpec; IVariableReference var = InstanceExpression as IVariableReference; if (fb != null) { IFixedExpression fe = InstanceExpression as IFixedExpression; if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) { ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); } if (InstanceExpression.eclass != ExprClass.Variable) { ec.Report.SymbolRelatedToPreviousError (spec); ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields", TypeManager.GetFullNameSignature (spec)); } else if (var != null && var.IsHoisted) { AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc); } return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); } eclass = ExprClass.Variable; // If the instance expression is a local variable or parameter. if (var == null || var.VariableInfo == null) return this; VariableInfo vi = var.VariableInfo; if (!vi.IsFieldAssigned (ec, Name, loc)) return null; variable_info = vi.GetSubStruct (Name); return this; }
protected override Expression DoResolve (ResolveContext ec) { constructor_method = Delegate.GetConstructor (type); var invoke_method = Delegate.GetInvokeMethod (type); if (!ec.HasSet (ResolveContext.Options.ConditionalAccessReceiver)) { if (method_group.HasConditionalAccess ()) { conditional_access_receiver = true; ec.Set (ResolveContext.Options.ConditionalAccessReceiver); } } Arguments arguments = CreateDelegateMethodArguments (ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc); method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate); if (conditional_access_receiver) ec.With (ResolveContext.Options.ConditionalAccessReceiver, false); if (method_group == null) return null; var delegate_method = method_group.BestCandidate; if (delegate_method.DeclaringType.IsNullableType) { ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type", delegate_method.GetSignatureForError ()); return null; } if (!AllowSpecialMethodsInvocation) Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc); ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; if (emg != null) { method_group.InstanceExpression = emg.ExtensionExpression; TypeSpec e_type = emg.ExtensionExpression.Type; if (TypeSpec.IsValueType (e_type)) { ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates", delegate_method.GetSignatureForError (), e_type.GetSignatureForError ()); } } TypeSpec rt = method_group.BestCandidateReturnType; if (rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) rt = ec.BuiltinTypes.Object; if (!Delegate.IsTypeCovariant (ec, rt, invoke_method.ReturnType)) { Expression ret_expr = new TypeExpression (delegate_method.ReturnType, loc); Error_ConversionFailed (ec, delegate_method, ret_expr); } if (method_group.IsConditionallyExcluded) { ec.Report.SymbolRelatedToPreviousError (delegate_method); MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator; if (m != null && m.IsPartialDefinition) { ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'", delegate_method.GetSignatureForError ()); } else { ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method)); } } var expr = method_group.InstanceExpression; if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType (expr.Type))) method_group.InstanceExpression = new BoxedCast (expr, ec.BuiltinTypes.Object); eclass = ExprClass.Value; return this; }
protected override Expression DoResolve (ResolveContext rc) { var sn = expr as SimpleName; const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type; // // Resolve the expression with flow analysis turned off, we'll do the definite // assignment checks later. This is because we don't know yet what the expression // will resolve to - it may resolve to a FieldExpr and in this case we must do the // definite assignment check on the actual field and not on the whole struct. // using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { if (sn != null) { expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity); // // 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) { using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) { 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)) return null; } var results = new List<string> (); if (expr is Namespace) { Namespace nexpr = expr as Namespace; string namespaced_partial; if (partial_name == null) namespaced_partial = nexpr.Name; else namespaced_partial = nexpr.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 ()); }
protected override Expression DoResolve (ResolveContext ec) { eclass = ExprClass.Value; // FIXME: Hack var caller_builder = (Constructor) ec.MemberContext; // // Spec mandates that constructor initializer will not have `this' access // using (ec.Set (ResolveContext.Options.BaseInitializer)) { if (argument_list != null) { bool dynamic; argument_list.Resolve (ec, out dynamic); if (dynamic) { ec.Report.Error (1975, loc, "The constructor call cannot be dynamically dispatched within constructor initializer"); return null; } } type = ec.CurrentType; if (this is ConstructorBaseInitializer) { if (ec.CurrentType.BaseType == null) return this; type = ec.CurrentType.BaseType; if (ec.CurrentType.IsStruct) { ec.Report.Error (522, loc, "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ()); return this; } } else { // // It is legal to have "this" initializers that take no arguments // in structs // // struct D { public D (int a) : this () {} // if (ec.CurrentType.IsStruct && argument_list == null) return this; } base_ctor = ConstructorLookup (ec, type, ref argument_list, loc); } if (base_ctor != null && base_ctor.MemberDefinition == caller_builder.Spec.MemberDefinition) { ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", caller_builder.GetSignatureForError ()); } return this; }
protected override Expression DoResolve (ResolveContext ec) { // Field initializer can be resolved (fail) many times if (source == null) return null; if (resolved == null) { // // Field initializers are tricky for partial classes. They have to // share same constructor (block) but they have they own resolve scope. // IMemberContext old = ec.MemberContext; ec.MemberContext = rc; using (ec.Set (ResolveContext.Options.FieldInitializerScope)) { resolved = base.DoResolve (ec) as ExpressionStatement; } ec.MemberContext = old; } return resolved; }
public TypeSpec InferReturnType (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) { Expression expr; AnonymousExpression am; if (compatibles.TryGetValue (delegate_type, out expr)) { am = expr as AnonymousExpression; return am == null ? null : am.ReturnType; } using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { ReportPrinter prev; if (TypeInferenceReportPrinter != null) { prev = ec.Report.SetPrinter (TypeInferenceReportPrinter); } else { prev = null; } var body = CompatibleMethodBody (ec, tic, null, delegate_type); if (body != null) { am = body.Compatible (ec, body); } else { am = null; } if (TypeInferenceReportPrinter != null) { ec.Report.SetPrinter (prev); } } if (am == null) return null; // compatibles.Add (delegate_type, am); return am.ReturnType; }
protected override Expression DoResolve (ResolveContext ec) { right = right.Resolve (ec); if (right == null) return null; MemberAccess ma = target as MemberAccess; using (ec.Set (ResolveContext.Options.CompoundAssignmentScope)) { target = target.Resolve (ec); } if (target == null) return null; if (target is MethodGroupExpr){ ec.Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'", ((MethodGroupExpr)target).Name, target.ExprClassName); return null; } if (target is EventExpr) return new EventAddOrRemove (target, op, right, loc).Resolve (ec); // // Only now we can decouple the original source/target // into a tree, to guarantee that we do not have side // effects. // if (left == null) left = new TargetExpression (target); source = new Binary (op, left, right, true, loc); if (target is DynamicMemberBinder) { Arguments targs = ((DynamicMemberBinder) target).Arguments; source = source.Resolve (ec); Arguments args = new Arguments (2); args.AddRange (targs); args.Add (new Argument (source)); source = new DynamicMemberBinder (ma.Name, args, loc).ResolveLValue (ec, right); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments (2); args.AddRange (targs); args.Add (new Argument (right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; var invoke = DynamicInvocation.CreateSpecialNameInvoke ( new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec); args = new Arguments (1); args.AddRange (targs); source = new DynamicEventCompoundAssign (ma.Name, args, (ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec); } return source; } return base.DoResolve (ec); }
// // Returns true if the body of lambda expression can be implicitly // converted to the delegate of type `delegate_type' // public bool ImplicitStandardConversionExists (ResolveContext ec, TypeSpec delegate_type) { using (ec.With (ResolveContext.Options.InferReturnType, false)) { using (ec.Set (ResolveContext.Options.ProbingMode)) { var prev = ec.Report.SetPrinter (TypeInferenceReportPrinter ?? new NullReportPrinter ()); var res = Compatible (ec, delegate_type) != null; ec.Report.SetPrinter (prev); return res; } } }
protected override Expression DoResolve(ResolveContext ec) { eclass = ExprClass.Value; // FIXME: Hack var caller_builder = (Constructor) ec.MemberContext; if (argument_list != null) { bool dynamic; // // Spec mandates that constructor initializer will not have `this' access // using (ec.Set (ResolveContext.Options.BaseInitializer)) { argument_list.Resolve (ec, out dynamic); } if (dynamic) { ec.Report.Error (1975, loc, "The constructor call cannot be dynamically dispatched within constructor initializer"); return null; } } type = ec.CurrentType; if (this is ConstructorBaseInitializer) { if (ec.CurrentType.BaseType == null) return this; type = ec.CurrentType.BaseType; if (ec.CurrentType.IsStruct) { ec.Report.Error (522, loc, "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ()); return this; } } else { // // It is legal to have "this" initializers that take no arguments // in structs, they are just no-ops. // // struct D { public D (int a) : this () {} // if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null) return this; } base_constructor_group = MemberLookupFinal ( ec, null, type, ConstructorBuilder.ConstructorName, 0, MemberKind.Constructor, BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly, loc) as MethodGroupExpr; if (base_constructor_group == null) return this; base_constructor_group = base_constructor_group.OverloadResolve ( ec, ref argument_list, false, loc); if (base_constructor_group == null) return this; if (!ec.IsStatic) base_constructor_group.InstanceExpression = ec.GetThis (loc); var base_ctor = base_constructor_group.BestCandidate; // TODO MemberCache: Does it work for inflated types ? if (base_ctor == caller_builder.Spec){ ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", caller_builder.GetSignatureForError ()); } return this; }