From 118da92603267f86228b58f91a45c97a2593a8fd Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 19 May 2017 15:01:47 +0200
Subject: [PATCH] Fix: serialization can handle promises that appear in varargs

---
 .../src/com/oracle/truffle/r/runtime/RSerialize.java         | 3 ++-
 .../oracle/truffle/r/runtime/data/RArgsValuesAndNames.java   | 4 +++-
 .../src/com/oracle/truffle/r/test/ExpectedTestOutput.test    | 4 ++++
 .../truffle/r/test/builtins/TestBuiltin_serialize.java       | 5 +++++
 4 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
index eda8d1fee8..8415803a34 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
@@ -1474,7 +1474,8 @@ public class RSerialize {
                             attributes = null;
                         }
                     }
-                    boolean hasTag = gnuRType == SEXPTYPE.CLOSXP || (gnuRType == SEXPTYPE.PROMSXP && !((RPromise) obj).isEvaluated()) || (type == SEXPTYPE.LISTSXP && !((RPairList) obj).isNullTag());
+                    boolean hasTag = gnuRType == SEXPTYPE.CLOSXP || gnuRType == SEXPTYPE.DOTSXP || (gnuRType == SEXPTYPE.PROMSXP && !((RPromise) obj).isEvaluated()) ||
+                                    (type == SEXPTYPE.LISTSXP && !((RPairList) obj).isNullTag());
                     int gpbits = getGPBits(obj);
                     int flags = Flags.packFlags(gnuRType, gpbits, isObject(obj), attributes != null, hasTag);
                     stream.writeInt(flags);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java
index 86d2782285..1f874d0842 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java
@@ -51,7 +51,9 @@ public final class RArgsValuesAndNames extends Arguments<Object> implements RTyp
 
     @Override
     public int getTypedValueInfo() {
-        throw RInternalError.shouldNotReachHere();
+        // RArgsValuesAndNames can get serialized under specific circumstances (ggplot2 does that)
+        // and getTypedValueInfo() must be defined for this to work.
+        return 0;
     }
 
     @Override
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index faec0e21a7..0635bc059c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -62412,6 +62412,10 @@ Error in seq.int(NaN) : 'from' cannot be NA, NaN or infinite
 #argv <- list(from = 0, to = 0.793110173512391, length.out = FALSE);do.call('seq.int', argv);
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testSerializeWithPromises#
+#{ f <- function(...) serialize(mget('...'),NULL); length(unserialize(f(a=3,b=2,c=1))[[1]]); }
+[1] 3
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#Ignored.ImplementationError#
 #options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL)
   [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 07 03 00 00 04 02 00 00 00
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
index 3e031ad10e..018b22c652 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
@@ -111,4 +111,9 @@ public class TestBuiltin_serialize extends TestBase {
 
         assertEval("{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) }");
     }
+
+    @Test
+    public void testSerializeWithPromises() {
+        assertEval("{ f <- function(...) serialize(mget('...'),NULL); length(unserialize(f(a=3,b=2,c=1))[[1]]); }");
+    }
 }
-- 
GitLab