diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
similarity index 97%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
index 0e432013b9279e2c8039d227160ed1200ac3b982..7a3a51a35b1df717d12b2d2e22cdfb39ef0be89e 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue;
@@ -78,6 +78,9 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
@@ -93,6 +96,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -331,10 +335,10 @@ public class CastBuilderTest {
     public void testFindFirstWithoutDefaultValue() {
         arg.asIntegerVector().findFirst();
 
-        assertCastFail(RNull.instance, "argument is of length zero");
-        assertCastFail(RMissing.instance, "argument is of length zero");
-        assertCastFail(RDataFactory.createIntVector(0), "argument is of length zero");
-        assertCastFail(RDataFactory.createList(), "argument is of length zero");
+        assertCastFail(RNull.instance, "invalid 'x' argument");
+        assertCastFail(RMissing.instance, "invalid 'x' argument");
+        assertCastFail(RDataFactory.createIntVector(0), "invalid 'x' argument");
+        assertCastFail(RDataFactory.createList(), "invalid 'x' argument");
         assertEquals(1, cast(1));
         assertEquals(1, cast(RDataFactory.createIntVector(new int[]{1, 2}, true)));
         assertEquals(1, cast("1"));
@@ -399,7 +403,7 @@ public class CastBuilderTest {
         arg.asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         assertEquals(Boolean.TRUE, cast(RRuntime.LOGICAL_TRUE));
         assertEquals(Boolean.FALSE, cast(RRuntime.LOGICAL_FALSE));
-        assertEquals(Boolean.FALSE, cast(RRuntime.LOGICAL_NA));
+        assertEquals(Boolean.TRUE, cast(RRuntime.LOGICAL_NA));
         assertEquals(Boolean.TRUE, cast(RDataFactory.createLogicalVector(new byte[]{RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE}, true)));
         assertEquals(Boolean.FALSE, cast(RDataFactory.createLogicalVector(0)));
         testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES);
@@ -872,6 +876,17 @@ public class CastBuilderTest {
         Assert.assertEquals(RError.Message.NA_INTRODUCED_COERCION.message, CastNode.getLastWarning());
     }
 
+    private static final RFunction DUMMY_FUNCTION = RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, null, null, null);
+
+    @Test
+    public void testReturnIfFunction() {
+        arg.allowNull().returnIf(instanceOf(RFunction.class)).asVector(false);
+        RFunction f = DUMMY_FUNCTION;
+        Object o = cast(f);
+        assertEquals(f, o);
+        testPipeline();
+    }
+
     /**
      * Casts given object using the configured pipeline in {@link #arg}.
      */
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java
similarity index 99%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java
index 00c93678c1e568fb04532789c84c1b124bc5354d..6b0be76aefe437245aeba7c56845903f0425c6d0 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import java.io.Serializable;
 import java.lang.reflect.Type;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
similarity index 99%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
index d45c80d6e1fe993e32ad0156bf913378d7fae275..3cfa577f864115872c0ad8d9f93ce70677ce63d8 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
@@ -62,12 +62,13 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.oracle.truffle.r.nodes.builtin.CastBuilderTest.DummyBuiltin;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.casts.MarkLookup;
 import com.oracle.truffle.r.nodes.casts.ResultTypesAnalyser;
 import com.oracle.truffle.r.nodes.casts.TypeExpr;
+import com.oracle.truffle.r.nodes.castsTests.CastBuilderTest.DummyBuiltin;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
similarity index 99%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
index 52e252a03528f8d642709f1571a535be1a5a2e4d..38f3f15c260a340b239dd0f24d2b5aaba0cc0944 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue;
@@ -57,10 +57,11 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.oracle.truffle.r.nodes.builtin.CastBuilderTest.DummyBuiltin;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.casts.SamplesCollector;
+import com.oracle.truffle.r.nodes.castsTests.CastBuilderTest.DummyBuiltin;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java
similarity index 99%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java
index a0161958213542f52ae3227e89408d16c0ba9039..c9fa1f4d53d1d7fbaba8aa9e8e1d77466e83ed0b 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import static com.oracle.truffle.r.nodes.casts.Not.negateType;
 import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index d00f5c16cbf2060273e529e0aa67c0f92fbce916..1a2e496913bcdd4e3d6d403e5c302cc84999bb60 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -147,7 +147,7 @@ public final class PipelineToCastNode {
                     prevCastNode = node;
                 } else {
                     CastNode finalPrevCastNode = prevCastNode;
-                    prevCastNode = new ChainedCastNode(finalPrevCastNode, node);
+                    prevCastNode = new ChainedCastNode(finalPrevCastNode, node, currCastStep.getNext() == null);
                 }
             }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
index fb0da67ec9e94116f2fbd052753947b78464b0b4..ba239b34feb2c0427d0447e3e5169347a20a3826 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
@@ -37,17 +37,24 @@ public final class ChainedCastNode extends CastNode {
     @Child private CastNode firstCast;
     @Child private CastNode secondCast;
 
-    public ChainedCastNode(CastNode firstCast, CastNode secondCast) {
+    private final boolean isFirstNode;
+
+    public ChainedCastNode(CastNode firstCast, CastNode secondCast, boolean isFirstNode) {
         this.firstCast = firstCast;
         this.secondCast = secondCast;
+        this.isFirstNode = isFirstNode;
     }
 
     @Override
     public Object execute(Object value) {
-        try {
+        if (isFirstNode) {
+            try {
+                return secondCast.execute(firstCast.execute(value));
+            } catch (PipelineReturnException ex) {
+                return ex.getResult();
+            }
+        } else {
             return secondCast.execute(firstCast.execute(value));
-        } catch (PipelineReturnException ex) {
-            return ex.getResult();
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 364e2d84845ab4342aec11ec046c780fefad8c6f..2c4d20041dfc60f61961441f60a1c0c3ee2d4dc7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -277,8 +277,8 @@ public class RRuntime {
         return b == LOGICAL_TRUE;
     }
 
-    public static boolean fromLogical(byte b, boolean naValue) {
-        return naValue ? b != LOGICAL_FALSE : b == LOGICAL_TRUE;
+    public static boolean fromLogical(byte b, boolean naReplacement) {
+        return naReplacement ? b != LOGICAL_FALSE : b == LOGICAL_TRUE;
     }
 
     // conversions from logical