diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
index 5d7b28af3fc1da1739ffc3456b7c816402c4f288..24672b60829f63b8fb5df40c2f7e5c3d7aa16526 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
@@ -29,9 +29,7 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.binary.BinaryBooleanScalarNodeGen.LogicalScalarCastNodeGen;
@@ -90,7 +88,7 @@ public abstract class BinaryBooleanScalarNode extends RBuiltinNode.Arg2 {
         return left;
     }
 
-    @ImportStatic({ForeignArray2R.class, Message.class})
+    @ImportStatic({RRuntime.class})
     protected abstract static class LogicalScalarCastNode extends RBaseNode {
 
         protected static final int CACHE_LIMIT = 3;
@@ -153,13 +151,15 @@ public abstract class BinaryBooleanScalarNode extends RBuiltinNode.Arg2 {
             return null;
         }
 
-        @Specialization(guards = {"isForeignVector(operand, hasSize)"})
+        @Specialization(guards = {"isForeignObject(operand)"})
         protected byte doForeignVector(TruffleObject operand,
-                        @Cached("HAS_SIZE.createNode()") @SuppressWarnings("unused") Node hasSize,
                         @Cached("create()") ForeignArray2R foreignArray2R,
                         @Cached("createRecursive()") LogicalScalarCastNode recursive) {
-            Object o = foreignArray2R.convert(operand);
-            return recursive.executeCast(o);
+            if (foreignArray2R.isForeignVector(operand)) {
+                Object o = foreignArray2R.convert(operand);
+                return recursive.executeCast(o);
+            }
+            return doFallback(operand);
         }
 
         protected LogicalScalarCastNode createRecursive() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
index 144f9715275a59198d1cb573a887ef75bcf9c106..167ed9506e76ef6839dfa0abf0c3bcd159c7fdc3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
@@ -13,8 +13,12 @@ package com.oracle.truffle.r.nodes.binary;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
@@ -28,9 +32,11 @@ import com.oracle.truffle.r.nodes.unary.TypeofNodeGen;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @TypeSystemReference(RTypes.class)
+@ImportStatic({ForeignArray2R.class, Message.class})
 public abstract class CastTypeNode extends RBaseNode {
 
     protected static final int NUMBER_OF_TYPES = RType.values().length;
@@ -61,6 +67,17 @@ public abstract class CastTypeNode extends RBaseNode {
         return null;
     }
 
+    @SuppressWarnings("unused")
+    @Specialization(guards = {"isForeignVector(value, hasSize)", "typeof.execute(value) != type",
+                    "type == cachedType", "!isNull(cast)"}, limit = "NUMBER_OF_TYPES")
+    protected static Object doCast(TruffleObject value, RType type,
+                    @Cached("type") RType cachedType,
+                    @Cached("createCast(cachedType)") CastNode cast,
+                    @Cached("HAS_SIZE.createNode()") Node hasSize,
+                    @Cached("create()") ForeignArray2R foreignArray2R) {
+        return cast.doCast(foreignArray2R.convert(value));
+    }
+
     @TruffleBoundary
     public static CastNode createCast(RType type) {
         return createCast(type, false, false, false, false);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java
index ffdfab68ea918cbe80bf88469a394ffd12e36050..e19e652678ef3909ff9129e9dec30b32fc186e1f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java
@@ -23,30 +23,27 @@
 package com.oracle.truffle.r.nodes.builtin.casts;
 
 import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 
-@ImportStatic({ForeignArray2R.class, Message.class})
+@ImportStatic({ForeignArray2R.class})
 public abstract class CastForeignNode extends CastNode {
 
     protected CastForeignNode() {
     }
 
-    @Specialization(guards = {"isForeignVector(obj, hasSize)"})
+    @Specialization(guards = {"foreignArray2R.isForeignVector(obj)"})
     protected Object castForeign(TruffleObject obj,
-                    @Cached("HAS_SIZE.createNode()") @SuppressWarnings("unused") Node hasSize,
                     @Cached("create()") ForeignArray2R foreignArray2R) {
         return foreignArray2R.convert(obj);
     }
 
-    @Fallback
-    protected Object passThrough(Object x) {
-        return x;
+    @Specialization(guards = {"!foreignArray2R.isForeignVector(obj)"})
+    protected Object passThrough(Object obj,
+                    @Cached("create()") ForeignArray2R foreignArray2R) {
+        return obj;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
index 9e70abd64665b293003018354688c1fc2cbe9285..db740ca48618cb897780231a7e813f32b7007cb3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
@@ -61,11 +61,16 @@ public abstract class GetNonSharedNode extends Node {
     }
 
     @Specialization(guards = "shareable.getClass() == shareableClass")
-    protected RTypedValue getNonShared(RSharingAttributeStorage shareable,
+    protected RTypedValue getNonSharedCached(RSharingAttributeStorage shareable,
                     @Cached("shareable.getClass()") Class<? extends RSharingAttributeStorage> shareableClass) {
         return shareableClass.cast(shareable).getNonShared();
     }
 
+    @Specialization(replaces = "getNonSharedCached")
+    protected RTypedValue getNonShared(RSharingAttributeStorage shareable) {
+        return shareable.getNonShared();
+    }
+
     @Fallback
     protected Object getNonShared(Object o) {
         RSharingAttributeStorage.verify(o);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
index bb0ee89090157db4a9aa1b38e2e6145d16efea89..4f2f375192eb681092cf8f87eef33ad04c367e80 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
@@ -28,9 +28,7 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
-import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
@@ -60,7 +58,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  * (e.g. logical). The only situation where semantics of finite is different to na.rm is double
  * values: na.rm removes NA and NaN, but not -/+Inf.
  */
-@ImportStatic({ForeignArray2R.class, Message.class, RRuntime.class})
+@ImportStatic({RRuntime.class})
 @TypeSystemReference(RTypes.class)
 public abstract class UnaryArithmeticReduceNode extends RBaseNode {
 
@@ -376,13 +374,15 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         return handleString(operand, naRm, finite, 0);
     }
 
-    @Specialization(guards = {"isForeignVector(obj, hasSize)"})
+    @Specialization(guards = {"isForeignObject(obj)"})
     protected Object doForeignVector(TruffleObject obj, boolean naRm, boolean finite,
-                    @Cached("HAS_SIZE.createNode()") @SuppressWarnings("unused") Node hasSize,
                     @Cached("create()") ForeignArray2R foreignArray2R,
                     @Cached("createRecursive()") UnaryArithmeticReduceNode recursive) {
-        Object vec = foreignArray2R.convert(obj);
-        return recursive.executeReduce(vec, naRm, finite);
+        if (foreignArray2R.isForeignVector(obj)) {
+            Object vec = foreignArray2R.convert(obj);
+            return recursive.executeReduce(vec, naRm, finite);
+        }
+        return doFallback(obj, naRm, finite);
     }
 
     @Fallback
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
index 37f5bbd40577900255b8c0621df9436f424fe470..acd72feaf1484c0c8e4a36165d7538c523617628 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
@@ -32,9 +32,7 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -55,7 +53,7 @@ import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
-@ImportStatic({ForeignArray2R.class, Message.class})
+@ImportStatic({RRuntime.class})
 @RBuiltin(name = "!", kind = PRIMITIVE, parameterNames = {""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
 public abstract class UnaryNotNode extends RBuiltinNode.Arg1 {
 
@@ -219,13 +217,15 @@ public abstract class UnaryNotNode extends RBuiltinNode.Arg1 {
         return RDataFactory.createEmptyLogicalVector();
     }
 
-    @Specialization(guards = {"isForeignVector(obj, hasSize)"})
+    @Specialization(guards = {"isForeignObject(obj)"})
     protected Object doForeign(VirtualFrame frame, TruffleObject obj,
-                    @Cached("HAS_SIZE.createNode()") @SuppressWarnings("unused") Node hasSize,
                     @Cached("create()") ForeignArray2R foreignArray2R,
                     @Cached("createRecursive()") UnaryNotNode recursive) {
-        Object vec = foreignArray2R.convert(obj);
-        return recursive.execute(frame, vec);
+        if (foreignArray2R.isForeignVector(obj)) {
+            Object vec = foreignArray2R.convert(obj);
+            return recursive.execute(frame, vec);
+        }
+        return invalidArgType(obj);
     }
 
     protected UnaryNotNode createRecursive() {
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 e9380c9401879609108663d3c69cd1a083a183d3..bb59cfc10cae05de573a6806be5509dc8c48a24c 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
@@ -360,7 +360,7 @@ public abstract class ForeignArray2R extends RBaseNode {
         return RRuntime.isForeignObject(obj) && ForeignAccess.sendHasSize(hasSize, (TruffleObject) obj);
     }
 
-    protected boolean isForeignVector(Object obj) {
+    public boolean isForeignVector(Object obj) {
         return isJavaIterable(obj) || isForeignArray(obj, hasSize);
     }
 
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 8bd5b6e68b9563df6f49186b63f669d347e3d5a5..a427b2e44237e58209a85f48549e645fc59e6d1f 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
@@ -142382,6 +142382,35 @@ NULL
 #if (!any(R.version$engine == "FastR")) { as.character(list()) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listEmpty); }
 character(0)
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testElseIf#
+#if (!any(R.version$engine == "FastR")) { c(1,1,1) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); ifelse(ta$integerArray, 1, 2) }
+[1] 1 1 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testElseIf#
+#if (!any(R.version$engine == "FastR")) { c(1,1,1) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); ifelse(ta$integerList, 1, 2) }
+[1] 1 1 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testElseIf#
+#if (!any(R.version$engine == "FastR")) { c(1,2,1) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); ifelse(ta$booleanArray, 1, 2) }
+[1] 1 2 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testElseIf#
+#if (!any(R.version$engine == "FastR")) { c(1,2,1) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); ifelse(ta$booleanList, 1, 2) }
+[1] 1 2 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testElseIf#
+#if (!any(R.version$engine == "FastR")) { c(NA, NA, NA) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); ifelse(ta$stringArray, 1, 2) }
+[1] NA NA NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testElseIf#
+#if (!any(R.version$engine == "FastR")) { c(NA, NA, NA) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); ifelse(ta$stringList, 1, 2) }
+[1] NA NA NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testElseIf#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.logical(test) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a vector', '<<<NEWLINE>>>') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); ifelse(ta) }
+Error in as.logical(test) :
+  no method for coercing this external object to a vector
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
 #if (!any(R.version$engine == "FastR")) { "a string" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticStringObject }
 [1] "a string"
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 be1cf379799e363f55dc5535dc2c570676c7a42f..ad80239ab65b27287f05fd591b93272cae55e0a4 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
@@ -1102,6 +1102,17 @@ public class TestJavaInterop extends TestBase {
         assertEvalFastR(CREATE_TRUFFLE_OBJECT + "for(i in to$listInteger) print(i)", "for(i in c(1,2,3)) print(i)");
     }
 
+    @Test
+    public void testElseIf() throws IllegalArgumentException {
+        assertEvalFastR(CREATE_TEST_ARRAYS + " ifelse(ta)", errorIn("as.logical(test)", "no method for coercing this external object to a vector"));
+        assertEvalFastR(CREATE_TEST_ARRAYS + " ifelse(ta$booleanArray, 1, 2)", "c(1,2,1)");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " ifelse(ta$booleanList, 1, 2)", "c(1,2,1)");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " ifelse(ta$integerArray, 1, 2)", "c(1,1,1)");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " ifelse(ta$integerList, 1, 2)", "c(1,1,1)");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " ifelse(ta$stringArray, 1, 2)", "c(NA, NA, NA)");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " ifelse(ta$stringList, 1, 2)", "c(NA, NA, NA)");
+    }
+
     @Test
     public void testForeignVectorArithmeticOp() throws NoSuchFieldException,
                     IllegalAccessException {