diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
index db90dae6c50d38ff99d11dd4e0073fa4f1846018..a81e194adf7fd2e3bade2b07eff2102740d98f8a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
@@ -243,7 +243,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         }
 
         if (!isList() && value instanceof RAbstractVector) {
-            value = ((RAbstractVector) value).castSafe(castType, valueIsNA);
+            value = ((RAbstractVector) value).castSafe(castType, valueIsNA, false);
         }
 
         vector = share(vector, value);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
index 009a71466344b12089f6fe90ff57ad6707b7c615..164d40610dfc4da9704996e4c9fdb816c29071a2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
@@ -127,8 +127,8 @@ public final class BinaryMapNode extends RBaseNode {
         RAbstractVector left = leftClass.cast(originalLeft);
         RAbstractVector right = rightClass.cast(originalRight);
 
-        RAbstractVector leftCast = left.castSafe(argumentType, leftIsNAProfile);
-        RAbstractVector rightCast = right.castSafe(argumentType, rightIsNAProfile);
+        RAbstractVector leftCast = left.castSafe(argumentType, leftIsNAProfile, false);
+        RAbstractVector rightCast = right.castSafe(argumentType, rightIsNAProfile, false);
 
         assert leftCast != null;
         assert rightCast != null;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
index cd8529b1b18f68f0d9cf00a2af637a0401170548..2ff5495c46850a8c5609786bf23324e65d99b800 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
@@ -40,14 +40,23 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 public abstract class CastBaseNode extends CastNode {
 
+    protected static boolean isReusable(RAbstractVector v) {
+        if (v instanceof RSharingAttributeStorage) {
+            return !((RSharingAttributeStorage) v).isShared();
+        }
+        return false;
+    }
+
     private final BranchProfile listCoercionErrorBranch = BranchProfile.create();
     private final ConditionProfile hasDimNamesProfile = ConditionProfile.createBinaryProfile();
     private final NullProfile hasDimensionsProfile = NullProfile.create();
@@ -90,10 +99,14 @@ public abstract class CastBaseNode extends CastNode {
         return preserveDimensions;
     }
 
-    public final boolean preserveAttributes() {
+    public final boolean preserveRegAttributes() {
         return preserveAttributes;
     }
 
+    public final boolean preserveAttributes() {
+        return preserveAttributes || preserveNames || preserveDimensions;
+    }
+
     protected abstract RType getTargetType();
 
     protected RError throwCannotCoerceListError(String type) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
index 88151421902d9518fbfeb23035b5ca4e27bcce3e..6ffad041e4fb8487ba00969848c3f334541226bc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
@@ -76,7 +76,7 @@ public abstract class CastComplexNode extends CastBaseNode {
     private Object castComplexRecursive(Object o) {
         if (recursiveCastComplex == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastComplex = insert(CastComplexNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes()));
+            recursiveCastComplex = insert(CastComplexNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes()));
         }
         return recursiveCastComplex.executeComplex(o);
     }
@@ -151,7 +151,7 @@ public abstract class CastComplexNode extends CastBaseNode {
         }
         RComplexVector ret = RDataFactory.createComplexVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
@@ -204,7 +204,7 @@ public abstract class CastComplexNode extends CastBaseNode {
         }
         RComplexVector ret = RDataFactory.createComplexVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
@@ -258,7 +258,7 @@ public abstract class CastComplexNode extends CastBaseNode {
             }
         }
         RComplexVector ret = RDataFactory.createComplexVector(result, !seenNA, getPreservedDimensions(list), getPreservedNames(list));
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(list);
         }
         return ret;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
index 24744b62d9a5544fdd8b24882f301fe42e57dae6..9abeb67a8dbd105abcaf074d9907ab0aae07ff15 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.unary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.function.opt.IsNonSharedNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
@@ -41,8 +40,6 @@ public abstract class CastDoubleBaseNode extends CastBaseNode {
     protected final NACheck naCheck = NACheck.create();
     protected final NAProfile naProfile = NAProfile.create();
 
-    @Child protected IsNonSharedNode reuseNonShared = IsNonSharedNode.create();
-
     protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
         super(preserveNames, preserveDimensions, preserveAttributes);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
index a8a666872041f5a8c4c8a22cdcddd11d46cbb74d..39060fa71a69d58f3156c6a12c2fbb2919de3939 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
@@ -67,7 +67,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
     private Object castDoubleRecursive(Object o) {
         if (recursiveCastDouble == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastDouble = insert(CastDoubleNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes()));
+            recursiveCastDouble = insert(CastDoubleNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes()));
         }
         return recursiveCastDouble.executeDouble(o);
     }
@@ -75,7 +75,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
     private RDoubleVector vectorCopy(RAbstractContainer operand, double[] data, boolean isComplete) {
         RDoubleVector ret = RDataFactory.createDoubleVector(data, isComplete, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
@@ -95,18 +95,12 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
 
     @Specialization
     protected RAbstractDoubleVector doIntVector(RAbstractIntVector operand) {
-        if (reuseNonShared.execute(operand)) {
-            return (RAbstractDoubleVector) operand.castSafe(RType.Double, naProfile.getConditionProfile());
-        }
-        return createResultVector(operand, index -> naCheck.convertIntToDouble(operand.getDataAt(index)));
+        return castWithReuse(operand, index -> naCheck.convertIntToDouble(operand.getDataAt(index)));
     }
 
     @Specialization
     protected RAbstractDoubleVector doLogicalVectorDims(RAbstractLogicalVector operand) {
-        if (reuseNonShared.execute(operand)) {
-            return (RAbstractDoubleVector) operand.castSafe(RType.Double, naProfile.getConditionProfile());
-        }
-        return createResultVector(operand, index -> naCheck.convertLogicalToDouble(operand.getDataAt(index)));
+        return castWithReuse(operand, index -> naCheck.convertLogicalToDouble(operand.getDataAt(index)));
     }
 
     @Specialization
@@ -140,7 +134,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
         }
         RDoubleVector ret = RDataFactory.createDoubleVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
@@ -166,10 +160,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
 
     @Specialization
     protected RAbstractDoubleVector doRawVector(RRawVector operand) {
-        if (reuseNonShared.execute(operand)) {
-            return (RAbstractDoubleVector) operand.castSafe(RType.Double, naProfile.getConditionProfile());
-        }
-        return createResultVector(operand, index -> RRuntime.raw2double(operand.getDataAt(index)));
+        return castWithReuse(operand, index -> RRuntime.raw2double(operand.getDataAt(index)));
     }
 
     @Specialization
@@ -217,7 +208,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
             }
         }
         RDoubleVector ret = RDataFactory.createDoubleVector(result, !seenNA, getPreservedDimensions(list), getPreservedNames(list));
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(list);
         }
         return ret;
