ec.Emit (OpCodes.Dup);
no_value_label = ec.DefineLabel ();
ec.Emit (OpCodes.Brfalse_S, no_value_label);
+
+ if (Variable.HoistedVariant != null)
+ ec.EmitThis ();
+
expr_unwrap.Emit (ec);
} else {
+ if (Variable?.HoistedVariant != null)
+ ec.EmitThis ();
+
expr.Emit (ec);
// Only to make verifier happy
value_on_stack = false;
}
- //
- // It's ok to have variable builder create out of order. It simplified emit
- // of statements like while (condition) { }
- //
- if (!Variable.Created)
- Variable.CreateBuilder (ec);
-
- Variable.EmitAssign (ec);
+ if (Variable.HoistedVariant != null) {
+ Variable.HoistedVariant.EmitAssignFromStack (ec);
+
+ if (expr_unwrap != null) {
+ ec.MarkLabel (no_value_label);
+ } else if (!value_on_stack) {
+ Variable.HoistedVariant.Emit (ec);
+ }
+ } else {
+ //
+ // It's ok to have variable builder created out of order. It simplifies emit
+ // of statements like while (condition) { }
+ //
+ if (!Variable.Created)
+ Variable.CreateBuilder (ec);
- if (expr_unwrap != null) {
- ec.MarkLabel (no_value_label);
- } else if (!value_on_stack) {
- Variable.Emit (ec);
+ Variable.EmitAssign (ec);
+
+ if (expr_unwrap != null) {
+ ec.MarkLabel (no_value_label);
+ } else if (!value_on_stack) {
+ Variable.Emit (ec);
+ }
}
}
}
eclass = ExprClass.Value;
TypeSpec etype = expr.Type;
+ if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (etype)) {
+ ec.Report.Error (8307, expr.Location, "The first operand of an `as' operator may not be a tuple literal without a natural type");
+ type = InternalType.ErrorType;
+ return this;
+ }
+
if (type == null) {
type = InternalType.ErrorType;
return this;
return DoResolveInvocation (rc);
}
+ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+ {
+ var sn = expr as SimpleName;
+ if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) {
+ var targets = new List<Expression> (arguments.Count);
+ var variables = new List<LocalVariable> (arguments.Count);
+ foreach (var arg in arguments) {
+ var arg_sn = arg.Expr as SimpleName;
+ if (arg_sn == null || arg_sn.Arity != 0) {
+ rc.Report.Error (8199, loc, "The syntax `var (...)' as an lvalue is reserved");
+ return ErrorExpression.Instance;
+ }
+
+ var lv = new LocalVariable (rc.CurrentBlock, arg_sn.Name, arg.Expr.Location);
+ rc.CurrentBlock.AddLocalName (lv);
+ variables.Add (lv);
+
+ targets.Add (new LocalVariableReference (lv, arg_sn.Location));
+ }
+
+ var res = new TupleDeconstruct (targets, variables, right_side, loc);
+ return res.Resolve (rc);
+ }
+
+ return base.DoResolveLValue (rc, right_side);
+ }
+
Expression DoResolveInvocation (ResolveContext ec)
{
Expression member_expr;
protected override Expression DoResolve (ResolveContext ec)
{
+ if (RequestedType is TupleTypeExpr) {
+ ec.Report.Error (8181, loc, "Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead.");
+ }
+
type = RequestedType.ResolveAsType (ec);
if (type == null)
return null;
array_element_type = best_type_inference.InferredTypeArguments[0];
best_type_inference = null;
- if (array_element_type == null ||
- array_element_type == InternalType.NullLiteral || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
- arguments.Count != rank.Dimension) {
+ if (array_element_type == null || InternalType.HasNoType (array_element_type) || arguments.Count != rank.Dimension) {
ec.Report.Error (826, loc,
"The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
return null;
}
type = e.Type;
- if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) {
+ if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || type.IsPointer || (e is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
Error_InvalidInitializer (ec, type.GetSignatureForError ());
return null;
}