[mcs] Fixes codegen for type pattern matching in probing expressions over hoisted...
[mono.git] / mcs / mcs / expression.cs
index 74f0aadd45b33f0f86b7ae297cb653f7a00cc1a3..896980968d82efd168067c2664980380ecbe842c 100644 (file)
@@ -1687,8 +1687,15 @@ namespace Mono.CSharp
                                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
@@ -1708,19 +1715,29 @@ namespace Mono.CSharp
                                        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.Emit (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);
+
+                                       Variable.EmitAssign (ec);
+
+                                       if (expr_unwrap != null) {
+                                               ec.MarkLabel (no_value_label);
+                                       } else if (!value_on_stack) {
+                                               Variable.Emit (ec);
+                                       }
                                }
                        }
                }
@@ -7118,7 +7135,24 @@ namespace Mono.CSharp
                {
                        var sn = expr as SimpleName;
                        if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) {
-                               throw new NotImplementedException ("var deconstruct");
+                               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);