@@ -239,6 +230,13 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
         throw error(RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "vector");
     }
 
+    private RAbstractDoubleVector castWithReuse(RAbstractVector v, IntToDoubleFunction elementFunction) {
+        if (isReusable(v)) {
+            return (RAbstractDoubleVector) v.castSafe(RType.Double, naProfile.getConditionProfile(), preserveAttributes());
+        }
+        return createResultVector(v, elementFunction);
+    }
+
     public static CastDoubleNode create() {
         return CastDoubleNodeGen.create(true, true, true);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
index dc79c02b5f39ffc9223f8325157dececc441c961..18c5757508adf68eee8a90bbba2db0354c08867f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
@@ -57,7 +57,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode {
     protected Object castIntegerRecursive(Object o) {
         if (recursiveCastInteger == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes()));
+            recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes()));
         }
         return recursiveCastInteger.executeInt(o);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
index aff2149c234a85ef32c501a5c04ebbd60f18964f..de06208d8ae22aa300ad17632c7895a5f3113a71 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -86,7 +87,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
     private RIntVector vectorCopy(RAbstractVector operand, int[] idata, boolean isComplete) {
         RIntVector ret = RDataFactory.createIntVector(idata, isComplete, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
@@ -160,8 +161,8 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
     }
 
     @Specialization
-    public RIntVector doLogicalVector(RAbstractLogicalVector operand) {
-        return createResultVector(operand, index -> naCheck.convertLogicalToInt(operand.getDataAt(index)));
+    public RAbstractIntVector doLogicalVector(RAbstractLogicalVector operand) {
+        return castWithReuse(operand, index -> naCheck.convertLogicalToInt(operand.getDataAt(index)));
     }
 
     @Specialization
@@ -209,7 +210,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
             }
         }
         RIntVector ret = RDataFactory.createIntVector(result, !seenNA, getPreservedDimensions(list), getPreservedNames(list));
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(list);
         }
         return ret;
@@ -241,6 +242,13 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
         return arg instanceof RIntVector;
     }
 
