diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
index cc09614f38e9b177055a10306df953c5685e74c0..6db16cea3c9e35643226d7397fdd843efb280cfe 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
@@ -81,14 +81,12 @@ public abstract class Names extends RBuiltinNode.Arg1 {
     protected Object getNames(TruffleObject obj,
                     @Cached("GET_SIZE.createNode()") Node getSizeNode,
                     @Cached("KEYS.createNode()") Node keysNode,
-                    @Cached("READ.createNode()") Node readNode,
-                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
-                    @Cached("UNBOX.createNode()") Node unboxNode) {
+                    @Cached("READ.createNode()") Node readNode) {
 
         try {
             String[] names;
             try {
-                names = readKeys(keysNode, obj, getSizeNode, readNode, isBoxedNode, unboxNode);
+                names = readKeys(keysNode, obj, getSizeNode, readNode);
             } catch (UnsupportedMessageException e) {
                 // because it is a java function, java.util.Map (has special handling too) ... ?
                 return RNull.instance;
@@ -96,7 +94,7 @@ public abstract class Names extends RBuiltinNode.Arg1 {
             String[] staticNames = new String[0];
             try {
                 if (JavaInterop.isJavaObject(Object.class, obj)) {
-                    staticNames = readKeys(keysNode, toJavaClass(obj), getSizeNode, readNode, isBoxedNode, unboxNode);
+                    staticNames = readKeys(keysNode, toJavaClass(obj), getSizeNode, readNode);
                 }
             } catch (UnknownIdentifierException | NoSuchFieldError | UnsupportedMessageException e) {
                 // because it is a class ... ?
@@ -118,18 +116,14 @@ public abstract class Names extends RBuiltinNode.Arg1 {
         return JavaInterop.toJavaClass(obj);
     }
 
-    private static String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode, Node isBoxedNode, Node unboxNode)
+    private static String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode)
                     throws UnknownIdentifierException, InteropException, UnsupportedMessageException {
-        TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj);
+        TruffleObject keys = ForeignAccess.sendKeys(keysNode, obj);
         if (keys != null) {
             int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys);
             String[] names = new String[size];
             for (int i = 0; i < size; i++) {
-                Object value;
-                value = ForeignAccess.sendRead(readNode, keys, i);
-                if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
-                    value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
-                }
+                Object value = ForeignAccess.sendRead(readNode, keys, i);
                 names[i] = (String) value;
             }
             return names;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
index bea08a0ce86a96e7a6b346089e5ff581d582c9e4..aefbeedf3e0ca1f840edfbf0eaa134e4b822aeb8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
@@ -22,9 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import java.io.IOException;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
 import com.oracle.truffle.r.nodes.builtin.base.InheritsBuiltin;
 import com.oracle.truffle.r.nodes.builtin.base.InheritsBuiltinNodeGen;
@@ -51,7 +50,6 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -69,6 +67,12 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck;
+import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck.RType.BOOLEAN;
+import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck.RType.DOUBLE;
+import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck.RType.INTEGER;
+import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.InteropTypeCheck.RType.STRING;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public final class ValuePrinterNode extends RBaseNode {
@@ -96,7 +100,7 @@ public final class ValuePrinterNode extends RBaseNode {
         @Child private Node isBoxedNode = com.oracle.truffle.api.interop.Message.IS_BOXED.createNode();
         @Child private Node unboxNode = com.oracle.truffle.api.interop.Message.UNBOX.createNode();
         @Child private Node keysNode = com.oracle.truffle.api.interop.Message.KEYS.createNode();
-        @Child private SetFixedAttributeNode namesAttrSetter = SetFixedAttributeNode.createNames();
+        @Child private Foreign2R foreign2R = Foreign2R.createForeign2R();
 
         @TruffleBoundary
         public Object convert(TruffleObject obj) {
@@ -118,13 +122,10 @@ public final class ValuePrinterNode extends RBaseNode {
                     Object value;
                     try {
                         value = ForeignAccess.sendRead(readNode, object, index);
-                        if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
-                            value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
-                        }
+                        return String.valueOf(foreign2R.execute(value));
                     } catch (UnknownIdentifierException | UnsupportedMessageException e) {
                         throw RInternalError.shouldNotReachHere(e);
                     }
-                    return String.valueOf(value);
                 }
 
                 @Override
@@ -132,155 +133,148 @@ public final class ValuePrinterNode extends RBaseNode {
                     throw RInternalError.shouldNotReachHere();
                 }
             }
+            class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector {
+
+                private final RStringVector names;
+
+                RListWrapper(int length, RStringVector names) {
+                    super(length);
+                    this.names = names;
+                    if (names != null) {
+                        DynamicObject attrs = RAttributesLayout.createNames(names);
+                        initAttributes(attrs);
+                    }
+                }
+
+                @Override
+                public Object getDataAtAsObject(int index) {
+                    return getDataAt(index);
+                }
+
+                @Override
+                public Object getDataAt(int index) {
+                    try {
+                        Object value = ForeignAccess.sendRead(readNode, obj, names != null ? names.getDataAt(index) : index);
+                        return foreign2R.execute(value);
+                    } catch (UnknownIdentifierException | UnsupportedMessageException e) {
+                        throw RInternalError.shouldNotReachHere(e);
+                    }
+                }
+
+                @Override
+                public RStringVector getNames() {
+                    return names;
+                }
+
+                @Override
+                public RList materialize() {
+                    throw RInternalError.shouldNotReachHere();
+                }
+            }
             try {
                 if (ForeignAccess.sendHasSize(hasSizeNode, obj)) {
                     int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, obj);
-                    boolean allBoolean = true;
-                    boolean allInteger = true;
-                    boolean allNumber = true;
-                    boolean allCharacter = true;
-                    boolean allString = true;
+                    InteropTypeCheck typeCheck = new InteropTypeCheck();
                     for (int i = 0; i < size; i++) {
                         Object value = ForeignAccess.sendRead(readNode, obj, i);
                         if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
                             value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
                         }
-                        allBoolean &= value instanceof Boolean;
-                        allInteger &= value instanceof Integer;
-                        allNumber &= value instanceof Number;
-                        allCharacter &= value instanceof Character;
-                        allString &= value instanceof String;
+                        if (typeCheck.checkForeign(value) == InteropTypeCheck.RType.NONE) {
+                            break;
+                        }
                     }
-                    if (allBoolean) {
-                        class RLogicalWrapper extends TruffleObjectWrapper implements RAbstractLogicalVector {
+                    switch (typeCheck.getType()) {
+                        case BOOLEAN:
+                            class RLogicalWrapper extends TruffleObjectWrapper implements RAbstractLogicalVector {
 
-                            RLogicalWrapper(int length) {
-                                super(length);
-                            }
+                                RLogicalWrapper(int length) {
+                                    super(length);
+                                }
 
-                            @Override
-                            public Object getDataAtAsObject(int index) {
-                                return getDataAt(index);
-                            }
+                                @Override
+                                public Object getDataAtAsObject(int index) {
+                                    return getDataAt(index);
+                                }
 
-                            @Override
-                            public byte getDataAt(int index) {
-                                Object value;
-                                try {
-                                    value = ForeignAccess.sendRead(readNode, obj, index);
-                                    if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
-                                        value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
+                                @Override
+                                public byte getDataAt(int index) {
+                                    try {
+                                        Object value = ForeignAccess.sendRead(readNode, obj, index);
+                                        return (byte) foreign2R.execute(value);
+                                    } catch (UnknownIdentifierException | UnsupportedMessageException e) {
+                                        throw RInternalError.shouldNotReachHere(e);
                                     }
-                                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                                    throw RInternalError.shouldNotReachHere(e);
                                 }
-                                return RRuntime.asLogical((Boolean) value);
-                            }
 
-                            @Override
-                            public RLogicalVector materialize() {
-                                throw RInternalError.shouldNotReachHere();
+                                @Override
+                                public RLogicalVector materialize() {
+                                    throw RInternalError.shouldNotReachHere();
+                                }
                             }
-                        }
-                        return new RLogicalWrapper(size);
-                    } else if (allInteger) {
-                        class RIntWrapper extends TruffleObjectWrapper implements RAbstractIntVector {
+                            return new RLogicalWrapper(size);
+                        case INTEGER:
+                            class RIntWrapper extends TruffleObjectWrapper implements RAbstractIntVector {
 
-                            RIntWrapper(int length) {
-                                super(length);
-                            }
+                                RIntWrapper(int length) {
+                                    super(length);
+                                }
 
-                            @Override
-                            public Object getDataAtAsObject(int index) {
-                                return getDataAt(index);
-                            }
+                                @Override
+                                public Object getDataAtAsObject(int index) {
+                                    return getDataAt(index);
+                                }
 
-                            @Override
-                            public int getDataAt(int index) {
-                                Object value;
-                                try {
-                                    value = ForeignAccess.sendRead(readNode, obj, index);
-                                    if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
-                                        value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
+                                @Override
+                                public int getDataAt(int index) {
+                                    try {
+                                        Object value = ForeignAccess.sendRead(readNode, obj, index);
+                                        return ((Number) foreign2R.execute(value)).intValue();
+                                    } catch (UnknownIdentifierException | UnsupportedMessageException e) {
+                                        throw RInternalError.shouldNotReachHere(e);
                                     }
-                                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                                    throw RInternalError.shouldNotReachHere(e);
                                 }
-                                return (Integer) value;
-                            }
-
-                            @Override
-                            public RIntVector materialize() {
-                                throw RInternalError.shouldNotReachHere();
-                            }
-                        }
-                        return new RIntWrapper(size);
-                    } else if (allNumber) {
-                        class RDoubleWrapper extends TruffleObjectWrapper implements RAbstractDoubleVector {
-
-                            RDoubleWrapper(int length) {
-                                super(length);
-                            }
-
-                            @Override
-                            public Object getDataAtAsObject(int index) {
-                                return getDataAt(index);
-                            }
 
-                            @Override
-                            public double getDataAt(int index) {
-                                Object value;
-                                try {
-                                    value = ForeignAccess.sendRead(readNode, obj, index);
-                                    if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
-                                        value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
-                                    }
-                                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                                    throw RInternalError.shouldNotReachHere(e);
+                                @Override
+                                public RIntVector materialize() {
+                                    throw RInternalError.shouldNotReachHere();
                                 }
-                                return ((Number) value).doubleValue();
                             }
+                            return new RIntWrapper(size);
+                        case DOUBLE:
+                            class RDoubleWrapper extends TruffleObjectWrapper implements RAbstractDoubleVector {
 
-                            @Override
-                            public RDoubleVector materialize() {
-                                throw RInternalError.shouldNotReachHere();
-                            }
-                        }
-                        return new RDoubleWrapper(size);
-                    } else if (allString || allCharacter) {
-                        return new RStringWrapper(size, obj);
-                    } else {
-                        class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector {
-
-                            RListWrapper(int length) {
-                                super(length);
-                            }
+                                RDoubleWrapper(int length) {
+                                    super(length);
+                                }
 
-                            @Override
-                            public Object getDataAtAsObject(int index) {
-                                return getDataAt(index);
-                            }
+                                @Override
+                                public Object getDataAtAsObject(int index) {
+                                    return getDataAt(index);
+                                }
 
-                            @Override
-                            public Object getDataAt(int index) {
-                                Object value;
-                                try {
-                                    value = ForeignAccess.sendRead(readNode, obj, index);
-                                    if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
-                                        value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
+                                @Override
+                                public double getDataAt(int index) {
+                                    try {
+                                        Object value = ForeignAccess.sendRead(readNode, obj, index);
+                                        return ((Number) foreign2R.execute(value)).doubleValue();
+                                    } catch (UnknownIdentifierException | UnsupportedMessageException e) {
+                                        throw RInternalError.shouldNotReachHere(e);
                                     }
-                                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                                    throw RInternalError.shouldNotReachHere(e);
                                 }
-                                return value;
-                            }
 
-                            @Override
-                            public RList materialize() {
-                                throw RInternalError.shouldNotReachHere();
+                                @Override
+                                public RDoubleVector materialize() {
+                                    throw RInternalError.shouldNotReachHere();
+                                }
                             }
-                        }
-                        return new RListWrapper(size);
+                            return new RDoubleWrapper(size);
+                        case STRING:
+                            return new RStringWrapper(size, obj);
+                        case NONE:
+                            return new RListWrapper(size, null);
+                        default:
+                            throw RInternalError.shouldNotReachHere();
                     }
                 }
                 TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj);
@@ -292,44 +286,7 @@ public final class ValuePrinterNode extends RBaseNode {
                         names.setDataAt(names.getInternalStore(), i, abstractNames.getDataAt(i));
                     }
 
-                    class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector {
-
-                        RListWrapper(int length) {
-                            super(length);
-                            DynamicObject attrs = RAttributesLayout.createNames(names);
-                            initAttributes(attrs);
-                        }
-
-                        @Override
-                        public Object getDataAtAsObject(int index) {
-                            return getDataAt(index);
-                        }
-
-                        @Override
-                        public Object getDataAt(int index) {
-                            Object value;
-                            try {
-                                value = ForeignAccess.sendRead(readNode, obj, names.getDataAt(index));
-                                if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
-                                    value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
-                                }
-                            } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                                throw RInternalError.shouldNotReachHere(e);
-                            }
-                            return value;
-                        }
-
-                        @Override
-                        public RStringVector getNames() {
-                            return names;
-                        }
-
-                        @Override
-                        public RList materialize() {
-                            throw RInternalError.shouldNotReachHere();
-                        }
-                    }
-                    return new RListWrapper(size);
+                    return new RListWrapper(size, names);
                 }
             } catch (InteropException e) {
                 // nothing to do
@@ -530,11 +487,6 @@ public final class ValuePrinterNode extends RBaseNode {
             throw RInternalError.shouldNotReachHere();
         }
 
-        @Override
-        public RType getRType() {
-            return RType.Integer;
-        }
-
         @Override
         public ForeignAccess getForeignAccess() {
             throw RInternalError.shouldNotReachHere();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
index e3c2e29a373bec5ea0d6026dc2f2b3b6c09eb518..c3278b4310ed49742d6456bf8a5c006b1a26d6b3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
@@ -79,13 +79,7 @@ final class ValuePrinters implements ValuePrinter<Object> {
         } else {
             // handle types that are meant for or can appear via Truffle interop
             Object x = v;
-            if (x instanceof Boolean) {
-                x = RRuntime.asLogical((Boolean) x);
-            } else if (x instanceof Long || x instanceof Short || x instanceof Float) {
-                x = ((Number) x).doubleValue();
-            } else if (x instanceof Character) {
-                x = ((Character) x).toString();
-            } else if (x instanceof RInteropScalar) {
+            if (x instanceof RInteropScalar) {
                 x = ((RInteropScalar) x).getRValue();
             }
             // try to box a scalar primitive value to the respective vector
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index a493d13ce2c342db57e014c1216d48975984bd55..93bad4256df8cc09352cf72034aa061adce059fe 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.KeyInfo;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ValueProfile;
@@ -220,16 +219,12 @@ public abstract class ExtractVectorNode extends RBaseNode {
                     @Cached("create()") CastStringNode castNode,
                     @Cached("createFirstString()") FirstStringNode firstString,
                     @Cached("createClassProfile()") ValueProfile positionProfile,
-                    @Cached("IS_NULL.createNode()") Node isNullNode,
-                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
-                    @Cached("UNBOX.createNode()") Node unboxNode,
                     @Cached("createForeign2RNode()") Foreign2R foreign2RNode) {
         Object[] pos = positionProfile.profile(positions);
         if (pos.length == 0) {
             throw error(RError.Message.GENERIC, "No positions for foreign access.");
         }
         try {
-            // TODO implicite unboxing ok? method calls seem to behave this way
             Object result = object;
             for (int i = 0; i < pos.length; i++) {
                 result = read(this, pos[i], foreignRead, keyInfoNode, hasSizeNode, (TruffleObject) result, firstString, castNode);
@@ -237,24 +232,12 @@ public abstract class ExtractVectorNode extends RBaseNode {
                     assert result instanceof TruffleObject;
                 }
             }
-            return unbox(result, isNullNode, isBoxedNode, unboxNode, foreign2RNode);
+            return foreign2RNode.execute(result);
         } catch (InteropException | NoSuchFieldError e) {
             throw RError.interopError(RError.findParentRBase(this), e, object);
         }
     }
 
-    private static Object unbox(Object obj, Node isNullNode, Node isBoxedNode, Node unboxNode, Foreign2R foreign2RNode) throws UnsupportedMessageException {
-        if (RRuntime.isForeignObject(obj)) {
-            if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) obj)) {
-                return RNull.instance;
-            }
-            if (ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) obj)) {
-                return foreign2RNode.execute(ForeignAccess.sendUnbox(unboxNode, (TruffleObject) obj));
-            }
-        }
-        return foreign2RNode.execute(obj);
-    }
-
     public static Object read(RBaseNode caller, Object positions, Node foreignRead, Node keyInfoNode, Node hasSizeNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode)
                     throws RError, InteropException {
         Object pos = positions;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index b1732b1e1c45ed98026d07c5249d1ef1fa8b0e89..58a993f8712f6aac3c59d263b5e5aacc19866943 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -539,7 +539,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
 
         @Child private CallArgumentsNode arguments;
         @Child private Node foreignCall;
-        @Child private Node isNullCall;
         @CompilationFinal private int foreignCallArgCount;
 
         public ForeignCall(CallArgumentsNode arguments) {
@@ -558,15 +557,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                     argumentsArray[i] = r2Foreign.execute(argumentsArray[i]);
                 }
                 Object result = ForeignAccess.sendExecute(foreignCall, function, argumentsArray);
-                if (RRuntime.isForeignObject(result)) {
-                    if (isNullCall == null) {
-                        CompilerDirectives.transferToInterpreterAndInvalidate();
-                        isNullCall = insert(Message.IS_NULL.createNode());
-                    }
-                    if (ForeignAccess.sendIsNull(isNullCall, (TruffleObject) result)) {
-                        return RNull.instance;
-                    }
-                }
                 return foreign2R.execute(result);
             } catch (ArityException | UnsupportedMessageException | UnsupportedTypeException e) {
                 CompilerDirectives.transferToInterpreter();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java
index 5642fa86b7857bc1780b2f765ce375f571841be6..df43ab4120f35065ede99648b15d3bd54e3f6d0c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java
@@ -30,8 +30,8 @@ import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -40,6 +40,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 public abstract class Foreign2R extends RBaseNode {
 
     @Child private Foreign2R recursive;
+    @Child private Node isNull;
     @Child private Node isBoxed;
     @Child private Node unbox;
 
@@ -85,7 +86,15 @@ public abstract class Foreign2R extends RBaseNode {
     }
 
     @Specialization(guards = "isForeignObject(obj)")
-    public Object doUnbox(TruffleObject obj) {
+    public Object doForeignObject(TruffleObject obj) {
+        if (isNull == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            isNull = insert(Message.IS_NULL.createNode());
+        }
+        if (ForeignAccess.sendIsNull(isNull, obj)) {
+            return RNull.instance;
+        }
+
         /*
          * For the time being, we have to ask "IS_BOXED" all the time (instead of simply trying
          * UNBOX first), because some TruffleObjects return bogus values from UNBOX when IS_BOXED is
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java
index ebf2d491225124af8bb65854e424c342c044ae02..b6aca07127a1c8bb2281047fdc47971949c92a9b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java
@@ -195,12 +195,11 @@ public abstract class ForeignArray2R extends RBaseNode {
      */
     public static RAbstractVector asAbstractVector(CollectedElements ce) {
         InteropTypeCheck.RType type = ce.typeCheck.getType();
-        if (type == null) {
-            return RDataFactory.createList(ce.elements.toArray(new Object[ce.elements.size()]));
-        }
         int size = ce.elements.size();
         boolean complete = true;
         switch (type) {
+            case NONE:
+                return RDataFactory.createList(ce.elements.toArray(new Object[ce.elements.size()]));
             case BOOLEAN:
                 byte[] bytes = new byte[size];
                 for (int i = 0; i < size; i++) {
@@ -263,13 +262,13 @@ public abstract class ForeignArray2R extends RBaseNode {
             BOOLEAN,
             DOUBLE,
             INTEGER,
-            STRING;
+            STRING,
+            NONE;
         }
 
         private RType type = null;
-        private boolean sameRType = true;
 
-        public void checkForeign(Object value) {
+        public RType checkForeign(Object value) {
             if (value instanceof Boolean) {
                 setType(RType.BOOLEAN);
             } else if (value instanceof Byte || value instanceof Integer || value instanceof Short) {
@@ -279,12 +278,12 @@ public abstract class ForeignArray2R extends RBaseNode {
             } else if (value instanceof Character || value instanceof String) {
                 setType(RType.STRING);
             } else {
-                this.type = null;
-                sameRType = false;
+                this.type = RType.NONE;
             }
+            return this.type;
         }
 
-        public void checkVector(RAbstractVector value) {
+        public RType checkVector(RAbstractVector value) {
             if (value instanceof RAbstractLogicalVector) {
                 setType(RType.BOOLEAN);
             } else if (value instanceof RAbstractIntVector) {
@@ -294,22 +293,23 @@ public abstract class ForeignArray2R extends RBaseNode {
             } else if (value instanceof RAbstractStringVector) {
                 setType(RType.STRING);
             } else {
-                this.type = null;
-                sameRType = false;
+                this.type = RType.NONE;
             }
+            return this.type;
         }
 
         private void setType(RType check) {
-            if (sameRType && this.type == null) {
-                this.type = check;
-            } else if (this.type != check) {
-                this.type = null;
-                sameRType = false;
+            if (this.type != RType.NONE) {
+                if (this.type == null) {
+                    this.type = check;
+                } else if (this.type != check) {
+                    this.type = RType.NONE;
+                }
             }
         }
 
         public RType getType() {
-            return sameRType ? type : null;
+            return type != null ? type : RType.NONE;
         }
     }
 
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 6ece459577d039a5b1fc206a9d530e9c0e187206..dc9999464e0b320d741dc95909a1792f791257d5 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
@@ -133622,6 +133622,25 @@ NULL
 #if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticBooleanObject }
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]<<<NEWLINE>>>[[1]]<<<NEWLINE>>>[1] 1<<<NEWLINE>>><<<NEWLINE>>>[[2]]<<<NEWLINE>>>[1] 2.1<<<NEWLINE>>><<<NEWLINE>>>[[3]]<<<NEWLINE>>>[1] "a"<<<NEWLINE>>><<<NEWLINE>>>[[4]]<<<NEWLINE>>>[1] TRUE<<<NEWLINE>>><<<NEWLINE>>>[[5]]<<<NEWLINE>>>NULL<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$mixedTypesArray }
+[external object]
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2.1
+
+[[3]]
+[1] "a"
+
+[[4]]
+[1] TRUE
+
+[[5]]
+NULL
+
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
 #if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1]  TRUE FALSE  TRUE\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldBooleanArray }
 [external object]
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index 6c62351cee58b76edf2d5d784269bc68e1e485e7..e28f6b0ebb6eb9d67d8ffc5806bc990efc3a815a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -390,6 +390,8 @@ public class TestJavaInterop extends TestBase {
                 testForValue(name, f.get(t));
             }
         }
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$mixedTypesArray",
+                        "cat('[external object]\n[[1]]\n[1] 1\n\n[[2]]\n[1] 2.1\n\n[[3]]\n[1] \"a\"\n\n[[4]]\n[1] TRUE\n\n[[5]]\nNULL\n\n', sep='')");
     }
 
     @Test
@@ -1417,12 +1419,16 @@ public class TestJavaInterop extends TestBase {
         return sb.toString();
     }
 
-    private static String getBooleanPrefix(Object value, int i) {
-        if (value.getClass().getComponentType() == Boolean.TYPE && (boolean) Array.get(value, i)) {
+    private static String getBooleanPrefix(Object array, int i) {
+        Object element = Array.get(array, i);
+        if (element == null) {
+            return "";
+        }
+        if (array.getClass().getComponentType() == Boolean.TYPE && (boolean) element) {
             return " ";
         }
-        if (i > 0 && value.getClass().getComponentType() == String.class &&
-                        (Array.get(value, i).equals("T") || Array.get(value, i).equals("F") || Array.get(value, i).equals("TRUE") || Array.get(value, i).equals("FALSE"))) {
+        if (i > 0 && array.getClass().getComponentType() == String.class &&
+                        (element.equals("T") || element.equals("F") || element.equals("TRUE") || element.equals("FALSE"))) {
             return " ";
         }
         return "";
@@ -1830,7 +1836,7 @@ public class TestJavaInterop extends TestBase {
             objectArray = new Object[]{new Object(), new Object(), new Object()};
             objectIntArray = new Object[]{1, 2, 3};
             objectDoubleArray = new Object[]{1.1, 2.1, 3.1};
-            mixedTypesArray = new Object[]{1, 2.1, 'a'};
+            mixedTypesArray = new Object[]{1, 2.1, 'a', true, null};
             hasNullIntArray = new Integer[]{1, null, 3};
 
             map = new HashMap<>();