+    private RAbstractIntVector castWithReuse(RAbstractVector v, IntToIntFunction elementFunction) {
+        if (isReusable(v)) {
+            return (RAbstractIntVector) v.castSafe(RType.Integer, naProfile.getConditionProfile(), preserveAttributes());
+        }
+        return createResultVector(v, elementFunction);
+    }
+
     public static CastIntegerNode create() {
         return CastIntegerNodeGen.create(true, true, true);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
index a569b25f638246f6848612d73d5f7a973779927e..72b6158aa0612f0ee0b8e4538a46d27534daaf22 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
@@ -96,7 +96,7 @@ public abstract class CastListNode extends CastBaseNode {
         }
         RList ret = RDataFactory.createList(data, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
index 9080f05e09a9f6421d18f00831fee0b042d63316..823521698e1a50cd5f95e8f73db19f7fc1962a65 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
@@ -67,7 +67,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode {
     protected Object castLogicalRecursive(Object o) {
         if (recursiveCastLogical == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastLogical = insert(CastLogicalNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes()));
+            recursiveCastLogical = insert(CastLogicalNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes()));
         }
         return recursiveCastLogical.execute(o);
     }
@@ -93,7 +93,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode {
     private RLogicalVector vectorCopy(RAbstractVector operand, byte[] bdata, boolean isComplete) {
         RLogicalVector ret = RDataFactory.createLogicalVector(bdata, isComplete, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
@@ -182,7 +182,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode {
             }
         }
         RLogicalVector ret = RDataFactory.createLogicalVector(result, !seenNA, getPreservedDimensions(list), getPreservedNames(list));
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(list);
         }
         return ret;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
index c66438279a68fe416dead3725adc170253c3d9ac..44b0149e20f5b7a5f4ccdaa3dc216fadb01a3d16 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
@@ -69,7 +69,7 @@ public abstract class CastRawNode extends CastBaseNode {
     protected Object castRawRecursive(Object o) {
         if (recursiveCastRaw == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastRaw = insert(CastRawNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes()));
+            recursiveCastRaw = insert(CastRawNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes()));
         }
         return recursiveCastRaw.executeRaw(o);
     }
@@ -157,7 +157,7 @@ public abstract class CastRawNode extends CastBaseNode {
     private RRawVector vectorCopy(RAbstractVector operand, byte[] bdata) {
         RRawVector ret = RDataFactory.createRawVector(bdata, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
@@ -306,7 +306,7 @@ public abstract class CastRawNode extends CastBaseNode {
             data[i] = ((RRaw) castRawRecursive(value.getDataAt(i))).getValue();
         }
         RRawVector result = RDataFactory.createRawVector(data, getPreservedDimensions(value), getPreservedNames(value));
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             result.copyRegAttributesFrom(value);
         }
         return result;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
index 1f413ee259640ac3c92cebc25bf33a3190a21733..ebec5af6e485d4e7016ec3162bad1b624eaaeb59 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
@@ -64,7 +64,7 @@ public abstract class CastStringNode extends CastStringBaseNode {
     private RStringVector vectorCopy(RAbstractContainer operand, String[] data) {
         RStringVector ret = RDataFactory.createStringVector(data, operand.isComplete(), getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
-        if (preserveAttributes()) {
+        if (preserveRegAttributes()) {
             ret.copyRegAttributesFrom(operand);
         }
         return ret;
@@ -133,7 +133,7 @@ public abstract class CastStringNode extends CastStringBaseNode {
     private Object castStringRecursive(Object o) {
         if (recursiveCastString == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastString = insert(CastStringNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes()));
+            recursiveCastString = insert(CastStringNodeGen.create(preserveNames(), preserveDimensions(), preserveRegAttributes()));
         }
         return recursiveCastString.executeString(o);
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
index e928ee140a045b2c9bc89268f8e28fe1964c11b2..af6a3028bc427305beaf140ce954cc6adc365b8d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
@@ -52,7 +52,7 @@ public final class RComplex extends RScalarVector implements RAbstractComplexVec
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Complex:
                 return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
index 5e7b39ec4557d4a3b697acabcdb3d287f08a7a4e..f8c0488a44e0c579aa393c39f7e671c8471297b4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
@@ -64,14 +64,14 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Complex:
                 return this;
             case Character:
-                return RClosures.createToStringVector(this);
+                return RClosures.createToStringVector(this, keepAttributes);
             case List:
-                return RClosures.createToListVector(this);
+                return RClosures.createToListVector(this, keepAttributes);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
index 1a034e6bf2826b734c754652aeed229adb94dc5d..6a66889e9cdeacff4129c7ab932ead664ee736bb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
@@ -53,7 +53,7 @@ public final class RDouble extends RScalarVector implements RAbstractDoubleVecto
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Integer:
                 return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
index 2cf039de0743c86ed84b3f189fd24d5a9522dc78..a94cce37d00277922034d1d28749b204d1ebf17c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
@@ -70,19 +70,19 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         // TODO might be possible to implement some of these without closures
         switch (type) {
             case Integer:
-                return RClosures.createToIntVector(this);
+                return RClosures.createToIntVector(this, keepAttributes);
             case Double:
                 return this;
             case Complex:
-                return RClosures.createToComplexVector(this);
+                return RClosures.createToComplexVector(this, keepAttributes);
             case Character:
-                return RClosures.createToStringVector(this);
+                return RClosures.createToStringVector(this, keepAttributes);
             case List:
-                return RClosures.createToListVector(this);
+                return RClosures.createToListVector(this, keepAttributes);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
index e4eace8649f0ecd70396b1798ab2db31860fe6db..52366b1ae86c5a4e41c6927140452ebbe52043c8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
@@ -48,18 +48,18 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Integer:
-                return RClosures.createToIntVector(this);
+                return RClosures.createToIntVector(this, keepAttributes);
             case Double:
                 return this;
             case Complex:
-                return RClosures.createToComplexVector(this);
+                return RClosures.createToComplexVector(this, keepAttributes);
             case Character:
-                return RClosures.createToStringVector(this);
+                return RClosures.createToStringVector(this, keepAttributes);
             case List:
-                return RClosures.createToListVector(this);
+                return RClosures.createToListVector(this, keepAttributes);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
index a5aea4b6f6ca4347adebbbf7248a22d8d0c3dc83..402dc97ac493f9fb5c52e46240f1c83a041e45ae 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
@@ -48,18 +48,18 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Integer:
                 return this;
             case Double:
                 return RDataFactory.createDoubleSequence(getStart(), getStride(), getLength());
             case Complex:
-                return RClosures.createToComplexVector(this);
+                return RClosures.createToComplexVector(this, keepAttributes);
             case Character:
-                return RClosures.createToStringVector(this);
+                return RClosures.createToStringVector(this, keepAttributes);
             case List:
-                return RClosures.createToListVector(this);
+                return RClosures.createToListVector(this, keepAttributes);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
index 8fa15af2a36250faf14c7d2bd464ece0d2be187c..d95bb428e4a28c9fed63b1a57ae8527276bf708f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
@@ -48,18 +48,18 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Integer:
                 return this;
             case Double:
-                return RClosures.createToDoubleVector(this);
+                return RClosures.createToDoubleVector(this, keepAttributes);
             case Complex:
-                return RClosures.createToComplexVector(this);
+                return RClosures.createToComplexVector(this, keepAttributes);
             case Character:
-                return RClosures.createToStringVector(this);
+                return RClosures.createToStringVector(this, keepAttributes);
             case List:
-                return RClosures.createToListVector(this);
+                return RClosures.createToListVector(this, keepAttributes);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java
index 3a618e1ff53c4c1f638f1543806c1e276cc4829d..eb0ea1f399ffd83e2dd88f286e7ec133c0467735 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java
@@ -62,7 +62,7 @@ public final class RInteger extends RScalarVector implements RAbstractIntVector
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Integer:
                 return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
index b0a64de5abacb4d56adc4cb4dd8111e27687eb0e..7fade92f1bed1c2e7ebb42f3232d09a46e5c6184 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
@@ -55,7 +55,7 @@ public final class RLogical extends RScalarVector implements RAbstractLogicalVec
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Logical:
                 return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
index 3a1a9ebb4f4cbaaa1541878964a135926363ebcf..3bde20df8e776d6571b91dd07dee09db4b6c2988 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
@@ -48,20 +48,20 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Logical:
                 return this;
             case Integer:
-                return RClosures.createToIntVector(this);
+                return RClosures.createToIntVector(this, keepAttributes);
             case Double:
-                return RClosures.createToDoubleVector(this);
+                return RClosures.createToDoubleVector(this, keepAttributes);
             case Complex:
-                return RClosures.createToComplexVector(this);
+                return RClosures.createToComplexVector(this, keepAttributes);
             case Character:
-                return RClosures.createToStringVector(this);
+                return RClosures.createToStringVector(this, keepAttributes);
             case List:
-                return RClosures.createToListVector(this);
+                return RClosures.createToListVector(this, keepAttributes);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
index 0c55726d53efdf18f95c15a6b20d7f417302a930..b88afcc338f6d90911ef2b781574012345ee81fb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
@@ -45,7 +45,7 @@ public final class RRaw extends RScalarVector implements RAbstractRawVector {
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Raw:
                 return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
index 85c9947b3c887b134cd18a779929d3fa630e9e36..26252b7da5746b0efdfd06af7ed539a09ff6c070 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
@@ -48,18 +48,18 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Raw:
                 return this;
             case Integer:
-                return RClosures.createToIntVector(this);
+                return RClosures.createToIntVector(this, keepAttributes);
             case Double:
-                return RClosures.createToDoubleVector(this);
+                return RClosures.createToDoubleVector(this, keepAttributes);
             case Complex:
-                return RClosures.createToComplexVector(this);
+                return RClosures.createToComplexVector(this, keepAttributes);
             case Character:
-                return RClosures.createToStringVector(this);
+                return RClosures.createToStringVector(this, keepAttributes);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java
index 48e050c17b68e3dafd469bbb20dea8e73cc5e2be..1ea23adc66f510252e67c8aa0696a03e7e9d2993 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java
@@ -57,7 +57,7 @@ public final class RScalarList extends RScalarVector implements RAbstractListVec
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case List:
                 return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java
index 98b4b5653f6f931907b8fb5b23b83b26ad582e82..abf51a343f797352297a0a94155670ef897b5d5b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java
@@ -48,7 +48,7 @@ public final class RString extends RScalarVector implements RAbstractStringVecto
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Character:
                 return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
index 712b3deb8dc0cb22f6c21155f4b7fd08e5253fe6..38fdbb99181b237ae911db36a6074201c5ed22c3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
@@ -49,12 +49,12 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttributes) {
         switch (type) {
             case Character:
                 return this;
             case List:
-                return RClosures.createToListVector(this);
+                return RClosures.createToListVector(this, keepAttributes);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
index 91dddf4b5fe7e541eeaaafa46cffb8c54bd08338..1cc4294efa9d58eb83760855b4e1a146a83c62dd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
@@ -43,133 +43,197 @@ public class RClosures {
 
     // Logical to ...
 
-    public static RAbstractIntVector createToIntVector(RLogicalVector vector) {
-        return new RLogicalToIntVectorClosure(vector);
+    public static RAbstractIntVector createToIntVector(RLogicalVector vector, boolean keepAttributes) {
+        return new RLogicalToIntVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractDoubleVector createToDoubleVector(RLogicalVector vector) {
-        return new RLogicalToDoubleVectorClosure(vector);
+    public static RAbstractDoubleVector createToDoubleVector(RLogicalVector vector, boolean keepAttributes) {
+        return new RLogicalToDoubleVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractComplexVector createToComplexVector(RLogicalVector vector) {
-        return new RLogicalToComplexVectorClosure(vector);
+    public static RAbstractComplexVector createToComplexVector(RLogicalVector vector, boolean keepAttributes) {
+        return new RLogicalToComplexVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractStringVector createToStringVector(RLogicalVector vector) {
-        return new RLogicalToStringVectorClosure(vector);
+    public static RAbstractStringVector createToStringVector(RLogicalVector vector, boolean keepAttributes) {
+        return new RLogicalToStringVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractListVector createToListVector(RLogicalVector vector) {
-        return new RLogicalToListVectorClosure(vector);
+    public static RAbstractListVector createToListVector(RLogicalVector vector, boolean keepAttributes) {
+        return new RLogicalToListVectorClosure(vector, keepAttributes);
     }
 
     // Int to ...
 
-    public static RAbstractComplexVector createToComplexVector(RIntSequence vector) {
-        return new RIntSequenceToComplexVectorClosure(vector);
+    public static RAbstractComplexVector createToComplexVector(RIntSequence vector, boolean keepAttributes) {
+        return new RIntSequenceToComplexVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractStringVector createToStringVector(RIntSequence vector) {
-        return new RIntSequenceToStringVectorClosure(vector);
+    public static RAbstractStringVector createToStringVector(RIntSequence vector, boolean keepAttributes) {
+        return new RIntSequenceToStringVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractListVector createToListVector(RIntSequence vector) {
-        return new RIntSequenceToListVectorClosure(vector);
+    public static RAbstractListVector createToListVector(RIntSequence vector, boolean keepAttributes) {
+        return new RIntSequenceToListVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractDoubleVector createToDoubleVector(RIntVector vector) {
-        return new RIntToDoubleVectorClosure(vector);
+    public static RAbstractDoubleVector createToDoubleVector(RIntVector vector, boolean keepAttributes) {
+        return new RIntToDoubleVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractComplexVector createToComplexVector(RIntVector vector) {
-        return new RIntToComplexVectorClosure(vector);
+    public static RAbstractComplexVector createToComplexVector(RIntVector vector, boolean keepAttributes) {
+        return new RIntToComplexVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractStringVector createToStringVector(RIntVector vector) {
-        return new RIntToStringVectorClosure(vector);
+    public static RAbstractStringVector createToStringVector(RIntVector vector, boolean keepAttributes) {
+        return new RIntToStringVectorClosure(vector, keepAttributes);
     }
 
-    public static RAbstractListVector createToListVector(RIntVector vector) {
-        return new RIntToListVectorClosure(vector);
+    public static RAbstractListVector createToListVector(RIntVector vector, boolean keepAttributes) {
+        return new RIntToListVectorClosure(vector, keepAttributes);
     }
 
     // Double to ...
 
     public static RAbstractComplexVector createToComplexVector(RDoubleSequence vector) {
-        return new RDoubleSequenceToComplexVectorClosure(vector);
+        return new RDoubleSequenceToComplexVectorClosure(vector, false);
+    }
+
+    public static RAbstractComplexVector createToComplexVector(RDoubleSequence vector, boolean keepAttributes) {
+        return new RDoubleSequenceToComplexVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractStringVector createToStringVector(RDoubleSequence vector) {
-        return new RDoubleSequenceToStringVectorClosure(vector);
+        return new RDoubleSequenceToStringVectorClosure(vector, false);
+    }
+
+    public static RAbstractStringVector createToStringVector(RDoubleSequence vector, boolean keepAttributes) {
+        return new RDoubleSequenceToStringVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractIntVector createToIntVector(RDoubleSequence vector) {
-        return new RDoubleSequenceToIntVectorClosure(vector);
+        return new RDoubleSequenceToIntVectorClosure(vector, false);
+    }
+
+    public static RAbstractIntVector createToIntVector(RDoubleSequence vector, boolean keepAttributes) {
+        return new RDoubleSequenceToIntVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractListVector createToListVector(RDoubleSequence vector) {
-        return new RDoubleSequenceToListVectorClosure(vector);
+        return new RDoubleSequenceToListVectorClosure(vector, false);
+    }
+
+    public static RAbstractListVector createToListVector(RDoubleSequence vector, boolean keepAttributes) {
+        return new RDoubleSequenceToListVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractComplexVector createToComplexVector(RDoubleVector vector) {
-        return new RDoubleToComplexVectorClosure(vector);
+        return new RDoubleToComplexVectorClosure(vector, false);
+    }
+
+    public static RAbstractComplexVector createToComplexVector(RDoubleVector vector, boolean keepAttributes) {
+        return new RDoubleToComplexVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractStringVector createToStringVector(RDoubleVector vector) {
-        return new RDoubleToStringVectorClosure(vector);
+        return new RDoubleToStringVectorClosure(vector, false);
+    }
+
+    public static RAbstractStringVector createToStringVector(RDoubleVector vector, boolean keepAttributes) {
+        return new RDoubleToStringVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractIntVector createToIntVector(RDoubleVector vector) {
-        return new RDoubleToIntVectorClosure(vector);
+        return new RDoubleToIntVectorClosure(vector, false);
+    }
+
+    public static RAbstractIntVector createToIntVector(RDoubleVector vector, boolean keepAttributes) {
+        return new RDoubleToIntVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractListVector createToListVector(RDoubleVector vector) {
-        return new RDoubleToListVectorClosure(vector);
+        return new RDoubleToListVectorClosure(vector, false);
+    }
+
+    public static RAbstractListVector createToListVector(RDoubleVector vector, boolean keepAttributes) {
+        return new RDoubleToListVectorClosure(vector, keepAttributes);
     }
 
     // Raw to ...
 
     public static RAbstractIntVector createToIntVector(RRawVector vector) {
-        return new RRawToIntVectorClosure(vector);
+        return new RRawToIntVectorClosure(vector, false);
+    }
+
+    public static RAbstractIntVector createToIntVector(RRawVector vector, boolean keepAttributes) {
+        return new RRawToIntVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractDoubleVector createToDoubleVector(RRawVector vector) {
-        return new RRawToDoubleVectorClosure(vector);
+        return new RRawToDoubleVectorClosure(vector, false);
+    }
+
+    public static RAbstractDoubleVector createToDoubleVector(RRawVector vector, boolean keepAttributes) {
+        return new RRawToDoubleVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractComplexVector createToComplexVector(RRawVector vector) {
-        return new RRawToComplexVectorClosure(vector);
+        return new RRawToComplexVectorClosure(vector, false);
+    }
+
+    public static RAbstractComplexVector createToComplexVector(RRawVector vector, boolean keepAttributes) {
+        return new RRawToComplexVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractStringVector createToStringVector(RRawVector vector) {
-        return new RRawToStringVectorClosure(vector);
+        return new RRawToStringVectorClosure(vector, false);
+    }
+
+    public static RAbstractStringVector createToStringVector(RRawVector vector, boolean keepAttributes) {
+        return new RRawToStringVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractListVector createToListVector(RRawVector vector) {
-        return new RRawToListVectorClosure(vector);
+        return new RRawToListVectorClosure(vector, false);
+    }
+
+    public static RAbstractListVector createToListVector(RRawVector vector, boolean keepAttributes) {
+        return new RRawToListVectorClosure(vector, keepAttributes);
     }
 
     // Complex to ...
 
     public static RAbstractStringVector createToStringVector(RComplexVector vector) {
-        return new RComplexToStringVectorClosure(vector);
+        return new RComplexToStringVectorClosure(vector, false);
+    }
+
+    public static RAbstractStringVector createToStringVector(RComplexVector vector, boolean keepAttributes) {
+        return new RComplexToStringVectorClosure(vector, keepAttributes);
     }
 
     public static RAbstractListVector createToListVector(RComplexVector vector) {
-        return new RComplexToListVectorClosure(vector);
+        return new RComplexToListVectorClosure(vector, false);
+    }
+
+    public static RAbstractListVector createToListVector(RComplexVector vector, boolean keepAttributes) {
+        return new RComplexToListVectorClosure(vector, keepAttributes);
     }
 
     // Character to ...
 
-    public static RAbstractListVector createToListVector(RStringVector vector) {
-        return new RStringToListVectorClosure(vector);
+    public static RAbstractListVector createToListVector(RStringVector vector, boolean keepAttributes) {
+        return new RStringToListVectorClosure(vector, keepAttributes);
     }
 
     // Factor to vector
 
     public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RAbstractVector levels) {
+        return createFactorToVector(factor, withNames, levels, false);
+    }
+
+    public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RAbstractVector levels, boolean keepAttributes) {
         if (levels instanceof RAbstractStringVector) {
-            return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames);
+            return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames, keepAttributes);
         } else {
             throw RError.error(RError.SHOW_CALLER, Message.MALFORMED_FACTOR);
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java
index 5cad98744466bd4b3cbba1d60dd3105eca592304..14fd6c978272552ff618e0d6de7bbf44392c94a7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
@@ -37,6 +38,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 
 abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbstractComplexVector {
 
+    protected RToComplexVectorClosure(boolean keepAttributes) {
+        super(keepAttributes);
+    }
+
     @Override
     public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createComplexVector(new double[newLength << 1], newIsComplete);
@@ -52,12 +57,24 @@ abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbst
             result[index] = data.getRealPart();
             result[index + 1] = data.getImaginaryPart();
         }
-        return RDataFactory.createComplexVector(result, getVector().isComplete());
+        RComplexVector materialized = RDataFactory.createComplexVector(result, getVector().isComplete());
+        copyAttributes(materialized);
+        return materialized;
+    }
+
+    @TruffleBoundary
+    private void copyAttributes(RComplexVector materialized) {
+        if (keepAttributes) {
+            materialized.initAttributes(getVector().getAttributes());
+        }
     }
 
     @Override
-    public final RComplexVector copyWithNewDimensions(int[] newDimensions) {
-        return materialize().copyWithNewDimensions(newDimensions);
+    public final RAbstractComplexVector copyWithNewDimensions(int[] newDimensions) {
+        if (!keepAttributes) {
+            return materialize().copyWithNewDimensions(newDimensions);
+        }
+        return this;
     }
 }
 
@@ -65,7 +82,8 @@ final class RLogicalToComplexVectorClosure extends RToComplexVectorClosure imple
 
     private final RLogicalVector vector;
 
-    RLogicalToComplexVectorClosure(RLogicalVector vector) {
+    RLogicalToComplexVectorClosure(RLogicalVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -85,7 +103,8 @@ final class RIntToComplexVectorClosure extends RToComplexVectorClosure implement
 
     private final RIntVector vector;
 
-    RIntToComplexVectorClosure(RIntVector vector) {
+    RIntToComplexVectorClosure(RIntVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -105,7 +124,8 @@ final class RIntSequenceToComplexVectorClosure extends RToComplexVectorClosure i
 
     private final RIntSequence vector;
 
-    RIntSequenceToComplexVectorClosure(RIntSequence vector) {
+    RIntSequenceToComplexVectorClosure(RIntSequence vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -125,7 +145,8 @@ final class RDoubleToComplexVectorClosure extends RToComplexVectorClosure implem
 
     private final RDoubleVector vector;
 
-    RDoubleToComplexVectorClosure(RDoubleVector vector) {
+    RDoubleToComplexVectorClosure(RDoubleVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -145,7 +166,8 @@ final class RDoubleSequenceToComplexVectorClosure extends RToComplexVectorClosur
 
     private final RDoubleSequence vector;
 
-    RDoubleSequenceToComplexVectorClosure(RDoubleSequence vector) {
+    RDoubleSequenceToComplexVectorClosure(RDoubleSequence vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -165,7 +187,8 @@ final class RRawToComplexVectorClosure extends RToComplexVectorClosure implement
 
     private final RRawVector vector;
 
-    RRawToComplexVectorClosure(RRawVector vector) {
+    RRawToComplexVectorClosure(RRawVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java
index cd5aa24729606acdbd01c37491406664e41135ef..8a341a3866c901aa271185cbc6df353885d99f78 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
@@ -34,6 +35,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
 abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstractDoubleVector {
 
+    protected RToDoubleVectorClosure(boolean keepAttributes) {
+        super(keepAttributes);
+    }
+
     @Override
     public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createDoubleVector(new double[newLength], newIsComplete);
@@ -47,12 +52,24 @@ abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstr
             double data = getDataAt(i);
             result[i] = data;
         }
-        return RDataFactory.createDoubleVector(result, getVector().isComplete(), getVector().getDimensions(), getVector().getNames());
+        RDoubleVector materialized = RDataFactory.createDoubleVector(result, getVector().isComplete());
+        copyAttributes(materialized);
+        return materialized;
+    }
+
+    @TruffleBoundary
+    private void copyAttributes(RDoubleVector materialized) {
+        if (keepAttributes) {
+            materialized.initAttributes(getVector().getAttributes());
+        }
     }
 
     @Override
-    public final RDoubleVector copyWithNewDimensions(int[] newDimensions) {
-        return materialize().copyWithNewDimensions(newDimensions);
+    public final RAbstractDoubleVector copyWithNewDimensions(int[] newDimensions) {
+        if (!keepAttributes) {
+            return materialize().copyWithNewDimensions(newDimensions);
+        }
+        return this;
     }
 }
 
@@ -60,7 +77,8 @@ final class RLogicalToDoubleVectorClosure extends RToDoubleVectorClosure impleme
 
     private final RLogicalVector vector;
 
-    RLogicalToDoubleVectorClosure(RLogicalVector vector) {
+    RLogicalToDoubleVectorClosure(RLogicalVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -83,7 +101,8 @@ final class RIntToDoubleVectorClosure extends RToDoubleVectorClosure implements
 
     private final RIntVector vector;
 
-    RIntToDoubleVectorClosure(RIntVector vector) {
+    RIntToDoubleVectorClosure(RIntVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -106,7 +125,8 @@ final class RIntSequenceToDoubleVectorClosure extends RToDoubleVectorClosure imp
 
     private final RIntSequence vector;
 
-    RIntSequenceToDoubleVectorClosure(RIntSequence vector) {
+    RIntSequenceToDoubleVectorClosure(RIntSequence vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -129,7 +149,8 @@ final class RRawToDoubleVectorClosure extends RToDoubleVectorClosure implements
 
     private final RRawVector vector;
 
-    RRawToDoubleVectorClosure(RRawVector vector) {
+    RRawToDoubleVectorClosure(RRawVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java
index 187b1260e7fcfd8951a4f6ec9346a295471144a3..ee9fafbb913ca62a0bc6aa93240ce4dbe1196d2e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -37,6 +38,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstractIntVector {
 
+    protected RToIntVectorClosure(boolean keepAttributes) {
+        super(keepAttributes);
+    }
+
     @Override
     public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createIntVector(new int[newLength], newIsComplete);
@@ -50,12 +55,24 @@ abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstract
             int data = getDataAt(i);
             result[i] = data;
         }
-        return RDataFactory.createIntVector(result, getVector().isComplete());
+        RIntVector materialized = RDataFactory.createIntVector(result, getVector().isComplete());
+        copyAttributes(materialized);
+        return materialized;
+    }
+
+    @TruffleBoundary
+    private void copyAttributes(RIntVector materialized) {
+        if (keepAttributes) {
+            materialized.copyAttributesFrom(getVector());
+        }
     }
 
     @Override
-    public final RIntVector copyWithNewDimensions(int[] newDimensions) {
-        return materialize().copyWithNewDimensions(newDimensions);
+    public final RAbstractIntVector copyWithNewDimensions(int[] newDimensions) {
+        if (!keepAttributes) {
+            return materialize().copyWithNewDimensions(newDimensions);
+        }
+        return this;
     }
 }
 
@@ -63,7 +80,8 @@ final class RLogicalToIntVectorClosure extends RToIntVectorClosure implements RA
 
     private final RLogicalVector vector;
 
-    RLogicalToIntVectorClosure(RLogicalVector vector) {
+    RLogicalToIntVectorClosure(RLogicalVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -86,7 +104,8 @@ final class RDoubleToIntVectorClosure extends RToIntVectorClosure implements RAb
 
     private final RDoubleVector vector;
 
-    RDoubleToIntVectorClosure(RDoubleVector vector) {
+    RDoubleToIntVectorClosure(RDoubleVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -114,7 +133,8 @@ final class RDoubleSequenceToIntVectorClosure extends RToIntVectorClosure implem
 
     private final RDoubleSequence vector;
 
-    RDoubleSequenceToIntVectorClosure(RDoubleSequence vector) {
+    RDoubleSequenceToIntVectorClosure(RDoubleSequence vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -145,7 +165,8 @@ final class RComplexToIntVectorClosure extends RToIntVectorClosure implements RA
 
     private final RComplexVector vector;
 
-    RComplexToIntVectorClosure(RComplexVector vector) {
+    RComplexToIntVectorClosure(RComplexVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -169,7 +190,8 @@ final class RRawToIntVectorClosure extends RToIntVectorClosure implements RAbstr
 
     private final RRawVector vector;
 
-    RRawToIntVectorClosure(RRawVector vector) {
+    RRawToIntVectorClosure(RRawVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java
index 8a03a34c89bb72bc9b4f3e8ecf5b98c502ab0ace..f6ef8f334c63b9c3fde8cf8f676d23d21fb9352f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -40,6 +41,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 abstract class RToListVectorClosure extends RToVectorClosure implements RAbstractListVector {
 
+    protected RToListVectorClosure(boolean keepAttributes) {
+        super(keepAttributes);
+    }
+
     @Override
     public Object getDataAtAsObject(int index) {
         return getDataAt(index);
@@ -53,12 +58,24 @@ abstract class RToListVectorClosure extends RToVectorClosure implements RAbstrac
             Object data = getDataAt(i);
             result[i] = data;
         }
-        return RDataFactory.createList(result);
+        RList materialized = RDataFactory.createList(result);
+        copyAttributes(materialized);
+        return materialized;
+    }
+
+    @TruffleBoundary
+    private void copyAttributes(RList materialized) {
+        if (keepAttributes) {
+            materialized.copyAttributesFrom(getVector());
+        }
     }
 
     @Override
     public RAbstractVector copyWithNewDimensions(int[] newDimensions) {
-        return materialize().copyWithNewDimensions(newDimensions);
+        if (!keepAttributes) {
+            return materialize().copyWithNewDimensions(newDimensions);
+        }
+        return this;
     }
 
     @Override
@@ -71,7 +88,8 @@ final class RLogicalToListVectorClosure extends RToListVectorClosure {
 
     private final RLogicalVector vector;
 
-    RLogicalToListVectorClosure(RLogicalVector vector) {
+    RLogicalToListVectorClosure(RLogicalVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -90,7 +108,8 @@ final class RIntToListVectorClosure extends RToListVectorClosure {
 
     private final RIntVector vector;
 
-    RIntToListVectorClosure(RIntVector vector) {
+    RIntToListVectorClosure(RIntVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -109,7 +128,8 @@ final class RIntSequenceToListVectorClosure extends RToListVectorClosure {
 
     private final RIntSequence vector;
 
-    RIntSequenceToListVectorClosure(RIntSequence vector) {
+    RIntSequenceToListVectorClosure(RIntSequence vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -128,7 +148,8 @@ final class RDoubleToListVectorClosure extends RToListVectorClosure {
 
     private final RDoubleVector vector;
 
-    RDoubleToListVectorClosure(RDoubleVector vector) {
+    RDoubleToListVectorClosure(RDoubleVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -147,7 +168,8 @@ final class RDoubleSequenceToListVectorClosure extends RToListVectorClosure {
 
     private final RDoubleSequence vector;
 
-    RDoubleSequenceToListVectorClosure(RDoubleSequence vector) {
+    RDoubleSequenceToListVectorClosure(RDoubleSequence vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -166,7 +188,8 @@ final class RComplexToListVectorClosure extends RToListVectorClosure {
 
     private final RComplexVector vector;
 
-    RComplexToListVectorClosure(RComplexVector vector) {
+    RComplexToListVectorClosure(RComplexVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -185,7 +208,8 @@ final class RStringToListVectorClosure extends RToListVectorClosure {
 
     private final RStringVector vector;
 
-    RStringToListVectorClosure(RStringVector vector) {
+    RStringToListVectorClosure(RStringVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -204,7 +228,8 @@ final class RRawToListVectorClosure extends RToListVectorClosure {
 
     private final RRawVector vector;
 
-    RRawToListVectorClosure(RRawVector vector) {
+    RRawToListVectorClosure(RRawVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
index e9a127adbd78625542c2c120db0d0964957c899e..904f0fa5bf53ca92e785bc1fc93564f2bf519a25 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
@@ -44,6 +44,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstractStringVector {
 
+    protected RToStringVectorClosure(boolean keepAttributes) {
+        super(keepAttributes);
+    }
+
     @Override
     public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createStringVector(new String[newLength], newIsComplete);
@@ -57,22 +61,24 @@ abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstr
             String data = getDataAt(i);
             result[i] = data;
         }
-        return RDataFactory.createStringVector(result, getVector().isComplete(), getDimensionsMaterialized(), getNamesMaterialized());
+        RStringVector materialized = RDataFactory.createStringVector(result, getVector().isComplete());
+        copyAttributes(materialized);
+        return materialized;
     }
 
     @TruffleBoundary
-    private int[] getDimensionsMaterialized() {
-        return getDimensions();
-    }
-
-    @TruffleBoundary
-    private RStringVector getNamesMaterialized() {
-        return getNames();
+    private void copyAttributes(RStringVector materialized) {
+        if (keepAttributes) {
+            materialized.copyAttributesFrom(getVector());
+        }
     }
 
     @Override
-    public final RStringVector copyWithNewDimensions(int[] newDimensions) {
-        return materialize().copyWithNewDimensions(newDimensions);
+    public final RAbstractStringVector copyWithNewDimensions(int[] newDimensions) {
+        if (!keepAttributes) {
+            return materialize().copyWithNewDimensions(newDimensions);
+        }
+        return this;
     }
 }
 
@@ -80,7 +86,8 @@ final class RLogicalToStringVectorClosure extends RToStringVectorClosure {
 
     private final RLogicalVector vector;
 
-    RLogicalToStringVectorClosure(RLogicalVector vector) {
+    RLogicalToStringVectorClosure(RLogicalVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -104,7 +111,8 @@ final class RIntToStringVectorClosure extends RToStringVectorClosure {
 
     private final RIntVector vector;
 
-    RIntToStringVectorClosure(RIntVector vector) {
+    RIntToStringVectorClosure(RIntVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -127,7 +135,8 @@ final class RIntSequenceToStringVectorClosure extends RToStringVectorClosure {
 
     private final RIntSequence vector;
 
-    RIntSequenceToStringVectorClosure(RIntSequence vector) {
+    RIntSequenceToStringVectorClosure(RIntSequence vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -150,7 +159,8 @@ final class RDoubleToStringVectorClosure extends RToStringVectorClosure {
 
     private final RDoubleVector vector;
 
-    RDoubleToStringVectorClosure(RDoubleVector vector) {
+    RDoubleToStringVectorClosure(RDoubleVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -174,7 +184,8 @@ final class RDoubleSequenceToStringVectorClosure extends RToStringVectorClosure
 
     private final RDoubleSequence vector;
 
-    RDoubleSequenceToStringVectorClosure(RDoubleSequence vector) {
+    RDoubleSequenceToStringVectorClosure(RDoubleSequence vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -198,7 +209,8 @@ final class RComplexToStringVectorClosure extends RToStringVectorClosure {
 
     private final RComplexVector vector;
 
-    RComplexToStringVectorClosure(RComplexVector vector) {
+    RComplexToStringVectorClosure(RComplexVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -221,7 +233,8 @@ final class RRawToStringVectorClosure extends RToStringVectorClosure {
 
     private final RRawVector vector;
 
-    RRawToStringVectorClosure(RRawVector vector) {
+    RRawToStringVectorClosure(RRawVector vector, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
     }
 
@@ -245,7 +258,8 @@ final class RFactorToStringVectorClosure extends RToStringVectorClosure {
     private final RAbstractStringVector levels;
     private final boolean withNames;
 
-    RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames) {
+    RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames, boolean keepAttributes) {
+        super(keepAttributes);
         this.vector = vector;
         this.levels = levels;
         this.withNames = withNames;
@@ -257,7 +271,7 @@ final class RFactorToStringVectorClosure extends RToStringVectorClosure {
     }
 
     @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, @SuppressWarnings("hiding") boolean keepAttributes) {
         switch (type) {
             case Character:
                 return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
index d2ff0cb3a9c9fdd820839f78aee86065b82a2c01..2f0146bee3eb5b7fc9c887c825786dfca23454fe 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
@@ -23,6 +23,8 @@
 package com.oracle.truffle.r.runtime.data.closures;
 
 import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
@@ -32,6 +34,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 abstract class RToVectorClosure implements RAbstractVector {
 
+    /** If {@code true}, attributes should be preserved when materializing. */
+    protected final boolean keepAttributes;
+
+    protected RToVectorClosure(boolean keepAttributes) {
+        this.keepAttributes = keepAttributes;
+    }
+
     public abstract RAbstractVector getVector();
 
     @Override
@@ -168,4 +177,11 @@ abstract class RToVectorClosure implements RAbstractVector {
     public boolean isS4() {
         return false;
     }
+
+    @Override
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile, boolean keepAttrs) {
+        // Closures are trimmed to use a concrete type in order to avoid polymorphism. Therefore,
+        // first materialize and then cast and do not create a closure over a closure.
+        return materialize().castSafe(type, isNAProfile, keepAttrs);
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java
index 2d16b9fbeaaadc411d77f097171a685915f6d079..71f6d47c49f979d040449e7f9f0384763c502cab 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java
@@ -68,9 +68,27 @@ public interface RAbstractVector extends RAbstractContainer {
      * implementation may decide to just wrap the original vector with a closure. This method is
      * optimized for invocation with a compile-time constant {@link RType}.
      *
+     * @see #castSafe(RType, ConditionProfile, boolean)
+     */
+    default RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+        return castSafe(type, isNAProfile, false);
+    }
+
+    /**
+     * Casts a vector to another {@link RType}. If a safe cast to the target {@link RType} is not
+     * supported <code>null</code> is returned. Instead of materializing the cast for each index the
+     * implementation may decide to just wrap the original vector with a closure. This method is
+     * optimized for invocation with a compile-time constant {@link RType}.
+     *
+     * @param type
+     * @param isNAProfile
+     * @param keepAttributes If {@code true}, the cast itself will keep the attributes. This is,
+     *            however, a rather slow operation and you should set this to {@code false} and use
+     *            nodes for copying attributes if possible.
+     *
      * @see RType#getPrecedence()
      */
-    default RAbstractVector castSafe(RType type, @SuppressWarnings("unused") ConditionProfile isNAProfile) {
+    default RAbstractVector castSafe(RType type, @SuppressWarnings("unused") ConditionProfile isNAProfile, @SuppressWarnings("unused") boolean keepAttributes) {
         if (type == getRType()) {
             return this;
         } else {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NAProfile.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NAProfile.java
index 36d1acc29d746ac92f6ac0dc5c03999cb820b236..084aec76db8bdbee914f6ec4a35ae48b8657ff8f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NAProfile.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NAProfile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it