From d061d28bf207323ea8a1b4c44b9623d9318e0ab9 Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Tue, 31 Jan 2017 20:44:44 +0100
Subject: [PATCH] Cast pipelines made static

---
 .../r/library/grDevices/DevicesCCalls.java    |   9 +-
 .../r/library/graphics/GraphicsCCalls.java    |  12 +
 .../truffle/r/library/grid/GridFunctions.java |  10 +-
 .../library/methods/MethodsListDispatch.java  |  53 ++--
 .../truffle/r/library/methods/Slot.java       |   9 +-
 .../r/library/methods/SubstituteDirect.java   |   4 +
 .../truffle/r/library/stats/BinDist.java      |   4 +-
 .../oracle/truffle/r/library/stats/Cdist.java |   5 +-
 .../r/library/stats/CompleteCases.java        |   6 +-
 .../truffle/r/library/stats/Covcor.java       |   7 +-
 .../truffle/r/library/stats/Cutree.java       |   5 +-
 .../truffle/r/library/stats/DoubleCentre.java |   5 +-
 .../r/library/stats/RMultinomNode.java        |   5 +-
 .../r/library/stats/RandFunctionsNodes.java   |  20 +-
 .../r/library/stats/StatsFunctionsNodes.java  |  33 ++-
 .../truffle/r/library/tools/C_ParseRd.java    |   5 +-
 .../truffle/r/library/tools/DirChmod.java     |   5 +-
 .../oracle/truffle/r/library/tools/Rmd5.java  |   5 +-
 .../truffle/r/library/tools/ToolsText.java    |   9 +-
 .../truffle/r/library/utils/CountFields.java  |   4 +
 .../oracle/truffle/r/library/utils/Crc64.java |   5 +-
 .../truffle/r/library/utils/Download.java     |   5 +-
 .../oracle/truffle/r/library/utils/Menu.java  |   5 +-
 .../oracle/truffle/r/library/utils/Rprof.java |   5 +-
 .../truffle/r/library/utils/TypeConvert.java  |   4 +
 .../truffle/r/nodes/builtin/base/APerm.java   |   5 +-
 .../truffle/r/nodes/builtin/base/Abbrev.java  |   5 +-
 .../truffle/r/nodes/builtin/base/All.java     |   4 +
 .../r/nodes/builtin/base/AllNames.java        |   7 +-
 .../truffle/r/nodes/builtin/base/Any.java     |   5 +
 .../truffle/r/nodes/builtin/base/AnyNA.java   |   7 +-
 .../truffle/r/nodes/builtin/base/Arg.java     |   7 +-
 .../truffle/r/nodes/builtin/base/Args.java    |   6 +-
 .../truffle/r/nodes/builtin/base/Array.java   |  16 +-
 .../truffle/r/nodes/builtin/base/AsCall.java  |   6 +-
 .../r/nodes/builtin/base/AsCharacter.java     |   5 +-
 .../nodes/builtin/base/AsCharacterFactor.java |   4 +
 .../r/nodes/builtin/base/AsComplex.java       |   5 +-
 .../r/nodes/builtin/base/AsDouble.java        |   5 +-
 .../r/nodes/builtin/base/AsFunction.java      |   5 +-
 .../r/nodes/builtin/base/AsInteger.java       |   5 +-
 .../r/nodes/builtin/base/AsLogical.java       |   5 +-
 .../truffle/r/nodes/builtin/base/AsRaw.java   |   7 +-
 .../r/nodes/builtin/base/AsVector.java        |   5 +-
 .../truffle/r/nodes/builtin/base/Assign.java  |   5 +-
 .../r/nodes/builtin/base/AttachFunctions.java |   9 +-
 .../truffle/r/nodes/builtin/base/Attr.java    |   7 +-
 .../r/nodes/builtin/base/Attributes.java      |   4 +
 .../builtin/base/BaseGammaFunctions.java      |   9 +-
 .../truffle/r/nodes/builtin/base/Bincode.java |   7 +-
 .../truffle/r/nodes/builtin/base/Bind.java    |  22 +-
 .../nodes/builtin/base/BitwiseFunctions.java  |  54 ++--
 .../truffle/r/nodes/builtin/base/Body.java    |   6 +-
 .../nodes/builtin/base/BrowserFunctions.java  |   9 +-
 .../truffle/r/nodes/builtin/base/CRC64.java   |   5 +-
 .../r/nodes/builtin/base/CacheClass.java      |   7 +-
 .../truffle/r/nodes/builtin/base/Call.java    |   7 +-
 .../truffle/r/nodes/builtin/base/Cat.java     |   7 +-
 .../truffle/r/nodes/builtin/base/Ceiling.java |  15 +-
 .../r/nodes/builtin/base/CharMatch.java       |   7 +-
 .../r/nodes/builtin/base/ChooseBuiltin.java   |   5 +-
 .../truffle/r/nodes/builtin/base/Col.java     |   5 +-
 .../r/nodes/builtin/base/ColMeans.java        |   7 +-
 .../truffle/r/nodes/builtin/base/ColSums.java |   7 +-
 .../r/nodes/builtin/base/ColSumsBase.java     |  17 +-
 .../truffle/r/nodes/builtin/base/Colon.java   |   4 +
 .../truffle/r/nodes/builtin/base/Combine.java |   5 +-
 .../nodes/builtin/base/CompileFunctions.java  |  10 +-
 .../truffle/r/nodes/builtin/base/Complex.java |   7 +-
 .../builtin/base/ConditionFunctions.java      |  44 ++--
 .../builtin/base/ConnectionFunctions.java     | 240 ++++++++++--------
 .../r/nodes/builtin/base/CopyDFAttr.java      |   6 +-
 .../r/nodes/builtin/base/Crossprod.java       |   5 +-
 .../truffle/r/nodes/builtin/base/CumMax.java  |   5 +-
 .../truffle/r/nodes/builtin/base/CumMin.java  |   5 +-
 .../truffle/r/nodes/builtin/base/CumProd.java |   5 +-
 .../truffle/r/nodes/builtin/base/CumSum.java  |   5 +-
 .../truffle/r/nodes/builtin/base/DPut.java    |   7 +-
 .../builtin/base/DatePOSIXFunctions.java      |  25 +-
 .../r/nodes/builtin/base/DebugFunctions.java  |  31 ++-
 .../r/nodes/builtin/base/DelayedAssign.java   |   5 +-
 .../truffle/r/nodes/builtin/base/Deparse.java |   7 +-
 .../truffle/r/nodes/builtin/base/Diag.java    |   7 +-
 .../truffle/r/nodes/builtin/base/Dim.java     |   4 +
 .../r/nodes/builtin/base/DimNames.java        |   4 +
 .../truffle/r/nodes/builtin/base/DoCall.java  |   5 +-
 .../truffle/r/nodes/builtin/base/Drop.java    |   4 +
 .../builtin/base/DuplicatedFunctions.java     |  10 +-
 .../nodes/builtin/base/DynLoadFunctions.java  |  17 +-
 .../r/nodes/builtin/base/EncodeString.java    |   5 +-
 .../nodes/builtin/base/EncodingFunctions.java |  11 +-
 .../r/nodes/builtin/base/EnvFunctions.java    |  69 +++--
 .../truffle/r/nodes/builtin/base/Eval.java    |  11 +-
 .../truffle/r/nodes/builtin/base/Exists.java  |   7 +-
 .../r/nodes/builtin/base/Expression.java      |   6 +-
 .../r/nodes/builtin/base/FileFunctions.java   |  80 +++---
 .../truffle/r/nodes/builtin/base/Floor.java   |  15 +-
 .../r/nodes/builtin/base/ForceAndCall.java    |   5 +-
 .../truffle/r/nodes/builtin/base/Formals.java |   4 +
 .../truffle/r/nodes/builtin/base/Format.java  |   6 +-
 .../truffle/r/nodes/builtin/base/FormatC.java |   7 +-
 .../r/nodes/builtin/base/FrameFunctions.java  |  25 +-
 .../truffle/r/nodes/builtin/base/Gc.java      |   7 +-
 .../r/nodes/builtin/base/GetClass.java        |   6 +-
 .../r/nodes/builtin/base/GetFunctions.java    |  13 +-
 .../r/nodes/builtin/base/GetOldClass.java     |   4 +
 .../truffle/r/nodes/builtin/base/GetText.java |   5 +-
 .../r/nodes/builtin/base/GrepFunctions.java   |  59 ++---
 .../builtin/base/HiddenInternalFunctions.java |  31 ++-
 .../truffle/r/nodes/builtin/base/IConv.java   |   5 +-
 .../r/nodes/builtin/base/Identical.java       |   7 +-
 .../r/nodes/builtin/base/InheritsBuiltin.java |   7 +-
 .../r/nodes/builtin/base/IntToBits.java       |   5 +-
 .../r/nodes/builtin/base/IntToUtf8.java       |   5 +-
 .../r/nodes/builtin/base/Invisible.java       |   6 +-
 .../nodes/builtin/base/IsFiniteFunctions.java |  12 +
 .../r/nodes/builtin/base/IsListFactor.java    |   5 +-
 .../truffle/r/nodes/builtin/base/IsNA.java    |   6 +-
 .../truffle/r/nodes/builtin/base/IsS4.java    |   6 +-
 .../r/nodes/builtin/base/IsSingle.java        |   5 +-
 .../r/nodes/builtin/base/IsTypeFunctions.java |  99 +++++++-
 .../r/nodes/builtin/base/IsUnsorted.java      |   5 +-
 .../r/nodes/builtin/base/LaFunctions.java     |  85 +++----
 .../truffle/r/nodes/builtin/base/Lapply.java  |   5 +-
 .../truffle/r/nodes/builtin/base/Length.java  |   6 +-
 .../truffle/r/nodes/builtin/base/Lengths.java |   5 +-
 .../r/nodes/builtin/base/List2Env.java        |   8 +-
 .../r/nodes/builtin/base/ListBuiltin.java     |   5 +
 .../nodes/builtin/base/LoadSaveFunctions.java |  15 +-
 .../r/nodes/builtin/base/LocaleFunctions.java |  39 +--
 .../r/nodes/builtin/base/LogFunctions.java    |  19 +-
 .../truffle/r/nodes/builtin/base/Ls.java      |   5 +-
 .../r/nodes/builtin/base/MakeNames.java       |   5 +-
 .../r/nodes/builtin/base/MakeUnique.java      |   5 +-
 .../truffle/r/nodes/builtin/base/Mapply.java  |   5 +-
 .../truffle/r/nodes/builtin/base/MatMult.java |   6 +-
 .../truffle/r/nodes/builtin/base/Match.java   |   5 +-
 .../r/nodes/builtin/base/MatchArg.java        |   4 +
 .../r/nodes/builtin/base/MatchFun.java        |   5 +-
 .../truffle/r/nodes/builtin/base/Matrix.java  |   5 +-
 .../truffle/r/nodes/builtin/base/Max.java     |   5 +-
 .../truffle/r/nodes/builtin/base/Mean.java    |   6 +-
 .../truffle/r/nodes/builtin/base/Merge.java   |   8 +-
 .../truffle/r/nodes/builtin/base/Min.java     |   5 +-
 .../truffle/r/nodes/builtin/base/NChar.java   |   7 +-
 .../r/nodes/builtin/base/NGetText.java        |   6 +-
 .../truffle/r/nodes/builtin/base/NZChar.java  |   5 +-
 .../truffle/r/nodes/builtin/base/Names.java   |   8 +-
 .../builtin/base/NamespaceFunctions.java      |  38 ++-
 .../r/nodes/builtin/base/NormalizePath.java   |   5 +-
 .../builtin/base/NumericalFunctions.java      |  29 +--
 .../truffle/r/nodes/builtin/base/OnExit.java  |   7 +-
 .../nodes/builtin/base/OptionsFunctions.java  |   9 +-
 .../truffle/r/nodes/builtin/base/Order.java   |   5 +-
 .../truffle/r/nodes/builtin/base/PMatch.java  |   7 +-
 .../truffle/r/nodes/builtin/base/PMinMax.java |  19 +-
 .../truffle/r/nodes/builtin/base/Parse.java   |   5 +-
 .../truffle/r/nodes/builtin/base/Paste.java   |   4 +-
 .../truffle/r/nodes/builtin/base/Paste0.java  |   4 +-
 .../r/nodes/builtin/base/PathExpand.java      |   7 +-
 .../truffle/r/nodes/builtin/base/Pretty.java  |   5 +-
 .../r/nodes/builtin/base/Primitive.java       |   5 +-
 .../r/nodes/builtin/base/PrintFunctions.java  |   9 +-
 .../truffle/r/nodes/builtin/base/Prod.java    |   6 +-
 .../r/nodes/builtin/base/Quantifier.java      |   9 +-
 .../truffle/r/nodes/builtin/base/Quit.java    |   5 +-
 .../truffle/r/nodes/builtin/base/Quote.java   |   4 +
 .../r/nodes/builtin/base/RNGFunctions.java    |  22 +-
 .../truffle/r/nodes/builtin/base/Range.java   |   5 +-
 .../truffle/r/nodes/builtin/base/Rank.java    |  18 +-
 .../r/nodes/builtin/base/RawFunctions.java    |  15 +-
 .../r/nodes/builtin/base/RawToBits.java       |   7 +-
 .../truffle/r/nodes/builtin/base/ReadDCF.java |   5 +-
 .../r/nodes/builtin/base/ReadREnviron.java    |   5 +-
 .../r/nodes/builtin/base/Readline.java        |   7 +-
 .../truffle/r/nodes/builtin/base/Recall.java  |   4 +
 .../r/nodes/builtin/base/RegFinalizer.java    |   6 +-
 .../truffle/r/nodes/builtin/base/Repeat.java  |  17 +-
 .../r/nodes/builtin/base/RepeatInternal.java  |  15 +-
 .../r/nodes/builtin/base/RepeatLength.java    |   7 +-
 .../truffle/r/nodes/builtin/base/Return.java  |  11 +
 .../truffle/r/nodes/builtin/base/Rm.java      |   7 +-
 .../truffle/r/nodes/builtin/base/Round.java   |  18 +-
 .../truffle/r/nodes/builtin/base/Row.java     |   7 +-
 .../r/nodes/builtin/base/RowMeans.java        |   8 +-
 .../truffle/r/nodes/builtin/base/RowSums.java |   8 +-
 .../r/nodes/builtin/base/RowsumFunctions.java |   7 +-
 .../builtin/base/S3DispatchFunctions.java     |   8 +
 .../truffle/r/nodes/builtin/base/Sample.java  |  26 +-
 .../truffle/r/nodes/builtin/base/Sample2.java |  19 +-
 .../truffle/r/nodes/builtin/base/Scan.java    |   5 +-
 .../r/nodes/builtin/base/SeqFunctions.java    |  16 +-
 .../builtin/base/SerializeFunctions.java      |  27 +-
 .../r/nodes/builtin/base/SetS4Object.java     |   5 +-
 .../r/nodes/builtin/base/SetTimeLimit.java    |   5 +-
 .../truffle/r/nodes/builtin/base/Setwd.java   |   5 +-
 .../r/nodes/builtin/base/ShortRowNames.java   |   7 +-
 .../truffle/r/nodes/builtin/base/Signif.java  |   5 +-
 .../r/nodes/builtin/base/SinkFunctions.java   |  11 +-
 .../truffle/r/nodes/builtin/base/Slot.java    |   5 +-
 .../r/nodes/builtin/base/SortFunctions.java   |  24 +-
 .../truffle/r/nodes/builtin/base/Split.java   |   4 +
 .../truffle/r/nodes/builtin/base/Sprintf.java |   5 +
 .../r/nodes/builtin/base/StandardGeneric.java |  17 +-
 .../builtin/base/StartsEndsWithFunctions.java |  23 +-
 .../truffle/r/nodes/builtin/base/Stop.java    |   6 +-
 .../truffle/r/nodes/builtin/base/Strrep.java  |   5 +-
 .../truffle/r/nodes/builtin/base/Strtoi.java  |   7 +-
 .../truffle/r/nodes/builtin/base/Strtrim.java |   7 +-
 .../r/nodes/builtin/base/Substitute.java      |   4 +
 .../truffle/r/nodes/builtin/base/Substr.java  |   6 +-
 .../truffle/r/nodes/builtin/base/Sum.java     |   5 +-
 .../truffle/r/nodes/builtin/base/Switch.java  |   6 +-
 .../r/nodes/builtin/base/SysFunctions.java    |  45 ++--
 .../r/nodes/builtin/base/Tabulate.java        |   5 +-
 .../r/nodes/builtin/base/TempFile.java        |   5 +-
 .../r/nodes/builtin/base/ToLowerOrUpper.java  |  11 +-
 .../r/nodes/builtin/base/TraceFunctions.java  |  40 ++-
 .../r/nodes/builtin/base/Traceback.java       |   7 +-
 .../r/nodes/builtin/base/Transpose.java       |   4 +
 .../nodes/builtin/base/TrigExpFunctions.java  |   5 +-
 .../truffle/r/nodes/builtin/base/Trunc.java   |  15 +-
 .../truffle/r/nodes/builtin/base/Typeof.java  |   6 +-
 .../truffle/r/nodes/builtin/base/UnClass.java |   5 +-
 .../truffle/r/nodes/builtin/base/Unique.java  |   5 +-
 .../truffle/r/nodes/builtin/base/Unlist.java  |   5 +-
 .../r/nodes/builtin/base/UpdateAttr.java      |   5 +-
 .../nodes/builtin/base/UpdateAttributes.java  |   7 +-
 .../r/nodes/builtin/base/UpdateClass.java     |   5 +-
 .../r/nodes/builtin/base/UpdateDim.java       |   9 +-
 .../r/nodes/builtin/base/UpdateDimNames.java  |   4 +
 .../r/nodes/builtin/base/UpdateLength.java    |  13 +-
 .../r/nodes/builtin/base/UpdateLevels.java    |   5 +-
 .../r/nodes/builtin/base/UpdateNames.java     |   4 +
 .../r/nodes/builtin/base/UpdateOldClass.java  |   6 +-
 .../r/nodes/builtin/base/UpdateSlot.java      |   5 +-
 .../nodes/builtin/base/UpdateStorageMode.java |   6 +-
 .../r/nodes/builtin/base/UpdateSubstr.java    |   6 +-
 .../r/nodes/builtin/base/Utf8ToInt.java       |   5 +-
 .../truffle/r/nodes/builtin/base/VApply.java  |   7 +-
 .../truffle/r/nodes/builtin/base/Vector.java  |   5 +-
 .../truffle/r/nodes/builtin/base/Warning.java |   5 +-
 .../r/nodes/builtin/base/WhichFunctions.java  |  23 +-
 .../r/nodes/builtin/base/WithVisible.java     |   4 +
 .../truffle/r/nodes/builtin/base/Xtfrm.java   |   6 +-
 .../builtin/base/foreign/CairoProps.java      |   7 +-
 .../foreign/CallAndExternalFunctions.java     |  12 +
 .../r/nodes/builtin/base/foreign/Dqrcf.java   |   6 +-
 .../r/nodes/builtin/base/foreign/Dqrdc2.java  |   6 +-
 .../r/nodes/builtin/base/foreign/Fft.java     |   5 +-
 .../builtin/base/foreign/Flushconsole.java    |   6 +-
 .../base/foreign/FortranAndCFunctions.java    |   8 +
 .../builtin/base/foreign/LookupAdapter.java   |   4 +
 .../base/foreign/MakeQuartzDefault.java       |   6 +-
 .../builtin/base/foreign/ReadTableHead.java   |   7 +-
 .../builtin/base/foreign/WriteTable.java      |   5 +-
 .../nodes/builtin/base/infix/AccessField.java |   5 +-
 .../builtin/base/infix/ParenBuiltin.java      |   6 +-
 .../r/nodes/builtin/base/infix/Subscript.java |   6 +-
 .../r/nodes/builtin/base/infix/Subset.java    |   7 +-
 .../r/nodes/builtin/base/infix/Tilde.java     |   6 +-
 .../nodes/builtin/base/infix/UpdateField.java |   5 +-
 .../builtin/base/infix/UpdateSubscript.java   |   6 +-
 .../builtin/base/infix/UpdateSubset.java      |   6 +-
 .../builtin/base/system/SystemFunction.java   |   5 +-
 .../r/nodes/builtin/fastr/FastRContext.java   |  93 +++----
 .../r/nodes/builtin/fastr/FastRDebug.java     |   5 +-
 .../r/nodes/builtin/fastr/FastRIdentity.java  |   6 +-
 .../r/nodes/builtin/fastr/FastRInterop.java   |  33 ++-
 .../r/nodes/builtin/fastr/FastRPkgSource.java |   5 +-
 .../builtin/fastr/FastRRefCountInfo.java      |   6 +-
 .../nodes/builtin/fastr/FastRStackTrace.java  |   5 +-
 .../r/nodes/builtin/fastr/FastRStats.java     |  32 +--
 .../nodes/builtin/fastr/FastRSyntaxTree.java  |   5 +-
 .../r/nodes/builtin/fastr/FastRThrowIt.java   |   8 +-
 .../r/nodes/builtin/fastr/FastRTrace.java     |   4 +
 .../r/nodes/builtin/fastr/FastRTree.java      |   7 +-
 .../r/nodes/builtin/fastr/FastRTry.java       |   4 +
 .../r/nodes/builtin/fastr/FastrDqrls.java     |   5 +-
 .../r/nodes/builtin/CastBuilderTest.java      |  35 ++-
 .../r/nodes/test/PipelineToCastNodeTests.java |   4 +-
 .../r/nodes/test/RBuiltinDiagnostics.java     |   7 +
 .../r/nodes/binary/BinaryArithmeticNode.java  |   5 +-
 .../r/nodes/binary/BinaryBooleanNode.java     |   5 +-
 .../nodes/binary/BinaryBooleanScalarNode.java |   4 +
 .../truffle/r/nodes/builtin/CastBuilder.java  |  15 +-
 .../nodes/builtin/NodeWithArgumentCasts.java  | 105 ++++++++
 .../truffle/r/nodes/builtin/RBuiltinNode.java |  14 +-
 .../r/nodes/builtin/RExternalBuiltinNode.java |  12 +-
 .../builtin/RInternalCodeBuiltinNode.java     |   6 +-
 .../builtin/casts/PipelineToCastNode.java     |  17 +-
 .../builtin/casts/fluent/PipelineBuilder.java |  29 ++-
 .../truffle/r/nodes/function/RCallNode.java   |   2 +-
 .../truffle/r/nodes/objects/GetPrimName.java  |   5 +-
 .../truffle/r/nodes/objects/NewObject.java    |   5 +-
 .../truffle/r/nodes/unary/UnaryNotNode.java   |   5 +
 .../truffle/r/runtime/nodes/RBaseNode.java    |  11 +
 .../test/builtins/TestBuiltin_asfunction.java |   4 +-
 .../r/test/builtins/TestBuiltin_asvector.java |   6 +-
 299 files changed, 2003 insertions(+), 1439 deletions(-)
 create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
index d46eed38a1..539994d1f7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.grDevices.DevicesCCallsFactory.C_DevOffNodeGen;
 import com.oracle.truffle.r.library.grDevices.pdf.PdfGraphicsDevice;
 import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -36,8 +35,8 @@ public class DevicesCCalls {
             return C_DevOffNodeGen.create();
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(C_DevOff.class);
             casts.arg(0).asIntegerVector().findFirst();
         }
 
@@ -65,6 +64,10 @@ public class DevicesCCalls {
         @Child private CastNode asLogicalNode;
         @Child private CastNode asIntNode;
 
+        static {
+            Casts.noCasts(C_PDF.class);
+        }
+
         public C_PDF() {
             asStringNode = newCastBuilder().asStringVector().findFirst().buildCastNode();
             asDoubleNode = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
index dbfc4dc4d9..695ba86dbb 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
@@ -37,6 +37,10 @@ public class GraphicsCCalls {
     public static final class C_PlotXY extends RExternalBuiltinNode {
         @Child private CastNode castXYNode;
 
+        static {
+            Casts.noCasts(C_PlotXY.class);
+        }
+
         public C_PlotXY() {
             castXYNode = newCastBuilder().mustBe(doubleValue().and(size(2))).asDoubleVector().buildCastNode();
         }
@@ -79,6 +83,10 @@ public class GraphicsCCalls {
 
     public static final class C_Par extends RExternalBuiltinNode {
 
+        static {
+            Casts.noCasts(C_Par.class);
+        }
+
         @Override
         @TruffleBoundary
         public Object call(RArgsValuesAndNames args) {
@@ -101,6 +109,10 @@ public class GraphicsCCalls {
         private double font = RRuntime.DOUBLE_NA;
         @Child private CastNode firstDoubleCast;
 
+        static {
+            Casts.noCasts(C_mtext.class);
+        }
+
         public C_mtext() {
             firstDoubleCast = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
index ca5d398f22..6623a2c7ca 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -52,6 +51,10 @@ public class GridFunctions {
     public static final class KillGrid extends RExternalBuiltinNode {
         @Child GridRFFI.KillGridNode killGridNode = RFFIFactory.getRFFI().getGridRFFI().createKillGridNode();
 
+        static {
+            Casts.noCasts(KillGrid.class);
+        }
+
         @Override
         @TruffleBoundary
         public Object call(RArgsValuesAndNames args) {
@@ -60,8 +63,9 @@ public class GridFunctions {
     }
 
     public abstract static class ValidUnits extends RExternalBuiltinNode.Arg1 {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(ValidUnits.class);
             casts.arg(0).mustBe(stringValue(), RError.Message.GENERIC, "'units' must be character").asStringVector().mustBe(notEmpty(), RError.Message.GENERIC, "'units' must be of length > 0");
         }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
index 0fa12c99f3..ce07d50f5b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen;
 import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyScalarNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyScalarNodeGen;
@@ -68,7 +68,8 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public class MethodsListDispatch {
 
-    private static void checkSingleString(CastBuilder casts, int argNum, String argName, String msg, boolean nonEmpty, Function<Object, String> clsHierFn, Function<Object, Integer> vecLenFn) {
+    private static void checkSingleString(Casts casts, int argNum, String argName, String msg, boolean nonEmpty, Function<Object, String> clsHierFn,
+                    Function<Object, Integer> vecLenFn) {
         //@formatter:off
         casts.arg(argNum, argName).
             defaultError(RError.NO_CALLER, RError.Message.SINGLE_STRING_WRONG_TYPE, msg, clsHierFn).
@@ -82,6 +83,10 @@ public class MethodsListDispatch {
 
     public abstract static class R_initMethodDispatch extends RExternalBuiltinNode.Arg1 {
 
+        static {
+            Casts.noCasts(R_initMethodDispatch.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected REnvironment initMethodDispatch(REnvironment env) {
@@ -99,8 +104,8 @@ public class MethodsListDispatch {
 
     public abstract static class R_methodsPackageMetaName extends RExternalBuiltinNode.Arg3 {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(R_methodsPackageMetaName.class);
             Function<Object, String> clsHierFn = ClassHierarchyScalarNode::get;
             Function<Object, Integer> vecLenFn = arg -> ((RAbstractStringVector) arg).getLength();
 
@@ -122,14 +127,11 @@ public class MethodsListDispatch {
 
     public abstract static class R_getClassFromCache extends RExternalBuiltinNode.Arg2 {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            //@formatter:off
-            casts.arg(0, "klass").defaultError(RError.Message.GENERIC, "class should be either a character-string name or a class definition").
-                mustBe(stringValue().or(instanceOf(RS4Object.class)));
+        static {
+            Casts casts = new Casts(R_getClassFromCache.class);
+            casts.arg(0, "klass").defaultError(RError.Message.GENERIC, "class should be either a character-string name or a class definition").mustBe(stringValue().or(instanceOf(RS4Object.class)));
 
             casts.arg(1, "table").mustNotBeNull(RError.NO_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
-            //@formatter:on
         }
 
         protected GetFixedAttributeNode createPckgAttrAccess() {
@@ -175,8 +177,8 @@ public class MethodsListDispatch {
 
     public abstract static class R_set_method_dispatch extends RExternalBuiltinNode.Arg1 {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(R_set_method_dispatch.class);
             casts.arg(0).asLogicalVector().findFirst(RRuntime.LOGICAL_NA);
         }
 
@@ -200,6 +202,10 @@ public class MethodsListDispatch {
     public abstract static class R_M_setPrimitiveMethods extends RExternalBuiltinNode.Arg5 {
         @Child private AccessSlotNode accessSlotNode;
 
+        static {
+            Casts.noCasts(R_M_setPrimitiveMethods.class);
+        }
+
         private AccessSlotNode initAccessSlotNode() {
             if (accessSlotNode == null) {
                 accessSlotNode = insert(AccessSlotNodeGen.create(true));
@@ -289,6 +295,10 @@ public class MethodsListDispatch {
 
     public abstract static class R_identC extends RExternalBuiltinNode.Arg2 {
 
+        static {
+            Casts.noCasts(R_identC.class);
+        }
+
         @Specialization
         protected Object identC(RAbstractStringVector e1, RAbstractStringVector e2) {
             if (e1.getLength() == 1 && e2.getLength() == 1 && e1.getDataAt(0).equals(e2.getDataAt(0))) {
@@ -309,25 +319,18 @@ public class MethodsListDispatch {
 
         @Child private GetGenericInternal getGenericInternal = GetGenericInternalNodeGen.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(R_getGeneric.class);
             Function<Object, String> clsHierFn = ClassHierarchyScalarNode::get;
-
-            //@formatter:off
             Function<Object, Integer> vecLenFn = arg -> ((RAbstractStringVector) arg).getLength();
 
             checkSingleString(casts, 0, "f", "The argument \"f\" to getGeneric", true, clsHierFn, vecLenFn);
 
-            casts.arg(1, "mustFind").
-                asLogicalVector().
-                findFirst(RRuntime.LOGICAL_NA).
-                map(toBoolean());
+            casts.arg(1, "mustFind").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
 
-            casts.arg(2, "env").
-                mustBe(instanceOf(REnvironment.class));
+            casts.arg(2, "env").mustBe(instanceOf(REnvironment.class));
 
             checkSingleString(casts, 3, "package", "The argument \"package\" to getGeneric", false, clsHierFn, vecLenFn);
-            //@formatter:on
         }
 
         @Specialization
@@ -434,6 +437,10 @@ public class MethodsListDispatch {
         @Child private LocalReadVariableNode readDotNextMethod;
         @Child private LocalReadVariableNode readDots;
 
+        static {
+            Casts.noCasts(R_nextMethodCall.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object nextMethodCall(RLanguage matchedCall, REnvironment ev) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
index b1bc33c799..51803d72d1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
@@ -20,7 +20,6 @@ import com.oracle.truffle.r.nodes.access.AccessSlotNode;
 import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen;
 import com.oracle.truffle.r.nodes.access.UpdateSlotNode;
 import com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastToAttributableNode;
@@ -37,8 +36,8 @@ public class Slot {
         @Child private AccessSlotNode accessSlotNode = AccessSlotNodeGen.create(false);
         @Child private CastToAttributableNode castAttributable = CastToAttributableNodeGen.create(true, true, true);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(R_getSlot.class);
             casts.arg(1, "name").defaultError(RError.NO_CALLER, RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe(
                             singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
         }
@@ -65,8 +64,8 @@ public class Slot {
         @Child private UpdateSlotNode updateSlotNode = UpdateSlotNodeGen.create();
         @Child private CastToAttributableNode castAttributable = CastToAttributableNodeGen.create(true, true, true);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(R_setSlot.class);
             casts.arg(1, "name").defaultError(RError.NO_CALLER, RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe(
                             singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
index 10d1a2d64a..420e634f2e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
@@ -38,6 +38,10 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 
 public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
 
+    static {
+        Casts.noCasts(SubstituteDirect.class);
+    }
+
     @Specialization
     @TruffleBoundary
     protected static Object substituteDirect(Object object, REnvironment env) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
index 2df583879a..93fb0bd2f5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
@@ -38,8 +38,8 @@ public abstract class BinDist extends RExternalBuiltinNode.Arg5 {
         return BinDistNodeGen.create();
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(BinDist.class);
         casts.arg(0).asDoubleVector();
         casts.arg(1).asDoubleVector();
         casts.arg(2).asDoubleVector().findFirst();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
index 9664f3ba08..be4422e729 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
@@ -22,7 +22,6 @@ import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -38,8 +37,8 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 {
 
     @Child private GetFixedAttributeNode getNamesAttrNode = GetFixedAttributeNode.createNames();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Cdist.class);
         casts.arg(0).asDoubleVector();
         casts.arg(1).asIntegerVector().findFirst();
         casts.arg(2).mustBe(instanceOf(RList.class));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
index cf77a3c203..ca606b3833 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2015, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -34,6 +34,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public final class CompleteCases extends RExternalBuiltinNode {
 
+    static {
+        Casts.noCasts(CompleteCases.class);
+    }
+
     private RError invalidType(Object entry) {
         throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, ((RTypedValue) entry).getRType().getName());
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
index 84091dec27..05fc0538c7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -47,11 +46,11 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         this.isCor = isCor;
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Covcor.class);
         casts.arg(0).mustNotBeNull(SHOW_CALLER, Message.IS_NULL, "x").asDoubleVector();
         casts.arg(1).asDoubleVector();
-        casts.arg(2).asIntegerVector().findFirst().mustBe(eq(4), this, Message.NYI, "covcor: other method than 4 not implemented.");
+        casts.arg(2).asIntegerVector().findFirst().mustBe(eq(4), Message.NYI, "covcor: other method than 4 not implemented.");
         casts.arg(3).asLogicalVector().findFirst().map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java
index 2d19c386ca..a2de828f38 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java
@@ -13,7 +13,6 @@ package com.oracle.truffle.r.library.stats;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -23,8 +22,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 public abstract class Cutree extends RExternalBuiltinNode.Arg2 {
 
-    @Override
-    public void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Cutree.class);
         casts.arg(0).asIntegerVector();
         casts.arg(1).asIntegerVector();
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
index 068f611650..0eb3928748 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
@@ -13,15 +13,14 @@ package com.oracle.truffle.r.library.stats;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
 public abstract class DoubleCentre extends RExternalBuiltinNode.Arg1 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(DoubleCentre.class);
         casts.arg(0).asDoubleVector();
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
index 98ea343547..c1ea604e1f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
@@ -24,7 +24,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.function.opt.ReuseNonSharedNode;
 import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode;
@@ -49,8 +48,8 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 {
         return RMultinomNodeGen.create();
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(RMultinomNode.class);
         casts.arg(0).asIntegerVector().findFirst().mustBe(notIntNA(), SHOW_CALLER, Message.INVALID_FIRST_ARGUMENT_NAME, "n");
         casts.arg(1).asIntegerVector().findFirst().mustBe(notIntNA(), SHOW_CALLER, Message.INVALID_SECOND_ARGUMENT_NAME, "size");
         casts.arg(2).asDoubleVector();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
index b977a26713..14f9409f3e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
@@ -31,7 +31,7 @@ import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction
 import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction2NodeGen;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction3NodeGen;
 import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
@@ -66,8 +66,8 @@ public final class RandFunctionsNodes {
 
     /**
      * Converts given value to actual length that should be used as length of the output vector. The
-     * argument must be cast using {@link #addLengthCast(CastBuilder)}. Using this node allows us to
-     * avoid casting of long vectors to integers if we only need to know their length.
+     * argument must be cast using {@link #addLengthCast(Casts)}. Using this node allows us to avoid
+     * casting of long vectors to integers if we only need to know their length.
      */
     protected abstract static class ConvertToLength extends Node {
         public abstract int execute(RAbstractVector value);
@@ -89,7 +89,7 @@ public final class RandFunctionsNodes {
             return vector.getLength();
         }
 
-        private static void addLengthCast(CastBuilder casts) {
+        private static void addLengthCast(Casts casts) {
             casts.arg(0).defaultError(SHOW_CALLER, INVALID_UNNAMED_ARGUMENTS).mustBe(abstractVectorValue()).asVector();
         }
     }
@@ -262,8 +262,8 @@ public final class RandFunctionsNodes {
             return RandFunction3NodeGen.create(RandFunctionsNodesFactory.RandFunctionDoubleExecutorNodeGen.create(function));
         }
 
-        @Override
-        protected final void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(RandFunction3Node.class);
             ConvertToLength.addLengthCast(casts);
             casts.arg(1).asDoubleVector();
             casts.arg(2).asDoubleVector();
@@ -292,8 +292,8 @@ public final class RandFunctionsNodes {
             return RandFunction2NodeGen.create(RandFunctionsNodesFactory.RandFunctionDoubleExecutorNodeGen.create(function));
         }
 
-        @Override
-        protected final void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(RandFunction2Node.class);
             ConvertToLength.addLengthCast(casts);
             casts.arg(1).asDoubleVector();
             casts.arg(2).asDoubleVector();
@@ -321,8 +321,8 @@ public final class RandFunctionsNodes {
             return RandFunction1NodeGen.create(RandFunctionsNodesFactory.RandFunctionDoubleExecutorNodeGen.create(function));
         }
 
-        @Override
-        protected final void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(RandFunction1Node.class);
             ConvertToLength.addLengthCast(casts);
             casts.arg(1).asDoubleVector();
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
index 5ea680278a..11a0662bdf 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function3_2
 import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_1NodeGen;
 import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_2NodeGen;
 import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RError;
@@ -149,8 +148,8 @@ public final class StatsFunctionsNodes {
             return Function3_2NodeGen.create(function);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Function3_2Node.class);
             casts.arg(0).asDoubleVector();
             casts.arg(1).asDoubleVector();
             casts.arg(2).asDoubleVector();
@@ -177,8 +176,8 @@ public final class StatsFunctionsNodes {
             return Function4_1NodeGen.create(function);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Function4_1Node.class);
             casts.arg(0).asDoubleVector();
             casts.arg(1).asDoubleVector();
             casts.arg(2).asDoubleVector();
@@ -205,8 +204,8 @@ public final class StatsFunctionsNodes {
             return Function4_2NodeGen.create(function);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Function4_2Node.class);
             casts.arg(0).asDoubleVector();
             casts.arg(1).asDoubleVector();
             casts.arg(2).asDoubleVector();
@@ -234,8 +233,8 @@ public final class StatsFunctionsNodes {
             return Function3_1NodeGen.create(function);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Function3_1Node.class);
             casts.arg(0).asDoubleVector();
             casts.arg(1).asDoubleVector();
             casts.arg(2).asDoubleVector();
@@ -261,8 +260,8 @@ public final class StatsFunctionsNodes {
             return Function2_1NodeGen.create(function);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Function2_1Node.class);
             casts.arg(0).asDoubleVector();
             casts.arg(1).asDoubleVector();
             casts.arg(2).asLogicalVector().findFirst().map(toBoolean());
@@ -287,8 +286,8 @@ public final class StatsFunctionsNodes {
             return Function2_2NodeGen.create(function);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Function2_2Node.class);
             casts.arg(0).asDoubleVector();
             casts.arg(1).asDoubleVector();
             casts.arg(2).asLogicalVector().findFirst().map(toBoolean());
@@ -308,8 +307,8 @@ public final class StatsFunctionsNodes {
             return ApproxTestNodeGen.create();
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(ApproxTest.class);
             casts.arg(2).asIntegerVector().findFirst();
             casts.arg(3).asDoubleVector().findFirst();
         }
@@ -346,8 +345,8 @@ public final class StatsFunctionsNodes {
             return ApproxNodeGen.create();
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Approx.class);
             casts.arg(2).asDoubleVector();
             casts.arg(3).asIntegerVector().findFirst();
             casts.arg(4).asDoubleVector().findFirst();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
index 07a64735eb..915a54f613 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.ffi.AsIntegerNode;
 import com.oracle.truffle.r.nodes.ffi.AsLogicalNode;
@@ -47,8 +46,8 @@ import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 {
     @Child ToolsRFFI.ParseRdNode parseRdNode = RFFIFactory.getRFFI().getToolsRFFI().createParseRdNode();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(C_ParseRd.class);
         /*
          * Most arguments require coercion using, e.g., asLogical; N.B. GNU R doesn't check
          * everything, e.g., srcfile. Since this is "internal" code we do not really expect argument
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
index 0be43a7188..9685b25687 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
@@ -27,7 +27,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -42,8 +41,8 @@ public abstract class DirChmod extends RExternalBuiltinNode.Arg2 {
     private static final int FILE_MASK = 0644;
     private static final int DIR_MASK = 0755;
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(DirChmod.class);
         casts.arg(0, "dir").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
         casts.arg(1).asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java
index adb3cbb030..7b9d09c4a8 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java
@@ -33,7 +33,6 @@ import java.security.NoSuchAlgorithmException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -45,8 +44,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public abstract class Rmd5 extends RExternalBuiltinNode.Arg1 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Rmd5.class);
         casts.arg(0).defaultError(RError.NO_CALLER, RError.Message.ARG_MUST_BE_CHARACTER, "files").mustBe(stringValue());
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
index 661cd6bd3b..576ff1bd55 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
@@ -25,7 +25,6 @@ import java.nio.file.Path;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -37,8 +36,8 @@ public class ToolsText {
 
     public abstract static class DoTabExpand extends RExternalBuiltinNode.Arg2 {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(DoTabExpand.class);
             casts.arg(0, "strings").defaultError(RError.NO_CALLER, RError.Message.MACRO_CAN_BE_APPLIED_TO, "STRING_ELT()", "character vector", typeName()).mustBe(stringValue());
             casts.arg(1, "starts").defaultError(RError.NO_CALLER, RError.Message.MACRO_CAN_BE_APPLIED_TO, "INTEGER()", "integer", typeName()).mustBe(integerValue()).asIntegerVector();
         }
@@ -79,8 +78,8 @@ public class ToolsText {
 
     public abstract static class CodeFilesAppend extends RExternalBuiltinNode.Arg2 {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(CodeFilesAppend.class);
             casts.arg(0, "file1").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
             casts.arg(1, "file2").mustBe(stringValue()).asStringVector();
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
index 3e898dc731..cb470182d5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
@@ -53,6 +53,10 @@ public final class CountFields extends RExternalBuiltinNode {
 
     }
 
+    static {
+        Casts.noCasts(CountFields.class);
+    }
+
     @TruffleBoundary
     private static Object countFields(RConnection file, char sepChar, String quoteSet, @SuppressWarnings("unused") int nskip, boolean blskip, char comChar) throws IOException {
         LocalData data = new LocalData();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java
index e042768748..51eb47a457 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java
@@ -26,15 +26,14 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public abstract class Crc64 extends RExternalBuiltinNode.Arg1 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Crc64.class);
         casts.arg(0).mustNotBeNull(RError.NO_CALLER,
                         RError.Message.INPUT_MUST_BE_STRING).mustBe(stringValue(), RError.NO_CALLER, RError.Message.INPUT_MUST_BE_STRING);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
index b60dbd422a..0017248292 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
@@ -37,7 +37,6 @@ import java.nio.file.StandardCopyOption;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -48,8 +47,8 @@ import com.oracle.truffle.r.runtime.RError.Message;
  */
 public abstract class Download extends RExternalBuiltinNode.Arg5 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Download.class);
         casts.arg(0).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).shouldBe(singleElement(), Message.ONLY_FIRST_USED).findFirst();
         casts.arg(1).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).shouldBe(singleElement(), Message.ONLY_FIRST_USED).findFirst();
         casts.arg(2).mustBe(logicalValue()).asLogicalVector().mustBe(notEmpty()).shouldBe(singleElement(), Message.ONLY_FIRST_USED).findFirst().map(toBoolean());
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
index 23ebf09462..05fca52ffd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
@@ -14,7 +14,6 @@ package com.oracle.truffle.r.library.utils;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.runtime.RError;
@@ -26,8 +25,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public abstract class Menu extends RExternalBuiltinNode.Arg1 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Menu.class);
         casts.arg(0, "choices").mustBe(Predef.stringValue()).asStringVector().mustBe(Predef.notEmpty());
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
index 4a9ab559d6..ac4688363f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
@@ -40,7 +40,6 @@ import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
 import com.oracle.truffle.api.instrumentation.StandardTags;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation;
@@ -81,8 +80,8 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*;
  */
 public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFactory.Listener, MemoryCopyTracer.Listener {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Rprof.class);
         casts.arg(0, "filename").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
         casts.arg(1, "append_mode").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
         casts.arg(2, "dinterval").asDoubleVector().findFirst(RRuntime.DOUBLE_NA);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
index 88a47ede7f..fb7fbf6c6a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
@@ -40,6 +40,10 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 {
 
     @Child private SetFixedAttributeNode setLevelsAttrNode = SetFixedAttributeNode.create(RRuntime.LEVELS_ATTR_KEY);
 
+    static {
+        Casts.noCasts(TypeConvert.class);
+    }
+
     private static boolean isNA(String s, RAbstractStringVector naStrings) {
         // naStrings are in addition to NA_character_
         if (RRuntime.isNA(s)) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
index 0198eb0e04..40b36e8afd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
@@ -26,7 +26,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -48,8 +47,8 @@ public abstract class APerm extends RBuiltinNode {
     private final BranchProfile emptyPermVector = BranchProfile.create();
     private final ConditionProfile mustResize = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(APerm.class);
         casts.arg("a").mustNotBeNull(RError.Message.FIRST_ARG_MUST_BE_ARRAY);
         casts.arg("perm").allowNull().mustBe(numericValue().or(stringValue()).or(complexValue())).mapIf(numericValue().or(complexValue()), asIntegerVector());
         casts.arg("resize").mustBe(numericValue().or(logicalValue()), Message.INVALID_LOGICAL, "resize").asLogicalVector().findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
index 33c348630c..acf3a5b1cc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
@@ -18,7 +18,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -30,8 +29,8 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 public abstract class Abbrev extends RBuiltinNode {
     private final NACheck naCheck = NACheck.create();
 
-    @Override
-    public void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Abbrev.class);
         casts.arg("x").mustBe(stringValue());
         casts.arg("minlength").asIntegerVector().findFirst().notNA();
         casts.arg("use.classes").asLogicalVector().findFirst().notNA().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java
index 6f117ef49d..f5ca96b1a7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java
@@ -33,6 +33,10 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 @RBuiltin(name = "all", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
 public abstract class All extends Quantifier {
 
+    static {
+        new QuantifierCasts(All.class);
+    }
+
     @Override
     protected boolean emptyVectorResult() {
         return true;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
index 053928da25..ce62baed1a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -52,8 +51,8 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
 @RBuiltin(name = "all.names", kind = INTERNAL, parameterNames = {"expr", "functions", "max.names", "unique"}, behavior = PURE)
 public abstract class AllNames extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AllNames.class);
         casts.arg("functions").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA(RRuntime.LOGICAL_FALSE);
         casts.arg("max.names").asIntegerVector().findFirst(0).notNA(0);
         casts.arg("unique").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).notNA(RRuntime.LOGICAL_TRUE);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java
index 7cf2116f10..3cefcf6e0a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java
@@ -27,12 +27,17 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.r.nodes.builtin.base.Quantifier.QuantifierCasts;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "any", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
 public abstract class Any extends Quantifier {
 
+    static {
+        new QuantifierCasts(Any.class);
+    }
+
     @Override
     protected boolean emptyVectorResult() {
         return false;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
index 57c48da529..dc146c10aa 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -56,8 +55,8 @@ public abstract class AnyNA extends RBuiltinNode {
 
     public abstract byte execute(VirtualFrame frame, Object value, boolean recursive);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AnyNA.class);
         casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java
index 0dca5bbfb1..130ec5a77e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.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
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RType;
@@ -42,8 +41,8 @@ public abstract class Arg extends UnaryArithmeticBuiltinNode {
         super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Arg.class);
         casts.arg("z").mustBe(numericValue().or(complexValue()), RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
index c239b07b29..3ea1d01a8f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -60,6 +60,10 @@ public abstract class Args extends RBuiltinNode {
     @Child private GetFunctions.Get getNode;
     @Child private FrameFunctions.ParentFrame parentFrameNode;
 
+    static {
+        Casts.noCasts(Args.class);
+    }
+
     @Specialization
     protected Object args(VirtualFrame frame, RAbstractStringVector funName) {
         if (funName.getLength() == 0) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
index 8b588ea714..0e7f1dadde 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
@@ -25,14 +25,12 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
-import java.util.function.Function;
-
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -46,7 +44,6 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -79,14 +76,9 @@ public abstract class Array extends RBuiltinNode {
         updateDimNames.executeRAbstractContainer(container, o);
     }
 
-    private String argType(Object arg) {
-        return ((RTypedValue) arg).getRType().getName();
-    }
-
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        Function<Object, Object> argType = this::argType;
-        casts.arg("data").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR_BUT_WAS, "data", argType).mustBe(abstractVectorValue());
+    static {
+        Casts casts = new Casts(Array.class);
+        casts.arg("data").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR_BUT_WAS, "data", typeName()).mustBe(abstractVectorValue());
         casts.arg("dim").defaultError(RError.SHOW_CALLER, RError.Message.CANNOT_BE_LENGTH, "dims", 0).mustNotBeNull().asIntegerVector().mustBe(notEmpty());
         casts.arg("dimnames").defaultError(RError.SHOW_CALLER, RError.Message.DIMNAMES_LIST).allowNull().mustBe(instanceOf(RList.class));
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
index cb65b88f22..afc469496d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -52,6 +52,10 @@ public abstract class AsCall extends RBuiltinNode {
     private final ConditionProfile nullNamesProfile = ConditionProfile.createBinaryProfile();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
+    static {
+        Casts.noCasts(AsCall.class);
+    }
+
     @Specialization
     protected RLanguage asCallFunction(RList x) {
         // TODO error checks
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
index 3dc2d41575..0c00091606 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -46,8 +45,8 @@ public abstract class AsCharacter extends RBuiltinNode {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AsCharacter.class);
         casts.arg("x").mapIf(instanceOf(RAbstractListVector.class).not(), asStringVector());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
index 170e9ec76a..a3878fe3db 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
@@ -49,6 +49,10 @@ public abstract class AsCharacterFactor extends RBuiltinNode {
     @Child CastToVectorNode castToVectorNode = CastToVectorNode.create();
     @Child private GetFixedAttributeNode getLevelsAttrNode = GetFixedAttributeNode.create(RRuntime.LEVELS_ATTR_KEY);
 
+    static {
+        Casts.noCasts(AsCharacterFactor.class);
+    }
+
     @Specialization
     protected RStringVector doAsCharacterFactor(Object x) {
         byte isFactor = (byte) inheritsNode.execute(x, CLASS_FACTOR_VEC, false);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
index 513e3e9adb..4687524829 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RDispatch;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -40,8 +39,8 @@ public abstract class AsComplex extends RBuiltinNode {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AsComplex.class);
         casts.arg("x").asComplexVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
index 88563df392..7c65477dad 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -39,8 +38,8 @@ public abstract class AsDouble extends RBuiltinNode {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AsDouble.class);
         casts.arg("x").asDoubleVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
index d36f0d5089..a049ddd75d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.r.nodes.access.AccessArgumentNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
@@ -65,8 +64,8 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 @RBuiltin(name = "as.function.default", kind = INTERNAL, parameterNames = {"x", "envir"}, behavior = PURE)
 public abstract class AsFunction extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AsFunction.class);
         casts.arg("x").mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(RExpression.class)), RError.SHOW_CALLER2, RError.Message.TYPE_EXPECTED, RType.List.getName());
         casts.arg("envir").mustBe(instanceOf(REnvironment.class), RError.Message.INVALID_ENVIRONMENT);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
index ab4de27010..f7beffc392 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -39,8 +38,8 @@ public abstract class AsInteger extends RBuiltinNode {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AsInteger.class);
         casts.arg("x").asIntegerVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
index 41a7bb1674..5df1046a5c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -39,8 +38,8 @@ public abstract class AsLogical extends RBuiltinNode {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AsLogical.class);
         casts.arg("x").asLogicalVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
index dafd3a6f8a..cd935a7b14 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.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
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -39,8 +38,8 @@ public abstract class AsRaw extends RBuiltinNode {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AsRaw.class);
         casts.arg("x").allowNull().asRawVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
index 3add337eed..facf4b7d25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
@@ -37,7 +37,6 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen.CastPairListNodeGen;
@@ -83,8 +82,8 @@ public abstract class AsVector extends RBuiltinNode {
 
     private final ConditionProfile hasClassProfile = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AsVector.class);
         casts.arg("mode").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
index 658e91d839..9b191ab4b9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.LoopNode;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -91,8 +90,8 @@ public abstract class Assign extends RBuiltinNode {
         }
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Assign.class);
         casts.arg("x").asStringVector().shouldBe(singleElement(), RError.Message.ONLY_FIRST_VARIABLE_NAME).findFirst(RError.Message.INVALID_FIRST_ARGUMENT);
 
         casts.arg("envir").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(REnvironment.class, RError.Message.INVALID_ARGUMENT, "envir");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
index b9103fc9e4..f1ef8beb37 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -49,8 +48,8 @@ public class AttachFunctions {
     @RBuiltin(name = "attach", visibility = OFF, kind = INTERNAL, parameterNames = {"what", "pos", "name"}, behavior = COMPLEX)
     public abstract static class Attach extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Attach.class);
             casts.arg("what").allowNull().mustBe(instanceOf(REnvironment.class).or(instanceOf(RAbstractListVector.class)), RError.Message.ATTACH_BAD_TYPE);
             casts.arg("pos").mustBe(numericValue(), Message.MUST_BE_INTEGER, "pos").asIntegerVector();
             casts.arg("name").mustBe(stringValue());
@@ -106,8 +105,8 @@ public class AttachFunctions {
     @RBuiltin(name = "detach", visibility = OFF, kind = INTERNAL, parameterNames = {"pos"}, behavior = COMPLEX)
     public abstract static class Detach extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Detach.class);
             casts.arg("pos").mustBe(numericValue(), Message.MUST_BE_INTEGER, "pos").asIntegerVector();
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
index 0329bf95e8..530f77eb8e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.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
@@ -38,7 +38,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.IterableAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetRowNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.UpdateAttr.InternStringNode;
 import com.oracle.truffle.r.nodes.builtin.base.UpdateAttrNodeGen.InternStringNodeGen;
@@ -74,8 +73,8 @@ public abstract class Attr extends RBuiltinNode {
         return new Object[]{RMissing.instance, RMissing.instance, RRuntime.asLogical(false)};
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Attr.class);
         // Note: checking RAttributable.class does not work for scalars
         // casts.arg("x").mustBe(RAttributable.class, Message.UNIMPLEMENTED_ARGUMENT_TYPE);
         casts.arg("which").mustBe(stringValue(), Message.MUST_BE_CHARACTER, "which").asStringVector().mustBe(singleElement(), RError.Message.EXACTLY_ONE_WHICH).findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
index 31586b70df..3c751dc990 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
@@ -56,6 +56,10 @@ public abstract class Attributes extends RBuiltinNode {
     @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
     @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
 
+    static {
+        Casts.noCasts(Attributes.class);
+    }
+
     @Specialization
     protected Object attributesNull(RAbstractContainer container,
                     @Cached("createBinaryProfile()") ConditionProfile hasAttributesProfile) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index 576d36eda1..e883fc44c5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.BaseGammaFunctionsFactory.DpsiFnCalcNodeGen;
 import com.oracle.truffle.r.runtime.RError;
@@ -73,8 +72,8 @@ public class BaseGammaFunctions {
 
         private final NACheck naValCheck = NACheck.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Lgamma.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector();
         }
 
@@ -116,8 +115,8 @@ public class BaseGammaFunctions {
             return dpsiFnCalc.executeDouble(x, n, kode, ans);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(DiGamma.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector();
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
index feb0ae5f27..1c9c02253c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -33,8 +32,8 @@ public abstract class Bincode extends RBuiltinNode {
     private final BranchProfile errorProfile = BranchProfile.create();
     private final NACheck naCheck = NACheck.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Bincode.class);
         casts.arg("x").asDoubleVector();
 
         casts.arg("breaks").asDoubleVector();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index b01b00dea1..13da55b7f9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -41,7 +41,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
@@ -525,18 +524,30 @@ public abstract class Bind extends RBaseNode {
         return result;
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "cbind", kind = INTERNAL, parameterNames = {"deparse.level", "..."}, behavior = COMPLEX)
     public abstract static class CbindInternal extends AbstractBind {
         public CbindInternal() {
             super(BindType.cbind);
         }
+
+        static {
+            new BindCasts(CbindInternal.class);
+        }
+
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "rbind", kind = INTERNAL, parameterNames = {"deparse.level", "..."}, behavior = COMPLEX)
     public abstract static class RbindInternal extends AbstractBind {
         public RbindInternal() {
             super(BindType.rbind);
         }
+
+        static {
+            new BindCasts(RbindInternal.class);
+        }
+
     }
 
     protected abstract static class AbstractBind extends RBuiltinNode {
@@ -557,9 +568,11 @@ public abstract class Bind extends RBaseNode {
             this.type = type;
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("deparse.level").asIntegerVector().findFirst(0);
+        static final class BindCasts extends Casts {
+            BindCasts(Class<? extends AbstractBind> extCls) {
+                super(extCls);
+                casts.arg("deparse.level").asIntegerVector().findFirst(0);
+            }
         }
 
         @Specialization
@@ -614,6 +627,7 @@ public abstract class Bind extends RBaseNode {
             }
             return result != null ? result.function : null;
         }
+
     }
 
     public RVector<?> genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, RVector<?> result, int[] resultDimensions, int[] firstDims, boolean rowsAndColumnsNotEqual,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
index ae96659c84..9fe775ec76 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
@@ -19,15 +19,13 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.shouldBe;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
-import java.util.function.Function;
-
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNodeGen;
@@ -137,19 +135,15 @@ public class BitwiseFunctions {
             }
             return RDataFactory.createIntVector(na, RDataFactory.INCOMPLETE_VECTOR);
         }
-
-        protected Function<Object, String> getArgType() {
-            return x -> typeofA.execute(x).getName();
-        }
     }
 
     @RBuiltin(name = "bitwiseAnd", kind = INTERNAL, parameterNames = {"a", "b"}, behavior = PURE)
     public abstract static class BitwiseAnd extends BasicBitwise {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.AND.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
-            casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.AND.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
+        static {
+            Casts casts = new Casts(BitwiseAnd.class);
+            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.AND.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
+            casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.AND.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
         }
 
         @Specialization
@@ -167,10 +161,10 @@ public class BitwiseFunctions {
     @RBuiltin(name = "bitwiseOr", kind = INTERNAL, parameterNames = {"a", "b"}, behavior = PURE)
     public abstract static class BitwiseOr extends BasicBitwise {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.OR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
-            casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.OR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
+        static {
+            Casts casts = new Casts(BitwiseOr.class);
+            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.OR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
+            casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.OR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
         }
 
         @Specialization
@@ -188,10 +182,10 @@ public class BitwiseFunctions {
     @RBuiltin(name = "bitwiseXor", kind = INTERNAL, parameterNames = {"a", "b"}, behavior = PURE)
     public abstract static class BitwiseXor extends BasicBitwise {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.XOR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
-            casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.XOR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
+        static {
+            Casts casts = new Casts(BitwiseXor.class);
+            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.XOR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
+            casts.arg("b").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.XOR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
         }
 
         @Specialization
@@ -209,9 +203,9 @@ public class BitwiseFunctions {
     @RBuiltin(name = "bitwiseShiftR", kind = INTERNAL, parameterNames = {"a", "n"}, behavior = PURE)
     public abstract static class BitwiseShiftR extends BasicBitwise {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.SHIFTR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
+        static {
+            Casts casts = new Casts(BitwiseShiftR.class);
+            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
             casts.arg("n").mapIf(stringValue(), asStringVector(), asIntegerVector());
         }
 
@@ -236,9 +230,9 @@ public class BitwiseFunctions {
     @RBuiltin(name = "bitwiseShiftL", kind = INTERNAL, parameterNames = {"a", "n"}, behavior = PURE)
     public abstract static class BitwiseShiftL extends BasicBitwise {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("a").defaultError(RError.ROOTNODE, RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.SHIFTL.name).mustBe(
+        static {
+            Casts casts = new Casts(BitwiseShiftL.class);
+            casts.arg("a").defaultError(RError.ROOTNODE, RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTL.name).mustBe(
                             doubleValue().or(integerValue())).asIntegerVector();
             casts.arg("n").allowNull().mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(), RError.SHOW_CALLER, RError.Message.NA_INTRODUCED_COERCION)).end(),
                             asIntegerVector());
@@ -265,10 +259,12 @@ public class BitwiseFunctions {
     @RBuiltin(name = "bitwiseNot", kind = INTERNAL, parameterNames = {"a"}, behavior = PURE)
     public abstract static class BitwiseNot extends BasicBitwise {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, getArgType(), Operation.NOT.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
-        }
+        // @formatter:off
+    static {
+        Casts casts = new Casts(BitwiseNot.class);
+            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.NOT.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
+    }
+        //@formatter:on
 
         @Specialization
         protected Object bitwNot(RAbstractIntVector a) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
index e852f86379..53812789a2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -36,6 +36,10 @@ import com.oracle.truffle.r.runtime.data.RNull;
 @RBuiltin(name = "body", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
 public abstract class Body extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(Body.class);
+    }
+
     @Specialization
     protected Object doBody(RFunction fun) {
         FunctionDefinitionNode fdn = (FunctionDefinitionNode) fun.getRootNode();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
index b84302c5ff..2e2226c339 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
@@ -34,7 +34,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNodeGen;
@@ -61,8 +60,8 @@ public class BrowserFunctions {
             return new Object[]{"", RNull.instance, RRuntime.LOGICAL_TRUE, 0};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(BrowserNode.class);
             // TODO: add support for conditions conditions
             casts.arg("condition").mustBe(nullValue(), RError.Message.GENERIC, "Only NULL conditions currently supported in browser");
             casts.arg("expr").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
@@ -102,8 +101,8 @@ public class BrowserFunctions {
 
     private abstract static class RetrieveAdapter extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(RetrieveAdapter.class);
             casts.arg("n").asIntegerVector().findFirst(0).mustBe(gt(0), Message.POSITIVE_CONTEXTS);
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
index 3c0d9280a5..8680eccad3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.utils.Crc64;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -39,8 +38,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "crc64", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
 public abstract class CRC64 extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(CRC64.class);
         casts.arg("x").defaultError(RError.NO_CALLER, Message.INPUT_MUST_BE_STRING).mustBe(stringValue());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java
index 9c0d5bd0f0..d95ff7128f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -18,7 +18,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -28,8 +27,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = ".cache_class", kind = PRIMITIVE, parameterNames = {"class", "extends"}, behavior = COMPLEX)
 public abstract class CacheClass extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(CacheClass.class);
         casts.arg("class").defaultError(RError.Message.GENERIC, "invalid class argument to internal .class_cache").mustBe(stringValue()).asStringVector().findFirst();
         // apparently, "extends" does not have to be a string vector (GNU R will not signal this
         // error) - but it does not seem to make much sense and it's doubtful if it's worth
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
index b219b18a59..ed84a24405 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
@@ -64,8 +63,8 @@ public abstract class Call extends RBuiltinNode {
         return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY};
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Call.class);
         casts.arg("").mustBe(stringValue(), RError.Message.FIRST_ARG_MUST_BE_STRING).asStringVector().findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
index f42bc2c3c5..d1e14444e7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.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
@@ -42,7 +42,6 @@ import java.util.ArrayList;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.ToStringNode;
 import com.oracle.truffle.r.nodes.unary.ToStringNodeGen;
@@ -77,8 +76,8 @@ public abstract class Cat extends RBuiltinNode {
         }
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Cat.class);
         casts.arg("sep").mustBe(stringValue(), RError.Message.INVALID_SEP);
 
         casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
index b8cf2bdb96..97a3965244 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RType;
@@ -47,16 +46,10 @@ public abstract class Ceiling extends UnaryArithmeticBuiltinNode {
         super(RType.Double, RError.Message.NON_NUMERIC_MATH, null);
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        //@formatter:off
-        casts.arg("x").
-            defaultError(this, RError.Message.NON_NUMERIC_MATH).
-            mustNotBeNull().
-            mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).
-            mustBe(numericValue()).
-            asDoubleVector(true, true, true);
-        //@formatter:on
+    static {
+        Casts casts = new Casts(Ceiling.class);
+        casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustNotBeNull().mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(true,
+                        true, true);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
index 335418deeb..86c6b72e20 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -28,8 +27,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "charmatch", kind = INTERNAL, parameterNames = {"x", "table", "noMatch"}, behavior = PURE)
 public abstract class CharMatch extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(CharMatch.class);
         casts.arg("x").mustBe(stringValue(), RError.NO_CALLER, Message.ARG_IS_NOT_OF_MODE, "character");
         casts.arg("table").mustBe(stringValue(), RError.NO_CALLER, Message.ARG_IS_NOT_OF_MODE, "character");
         casts.arg("noMatch").asIntegerVector().findFirst(RRuntime.INT_NA);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
index 7a63eaf5b9..c72287f73e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
@@ -32,7 +32,6 @@ import java.util.function.IntToDoubleFunction;
 import java.util.function.IntUnaryOperator;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -53,8 +52,8 @@ public abstract class ChooseBuiltin extends RBuiltinNode {
 
     private final NACheck na = NACheck.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(ChooseBuiltin.class);
         casts.arg("n").mustBe(numericValue(), RError.SHOW_CALLER, Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector());
         casts.arg("k").mustBe(numericValue(), RError.SHOW_CALLER, Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
index 99cca9a919..242bce76a3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -41,8 +40,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 @RBuiltin(name = "col", kind = INTERNAL, parameterNames = {"dims"}, behavior = PURE)
 public abstract class Col extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Col.class);
         casts.arg("dims").defaultError(RError.SHOW_CALLER, RError.Message.MATRIX_LIKE_REQUIRED, "col").mustBe(integerValue()).asIntegerVector().mustBe(size(2));
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java
index 744d723842..121a78c81f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -24,11 +24,16 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
 //Implements .colMeans
+@SuppressWarnings("unused")
 @RBuiltin(name = "colMeans", kind = INTERNAL, parameterNames = {"X", "m", "n", "na.rm"}, behavior = PURE)
 public abstract class ColMeans extends ColSumsBase {
 
     @Child private BinaryArithmetic add = BinaryArithmetic.ADD.createOperation();
 
+    static {
+        new ColSumsCasts(ColMeans.class);
+    }
+
     @Specialization(guards = "!naRm")
     protected RDoubleVector colMeansNaRmFalse(RAbstractDoubleVector x, int rowNum, int colNum, @SuppressWarnings("unused") boolean naRm) {
         checkVectorLength(x, rowNum, colNum);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java
index bafef83f8f..7dce23f2da 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.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
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
+@SuppressWarnings("unused")
 @RBuiltin(name = "colSums", kind = INTERNAL, parameterNames = {"X", "m", "n", "na.rm"}, behavior = PURE)
 public abstract class ColSums extends ColSumsBase {
 
@@ -45,6 +46,10 @@ public abstract class ColSums extends ColSumsBase {
     private final ConditionProfile removeNA = ConditionProfile.createBinaryProfile();
     private final ValueProfile concreteVectorProfile = ValueProfile.createClassProfile();
 
+    static {
+        new ColSumsCasts(ColSums.class);
+    }
+
     @Specialization
     protected RDoubleVector colSums(RAbstractDoubleVector x, int rowNum, int colNum, boolean rnaParam) {
         checkVectorLength(x, rowNum, colNum);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java
index 86d65c04da..1f14bc7a11 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.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
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -47,12 +46,14 @@ public abstract class ColSumsBase extends RBuiltinNode {
     protected final NACheck na = NACheck.create();
     private final ConditionProfile vectorLengthProfile = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected final void createCasts(CastBuilder casts) {
-        casts.arg("X").mustBe(numericValue(), RError.SHOW_CALLER, RError.Message.X_NUMERIC);
-        casts.arg("m").defaultError(RError.SHOW_CALLER, INVALID_ARGUMENT, "n").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA);
-        casts.arg("n").defaultError(RError.SHOW_CALLER, INVALID_ARGUMENT, "p").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA);
-        casts.arg("na.rm").asLogicalVector().findFirst().notNA().map(toBoolean());
+    static final class ColSumsCasts extends Casts {
+        ColSumsCasts(Class<? extends ColSumsBase> extCls) {
+            super(extCls);
+            casts.arg("X").mustBe(numericValue(), RError.SHOW_CALLER, RError.Message.X_NUMERIC);
+            casts.arg("m").defaultError(RError.SHOW_CALLER, INVALID_ARGUMENT, "n").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA);
+            casts.arg("n").defaultError(RError.SHOW_CALLER, INVALID_ARGUMENT, "p").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA);
+            casts.arg("na.rm").asLogicalVector().findFirst().notNA().map(toBoolean());
+        }
     }
 
     protected final void checkVectorLength(RAbstractVector x, int rowNum, int colNum) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
index 0be1946f75..9fa28b86e3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
@@ -58,6 +58,10 @@ public abstract class Colon extends RBuiltinNode {
     @Child private ColonCastNode rightCast = ColonCastNodeGen.create();
     @Child private ColonInternal internal = ColonInternalNodeGen.create();
 
+    static {
+        Casts.noCasts(Colon.class);
+    }
+
     @Specialization
     protected RSequence colon(Object left, Object right) {
         return internal.execute(leftCast.execute(left), rightCast.execute(right));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 56d47d9a6f..1e068b47c7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -49,7 +49,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.CombineNodeGen.CombineInputCastNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen;
@@ -104,8 +103,8 @@ public abstract class Combine extends RBuiltinNode {
     private final ConditionProfile hasNewNamesProfile = ConditionProfile.createBinaryProfile();
     @CompilationFinal private final ValueProfile[] argProfiles = new ValueProfile[MAX_PROFILES];
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Combine.class);
         casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java
index fd951173e3..7fb2b3ce4d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
@@ -38,8 +37,8 @@ public class CompileFunctions {
     @RBuiltin(name = "compilePKGS", kind = INTERNAL, parameterNames = "enable", behavior = PURE)
     public abstract static class CompilePKGS extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(CompilePKGS.class);
             casts.arg("enable").asIntegerVector().findFirst(0);
         }
 
@@ -51,8 +50,9 @@ public class CompileFunctions {
 
     @RBuiltin(name = "enableJIT", kind = INTERNAL, parameterNames = "level", behavior = PURE)
     public abstract static class EnableJIT extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(EnableJIT.class);
             casts.arg("level").asIntegerVector().findFirst(0);
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java
index a18522b376..f8826494d7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.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
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -42,8 +41,8 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 @RBuiltin(name = "complex", kind = INTERNAL, parameterNames = {"length.out", "real", "imaginary"}, behavior = PURE)
 public abstract class Complex extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Complex.class);
         casts.arg("length.out").asIntegerVector().findFirst(Message.INVALID_LENGTH);
         casts.arg("real").mapNull(emptyDoubleVector()).asDoubleVector();
         casts.arg("imaginary").mapNull(emptyDoubleVector()).asDoubleVector();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
index d9d86038cf..00bae3fd40 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
@@ -28,6 +28,8 @@ import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
+import com.oracle.truffle.r.nodes.builtin.base.foreign.CallAndExternalFunctions.DotExternal2;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -58,8 +60,9 @@ public class ConditionFunctions {
 
     @RBuiltin(name = ".addCondHands", visibility = OFF, kind = INTERNAL, parameterNames = {"classes", "handlers", "parentenv", "target", "calling"}, behavior = COMPLEX)
     public abstract static class AddCondHands extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(AddCondHands.class);
             casts.arg("classes").allowNull().mustBe(stringValue()).asStringVector();
             casts.arg("handlers").allowNull().mustBe(instanceOf(RList.class));
             casts.arg("calling").asLogicalVector().findFirst();
@@ -116,15 +119,16 @@ public class ConditionFunctions {
             }
         }
 
-        protected void restart(CastBuilder casts) {
+        protected static void restart(Casts casts) {
             casts.arg("restart").mustBe(instanceOf(RList.class), RError.Message.BAD_RESTART);
         }
     }
 
     @RBuiltin(name = ".addRestart", kind = INTERNAL, parameterNames = "restart", behavior = COMPLEX)
     public abstract static class AddRestart extends RestartAdapter {
-        @Override
-        public void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(AddRestart.class);
             restart(casts);
         }
 
@@ -150,8 +154,9 @@ public class ConditionFunctions {
 
     @RBuiltin(name = ".getRestart", kind = INTERNAL, parameterNames = "restart", behavior = COMPLEX)
     public abstract static class GetRestart extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(GetRestart.class);
             casts.arg("restart").asIntegerVector().findFirst();
         }
 
@@ -164,8 +169,9 @@ public class ConditionFunctions {
 
     @RBuiltin(name = ".invokeRestart", kind = INTERNAL, parameterNames = {"restart", "args"}, behavior = COMPLEX)
     public abstract static class InvokeRestart extends RestartAdapter {
-        @Override
-        public void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(InvokeRestart.class);
             restart(casts);
         }
 
@@ -183,6 +189,11 @@ public class ConditionFunctions {
 
     @RBuiltin(name = ".signalCondition", kind = INTERNAL, parameterNames = {"condition", "msg", "call"}, behavior = COMPLEX)
     public abstract static class SignalCondition extends RBuiltinNode {
+
+        static {
+            Casts.noCasts(SignalCondition.class);
+        }
+
         @Specialization
         protected RNull signalCondition(RList condition, RAbstractStringVector msg, Object call) {
             RErrorHandling.signalCondition(condition, msg.getDataAt(0), call);
@@ -200,8 +211,9 @@ public class ConditionFunctions {
 
     @RBuiltin(name = "seterrmessage", visibility = OFF, kind = INTERNAL, parameterNames = "msg", behavior = COMPLEX)
     public abstract static class Seterrmessage extends RBuiltinNode {
-        @Override
-        public void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(Seterrmessage.class);
             casts.arg("msg").defaultError(RError.Message.ERR_MSG_MUST_BE_STRING).mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
         }
 
@@ -214,8 +226,9 @@ public class ConditionFunctions {
 
     @RBuiltin(name = ".dfltWarn", kind = INTERNAL, parameterNames = {"message", "call"}, behavior = COMPLEX)
     public abstract static class DfltWarn extends RBuiltinNode {
-        @Override
-        public void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(DfltWarn.class);
             casts.arg("message").defaultError(RError.Message.ERR_MSG_BAD).mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
         }
 
@@ -228,8 +241,9 @@ public class ConditionFunctions {
 
     @RBuiltin(name = ".dfltStop", kind = INTERNAL, parameterNames = {"message", "call"}, behavior = COMPLEX)
     public abstract static class DfltStop extends RBuiltinNode {
-        @Override
-        public void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(DfltStop.class);
             casts.arg("message").defaultError(RError.Message.ERR_MSG_BAD).mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index ae401acf12..579c88b0ea 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -57,7 +57,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.ConnectionFunctionsFactory.WriteDataNodeGen;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.HeadPhaseBuilder;
@@ -134,52 +134,52 @@ public abstract class ConnectionFunctions {
         }
     }
 
-    public static final class Casts {
-        private static void description(CastBuilder casts) {
+    public static final class CastsHelper {
+        private static void description(Casts casts) {
             casts.arg("description").mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().notNA();
         }
 
-        private static HeadPhaseBuilder<String> open(CastBuilder casts) {
+        private static HeadPhaseBuilder<String> open(Casts casts) {
             return casts.arg("open").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().notNA();
         }
 
-        private static void encoding(CastBuilder casts) {
+        private static void encoding(Casts casts) {
             casts.arg("encoding").asStringVector().mustBe(singleElement()).findFirst();
         }
 
-        private static void raw(CastBuilder casts) {
+        private static void raw(Casts casts) {
             casts.arg("raw").asLogicalVector().findFirst().notNA().map(toBoolean());
         }
 
-        private static void blocking(CastBuilder casts) {
+        private static void blocking(Casts casts) {
             casts.arg("blocking").asLogicalVector().findFirst().notNA().map(toBoolean());
         }
 
-        public static void connection(CastBuilder casts) {
+        public static void connection(Casts casts) {
             casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
         }
 
-        private static void nchars(CastBuilder casts) {
+        private static void nchars(Casts casts) {
             casts.arg("nchars").asIntegerVector().mustBe(notEmpty());
         }
 
-        private static void useBytes(CastBuilder casts) {
+        private static void useBytes(Casts casts) {
             casts.arg("useBytes").asLogicalVector().findFirst().notNA().map(toBoolean());
         }
 
-        private static void n(CastBuilder casts) {
+        private static void n(Casts casts) {
             casts.arg("n").asIntegerVector().findFirst().mustBe(gte(0));
         }
 
-        private static void size(CastBuilder casts) {
+        private static void size(Casts casts) {
             casts.arg("size").asIntegerVector().findFirst();
         }
 
-        private static void swap(CastBuilder casts) {
+        private static void swap(Casts casts) {
             casts.arg("swap").asLogicalVector().findFirst().notNA().map(toBoolean());
         }
 
-        private static void method(CastBuilder casts) {
+        private static void method(Casts casts) {
             casts.arg("method").asStringVector().findFirst();
         }
     }
@@ -187,14 +187,14 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "file", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method", "raw"}, behavior = IO)
     public abstract static class File extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.description(casts);
-            Casts.open(casts);
+        static {
+            Casts casts = new Casts(File.class);
+            CastsHelper.description(casts);
+            CastsHelper.open(casts);
             casts.arg("blocking").asLogicalVector().findFirst().mustBe(logicalTrue(), RError.Message.NYI, "non-blocking mode not supported").map(toBoolean());
-            Casts.encoding(casts);
-            Casts.method(casts);
-            Casts.raw(casts);
+            CastsHelper.encoding(casts);
+            CastsHelper.method(casts);
+            CastsHelper.raw(casts);
         }
 
         @Specialization
@@ -236,12 +236,14 @@ public abstract class ConnectionFunctions {
             this.cType = cType;
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.description(casts);
-            Casts.open(casts);
-            Casts.encoding(casts);
-            casts.arg("compression").asIntegerVector().findFirst().notNA().mustBe(gte(cType == RCompression.Type.XZ ? -9 : 0).and(lte(9)));
+        static final class ZZCasts extends Casts {
+            protected ZZCasts(Class<? extends ZZFileAdapter> extCls, RCompression.Type cType) {
+                super(extCls);
+                CastsHelper.description(this);
+                CastsHelper.open(this);
+                CastsHelper.encoding(this);
+                casts.arg("compression").asIntegerVector().findFirst().notNA().mustBe(gte(cType == RCompression.Type.XZ ? -9 : 0).and(lte(9)));
+            }
         }
 
         @Specialization
@@ -260,37 +262,56 @@ public abstract class ConnectionFunctions {
         }
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "gzfile", kind = INTERNAL, parameterNames = {"description", "open", "encoding", "compression"}, behavior = IO)
     public abstract static class GZFile extends ZZFileAdapter {
         protected GZFile() {
             super(RCompression.Type.GZIP);
         }
+
+        static {
+            new ZZCasts(GZFile.class, RCompression.Type.GZIP);
+        }
+
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "bzfile", kind = INTERNAL, parameterNames = {"description", "open", "encoding", "compression"}, behavior = IO)
     public abstract static class BZFile extends ZZFileAdapter {
         protected BZFile() {
             super(RCompression.Type.BZIP2);
         }
+
+        static {
+            new ZZCasts(BZFile.class, RCompression.Type.BZIP2);
+        }
+
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "xzfile", kind = INTERNAL, parameterNames = {"description", "open", "encoding", "compression"}, behavior = IO)
     public abstract static class XZFile extends ZZFileAdapter {
         protected XZFile() {
             super(RCompression.Type.XZ);
         }
+
+        static {
+            new ZZCasts(XZFile.class, RCompression.Type.XZ);
+        }
+
     }
 
     @RBuiltin(name = "textConnection", kind = INTERNAL, parameterNames = {"description", "text", "open", "env", "encoding"}, behavior = IO)
     public abstract static class TextConnection extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.description(casts);
+
+        static {
+            Casts casts = new Casts(TextConnection.class);
+            CastsHelper.description(casts);
             // TODO how to have either a RNull or a String/RStringVector and have the latter coerced
             // to a
             // RAbstractStringVector to avoid the explicit handling in the specialization
             casts.arg("text").allowNull().mustBe(stringValue());
-            Casts.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE);
+            CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE);
             casts.arg("env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
             casts.arg("encoding").asIntegerVector().findFirst().notNA();
         }
@@ -330,8 +351,9 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "textConnectionValue", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
     public abstract static class TextConnectionValue extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(TextConnectionValue.class);
             casts.arg("con").defaultError(Message.NOT_A_TEXT_CONNECTION).mustBe(integerValue()).asIntegerVector().findFirst();
         }
 
@@ -350,13 +372,13 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "socketConnection", kind = INTERNAL, parameterNames = {"host", "port", "server", "blocking", "open", "encoding", "timeout"}, behavior = IO)
     public abstract static class SocketConnection extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SocketConnection.class);
             casts.arg("host").mustBe(stringValue()).asStringVector().findFirst();
             casts.arg("port").asIntegerVector().findFirst().notNA().mustBe(gte(0));
             casts.arg("server").asLogicalVector().findFirst().notNA().map(toBoolean());
-            Casts.open(casts);
-            Casts.blocking(casts);
+            CastsHelper.open(casts);
+            CastsHelper.blocking(casts);
             casts.arg("timeout").asIntegerVector().findFirst();
         }
 
@@ -379,13 +401,13 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "url", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method"}, behavior = IO)
     public abstract static class URLConnection extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.description(casts);
-            Casts.open(casts);
-            Casts.blocking(casts);
-            Casts.encoding(casts);
-            Casts.method(casts);
+        static {
+            Casts casts = new Casts(URLConnection.class);
+            CastsHelper.description(casts);
+            CastsHelper.open(casts);
+            CastsHelper.blocking(casts);
+            CastsHelper.encoding(casts);
+            CastsHelper.method(casts);
         }
 
         @Specialization
@@ -407,8 +429,8 @@ public abstract class ConnectionFunctions {
         private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"description", "class", "mode", "text", "opened", "can read", "can write"},
                         RDataFactory.COMPLETE_VECTOR);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Summary.class);
             casts.arg("object").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
         }
 
@@ -431,11 +453,11 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "open", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "open", "blocking"}, behavior = IO)
     public abstract static class Open extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
-            Casts.open(casts);
-            Casts.blocking(casts);
+        static {
+            Casts casts = new Casts(Open.class);
+            CastsHelper.connection(casts);
+            CastsHelper.open(casts);
+            CastsHelper.blocking(casts);
         }
 
         @Specialization
@@ -460,9 +482,10 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "isOpen", kind = INTERNAL, parameterNames = {"con", "rw"}, behavior = IO)
     public abstract static class IsOpen extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
+
+        static {
+            Casts casts = new Casts(IsOpen.class);
+            CastsHelper.connection(casts);
             casts.arg("rw").asIntegerVector().findFirst();
         }
 
@@ -489,9 +512,10 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "close", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "type"}, behavior = IO)
     public abstract static class Close extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
+
+        static {
+            Casts casts = new Casts(Close.class);
+            CastsHelper.connection(casts);
             casts.arg("type").asStringVector().findFirst();
         }
 
@@ -511,13 +535,13 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "readLines", kind = INTERNAL, parameterNames = {"con", "n", "ok", "warn", "encoding", "skipNul"}, behavior = IO)
     public abstract static class ReadLines extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
+        static {
+            Casts casts = new Casts(ReadLines.class);
+            CastsHelper.connection(casts);
             casts.arg("n").asIntegerVector().findFirst().notNA();
             casts.arg("ok").asLogicalVector().findFirst().notNA().map(toBoolean());
             casts.arg("warn").asLogicalVector().findFirst().notNA().map(toBoolean());
-            Casts.encoding(casts);
+            CastsHelper.encoding(casts);
             casts.arg("skipNul").asLogicalVector().findFirst().notNA().map(toBoolean());
         }
 
@@ -539,12 +563,13 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "writeLines", visibility = OFF, kind = INTERNAL, parameterNames = {"text", "con", "sep", "useBytes"}, behavior = IO)
     public abstract static class WriteLines extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(WriteLines.class);
             casts.arg("text").asStringVector().mustBe(instanceOf(RAbstractStringVector.class));
-            Casts.connection(casts);
+            CastsHelper.connection(casts);
             casts.arg("sep").asStringVector().findFirst();
-            Casts.useBytes(casts);
+            CastsHelper.useBytes(casts);
         }
 
         @Specialization
@@ -561,9 +586,10 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "flush", visibility = OFF, kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
     public abstract static class Flush extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
+
+        static {
+            Casts casts = new Casts(Flush.class);
+            CastsHelper.connection(casts);
         }
 
         @Specialization
@@ -581,10 +607,10 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "pushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"data", "con", "newLine", "type"}, behavior = IO)
     public abstract static class PushBack extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(PushBack.class);
             casts.arg("data").asStringVector().mustBe(instanceOf(RAbstractStringVector.class));
-            Casts.connection(casts);
+            CastsHelper.connection(casts);
             casts.arg("newLine").asLogicalVector().findFirst().notNA().map(toBoolean());
             casts.arg("type").asIntegerVector().findFirst();
         }
@@ -599,9 +625,10 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "pushBackLength", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
     public abstract static class PushBackLength extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
+
+        static {
+            Casts casts = new Casts(PushBackLength.class);
+            CastsHelper.connection(casts);
         }
 
         @Specialization
@@ -613,9 +640,9 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "clearPushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
     public abstract static class PushBackClear extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
+        static {
+            Casts casts = new Casts(PushBackClear.class);
+            CastsHelper.connection(casts);
         }
 
         @Specialization
@@ -628,11 +655,11 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "readChar", kind = INTERNAL, parameterNames = {"con", "nchars", "useBytes"}, behavior = IO)
     public abstract static class ReadChar extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
-            Casts.nchars(casts);
-            Casts.useBytes(casts);
+        static {
+            Casts casts = new Casts(ReadChar.class);
+            CastsHelper.connection(casts);
+            CastsHelper.nchars(casts);
+            CastsHelper.useBytes(casts);
         }
 
         @SuppressWarnings("unused")
@@ -662,14 +689,15 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "writeChar", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "nchars", "sep", "useBytes"}, behavior = IO)
     public abstract static class WriteChar extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(WriteChar.class);
             casts.arg("object").asStringVector();
             casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustBe(integerValue().or(rawValue())).mapIf(integerValue(),
                             asIntegerVector().setNext(findFirst().integerElement()));
-            Casts.nchars(casts);
+            CastsHelper.nchars(casts);
             casts.arg("sep").allowNull().mustBe(stringValue());
-            Casts.useBytes(casts);
+            CastsHelper.useBytes(casts);
         }
 
         @TruffleBoundary
@@ -717,15 +745,15 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "readBin", kind = INTERNAL, parameterNames = {"con", "what", "n", "size", "signed", "swap"}, behavior = IO)
     public abstract static class ReadBin extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(ReadBin.class);
             // TODO con can be a RAWSXP (not implemented)
-            Casts.connection(casts);
+            CastsHelper.connection(casts);
             casts.arg("what").asStringVector().findFirst();
-            Casts.n(casts);
-            Casts.size(casts);
+            CastsHelper.n(casts);
+            CastsHelper.size(casts);
             casts.arg("signed").asLogicalVector().findFirst().notNA().map(toBoolean());
-            Casts.swap(casts);
+            CastsHelper.swap(casts);
         }
 
         @Specialization
@@ -1003,14 +1031,14 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "writeBin", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "size", "swap", "useBytes"}, behavior = IO)
     public abstract static class WriteBin extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(WriteBin.class);
             // TODO atomic, i.e. not RList or RExpression
             casts.arg("object").asVector().mustBe(instanceOf(RAbstractVector.class));
             casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustBe(integerValue().or(rawValue())).mapIf(integerValue(), asIntegerVector().setNext(findFirst().integerElement()));
-            Casts.size(casts);
-            Casts.swap(casts);
-            Casts.useBytes(casts);
+            CastsHelper.size(casts);
+            CastsHelper.swap(casts);
+            CastsHelper.useBytes(casts);
         }
 
         @TruffleBoundary
@@ -1050,8 +1078,8 @@ public abstract class ConnectionFunctions {
     @RBuiltin(name = "getConnection", kind = INTERNAL, parameterNames = {"what"}, behavior = IO)
     public abstract static class GetConnection extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(GetConnection.class);
             casts.arg("what").asIntegerVector().findFirst();
         }
 
@@ -1078,9 +1106,10 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "isSeekable", kind = INTERNAL, parameterNames = "con", behavior = IO)
     public abstract static class IsSeekable extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
+
+        static {
+            Casts casts = new Casts(IsSeekable.class);
+            CastsHelper.connection(casts);
         }
 
         @Specialization
@@ -1092,9 +1121,10 @@ public abstract class ConnectionFunctions {
 
     @RBuiltin(name = "seek", kind = INTERNAL, parameterNames = {"con", "where", "origin", "rw"}, behavior = IO)
     public abstract static class Seek extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.connection(casts);
+
+        static {
+            Casts casts = new Casts(Seek.class);
+            CastsHelper.connection(casts);
             casts.arg("where").asDoubleVector().findFirst();
             casts.arg("origin").asIntegerVector().findFirst();
             casts.arg("rw").asIntegerVector().findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java
index 491c440ba7..d9f2875e1c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -36,6 +36,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 @RBuiltin(name = "copyDFattr", kind = INTERNAL, parameterNames = {"", ""}, behavior = COMPLEX)
 public abstract class CopyDFAttr extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(CopyDFAttr.class);
+    }
+
     @Specialization()
     protected RAttributable copy(RAbstractContainer in, RAbstractVector out) {
         RVector<?> res = out.materialize();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
index 01f77b91cb..842176d655 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -48,8 +47,8 @@ public abstract class Crossprod extends RBuiltinNode {
     @Child private MatMult matMult = MatMultNodeGen.create(/* promoteDimNames: */ false);
     @Child private Transpose transpose;
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Crossprod.class);
         casts.arg("x").mustBe(numericValue().or(complexValue()), RError.ROOTNODE, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR);
         casts.arg("y").defaultError(RError.ROOTNODE, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR).allowNull().mustBe(numericValue().or(complexValue()));
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
index f23a4ff164..236988ed46 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
@@ -25,7 +25,6 @@ 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.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -47,8 +46,8 @@ public abstract class CumMax extends RBuiltinNode {
     private final NACheck na = NACheck.create();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(CumMax.class);
         casts.arg("x").allowNull().mustBe(complexValue().not(), RError.Message.CUMMAX_UNDEFINED_FOR_COMPLEX).mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false),
                         asDoubleVector(true, false, false));
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
index 0307625765..ae28196a60 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
@@ -25,7 +25,6 @@ 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.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -47,8 +46,8 @@ public abstract class CumMin extends RBuiltinNode {
     private final NACheck na = NACheck.create();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(CumMin.class);
         casts.arg("x").allowNull().mustBe(complexValue().not(), RError.Message.CUMMIN_UNDEFINED_FOR_COMPLEX).mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false),
                         asDoubleVector(true, false, false));
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
index 20dcf0d352..ef609bb011 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
@@ -20,7 +20,6 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -43,8 +42,8 @@ public abstract class CumProd extends RBuiltinNode {
 
     @Child private BinaryArithmetic mul = BinaryArithmetic.MULTIPLY.createOperation();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(CumProd.class);
         casts.arg("x").allowNull().mapIf(complexValue().not(), asDoubleVector(true, false, false));
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
index 92649d60d5..7a1886ac6e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
@@ -37,7 +37,6 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -63,8 +62,8 @@ public abstract class CumSum extends RBuiltinNode {
 
     @Child private BinaryArithmetic add = BinaryArithmetic.ADD.createOperation();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(CumSum.class);
         casts.arg("x").allowNull().mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false), chain(mapIf(complexValue().not(), asDoubleVector(true, false, false))).end());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
index f3621cd18b..8a72551092 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.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
@@ -30,7 +30,6 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
@@ -44,8 +43,8 @@ import com.oracle.truffle.r.runtime.conn.RConnection;
 @RBuiltin(name = "dput", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "file", "opts"}, behavior = IO)
 public abstract class DPut extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(DPut.class);
         casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
         casts.arg("opts").asIntegerVector().findFirst();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
index 8709521c22..f5ea8c6b09 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
@@ -40,7 +40,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -140,8 +139,8 @@ public class DatePOSIXFunctions {
 
         @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Date2POSIXlt.class);
             casts.arg("x").mapNull(emptyDoubleVector()).asDoubleVector();
         }
 
@@ -176,8 +175,8 @@ public class DatePOSIXFunctions {
 
         @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(AsPOSIXlt.class);
             casts.arg("x").mapNull(emptyDoubleVector()).asDoubleVector(true, false, false);
             casts.arg("tz").asStringVector().findFirst("");
         }
@@ -216,8 +215,8 @@ public class DatePOSIXFunctions {
     @RBuiltin(name = "as.POSIXct", kind = INTERNAL, parameterNames = {"x", "tz"}, behavior = READS_STATE)
     public abstract static class AsPOSIXct extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(AsPOSIXct.class);
             casts.arg("x").mustBe(RAbstractListVector.class);
             casts.arg("tz").asStringVector().findFirst("");
         }
@@ -275,8 +274,8 @@ public class DatePOSIXFunctions {
     public abstract static class POSIXlt2Date extends RBuiltinNode {
         private static final RStringVector CLASS_ATTR = (RStringVector) RDataFactory.createStringVectorFromScalar("Date").makeSharedPermanent();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(POSIXlt2Date.class);
             casts.arg("x").mustBe(RAbstractListVector.class);
         }
 
@@ -333,8 +332,8 @@ public class DatePOSIXFunctions {
             // TODO: find a proper source for this mapping
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(FormatPOSIXlt.class);
             casts.arg("x").mustBe(RAbstractListVector.class);
             casts.arg("format").asStringVector().mustBe(notEmpty());
             casts.arg("usetz").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
@@ -391,8 +390,8 @@ public class DatePOSIXFunctions {
     @RBuiltin(name = "strptime", kind = INTERNAL, parameterNames = {"x", "format", "tz"}, behavior = PURE)
     public abstract static class StrPTime extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(StrPTime.class);
             casts.arg("x").mapNull(emptyStringVector()).asStringVector();
             casts.arg("format").mapNull(emptyStringVector()).asStringVector();
             casts.arg("tz").mapNull(emptyStringVector()).asStringVector();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
index a4ed591f4a..61b783d1ba 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling;
 import com.oracle.truffle.r.runtime.RError;
@@ -43,9 +42,11 @@ public class DebugFunctions {
 
     protected abstract static class ErrorAndFunAdapter extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("fun").mustBe(RFunction.class, Message.ARG_MUST_BE_CLOSURE);
+        static final class ErrorAndFunCasts extends Casts {
+            ErrorAndFunCasts(Class<? extends ErrorAndFunAdapter> extCls) {
+                super(extCls);
+                casts.arg("fun").mustBe(RFunction.class, Message.ARG_MUST_BE_CLOSURE);
+            }
         }
 
         protected void doDebug(RFunction fun, Object text, Object condition, boolean once) throws RError {
@@ -58,9 +59,14 @@ public class DebugFunctions {
         }
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "debug", visibility = OFF, kind = INTERNAL, parameterNames = {"fun", "text", "condition"}, behavior = COMPLEX)
     public abstract static class Debug extends ErrorAndFunAdapter {
 
+        static {
+            new ErrorAndFunCasts(Debug.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected RNull doDebug(RFunction fun, Object text, Object condition) {
@@ -69,9 +75,14 @@ public class DebugFunctions {
         }
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "debugonce", visibility = OFF, kind = INTERNAL, parameterNames = {"fun", "text", "condition"}, behavior = COMPLEX)
     public abstract static class DebugOnce extends ErrorAndFunAdapter {
 
+        static {
+            new ErrorAndFunCasts(DebugOnce.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected RNull debugonce(RFunction fun, Object text, Object condition) {
@@ -81,9 +92,14 @@ public class DebugFunctions {
         }
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "undebug", visibility = OFF, kind = INTERNAL, parameterNames = {"fun"}, behavior = COMPLEX)
     public abstract static class UnDebug extends ErrorAndFunAdapter {
 
+        static {
+            new ErrorAndFunCasts(UnDebug.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected RNull undebug(RFunction func) {
@@ -94,9 +110,14 @@ public class DebugFunctions {
         }
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "isdebugged", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
     public abstract static class IsDebugged extends ErrorAndFunAdapter {
 
+        static {
+            new ErrorAndFunCasts(IsDebugged.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected byte isDebugged(RFunction func) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
index defed06f11..6db3144a98 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -49,8 +48,8 @@ public abstract class DelayedAssign extends RBuiltinNode {
 
     private final BranchProfile errorProfile = BranchProfile.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(DelayedAssign.class);
         casts.arg("x").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_FIRST_ARGUMENT).findFirst();
         casts.arg("eval.env").mustNotBeNull(RError.SHOW_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
         casts.arg("assign.env").mustNotBeNull(RError.SHOW_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
index 8fb0d1ffbe..e1abc2461e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
@@ -31,8 +30,8 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 @RBuiltin(name = "deparse", kind = INTERNAL, parameterNames = {"expr", "width.cutoff", "backtick", "control", "nlines"}, behavior = PURE)
 public abstract class Deparse extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Deparse.class);
         casts.arg("width.cutoff").asIntegerVector().findFirst(0);
         casts.arg("backtick").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean());
         casts.arg("control").asIntegerVector().findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
index b8130992c8..6ddd7cabaf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1998-2013, The R Core Team
  * Copyright (c) 2003-2015, The R Foundation
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -21,7 +21,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -37,8 +36,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 @RBuiltin(name = "diag", kind = INTERNAL, parameterNames = {"x", "nrow", "ncol"}, behavior = PURE)
 public abstract class Diag extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Diag.class);
         casts.arg("x").allowNull().mapIf(complexValue().not(), asDoubleVector());
 
         casts.arg("nrow").asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_LARGE_NA_VALUE, "nrow").mustBe(gte0(), Message.INVALID_NEGATIVE_VALUE, "nrow");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
index f9af807d25..9e495172e5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
@@ -39,6 +39,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 @RBuiltin(name = "dim", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class Dim extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(Dim.class);
+    }
+
     @Specialization
     protected Object dim(RAbstractContainer container,
                     @Cached("createBinaryProfile()") ConditionProfile hasDimensionsProfile,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
index 0de9caa23a..2993a023e5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
@@ -41,6 +41,10 @@ public abstract class DimNames extends RBuiltinNode {
 
     private final ConditionProfile nullProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(DimNames.class);
+    }
+
     @Specialization(guards = "!isRAbstractContainer(operand)")
     protected RNull getDimNames(@SuppressWarnings("unused") Object operand) {
         return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index e5eba227ee..9976ccbaa8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctions.Get;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen;
@@ -80,8 +79,8 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
 
     @Child private RExplicitCallNode call = RExplicitCallNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(DoCall.class);
         casts.arg("what").defaultError(Message.MUST_BE_STRING_OR_FUNCTION, "what").mustBe(instanceOf(RFunction.class).or(stringValue()));
         casts.arg("args").mustBe(RAbstractListVector.class, Message.SECOND_ARGUMENT_LIST);
         casts.arg("quote").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
index 5edaedbcbe..295782ffed 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
@@ -50,6 +50,10 @@ public abstract class Drop extends RBuiltinNode {
     private final ConditionProfile resultIsScalarProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile noDimNamesProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(Drop.class);
+    }
+
     @Specialization
     protected RAbstractVector doDrop(RAbstractVector x,
                     @Cached("create()") GetDimAttributeNode getDimsNode,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
index d137a43dd3..88cf01b06e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
@@ -46,7 +46,7 @@ public class DuplicatedFunctions {
 
         private final ConditionProfile incomparable = ConditionProfile.createBinaryProfile();
 
-        protected void casts(CastBuilder casts) {
+        protected static void casts(Casts casts) {
             // these are similar to those in DuplicatedFunctions.java
             casts.arg("x").mapNull(emptyList()).mustBe(abstractVectorValue(), RError.SHOW_CALLER,
                             RError.Message.APPLIES_TO_VECTORS,
@@ -85,8 +85,8 @@ public class DuplicatedFunctions {
     @RBuiltin(name = "duplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax"}, behavior = PURE)
     public abstract static class Duplicated extends Adapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Duplicated.class);
             casts(casts);
             // currently not supported and not tested, but NA is a correct value (the same for empty
             // vectors) whereas 0 is not (throws an error)
@@ -132,8 +132,8 @@ public class DuplicatedFunctions {
     @RBuiltin(name = "anyDuplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast"}, behavior = PURE)
     public abstract static class AnyDuplicated extends Adapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(AnyDuplicated.class);
             casts(casts);
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
index 5caba01447..688dd47a2c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -62,8 +61,8 @@ public class DynLoadFunctions {
     public abstract static class DynLoad extends RBuiltinNode {
         @Child private DLL.LoadPackageDLLNode loadPackageDLLNode = DLL.LoadPackageDLLNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(DynLoad.class);
             casts.arg("lib").mustBe(stringValue()).asStringVector().mustBe(size(1), RError.Message.CHAR_ARGUMENT).findFirst();
             casts.arg("local").asLogicalVector().findFirst().map(toBoolean());
             casts.arg("now").asLogicalVector().findFirst().map(toBoolean());
@@ -86,8 +85,8 @@ public class DynLoadFunctions {
     public abstract static class DynUnload extends RBuiltinNode {
         @Child DLL.UnloadNode dllUnloadNode = DLL.UnloadNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(DynUnload.class);
             casts.arg("lib").mustBe(stringValue()).asStringVector().mustBe(size(1), RError.Message.CHAR_ARGUMENT).findFirst();
         }
 
@@ -130,8 +129,8 @@ public class DynLoadFunctions {
     public abstract static class IsLoaded extends RBuiltinNode {
         @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(IsLoaded.class);
             casts.arg("symbol").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst();
             casts.arg("PACKAGE").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst();
             casts.arg("type").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst();
@@ -166,8 +165,8 @@ public class DynLoadFunctions {
     public abstract static class GetSymbolInfo extends RBuiltinNode {
         @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(GetSymbolInfo.class);
             casts.arg("symbol").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst();
             casts.arg("withRegistrationInfo").mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
index 929833c85d..2cdec5a98c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
@@ -24,7 +24,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -49,8 +48,8 @@ public abstract class EncodeString extends RBuiltinNode {
     private final NACheck na = NACheck.create();
     private final BranchProfile everSeenNA = BranchProfile.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(EncodeString.class);
         casts.arg("x").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT);
 
         casts.arg("width").asIntegerVector().findFirst().mustBe(intNA().or(gte0()));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
index 9e6d68c9d4..9b05c97603 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -40,8 +39,9 @@ public class EncodingFunctions {
 
     @RBuiltin(name = "Encoding", kind = INTERNAL, parameterNames = "x", behavior = PURE)
     public abstract static class Encoding extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(Encoding.class);
             casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.CHAR_VEC_ARGUMENT);
         }
 
@@ -54,8 +54,9 @@ public class EncodingFunctions {
 
     @RBuiltin(name = "setEncoding", kind = INTERNAL, parameterNames = {"x", "value"}, behavior = PURE)
     public abstract static class SetEncoding extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SetEncoding.class);
             casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.CHAR_VEC_ARGUMENT).mustBe(stringValue());
             // asStringVector is required for notEmpty() to receive a proper type in case of scalars
             casts.arg("value").defaultError(RError.SHOW_CALLER, RError.Message.GENERIC, "a character vector 'value' expected").mustBe(stringValue()).asStringVector().mustBe(notEmpty(),
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 4c70173380..f71df176ee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -50,7 +50,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RList2EnvNode;
 import com.oracle.truffle.r.nodes.builtin.base.EnvFunctionsFactory.CopyNodeGen;
@@ -95,8 +94,8 @@ public class EnvFunctions {
     @RBuiltin(name = "as.environment", kind = PRIMITIVE, parameterNames = {"fun"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX)
     public abstract static class AsEnvironment extends Adapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(AsEnvironment.class);
             casts.arg("fun").mapIf(numericValue(), asIntegerVector());
         }
 
@@ -231,6 +230,10 @@ public class EnvFunctions {
     @RBuiltin(name = "topenv", kind = INTERNAL, parameterNames = {"envir", "matchThisEnv"}, behavior = COMPLEX)
     public abstract static class TopEnv extends Adapter {
 
+        static {
+            Casts.noCasts(TopEnv.class);
+        }
+
         @Child private FrameFunctions.ParentFrame parentFrameNode;
 
         @Specialization
@@ -281,8 +284,8 @@ public class EnvFunctions {
     @RBuiltin(name = "parent.env", kind = INTERNAL, parameterNames = {"env"}, behavior = READS_FRAME)
     public abstract static class ParentEnv extends Adapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(ParentEnv.class);
             casts.arg("env").mustBe(instanceOf(REnvironment.class), RError.SHOW_CALLER, Message.ARGUMENT_NOT_ENVIRONMENT);
         }
 
@@ -299,8 +302,8 @@ public class EnvFunctions {
     @RBuiltin(name = "parent.env<-", kind = INTERNAL, parameterNames = {"env", "value"}, behavior = COMPLEX)
     public abstract static class SetParentEnv extends Adapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SetParentEnv.class);
             casts.arg("env").mustBe(instanceOf(REnvironment.class), Message.NON_LANG_ASSIGNMENT_TARGET);
             casts.arg("value").mustNotBeNull(Message.USE_NULL_ENV_DEFUNCT, "NULL").mustBe(instanceOf(REnvironment.class), Message.ARGUMENT_NAME_NOT_ENVIRONMENT, "parent");
         }
@@ -319,6 +322,10 @@ public class EnvFunctions {
     @RBuiltin(name = "is.environment", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsEnvironment extends RBuiltinNode {
 
+        static {
+            Casts.noCasts(IsEnvironment.class);
+        }
+
         @Specialization
         protected byte isEnvironment(Object env) {
             return env instanceof REnvironment ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE;
@@ -331,6 +338,10 @@ public class EnvFunctions {
         private final ConditionProfile attributable = ConditionProfile.createBinaryProfile();
         @Child private GetFixedAttributeNode getEnvAttrNode;
 
+        static {
+            Casts.noCasts(Environment.class);
+        }
+
         @Specialization
         protected Object environment(VirtualFrame frame, @SuppressWarnings("unused") RNull fun,
                         @Cached("new()") GetCallerFrameNode callerFrame,
@@ -390,8 +401,8 @@ public class EnvFunctions {
     @RBuiltin(name = "environment<-", kind = PRIMITIVE, parameterNames = {"env", "value"}, behavior = COMPLEX)
     public abstract static class UpdateEnvironment extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(UpdateEnvironment.class);
             casts.arg("value").allowNull().mustBe(REnvironment.class, Message.REPLACEMENT_NOT_ENVIRONMENT);
         }
 
@@ -464,6 +475,10 @@ public class EnvFunctions {
     @RBuiltin(name = "environmentName", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
     public abstract static class EnvironmentName extends RBuiltinNode {
 
+        static {
+            Casts.noCasts(EnvironmentName.class);
+        }
+
         @Specialization
         protected String environmentName(REnvironment env) {
             return env.getName();
@@ -479,8 +494,8 @@ public class EnvFunctions {
     @RBuiltin(name = "new.env", kind = INTERNAL, parameterNames = {"hash", "parent", "size"}, behavior = COMPLEX)
     public abstract static class NewEnv extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(NewEnv.class);
             casts.arg("hash").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
             casts.arg("parent").mustBe(REnvironment.class, Message.MUST_BE_ENVIRON);
             casts.arg("size").mustNotBeNull().asIntegerVector().findFirst(0);
@@ -506,8 +521,8 @@ public class EnvFunctions {
     @RBuiltin(name = "lockEnvironment", visibility = OFF, kind = INTERNAL, parameterNames = {"env", "bindings"}, behavior = COMPLEX)
     public abstract static class LockEnvironment extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(LockEnvironment.class);
             casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
             // TODO: the actual interpretation of this parameter remains dubious
             casts.arg("bindings").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
@@ -523,8 +538,8 @@ public class EnvFunctions {
     @RBuiltin(name = "environmentIsLocked", kind = INTERNAL, parameterNames = {"env"}, behavior = PURE)
     public abstract static class EnvironmentIsLocked extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(EnvironmentIsLocked.class);
             casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
         }
 
@@ -537,8 +552,8 @@ public class EnvFunctions {
     @RBuiltin(name = "lockBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = COMPLEX)
     public abstract static class LockBinding extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(LockBinding.class);
             casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
             casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
         }
@@ -553,8 +568,8 @@ public class EnvFunctions {
     @RBuiltin(name = "unlockBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = COMPLEX)
     public abstract static class UnlockBinding extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(UnlockBinding.class);
             casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
             casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
         }
@@ -569,8 +584,8 @@ public class EnvFunctions {
     @RBuiltin(name = "bindingIsLocked", kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = PURE)
     public abstract static class BindingIsLocked extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(BindingIsLocked.class);
             casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
             casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
         }
@@ -584,8 +599,8 @@ public class EnvFunctions {
     @RBuiltin(name = "makeActiveBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "fun", "env"}, behavior = COMPLEX)
     public abstract static class MakeActiveBinding extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(MakeActiveBinding.class);
             casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
             casts.arg("fun").mustBe(RFunction.class, RError.SHOW_CALLER, Message.NOT_A_FUNCTION);
             casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
@@ -602,8 +617,8 @@ public class EnvFunctions {
     @RBuiltin(name = "bindingIsActive", kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = PURE)
     public abstract static class BindingIsActive extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(BindingIsActive.class);
             casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
             casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
         }
@@ -621,8 +636,8 @@ public class EnvFunctions {
 
         @Child private CopyNode copy;
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(EnvToList.class);
             casts.arg("x").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
             casts.arg("all.names").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
             casts.arg("sorted").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
index aba09031a8..3367d84ad0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
@@ -37,7 +37,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.EvalNodeGen.EvalEnvCastNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.FrameFunctions.SysFrame;
@@ -134,13 +133,11 @@ public abstract class Eval extends RBuiltinNode {
     @Child private EvalEnvCast envCast = EvalEnvCastNodeGen.create();
     @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        // @formatter:off
-        casts.arg("envir").allowNull().mustBe(instanceOf(REnvironment.class).or(instanceOf(RList.class)).or(instanceOf(RPairList.class)).or(numericValue())).
-                mapIf(numericValue(), chain(asIntegerVector()).with(mustBe(singleElement())).with(findFirst().integerElement()).end());
+    static {
+        Casts casts = new Casts(Eval.class);
+        casts.arg("envir").allowNull().mustBe(instanceOf(REnvironment.class).or(instanceOf(RList.class)).or(instanceOf(RPairList.class)).or(numericValue())).mapIf(numericValue(),
+                        chain(asIntegerVector()).with(mustBe(singleElement())).with(findFirst().integerElement()).end());
         casts.arg("enclos").allowNull().mustBe(REnvironment.class);
-        // @formatter:on
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java
index e70b055c12..f08f18daa3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.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
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode;
 import com.oracle.truffle.r.nodes.attributes.TypeFromModeNodeGen;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -52,8 +51,8 @@ public abstract class Exists extends RBuiltinNode {
      */
     public abstract byte execute(String nameVec, REnvironment env, String mode, boolean inherits);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Exists.class);
         casts.arg("x").mustBe(stringValue(), Message.INVALID_FIRST_ARGUMENT).asStringVector().findFirst();
         casts.arg("envir").mustBe(REnvironment.class);
         casts.arg("mode").mustBe(stringValue()).asStringVector().findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
index a0c481ef01..f4b9d0c8e5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -44,6 +44,10 @@ public abstract class Expression extends RBuiltinNode {
      */
     private final ConditionProfile isEvaluatedProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(Expression.class);
+    }
+
     @Specialization
     @ExplodeLoop
     protected Object doExpression(RArgsValuesAndNames args) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index c6e17bcdab..5534dd4505 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -59,7 +59,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
@@ -93,8 +92,8 @@ public class FileFunctions {
         private static final int WRITE = 2;
         private static final int READ = 4;
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(FileAccess.class);
             casts.arg("names").mustBe(stringValue()).asStringVector();
             casts.arg("mode").asIntegerVector().findFirst().mustBe(gte(0).and(lte(7)));
         }
@@ -125,8 +124,9 @@ public class FileFunctions {
 
     @RBuiltin(name = "file.append", kind = INTERNAL, parameterNames = {"file1", "file2"}, behavior = IO)
     public abstract static class FileAppend extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(FileAppend.class);
             casts.arg("file1").mustBe(stringValue()).asStringVector();
             casts.arg("file2").mustBe(stringValue()).asStringVector();
         }
@@ -220,8 +220,9 @@ public class FileFunctions {
 
     @RBuiltin(name = "file.create", kind = INTERNAL, parameterNames = {"vec", "showWarnings"}, behavior = IO)
     public abstract static class FileCreate extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(FileCreate.class);
             casts.arg("vec").mustBe(stringValue()).asStringVector();
             casts.arg("showWarnings").asLogicalVector().findFirst().mapIf(logicalNA(), constant(RRuntime.LOGICAL_FALSE));
         }
@@ -266,8 +267,8 @@ public class FileFunctions {
 
         @Child private SetClassAttributeNode setClassAttrNode;
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(FileInfo.class);
             casts.arg("extra_cols").asLogicalVector().findFirst().map(toBoolean());
         }
 
@@ -423,8 +424,9 @@ public class FileFunctions {
     }
 
     private abstract static class FileLinkAdaptor extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(FileLinkAdaptor.class);
             casts.arg("from").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector();
             casts.arg("to").mustBe(stringValue(), RError.Message.INVALID_SECOND_FILENAME).asStringVector();
         }
@@ -487,8 +489,8 @@ public class FileFunctions {
     @RBuiltin(name = "file.remove", kind = INTERNAL, parameterNames = {"file"}, behavior = IO)
     public abstract static class FileRemove extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(FileRemove.class);
             casts.arg("file").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector();
         }
 
@@ -515,8 +517,9 @@ public class FileFunctions {
 
     @RBuiltin(name = "file.rename", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO)
     public abstract static class FileRename extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(FileRename.class);
             casts.arg("from").mustBe(stringValue()).asStringVector();
             casts.arg("to").mustBe(stringValue()).asStringVector();
         }
@@ -551,8 +554,8 @@ public class FileFunctions {
     @RBuiltin(name = "file.exists", kind = INTERNAL, parameterNames = {"file"}, behavior = IO)
     public abstract static class FileExists extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(FileExists.class);
             casts.arg("file").mustBe(stringValue()).asStringVector();
         }
 
@@ -580,8 +583,8 @@ public class FileFunctions {
         private static final String DOT = ".";
         private static final String DOTDOT = "..";
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(ListFiles.class);
             casts.arg("path").mustBe(stringValue()).asStringVector();
             casts.arg("pattern").allowNull().mustBe(stringValue());
             casts.arg("all.files").asLogicalVector().findFirst().notNA().map(toBoolean());
@@ -721,8 +724,9 @@ public class FileFunctions {
 
     @RBuiltin(name = "list.dirs", kind = INTERNAL, parameterNames = {"directory", "full.names", "recursive"}, behavior = IO)
     public abstract static class ListDirs extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(ListDirs.class);
             casts.arg("directory").mustBe(stringValue()).asStringVector();
             casts.arg("full.names").asLogicalVector().findFirst().notNA().map(toBoolean());
             casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean());
@@ -777,8 +781,8 @@ public class FileFunctions {
     @RBuiltin(name = "file.path", kind = INTERNAL, parameterNames = {"paths", "fsep"}, behavior = IO)
     public abstract static class FilePath extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(FilePath.class);
             casts.arg("paths").mustBe(instanceOf(RList.class), RError.Message.INVALID_FIRST_ARGUMENT);
             casts.arg("fsep").mustBe(stringValue()).asStringVector().findFirst().notNA();
         }
@@ -876,8 +880,8 @@ public class FileFunctions {
     @RBuiltin(name = "file.copy", kind = INTERNAL, parameterNames = {"from", "to", "overwrite", "recursive", "copy.mode", "copy.date"}, behavior = IO)
     public abstract static class FileCopy extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(FileCopy.class);
             casts.arg("from").mustBe(stringValue()).asStringVector();
             casts.arg("to").mustBe(stringValue()).asStringVector();
             casts.arg("overwrite").asLogicalVector().findFirst().notNA().map(toBoolean());
@@ -1011,8 +1015,8 @@ public class FileFunctions {
     @RBuiltin(name = "file.show", kind = INTERNAL, parameterNames = {"files", "header", "title", "delete.file", "pager"}, visibility = OFF, behavior = IO)
     public abstract static class FileShow extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(FileShow.class);
             casts.arg("files").asStringVector();
             casts.arg("header").asStringVector();
             casts.arg("title").asStringVector();
@@ -1068,8 +1072,9 @@ public class FileFunctions {
 
     @RBuiltin(name = "dirname", kind = INTERNAL, parameterNames = {"path"}, behavior = IO)
     public abstract static class DirName extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(DirName.class);
             casts.arg("path").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT);
         }
 
@@ -1087,8 +1092,8 @@ public class FileFunctions {
     @RBuiltin(name = "basename", kind = INTERNAL, parameterNames = {"path"}, behavior = IO)
     public abstract static class BaseName extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(BaseName.class);
             casts.arg("path").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT);
         }
 
@@ -1106,8 +1111,8 @@ public class FileFunctions {
     @RBuiltin(name = "unlink", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "recursive", "force"}, behavior = IO)
     public abstract static class Unlink extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Unlink.class);
             casts.arg("x").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT);
             casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean());
             casts.arg("force").asLogicalVector().findFirst().notNA().map(toBoolean());
@@ -1175,8 +1180,8 @@ public class FileFunctions {
     @RBuiltin(name = "dir.create", visibility = OFF, kind = INTERNAL, parameterNames = {"path", "showWarnings", "recursive", "mode"}, behavior = IO)
     public abstract static class DirCreate extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(DirCreate.class);
             casts.arg("path").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
             casts.arg("showWarnings").asLogicalVector().findFirst().map(toBoolean());
             casts.arg("recursive").asLogicalVector().findFirst().map(toBoolean());
@@ -1232,8 +1237,9 @@ public class FileFunctions {
 
     @RBuiltin(name = "dir.exists", kind = INTERNAL, parameterNames = "paths", behavior = IO)
     public abstract static class DirExists extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(DirExists.class);
             casts.arg("paths").mustBe(stringValue()).asStringVector();
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
index 39e733fef1..605e55f3fb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RType;
@@ -47,16 +46,10 @@ public abstract class Floor extends UnaryArithmeticBuiltinNode {
         super(RType.Double, RError.Message.NON_NUMERIC_MATH, null);
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        //@formatter:off
-        casts.arg("x").
-            defaultError(this, RError.Message.NON_NUMERIC_MATH).
-            mustNotBeNull().
-            mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).
-            mustBe(numericValue()).
-            asDoubleVector(true, true, true);
-        //@formatter:on
+    static {
+        Casts casts = new Casts(Floor.class);
+        casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustNotBeNull().mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(true,
+                        true, true);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java
index 6dc5964db0..3368086a65 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode;
@@ -48,8 +47,8 @@ public abstract class ForceAndCall extends RBuiltinNode {
 
     @Child private PromiseHelperNode promiseHelper;
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(ForceAndCall.class);
         casts.arg("n").asIntegerVector().findFirst();
         // TODO other types are possible for FUN that we don't yet handle
         casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
index 0ef6c1371b..ce083781b2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
@@ -43,6 +43,10 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 @RBuiltin(name = "formals", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
 public abstract class Formals extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(Formals.class);
+    }
+
     @SuppressWarnings("unused")
     @Specialization(limit = "3", guards = "fun == cachedFunction")
     protected Object formalsCached(RFunction fun,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
index 5c9e5594e3..7c312cd0e9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -86,8 +86,8 @@ public abstract class Format extends RBuiltinNode {
         return (RAbstractIntVector) castInteger.execute(operand);
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Format.class);
         casts.arg("x");
         casts.arg("trim").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean());
         casts.arg("digits").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(R_MIN_DIGITS_OPT).and(lte(R_MAX_DIGITS_OPT))));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
index c69f2dac6a..b872f1187f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -18,7 +18,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
@@ -40,8 +39,8 @@ public abstract class FormatC extends RBuiltinNode {
         return (RStringVector) ((RStringVector) castStringNode.executeString(o)).copyDropAttributes();
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(FormatC.class);
         casts.arg("x");
         casts.arg("mode").asStringVector().findFirst();
         casts.arg("width").asIntegerVector().findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
index e8bf7b2b54..109ff35ab3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
@@ -45,7 +45,6 @@ import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.FrameFunctionsFactory.SysFrameNodeGen;
 import com.oracle.truffle.r.nodes.function.ArgumentMatcher;
@@ -187,8 +186,8 @@ public class FrameFunctions {
     @RBuiltin(name = "sys.call", kind = INTERNAL, parameterNames = {"which"}, behavior = COMPLEX)
     public abstract static class SysCall extends FrameHelper {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SysCall.class);
             casts.arg("which").asIntegerVector().findFirst();
         }
 
@@ -238,8 +237,8 @@ public class FrameFunctions {
             return FrameAccess.READ_ONLY;
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(MatchCall.class);
             casts.arg("definition").mustBe(RFunction.class);
             casts.arg("call").mustBe(RLanguage.class);
             casts.arg("expand.dots").asLogicalVector().findFirst();
@@ -447,8 +446,8 @@ public class FrameFunctions {
             return FrameAccess.MATERIALIZE;
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SysFrame.class);
             casts.arg("which").asIntegerVector().findFirst();
         }
 
@@ -555,8 +554,8 @@ public class FrameFunctions {
         private final BranchProfile promiseProfile = BranchProfile.create();
         private final BranchProfile nonNullCallerProfile = BranchProfile.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SysParent.class);
             casts.arg("n").asIntegerVector().findFirst();
         }
 
@@ -589,8 +588,8 @@ public class FrameFunctions {
             return FrameAccess.READ_ONLY;
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SysFunction.class);
             casts.arg("which").asIntegerVector().findFirst();
         }
 
@@ -661,8 +660,8 @@ public class FrameFunctions {
 
         public abstract REnvironment execute(VirtualFrame frame, int n);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(ParentFrame.class);
             casts.arg("n").asIntegerVector().findFirst();
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
index 4f5573978e..ad8d21132c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -30,7 +30,6 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -40,8 +39,8 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 @RBuiltin(name = "gc", kind = INTERNAL, parameterNames = {"verbose", "reset"}, behavior = COMPLEX)
 public abstract class Gc extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Gc.class);
         casts.arg("verbose").asLogicalVector().findFirst().map(toBoolean());
         casts.arg("reset").asLogicalVector().findFirst().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java
index cc9cc4610d..2a2ddedc86 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -25,6 +25,10 @@ public abstract class GetClass extends RBuiltinNode {
 
     @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(true, false);
 
+    static {
+        Casts.noCasts(GetClass.class);
+    }
+
     @Specialization
     protected RAbstractStringVector getClass(Object x) {
         return classHierarchy.execute(x);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
index 0fcf141e87..cae0c2dcee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
@@ -46,7 +46,6 @@ import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode;
 import com.oracle.truffle.r.nodes.attributes.TypeFromModeNodeGen;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
@@ -168,8 +167,8 @@ public class GetFunctions {
 
         public abstract Object execute(VirtualFrame frame, String x, REnvironment environment, String mode, boolean inherits);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Get.class);
             casts.arg("x").mustBe(stringValue()).asStringVector().findFirst();
             casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(integerValue()).or(doubleValue()).or(instanceOf(RS4Object.class))).mapIf(integerValue().or(doubleValue()),
                             chain(asIntegerVector()).with(findFirst().integerElement()).end());
@@ -205,8 +204,8 @@ public class GetFunctions {
 
         private final ConditionProfile inheritsProfile = ConditionProfile.createBinaryProfile();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Get0.class);
             casts.arg("x").mustBe(stringValue()).asStringVector().findFirst();
             casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(integerValue()).or(doubleValue()).or(instanceOf(RS4Object.class))).mapIf(integerValue().or(doubleValue()),
                             chain(asIntegerVector()).with(findFirst().integerElement()).end());
@@ -252,8 +251,8 @@ public class GetFunctions {
 
         @CompilationFinal private boolean needsCallerFrame;
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(MGet.class);
             casts.arg("x").mustBe(stringValue()).asStringVector();
             casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(integerValue()).or(doubleValue()).or(instanceOf(RS4Object.class))).mapIf(integerValue().or(doubleValue()),
                             chain(asIntegerVector()).with(findFirst().integerElement()).end());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
index 26ce406f1c..374a9e866f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
@@ -40,6 +40,10 @@ public abstract class GetOldClass extends RBuiltinNode {
     private final ConditionProfile isObjectProfile = ConditionProfile.createBinaryProfile();
     @Child private GetClassAttributeNode getClassNode = GetClassAttributeNode.create();
 
+    static {
+        Casts.noCasts(GetOldClass.class);
+    }
+
     @Specialization
     protected Object getOldClass(RAbstractContainer arg) {
         if (isObjectProfile.profile(getClassNode.isObject(arg))) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
index 8e7d4ca5a1..32583e1a76 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -35,8 +34,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "gettext", kind = INTERNAL, parameterNames = {"domain", "args"}, behavior = PURE)
 public abstract class GetText extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(GetText.class);
         casts.arg("domain").asStringVector().findFirst("");
         casts.arg("args").asStringVector();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 762279f951..2153136a4d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -23,6 +23,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
@@ -66,45 +67,45 @@ public class GrepFunctions {
     public abstract static class CommonCodeAdapter extends RBuiltinNode {
         @Child protected PCRERFFI.PCRERFFINode pcreRFFINode = RFFIFactory.getRFFI().getPCRERFFI().createPCRERFFINode();
 
-        protected void castPattern(CastBuilder casts) {
+        protected static void castPattern(Casts casts) {
             // with default error message, NO_CALLER does not work
             casts.arg("pattern").mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT,
                             "pattern");
         }
 
-        protected void castText(CastBuilder casts, String textId) {
+        protected static void castText(Casts casts, String textId) {
             casts.arg(textId).mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, textId);
         }
 
-        protected void castIgnoreCase(CastBuilder casts) {
+        protected static void castIgnoreCase(Casts casts) {
             casts.arg("ignore.case").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         }
 
-        protected void castPerl(CastBuilder casts) {
+        protected static void castPerl(Casts casts) {
             casts.arg("perl").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         }
 
-        protected void castFixed(CastBuilder casts, byte defaultValue) {
+        protected static void castFixed(Casts casts, byte defaultValue) {
             casts.arg("fixed").asLogicalVector().findFirst(defaultValue);
         }
 
-        protected void castValue(CastBuilder casts) {
+        protected static void castValue(Casts casts) {
             casts.arg("value").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         }
 
-        protected void castUseBytes(CastBuilder casts) {
+        protected static void castUseBytes(Casts casts) {
             casts.arg("useBytes").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         }
 
-        protected void castInvert(CastBuilder casts) {
+        protected static void castInvert(Casts casts) {
             casts.arg("invert").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         }
 
-        protected void castCosts(CastBuilder casts) {
+        protected static void castCosts(Casts casts) {
             casts.arg("costs").asIntegerVector();
         }
 
-        protected void castBounds(CastBuilder casts) {
+        protected static void castBounds(Casts casts) {
             casts.arg("bounds").asDoubleVector();
         }
 
@@ -319,8 +320,8 @@ public class GrepFunctions {
     @RBuiltin(name = "grep", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE)
     public abstract static class Grep extends GrepAdapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Grep.class);
             castPattern(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
@@ -342,8 +343,8 @@ public class GrepFunctions {
     @RBuiltin(name = "grepl", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE)
     public abstract static class GrepL extends GrepAdapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(GrepL.class);
             castPattern(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
@@ -365,7 +366,7 @@ public class GrepFunctions {
 
     protected abstract static class SubAdapter extends CommonCodeAdapter {
 
-        protected void castReplacement(CastBuilder casts) {
+        protected static void castReplacement(Casts casts) {
             // with default error message, NO_CALLER does not work
             casts.arg("replacement").mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.NO_CALLER,
                             RError.Message.INVALID_ARGUMENT, "replacement");
@@ -641,8 +642,8 @@ public class GrepFunctions {
     @RBuiltin(name = "sub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE)
     public abstract static class Sub extends SubAdapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Sub.class);
             castPattern(casts);
             castReplacement(casts);
             castText(casts, "text");
@@ -663,8 +664,8 @@ public class GrepFunctions {
     @RBuiltin(name = "gsub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE)
     public abstract static class GSub extends SubAdapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(GSub.class);
             castPattern(casts);
             castReplacement(casts);
             castText(casts, "text");
@@ -692,8 +693,8 @@ public class GrepFunctions {
         @Child SetFixedAttributeNode setCaptureNamesAttrNode = SetFixedAttributeNode.create("capture.names");
         @Child SetFixedAttributeNode setDimNamesAttrNode = SetFixedAttributeNode.createDimNames();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Regexp.class);
             castPattern(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
@@ -880,8 +881,8 @@ public class GrepFunctions {
         @Child SetFixedAttributeNode setCaptureNamesAttrNode = SetFixedAttributeNode.create("capture.names");
         @Child SetFixedAttributeNode setDimNamesAttrNode = SetFixedAttributeNode.createDimNames();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Gregexpr.class);
             castPattern(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
@@ -1019,8 +1020,8 @@ public class GrepFunctions {
     @RBuiltin(name = "agrep", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "costs", "bounds", "useBytes", "fixed"}, behavior = PURE)
     public abstract static class AGrep extends CommonCodeAdapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(AGrep.class);
             castPattern(casts);
             castText(casts, "x");
             castIgnoreCase(casts);
@@ -1135,8 +1136,8 @@ public class GrepFunctions {
     @RBuiltin(name = "agrepl", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "costs", "bounds", "useBytes", "fixed"}, behavior = PURE)
     public abstract static class AGrepL extends CommonCodeAdapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(AGrepL.class);
             castPattern(casts);
             castText(casts, "x");
             castIgnoreCase(casts);
@@ -1166,8 +1167,8 @@ public class GrepFunctions {
     @RBuiltin(name = "strsplit", kind = INTERNAL, parameterNames = {"x", "split", "fixed", "perl", "useBytes"}, behavior = PURE)
     public abstract static class Strsplit extends CommonCodeAdapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Strsplit.class);
             casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER);
             casts.arg("split").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER);
             castFixed(casts, RRuntime.LOGICAL_FALSE);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
index c30b36ab7e..6d4a9370e3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
@@ -37,7 +37,6 @@ import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
@@ -90,8 +89,8 @@ public class HiddenInternalFunctions {
             }
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(MakeLazy.class);
             casts.arg("names").mustBe(stringValue()).asStringVector();
             casts.arg("eval.env").mustBe(instanceOf(REnvironment.class));
             casts.arg("assign.env").mustBe(instanceOf(REnvironment.class));
@@ -144,8 +143,9 @@ public class HiddenInternalFunctions {
      */
     @RBuiltin(name = "importIntoEnv", kind = INTERNAL, parameterNames = {"impenv", "impnames", "expenv", "expnames"}, behavior = COMPLEX)
     public abstract static class ImportIntoEnv extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(ImportIntoEnv.class);
             casts.arg("impenv").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class), RError.Message.BAD_ENVIRONMENT, "import");
             casts.arg("impnames").defaultError(RError.Message.INVALID_ARGUMENT, "names").mustBe(stringValue()).asStringVector();
             casts.arg("expenv").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class), RError.Message.BAD_ENVIRONMENT, "import");
@@ -188,8 +188,8 @@ public class HiddenInternalFunctions {
 
         @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(LazyLoadDBFetch.class);
             casts.arg("compressed").asIntegerVector().findFirst();
         }
 
@@ -278,6 +278,10 @@ public class HiddenInternalFunctions {
         private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{".C", ".Call", ".Fortran", ".External"}, RDataFactory.COMPLETE_VECTOR);
         private static final RStringVector NATIVE_ROUTINE_LIST = RDataFactory.createStringVectorFromScalar("NativeRoutineList");
 
+        static {
+            Casts.noCasts(GetRegisteredRoutines.class);
+        }
+
         @Specialization
         protected RList getRegisteredRoutines(@SuppressWarnings("unused") RNull info) {
             throw RError.error(this, RError.Message.NULL_DLLINFO);
@@ -323,6 +327,10 @@ public class HiddenInternalFunctions {
     public abstract static class GetVarsFromFrame extends RBuiltinNode {
         @Child private PromiseHelperNode promiseHelper;
 
+        static {
+            Casts.noCasts(GetVarsFromFrame.class);
+        }
+
         @Specialization
         protected RList getVarsFromFrame(VirtualFrame frame, RAbstractStringVector varsVec, REnvironment env, byte forceArg) {
             boolean force = RRuntime.fromLogical(forceArg);
@@ -357,8 +365,8 @@ public class HiddenInternalFunctions {
 
         @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(LazyLoadDBinsertValue.class);
             casts.arg("ascii").asIntegerVector().findFirst();
             casts.arg("compsxp").asIntegerVector().findFirst();
         }
@@ -458,6 +466,11 @@ public class HiddenInternalFunctions {
 
     @RBuiltin(name = "lazyLoadDBflush", kind = INTERNAL, parameterNames = "path", behavior = COMPLEX)
     public abstract static class LazyLoadDBFlush extends RBuiltinNode {
+
+        static {
+            Casts.noCasts(LazyLoadDBFlush.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected RNull doLazyLoadDBFlush(RAbstractStringVector dbPath) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
index a470aa85cc..62b894730e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -40,8 +39,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "iconv", kind = INTERNAL, parameterNames = {"x", "from", "to", "sub", "mark", "toRaw"}, behavior = PURE)
 public abstract class IConv extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(IConv.class);
         casts.arg("x").mustBe(stringValue(), RError.NO_CALLER, RError.Message.NOT_CHARACTER_VECTOR, "x");
         // with default error message, NO_CALLER does not work
         casts.arg("from").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "from").mustBe(stringValue()).asStringVector().mustBe(size(1));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
index f1a329fcac..3f5769de60 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.IterableAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -77,8 +76,8 @@ public abstract class Identical extends RBuiltinNode {
     @Child private IterableAttributeNode attrIterNodeX = IterableAttributeNode.create();
     @Child private IterableAttributeNode attrIterNodeY = IterableAttributeNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Identical.class);
         casts.arg("num.eq").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         casts.arg("single.NA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         casts.arg("attrib.as.set").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java
index d4c874044f..b45abeda28 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -20,7 +20,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.InheritsNode;
 import com.oracle.truffle.r.nodes.unary.InheritsNodeGen;
@@ -34,8 +33,8 @@ public abstract class InheritsBuiltin extends RBuiltinNode {
 
     public abstract Object execute(Object x, Object what, Object which);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(InheritsBuiltin.class);
         casts.arg("what").mustBe(stringValue(), NOT_CHARACTER_VECTOR, "what");
         casts.arg("which").mustBe(logicalValue(), NOT_LEN_ONE_LOGICAL_VECTOR, "which").asLogicalVector().findFirst().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
index 08ed846aea..0b85315703 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -37,8 +36,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 @RBuiltin(name = "intToBits", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
 public abstract class IntToBits extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(IntToBits.class);
         casts.arg("x").asIntegerVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
index 030149ca78..51a84c924e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 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.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -44,8 +43,8 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 @RBuiltin(name = "intToUtf8", kind = INTERNAL, parameterNames = {"x", "multiple"}, behavior = PURE)
 public abstract class IntToUtf8 extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(IntToUtf8.class);
         casts.arg("x").asIntegerVector();
         casts.arg("multiple").mustNotBeNull().asLogicalVector().findFirst().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java
index c30e266676..55ec16e7d4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.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
@@ -34,6 +34,10 @@ import com.oracle.truffle.r.runtime.data.RNull;
 @RBuiltin(name = "invisible", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX)
 public abstract class Invisible extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(Invisible.class);
+    }
+
     @Override
     public Object[] getDefaultParameterValues() {
         return new Object[]{RNull.instance};
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
index c84b1304c6..f1ce895c28 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
@@ -132,6 +132,10 @@ public class IsFiniteFunctions {
     @RBuiltin(name = "is.finite", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsFinite extends Adapter {
 
+        static {
+            Casts.noCasts(IsFinite.class);
+        }
+
         @Specialization
         protected RLogicalVector doIsFinite(RAbstractDoubleVector vec) {
             return doFunDouble(vec, RRuntime::isFinite);
@@ -166,6 +170,10 @@ public class IsFiniteFunctions {
     @RBuiltin(name = "is.infinite", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsInfinite extends Adapter {
 
+        static {
+            Casts.noCasts(IsInfinite.class);
+        }
+
         @Specialization
         protected RLogicalVector doIsInfinite(RAbstractDoubleVector vec) {
             return doFunDouble(vec, Double::isInfinite);
@@ -190,6 +198,10 @@ public class IsFiniteFunctions {
     @RBuiltin(name = "is.nan", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsNaN extends Adapter {
 
+        static {
+            Casts.noCasts(IsNaN.class);
+        }
+
         private static boolean isNaN(double value) {
             return Double.isNaN(value) && !RRuntime.isNA(value);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java
index f7e53501ec..48cc21c956 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java
@@ -19,7 +19,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.IsListFactorNodeGen.IsListFactorInternalNodeGen;
 import com.oracle.truffle.r.nodes.unary.IsFactorNode;
@@ -70,8 +69,8 @@ public abstract class IsListFactor extends RBuiltinNode {
         }
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(IsListFactor.class);
         casts.arg("recursive").asLogicalVector().findFirst().map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
index 4a85c00052..39826ee9a7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.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
@@ -64,6 +64,10 @@ public abstract class IsNA extends RBuiltinNode {
 
     private final ConditionProfile nullDimNamesProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(IsNA.class);
+    }
+
     private Object isNARecursive(Object o) {
         if (recursiveIsNA == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java
index f4b26fcf8a..d4939ab3a5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.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
@@ -36,6 +36,10 @@ import com.oracle.truffle.r.runtime.data.RTypedValue;
 @RBuiltin(name = "isS4", kind = PRIMITIVE, parameterNames = {"object"}, behavior = PURE)
 public abstract class IsS4 extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(IsS4.class);
+    }
+
     public abstract byte execute(Object value);
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
index 43baa46886..b9d87fff25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -34,8 +33,8 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 @RBuiltin(name = "is.single", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
 public abstract class IsSingle extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(IsSingle.class);
         casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENTS_PASSED, 0, "'is.single'", 1);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
index c8337dda05..7613e80ff4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
@@ -47,6 +47,7 @@ import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
 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.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -76,15 +77,21 @@ public class IsTypeFunctions {
 
     protected abstract static class MissingAdapter extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("x").mustNotBeMissing((RBaseNode) null, RError.Message.ARGUMENT_MISSING, "x");
+        static final class MissingAdapterCasts extends Casts {
+            MissingAdapterCasts(Class<? extends MissingAdapter> extCls) {
+                super(extCls);
+                casts.arg("x").mustNotBeMissing((RBaseNode) null, RError.Message.ARGUMENT_MISSING, "x");
+            }
         }
     }
 
     @RBuiltin(name = "is.array", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsArray extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsArray.class);
+        }
+
         private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile();
         @Child private GetDimAttributeNode getDim = GetDimAttributeNodeGen.create();
 
@@ -104,6 +111,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.recursive", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsRecursive extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsRecursive.class);
+        }
+
         @Specialization
         protected byte isRecursive(RNull arg) {
             return RRuntime.LOGICAL_FALSE;
@@ -134,6 +145,10 @@ public class IsTypeFunctions {
 
         @Child private InheritsCheckNode inheritsFactorCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR);
 
+        static {
+            new MissingAdapterCasts(IsAtomic.class);
+        }
+
         @Specialization
         protected byte isAtomic(RNull arg) {
             return RRuntime.LOGICAL_TRUE;
@@ -162,6 +177,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.call", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsCall extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsCall.class);
+        }
+
         @Specialization
         protected byte isType(RLanguage lang) {
             return RRuntime.LOGICAL_TRUE;
@@ -176,6 +195,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.character", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsCharacter extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsCharacter.class);
+        }
+
         @Specialization
         protected byte isType(RAbstractStringVector value) {
             return RRuntime.LOGICAL_TRUE;
@@ -194,6 +217,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.complex", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsComplex extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsComplex.class);
+        }
+
         @Specialization
         protected byte isType(RAbstractComplexVector value) {
             return RRuntime.LOGICAL_TRUE;
@@ -212,6 +239,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.double", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsDouble extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsDouble.class);
+        }
+
         @Specialization
         protected byte isType(RAbstractDoubleVector value) {
             return RRuntime.LOGICAL_TRUE;
@@ -230,6 +261,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.expression", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsExpression extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsExpression.class);
+        }
+
         @Specialization
         protected byte isType(RExpression expr) {
             return RRuntime.LOGICAL_TRUE;
@@ -244,6 +279,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.function", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsFunction extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsFunction.class);
+        }
+
         @Specialization
         protected byte isType(RFunction value) {
             return RRuntime.LOGICAL_TRUE;
@@ -258,6 +297,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.integer", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsInteger extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsInteger.class);
+        }
+
         @Specialization
         protected byte isType(RAbstractIntVector value) {
             return RRuntime.LOGICAL_TRUE;
@@ -275,6 +318,11 @@ public class IsTypeFunctions {
 
     @RBuiltin(name = "is.language", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsLanguage extends MissingAdapter {
+
+        static {
+            new MissingAdapterCasts(IsLanguage.class);
+        }
+
         @Specialization
         protected byte isType(RSymbol value) {
             return RRuntime.LOGICAL_TRUE;
@@ -301,6 +349,10 @@ public class IsTypeFunctions {
 
         private final ConditionProfile isListProfile = ConditionProfile.createBinaryProfile();
 
+        static {
+            new MissingAdapterCasts(IsList.class);
+        }
+
         public abstract byte execute(Object value);
 
         @Specialization
@@ -322,6 +374,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.logical", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsLogical extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsLogical.class);
+        }
+
         @Specialization
         protected byte isType(RAbstractLogicalVector value) {
             return RRuntime.LOGICAL_TRUE;
@@ -343,6 +399,10 @@ public class IsTypeFunctions {
         private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile();
         @Child private GetDimAttributeNode getDim = GetDimAttributeNodeGen.create();
 
+        static {
+            new MissingAdapterCasts(IsMatrix.class);
+        }
+
         @Specialization
         protected byte isType(RAbstractVector vector) {
             return RRuntime.asLogical(isMatrixProfile.profile(getDim.isMatrix(vector)));
@@ -357,6 +417,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.name", aliases = {"is.symbol"}, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsName extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsName.class);
+        }
+
         @Specialization
         protected byte isType(RSymbol value) {
             return RRuntime.LOGICAL_TRUE;
@@ -371,6 +435,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.numeric", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsNumeric extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsNumeric.class);
+        }
+
         @Specialization(guards = "!isFactor(value)")
         protected byte isType(RAbstractIntVector value) {
             return RRuntime.LOGICAL_TRUE;
@@ -405,6 +473,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.null", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsNull extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsNull.class);
+        }
+
         @Specialization
         protected byte isType(RNull value) {
             return RRuntime.LOGICAL_TRUE;
@@ -428,6 +500,10 @@ public class IsTypeFunctions {
 
         @Child private GetClassAttributeNode getClassNode = GetClassAttributeNode.create();
 
+        static {
+            Casts.noCasts(IsObject.class);
+        }
+
         public abstract byte execute(Object value);
 
         @Specialization
@@ -443,6 +519,11 @@ public class IsTypeFunctions {
 
     @RBuiltin(name = "is.pairlist", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsPairList extends MissingAdapter {
+
+        static {
+            new MissingAdapterCasts(IsPairList.class);
+        }
+
         @Specialization
         protected byte isType(RNull value) {
             return RRuntime.LOGICAL_TRUE;
@@ -462,6 +543,10 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.raw", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsRaw extends MissingAdapter {
 
+        static {
+            new MissingAdapterCasts(IsRaw.class);
+        }
+
         @Specialization
         protected byte isType(RAbstractRawVector value) {
             return RRuntime.LOGICAL_TRUE;
@@ -486,10 +571,10 @@ public class IsTypeFunctions {
         private final BranchProfile namesAttrProfile = BranchProfile.create();
         @Child private GetFixedAttributeNode namesGetter = GetFixedAttributeNode.createNames();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("x").mustNotBeMissing((RBaseNode) null, RError.Message.ARGUMENT_MISSING, "x");
-            casts.arg("mode").defaultError(this, RError.Message.INVALID_ARGUMENT, "mode").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
+        static {
+            Casts casts = new Casts(IsVector.class);
+            casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENT_MISSING, "x");
+            casts.arg("mode").defaultError(RError.Message.INVALID_ARGUMENT, "mode").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
         }
 
         @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
index c26d7aa286..cb571f301f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.binary.BinaryMapBooleanFunctionNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.Order.CmpNode;
 import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.CmpNodeGen;
@@ -55,8 +54,8 @@ public abstract class IsUnsorted extends RBuiltinNode {
 
     private final ConditionProfile strictlyProfile = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(IsUnsorted.class);
         casts.arg("strictly").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).notNA().map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 41691b554b..96c4acfe18 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
@@ -87,10 +86,12 @@ public class LaFunctions {
         protected static final String[] NAMES = new String[]{"values", "vectors"};
         protected final BranchProfile errorProfile = BranchProfile.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_NUMERIC, "x");
-            casts.arg("onlyValues").defaultError(RError.Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().notNA().map(toBoolean());
+        static final class RsgCasts extends Casts {
+            RsgCasts(Class<? extends RsgAdapter> extClass) {
+                super(extClass);
+                casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_NUMERIC, "x");
+                casts.arg("onlyValues").defaultError(RError.Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().notNA().map(toBoolean());
+            }
         }
     }
 
@@ -99,6 +100,10 @@ public class LaFunctions {
 
         private final ConditionProfile hasComplexValues = ConditionProfile.createBinaryProfile();
 
+        static {
+            new RsgCasts(Rg.class);
+        }
+
         @Specialization
         protected Object doRg(RDoubleVector matrix, boolean onlyValues,
                         @Cached("create()") GetDimAttributeNode getDimsNode) {
@@ -193,6 +198,11 @@ public class LaFunctions {
 
     @RBuiltin(name = "La_rs", kind = INTERNAL, parameterNames = {"matrix", "onlyValues"}, behavior = PURE)
     public abstract static class Rs extends RsgAdapter {
+
+        static {
+            new RsgCasts(Rs.class);
+        }
+
         @Specialization
         protected Object doRs(RDoubleVector matrix, boolean onlyValues,
                         @Cached("create()") GetDimAttributeNode getDimsNode) {
@@ -255,8 +265,8 @@ public class LaFunctions {
 
         private final BranchProfile errorProfile = BranchProfile.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Qr.class);
             casts.arg("in").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a");
         }
 
@@ -311,8 +321,8 @@ public class LaFunctions {
         private static final char SIDE = 'L';
         private static final char TRANS = 'T';
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(QrCoefReal.class);
             casts.arg("q").mustBe(instanceOf(RList.class));
             casts.arg("b").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "b");
         }
@@ -379,19 +389,11 @@ public class LaFunctions {
 
         @Child private SetFixedAttributeNode setLogAttrNode = SetFixedAttributeNode.create("logarithm");
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            //@formatter:off
-            casts.arg("a").asDoubleVector(false, true, false).
-                mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").
-                mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a");
-
-            casts.arg("uselog").defaultError(RError.Message.MUST_BE_LOGICAL, "logarithm").
-                asLogicalVector().
-                findFirst().
-                notNA().
-                map(toBoolean());
-            //@formatter:on
+        static {
+            Casts casts = new Casts(DetGeReal.class);
+            casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a");
+
+            casts.arg("uselog").defaultError(RError.Message.MUST_BE_LOGICAL, "logarithm").asLogicalVector().findFirst().notNA().map(toBoolean());
         }
 
         @Specialization
@@ -465,22 +467,14 @@ public class LaFunctions {
         @Child private SetFixedAttributeNode setPivotAttrNode = SetFixedAttributeNode.create("pivot");
         @Child private SetFixedAttributeNode setRankAttrNode = SetFixedAttributeNode.create("rank");
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            //@formatter:off
-            casts.arg("a").asDoubleVector(false, true, false).
-                mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").
-                mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a").
-                mustBe(dimGt(1, 0), RError.Message.DIMS_GT_ZERO, "a");
-
-            casts.arg("pivot").asLogicalVector().
-                findFirst().
-                notNA().
-                map(toBoolean());
-
-            casts.arg("tol").asDoubleVector().
-                findFirst(RRuntime.DOUBLE_NA);
-            //@formatter:on
+        static {
+            Casts casts = new Casts(LaChol.class);
+            casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a").mustBe(
+                            dimGt(1, 0), RError.Message.DIMS_GT_ZERO, "a");
+
+            casts.arg("pivot").asLogicalVector().findFirst().notNA().map(toBoolean());
+
+            casts.arg("tol").asDoubleVector().findFirst(RRuntime.DOUBLE_NA);
         }
 
         @Specialization
@@ -541,19 +535,14 @@ public class LaFunctions {
             return vec -> vec.getDimensions()[dim];
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            //@formatter:off
-            casts.arg("a").mustBe(numericValue()).asVector().
-                mustBe(matrix(), RError.ROOTNODE, RError.Message.MUST_BE_NUMERIC_MATRIX, "a").
-                mustBe(not(dimEq(0, 0)), RError.ROOTNODE, RError.Message.GENERIC, "'a' is 0-diml").
-                mustBe(squareMatrix(), RError.ROOTNODE, RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
+        static {
+            Casts casts = new Casts(LaSolve.class);
+            casts.arg("a").mustBe(numericValue()).asVector().mustBe(matrix(), RError.ROOTNODE, RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)), RError.ROOTNODE,
+                            RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.ROOTNODE, RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
 
-            casts.arg("bin").asDoubleVector(false, true, false).
-                mustBe(or(not(matrix()), not(dimEq(1, 0))), RError.ROOTNODE, RError.Message.GENERIC, "no right-hand side in 'b'");
+            casts.arg("bin").asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), RError.ROOTNODE, RError.Message.GENERIC, "no right-hand side in 'b'");
 
             casts.arg("tolin").asDoubleVector().findFirst(RRuntime.DOUBLE_NA);
-            //@formatter:on
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
index 89f801a703..a3bb7941e9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNodeGen;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.LapplyNodeGen.LapplyInternalNodeGen;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
@@ -70,8 +69,8 @@ public abstract class Lapply extends RBuiltinNode {
 
     @Child private LapplyInternalNode lapply = LapplyInternalNodeGen.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Lapply.class);
         // to make conversion of X parameter 100% correct, we'd need to match semantics of
         // asVector() to whatever GNU R is doing there; still this can be a problem only if the
         // internal is called directly (otherwise, it's guaranteed that it's a vector)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java
index ae8bc87066..df92d3e9fa 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.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
@@ -38,6 +38,10 @@ public abstract class Length extends RBuiltinNode {
 
     public abstract int executeInt(VirtualFrame frame, Object vector);
 
+    static {
+        Casts.noCasts(Length.class);
+    }
+
     @Specialization
     protected int getLength(VirtualFrame frame, Object vector,
                     @Cached("create()") RLengthNode lengthNode) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
index e8b4549af0..3b1cff197b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -52,8 +51,8 @@ public abstract class Lengths extends RBuiltinNode {
 
     @Child private RLengthNode lengthNode;
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Lengths.class);
         casts.arg("x").defaultError(RError.SHOW_CALLER, X_LIST_ATOMIC).allowNull().mustBe(abstractVectorValue());
         casts.arg("use.names").mustBe(numericValue(), RError.SHOW_CALLER, INVALID_VALUE, "use.names").asLogicalVector().findFirst().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java
index e87f6b3685..f1ab5acbb7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RList2EnvNode;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -37,8 +36,9 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "list2env", kind = INTERNAL, parameterNames = {"x", "envir"}, behavior = PURE)
 public abstract class List2Env extends RBuiltinNode {
-    @Override
-    protected void createCasts(CastBuilder casts) {
+
+    static {
+        Casts casts = new Casts(List2Env.class);
         casts.arg("x").mustBe(RAbstractListVector.class, Message.FIRST_ARGUMENT_NOT_NAMED_LIST);
         casts.arg("envir").mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir");
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java
index 2d945ceecf..4ef832ba33 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -53,6 +54,10 @@ public abstract class ListBuiltin extends RBuiltinNode {
 
     @CompilationFinal private RStringVector suppliedSignatureArgNames;
 
+    static {
+        Casts.noCasts(ListBuiltin.class);
+    }
+
     /**
      * Creates a shared permanent vector so that it can be re-used for every list(...) with the same
      * arguments.
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
index 3f9917adf7..462f900017 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.SerializeFunctions.Adapter;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
@@ -60,8 +59,8 @@ public class LoadSaveFunctions {
 
         private final NACheck naCheck = NACheck.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(LoadFromConn2.class);
             casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
             casts.arg("envir").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
             casts.arg("verbose").asLogicalVector().findFirst().map(toBoolean());
@@ -117,8 +116,8 @@ public class LoadSaveFunctions {
     public abstract static class Load extends RBuiltinNode {
         // now deprecated but still used by some packages
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Load.class);
             casts.arg("file").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.FIRST_ARGUMENT_NOT_FILENAME).findFirst();
             casts.arg("envir").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
         }
@@ -194,10 +193,10 @@ public class LoadSaveFunctions {
         private static final String ASCII_HEADER = "RDA2\n";
         private static final String XDR_HEADER = "RDX2\n";
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SaveToConn.class);
             casts.arg("list").mustBe(stringValue()).asStringVector();
-            ConnectionFunctions.Casts.connection(casts);
+            ConnectionFunctions.CastsHelper.connection(casts);
             casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL);
             casts.arg("version").allowNull().mustBe(integerValue());
             casts.arg("environment").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
index 8e56256388..29231259c8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
@@ -38,7 +38,7 @@ import java.nio.charset.Charset;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -55,9 +55,9 @@ public class LocaleFunctions {
     @RBuiltin(name = "Sys.getlocale", kind = INTERNAL, parameterNames = {"category"}, behavior = READS_STATE)
     public abstract static class GetLocale extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.category(casts);
+        static {
+            Casts casts = new Casts(GetLocale.class);
+            CastsHelper.category(casts);
         }
 
         @Specialization
@@ -93,9 +93,9 @@ public class LocaleFunctions {
     @RBuiltin(name = "Sys.setlocale", kind = INTERNAL, parameterNames = {"category", "locale"}, behavior = MODIFIES_STATE)
     public abstract static class SetLocale extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.category(casts);
+        static {
+            Casts casts = new Casts(SetLocale.class);
+            CastsHelper.category(casts);
             casts.arg("locale").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
         }
 
@@ -134,9 +134,10 @@ public class LocaleFunctions {
 
     @RBuiltin(name = "enc2native", kind = PRIMITIVE, parameterNames = "x", behavior = READS_STATE)
     public abstract static class Enc2Native extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.xCharacterVector(casts);
+
+        static {
+            Casts casts = new Casts(Enc2Native.class);
+            CastsHelper.xCharacterVector(casts);
         }
 
         @Specialization
@@ -148,9 +149,10 @@ public class LocaleFunctions {
 
     @RBuiltin(name = "enc2utf8", kind = PRIMITIVE, parameterNames = "x", behavior = READS_STATE)
     public abstract static class Enc2Utf8 extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.xCharacterVector(casts);
+
+        static {
+            Casts casts = new Casts(Enc2Utf8.class);
+            CastsHelper.xCharacterVector(casts);
         }
 
         @Specialization
@@ -162,8 +164,9 @@ public class LocaleFunctions {
 
     @RBuiltin(name = "bindtextdomain", kind = PRIMITIVE, parameterNames = {"domain", "dirname"}, behavior = READS_STATE)
     public abstract static class BindTextDomain extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(BindTextDomain.class);
             casts.arg("domain").mustBe(stringValue(), INVALID_VALUE, "domain");
         }
 
@@ -175,12 +178,12 @@ public class LocaleFunctions {
         }
     }
 
-    private static final class Casts {
-        private static void xCharacterVector(CastBuilder casts) {
+    private static final class CastsHelper {
+        private static void xCharacterVector(Casts casts) {
             casts.arg("x").mustBe(stringValue(), ARGUMENT_NOT_CHAR_VECTOR);
         }
 
-        private static void category(CastBuilder casts) {
+        private static void category(Casts casts) {
             casts.arg("category").mustBe(numericValue(), NO_CALLER, INVALID_ARGUMENT, "category").asIntegerVector().findFirst();
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index 457eca9da9..e157019c8e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.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
@@ -34,7 +34,6 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -62,8 +61,8 @@ public class LogFunctions {
             return new Object[]{RMissing.instance, Math.E};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Log.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
             casts.arg("base").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue()).asDoubleVector().findFirst();
         }
@@ -141,8 +140,8 @@ public class LogFunctions {
 
         private static final double LOG_10 = Math.log(10);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Log10.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
         }
 
@@ -168,8 +167,8 @@ public class LogFunctions {
 
         private static final double LOG_2 = Math.log(2);
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Log2.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
         }
 
@@ -193,8 +192,8 @@ public class LogFunctions {
             super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Log1p.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
index aa4568846a..0e05ca0385 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -39,8 +38,8 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 @RBuiltin(name = "ls", aliases = {"objects"}, kind = INTERNAL, parameterNames = {"envir", "all.names", "sorted"}, behavior = PURE)
 public abstract class Ls extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Ls.class);
         casts.arg("envir").mustBe(REnvironment.class, NO_CALLER, INVALID_ARGUMENT, "envir");
         casts.arg("all.names").asLogicalVector().findFirst().map(toBoolean());
         casts.arg("sorted").asLogicalVector().findFirst().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
index 60c4ed1f56..d1ac331fb5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -46,8 +45,8 @@ public abstract class MakeNames extends RBuiltinNode {
     private final ConditionProfile namesLengthZero = ConditionProfile.createBinaryProfile();
     private final NACheck dummyCheck = NACheck.create(); // never triggered (used for vector update)
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(MakeNames.class);
         casts.arg("names").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER_NAMES);
         casts.arg("allow_").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "allow_").asLogicalVector().findFirst().mustBe(notLogicalNA());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
index 452d330fa5..9a0d72178e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -45,8 +44,8 @@ public abstract class MakeUnique extends RBuiltinNode {
     private final ConditionProfile duplicatesProfile = ConditionProfile.createBinaryProfile();
     private final NACheck dummyCheck = NACheck.create(); // never triggered (used for vector update)
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(MakeUnique.class);
         casts.arg("names").defaultError(RError.SHOW_CALLER, RError.Message.NOT_CHARACTER_VECTOR, "names").mustBe(stringValue());
         casts.arg("sep").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING, "sep").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
index 2b0974310b..0eaf07b3d5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.MapplyNodeGen.MapplyInternalNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.Subscript;
@@ -67,8 +66,8 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 @RBuiltin(name = "mapply", kind = INTERNAL, parameterNames = {"FUN", "dots", "MoreArgs"}, splitCaller = true, behavior = COMPLEX)
 public abstract class Mapply extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Mapply.class);
         // let's assume that mapply internal is never called directly, otherwise all hell ensues -
         // even in GNU R .Internal(mapply(rep, 1:4, NULL)) causes a segfault
         casts.arg("FUN").mustBe(instanceOf(RFunction.class));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index 7bee0fa552..88b10299f8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.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
@@ -84,6 +84,10 @@ public abstract class MatMult extends RBuiltinNode {
 
     private final NACheck na;
 
+    static {
+        Casts.noCasts(MatMult.class);
+    }
+
     public MatMult(boolean promoteDimNames) {
         this.promoteDimNames = promoteDimNames;
         this.na = NACheck.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index b950ea128f..291aad6c29 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
 import com.oracle.truffle.r.nodes.helpers.RFactorNodes;
@@ -73,8 +72,8 @@ public abstract class Match extends RBuiltinNode {
     private final NACheck naCheck = NACheck.create();
     private final ConditionProfile bigTableProfile = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Match.class);
         // TODO initially commented out because of use of scalars, the commented out version
         // converted to new cast pipelines API
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
index 52cd9569f1..170e794180 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
@@ -65,6 +65,10 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 @RBuiltin(name = "match.arg", kind = SUBSTITUTE, parameterNames = {"arg", "choices", "several.ok"}, nonEvalArgs = {0}, behavior = COMPLEX)
 public abstract class MatchArg extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(MatchArg.class);
+    }
+
     @Override
     public Object[] getDefaultParameterValues() {
         return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_FALSE};
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
index 5c0e919964..69cb73a3f1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
@@ -37,7 +37,6 @@ import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.MatchFunNodeGen.MatchFunInternalNodeGen;
 import com.oracle.truffle.r.nodes.function.GetCallerFrameNode;
@@ -65,8 +64,8 @@ public abstract class MatchFun extends RBuiltinNode {
         return new Object[]{RMissing.instance, RRuntime.LOGICAL_TRUE};
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(MatchFun.class);
         casts.arg("descend").asLogicalVector().findFirst().map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
index 45ca370e1f..90f7823259 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
@@ -33,7 +33,6 @@ 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.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -66,8 +65,8 @@ public abstract class Matrix extends RBuiltinNode {
         return (RAbstractVector) updateDimNames.executeRAbstractContainer(vector, o);
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Matrix.class);
         casts.arg("data").asVector().mustBe(instanceOf(RAbstractVector.class));
         casts.arg("nrow").asIntegerVector().findFirst(RError.Message.NON_NUMERIC_MATRIX_EXTENT);
         casts.arg("ncol").asIntegerVector().findFirst(RError.Message.NON_NUMERIC_MATRIX_EXTENT);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
index 8c8030262b..2e898cf529 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode.ReduceSemantics;
@@ -48,8 +47,8 @@ public abstract class Max extends RBuiltinNode {
 
     @Child private UnaryArithmeticReduceNode reduce = UnaryArithmeticReduceNodeGen.create(semantics, BinaryArithmetic.MAX);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Max.class);
         casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java
index c0c491b677..dc04a0b928 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.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
@@ -46,6 +46,10 @@ public abstract class Mean extends RBuiltinNode {
     @Child private BinaryArithmetic add = BinaryArithmetic.ADD.createOperation();
     @Child private BinaryArithmetic div = BinaryArithmetic.DIV.createOperation();
 
+    static {
+        Casts.noCasts(Mean.class);
+    }
+
     @Specialization
     protected double mean(RAbstractDoubleVector x) {
         if (x.getLength() == 0) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
index cef620df87..955e3d4b9f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
@@ -38,19 +38,19 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 @RBuiltin(name = "merge", kind = INTERNAL, parameterNames = {"xinds", "yinds", "all.x", "all.y"}, behavior = PURE)
 public abstract class Merge extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Merge.class);
         addIntegerCast(casts, "xinds");
         addIntegerCast(casts, "yinds");
         addLogicalCast(casts, "all.x");
         addLogicalCast(casts, "all.y");
     }
 
-    private static void addIntegerCast(CastBuilder casts, String name) {
+    private static void addIntegerCast(Casts casts, String name) {
         casts.arg(name).mustBe(integerValue()).asIntegerVector().mustBe(notEmpty());
     }
 
-    private static void addLogicalCast(CastBuilder casts, String name) {
+    private static void addLogicalCast(Casts casts, String name) {
         casts.arg(name).defaultError(INVALID_LOGICAL, "all.x").mustBe(numericValue()).asLogicalVector().findFirst().notNA().map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
index 926920a97f..09b73c273d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode.ReduceSemantics;
@@ -48,8 +47,8 @@ public abstract class Min extends RBuiltinNode {
 
     @Child private UnaryArithmeticReduceNode reduce = UnaryArithmeticReduceNodeGen.create(semantics, BinaryArithmetic.MIN);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Min.class);
         casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
index c2faec1d69..b55927dda5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.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
@@ -37,7 +37,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAt
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -52,8 +51,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "nchar", kind = INTERNAL, parameterNames = {"x", "type", "allowNA", "keepNA"}, behavior = PURE)
 public abstract class NChar extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(NChar.class);
         casts.arg("x").allowNull().mapIf(integerValue(), asIntegerVector(), asStringVector(true, false, false));
         casts.arg("type").asStringVector().findFirst();
         casts.arg("allowNA").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java
index 3756b5ba7c..147a393876 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -38,8 +38,8 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 @RBuiltin(name = "ngettext", kind = INTERNAL, parameterNames = {"n", "msg1", "msg2", "domain"}, behavior = COMPLEX)
 public abstract class NGetText extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(NGetText.class);
         casts.arg("n").asIntegerVector().findFirst().mustBe(gte0());
 
         casts.arg("msg1").defaultError(RError.Message.MUST_BE_STRING, "msg1").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
index cd2f85f3ec..bfd884b2fb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -39,8 +38,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "nzchar", kind = PRIMITIVE, parameterNames = {"x", "keepNA"}, behavior = PURE)
 public abstract class NZChar extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(NZChar.class);
         casts.arg("x").asStringVector();
         casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
index 55c50f7636..fa425d7e20 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
@@ -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
@@ -32,6 +32,8 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
+import com.oracle.truffle.r.nodes.unary.UnaryNotNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -44,6 +46,10 @@ public abstract class Names extends RBuiltinNode {
     private final ConditionProfile hasNames = ConditionProfile.createBinaryProfile();
     @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
 
+    static {
+        Casts.noCasts(Names.class);
+    }
+
     @Specialization
     protected Object getNames(RAbstractContainer container) {
         RStringVector names = getNames.getNames(container);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
index 2f170e5f66..919e2805fb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
@@ -29,6 +29,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
@@ -43,17 +44,18 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 
 public class NamespaceFunctions {
 
-    private static final class Casts {
-        private static void name(CastBuilder casts) {
+    private static final class CastsHelper {
+        private static void name(Casts casts) {
             casts.arg("name").mustBe(stringValue().or(instanceOf(RSymbol.class)));
         }
     }
 
     @RBuiltin(name = "getRegisteredNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = READS_STATE)
     public abstract static class GetRegisteredNamespace extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.name(casts);
+
+        static {
+            Casts casts = new Casts(GetRegisteredNamespace.class);
+            CastsHelper.name(casts);
         }
 
         @Specialization
@@ -79,9 +81,10 @@ public class NamespaceFunctions {
 
     @RBuiltin(name = "isRegisteredNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = READS_STATE)
     public abstract static class IsRegisteredNamespace extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.name(casts);
+
+        static {
+            Casts casts = new Casts(IsRegisteredNamespace.class);
+            CastsHelper.name(casts);
         }
 
         @Specialization
@@ -107,6 +110,11 @@ public class NamespaceFunctions {
 
     @RBuiltin(name = "isNamespaceEnv", kind = INTERNAL, parameterNames = {"env"}, behavior = PURE)
     public abstract static class IsNamespaceEnv extends RBuiltinNode {
+
+        static {
+            Casts.noCasts(IsNamespaceEnv.class);
+        }
+
         @Specialization
         protected byte doIsNamespaceEnv(REnvironment env) {
             return RRuntime.asLogical(env.isNamespaceEnv());
@@ -128,9 +136,10 @@ public class NamespaceFunctions {
 
     @RBuiltin(name = "registerNamespace", kind = INTERNAL, parameterNames = {"name", "env"}, behavior = MODIFIES_STATE)
     public abstract static class RegisterNamespace extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.name(casts);
+
+        static {
+            Casts casts = new Casts(RegisterNamespace.class);
+            CastsHelper.name(casts);
             casts.arg("env").mustBe(instanceOf(REnvironment.class));
         }
 
@@ -154,9 +163,10 @@ public class NamespaceFunctions {
 
     @RBuiltin(name = "unregisterNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = MODIFIES_STATE)
     public abstract static class UnregisterNamespace extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.name(casts);
+
+        static {
+            Casts casts = new Casts(UnregisterNamespace.class);
+            CastsHelper.name(casts);
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
index 528fb50198..835eb027f5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
@@ -38,7 +38,6 @@ import java.nio.file.NoSuchFileException;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -54,8 +53,8 @@ public abstract class NormalizePath extends RBuiltinNode {
 
     private final ConditionProfile doesNotNeedToWork = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(NormalizePath.class);
         casts.arg("path").mustBe(stringValue(), NOT_CHARACTER_VECTOR, "path");
         casts.arg("winslash").defaultError(NOT_CHARACTER_VECTOR, "winslash").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(eq("/").or(eq("\\\\")).or(eq("\\")),
                         WRONG_WINSLASH);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
index 887b5f16dd..26a9bc602f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -62,8 +61,8 @@ public class NumericalFunctions {
             super(RType.Integer, RError.Message.NON_NUMERIC_MATH, null);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Abs.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(numericValue().or(complexValue()));
         }
 
@@ -105,8 +104,8 @@ public class NumericalFunctions {
             super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Re.class);
             casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
         }
 
@@ -148,8 +147,8 @@ public class NumericalFunctions {
             super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Im.class);
             casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
         }
 
@@ -191,8 +190,8 @@ public class NumericalFunctions {
             super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Conj.class);
             casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
         }
 
@@ -224,8 +223,8 @@ public class NumericalFunctions {
             super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Mod.class);
             casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
         }
 
@@ -267,8 +266,8 @@ public class NumericalFunctions {
             super(RType.Double, RError.Message.NON_NUMERIC_MATH, null);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Sign.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue());
         }
 
@@ -295,8 +294,8 @@ public class NumericalFunctions {
             super(RType.Double, RError.Message.NON_NUMERIC_MATH, null);
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Sqrt.class);
             casts.arg("x").defaultError(RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue().or(complexValue()));
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
index 3eb6440923..7d3f43e6bb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -36,7 +36,6 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.FrameSlotNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RError;
@@ -66,8 +65,8 @@ public abstract class OnExit extends RBuiltinNode {
 
     private final BranchProfile invalidateProfile = BranchProfile.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(OnExit.class);
         casts.arg("add").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
index 3edeeca12f..cc56be1bf2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
@@ -37,7 +37,6 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -65,6 +64,10 @@ public class OptionsFunctions {
 
         private final ConditionProfile argNameNull = ConditionProfile.createBinaryProfile();
 
+        static {
+            Casts.noCasts(Options.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected RList options(@SuppressWarnings("unused") RMissing x) {
@@ -191,8 +194,8 @@ public class OptionsFunctions {
     @RBuiltin(name = "getOption", kind = INTERNAL, parameterNames = "x", behavior = READS_STATE)
     public abstract static class GetOption extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(GetOption.class);
             casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING, "x").mustBe(stringValue()).asStringVector().findFirst();
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
index 1dde2ca238..13d246bb06 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RPrecedenceBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.CmpNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.IsAtomicNANodeGen;
@@ -149,8 +148,8 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         return (RAbstractVector) castVector2.execute(value);
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Order.class);
         casts.arg("na.last").mustBe(numericValue(), INVALID_LOGICAL, "na.last").asLogicalVector().findFirst();
         casts.arg("decreasing").mustBe(numericValue(), INVALID_LOGICAL, "decreasing").asLogicalVector().findFirst().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
index ad4cbd55f2..55db842837 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -45,8 +44,8 @@ public abstract class PMatch extends RBuiltinNode {
 
     public abstract RIntVector execute(RAbstractStringVector x, RAbstractStringVector table, int nomatch, boolean duplicatesOk);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(PMatch.class);
         casts.arg("x").asStringVector();
         casts.arg("table").asStringVector();
         casts.arg("nomatch").mapNull(constant(RRuntime.INT_NA)).asIntegerVector();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index 3dc425ca9c..89f53b790c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.PMinMaxNodeGen.MultiElemStringHandlerNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
@@ -90,9 +89,11 @@ public abstract class PMinMax extends RBuiltinNode {
         this.op = factory.createOperation();
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        casts.arg("na.rm").defaultError(SHOW_CALLER, Message.INVALID_VALUE, "na.rm").mustBe(numericValue()).asLogicalVector().findFirst().mustBe(logicalNA().not()).map(toBoolean());
+    static final class PMinMaxCasts extends Casts {
+        PMinMaxCasts(Class<? extends PMinMax> extCls) {
+            super(extCls);
+            casts.arg("na.rm").defaultError(SHOW_CALLER, Message.INVALID_VALUE, "na.rm").mustBe(numericValue()).asLogicalVector().findFirst().mustBe(logicalNA().not()).map(toBoolean());
+        }
     }
 
     private byte handleString(Object[] argValues, boolean naRm, int offset, int ind, int maxLength, byte warning, Object data) {
@@ -346,6 +347,11 @@ public abstract class PMinMax extends RBuiltinNode {
             super(new ReduceSemantics(RRuntime.INT_MIN_VALUE, Double.NEGATIVE_INFINITY, false, RError.Message.NO_NONMISSING_MAX, RError.Message.NO_NONMISSING_MAX_NA, false, true),
                             BinaryArithmetic.MAX);
         }
+
+        static {
+            new PMinMaxCasts(PMax.class);
+        }
+
     }
 
     @RBuiltin(name = "pmin", kind = INTERNAL, parameterNames = {"na.rm", "..."}, behavior = PURE)
@@ -355,6 +361,11 @@ public abstract class PMinMax extends RBuiltinNode {
             super(new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN, RError.Message.NO_NONMISSING_MIN_NA, false, true),
                             BinaryArithmetic.MIN);
         }
+
+        static {
+            new PMinMaxCasts(PMin.class);
+        }
+
     }
 
     protected boolean isIntegerPrecedence(RArgsValuesAndNames args) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index dbf7704245..7d68d79d72 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
@@ -101,8 +100,8 @@ public abstract class Parse extends RBuiltinNode {
     @Child private SetFixedAttributeNode setWholeSrcRefAttrNode = SetFixedAttributeNode.create("wholeSrcref");
     @Child private SetFixedAttributeNode setSrcFileAttrNode = SetFixedAttributeNode.create("srcfile");
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Parse.class);
         // Note: string is captured by the R wrapper and transformed to a file, other types not
         casts.arg("conn").defaultError(MUST_BE_STRING_OR_CONNECTION, "file").mustNotBeNull().asIntegerVector().findFirst();
         casts.arg("n").asIntegerVector().findFirst(RRuntime.INT_NA).notNA(-1);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
index 4c01c4204c..edd0e1c736 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
@@ -73,8 +73,8 @@ public abstract class Paste extends RBuiltinNode {
     private final ConditionProfile isNotStringProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile hasNoClassProfile = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Paste.class);
         casts.arg(0).mustBe(RAbstractListVector.class);
         casts.arg("sep").asStringVector().findFirst(Message.INVALID_SEPARATOR);
         casts.arg("collapse").allowNull().mustBe(stringValue()).asStringVector().findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java
index ce0645cb65..4b85eb3b4f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java
@@ -42,8 +42,8 @@ public abstract class Paste0 extends RBuiltinNode {
 
     @Child private Paste pasteNode = PasteNodeGen.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Paste0.class);
         casts.arg("list").mustBe(RList.class);
         casts.arg("collapse").allowNull().mustBe(stringValue()).asStringVector().findFirst();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java
index 640b323010..fe07eed30f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -38,8 +37,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "path.expand", kind = INTERNAL, parameterNames = "path", behavior = IO)
 public abstract class PathExpand extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(PathExpand.class);
         casts.arg("path").mustBe(stringValue());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
index b1881322b5..aa7eaefcc7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
@@ -21,7 +21,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -36,8 +35,8 @@ public abstract class Pretty extends RBuiltinNode {
 
     private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"l", "u", "n"}, RDataFactory.COMPLETE_VECTOR);
 
-    @Override
-    public void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Pretty.class);
         casts.arg("l").asDoubleVector().findFirst().mustBe(isFinite());
         casts.arg("u").asDoubleVector().findFirst().mustBe(isFinite());
         casts.arg("n").asIntegerVector().findFirst().notNA().mustBe(gte0());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
index e2edcc133d..0a6d792c11 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -45,8 +44,8 @@ public abstract class Primitive extends RBuiltinNode {
 
     private final BranchProfile errorProfile = BranchProfile.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Primitive.class);
         casts.arg("name").defaultError(Message.STRING_ARGUMENT_REQUIRED).mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
index 4e4786a07b..e2d8b344dd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
@@ -37,7 +37,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.printer.PrintParameters;
 import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNode;
@@ -60,8 +59,8 @@ public class PrintFunctions {
 
         @Child private ValuePrinterNode valuePrinter = new ValuePrinterNode();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(PrintDefault.class);
             casts.arg("digits").allowNull().asIntegerVector().findFirst().mustBe(notIntNA()).mustBe(gte(Format.R_MIN_DIGITS_OPT).and(lte(Format.R_MAX_DIGITS_OPT)));
 
             casts.arg("quote").asLogicalVector().findFirst().notNA().map(toBoolean());
@@ -111,8 +110,8 @@ public class PrintFunctions {
 
         @Child private ValuePrinterNode valuePrinter = new ValuePrinterNode();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(PrintFunction.class);
             casts.arg("x").mustBe(instanceOf(RFunction.class));
 
             casts.arg("useSource").defaultError(RError.Message.INVALID_ARGUMENT, "useSource").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
index 8c3caafcc5..132a964889 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -32,6 +32,10 @@ public abstract class Prod extends RBuiltinNode {
 
     // TODO: handle multiple arguments, handle na.rm
 
+    static {
+        Casts.noCasts(Prod.class);
+    }
+
     @Override
     public Object[] getDefaultParameterValues() {
         return new Object[]{RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE};
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
index ea915b2219..319c2ec107 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -78,9 +77,11 @@ public abstract class Quantifier extends RBuiltinNode {
         return new Object[]{RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE};
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+    static final class QuantifierCasts extends Casts {
+        QuantifierCasts(Class<? extends Quantifier> extCls) {
+            super(extCls);
+            casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        }
     }
 
     private void createArgCast(int index) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
index 30d73cb3be..4a3d93122c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
@@ -19,7 +19,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RCleanUp;
 import com.oracle.truffle.r.runtime.RError;
@@ -34,8 +33,8 @@ import com.oracle.truffle.r.runtime.data.RNull;
 @RBuiltin(name = "quit", visibility = OFF, kind = INTERNAL, parameterNames = {"save", "status", "runLast"}, behavior = COMPLEX)
 public abstract class Quit extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Quit.class);
         casts.arg("save").mustBe(stringValue(), RError.Message.QUIT_ASK).asStringVector().findFirst();
         casts.arg("status").asIntegerVector().findFirst();
         casts.arg("runLast").asLogicalVector().findFirst();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
index fbce580f57..98620c384f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
@@ -40,6 +40,10 @@ public abstract class Quote extends RBuiltinNode {
 
     protected static final int LIMIT = 3;
 
+    static {
+        Casts.noCasts(Quote.class);
+    }
+
     private final ConditionProfile shareableProfile = ConditionProfile.createBinaryProfile();
 
     public abstract Object execute(RPromise expr);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
index 56eb613f49..315f03279d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.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
@@ -38,7 +38,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -52,10 +52,10 @@ public class RNGFunctions {
     @RBuiltin(name = "set.seed", visibility = OFF, kind = INTERNAL, parameterNames = {"seed", "kind", "normal.kind"}, behavior = MODIFIES_STATE)
     public abstract static class SetSeed extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SetSeed.class);
             casts.arg("seed").allowNull().mustBe(numericValue(), SHOW_CALLER, SEED_NOT_VALID_INT).asIntegerVector().findFirst();
-            Casts.kindInteger(casts, "kind", INVALID_ARGUMENT, "kind");
+            CastsHelper.kindInteger(casts, "kind", INVALID_ARGUMENT, "kind");
             // TODO: implement normal.kind specializations with String
             casts.arg("normal.kind").allowNull().mustBe(anyValue().not(), UNIMPLEMENTED_TYPE_IN_FUNCTION, "String", "set.seed").mustBe(stringValue(), SHOW_CALLER, INVALID_NORMAL_TYPE_IN_RGNKIND);
         }
@@ -83,10 +83,10 @@ public class RNGFunctions {
     @RBuiltin(name = "RNGkind", kind = INTERNAL, parameterNames = {"kind", "normkind"}, behavior = MODIFIES_STATE)
     public abstract static class RNGkind extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.kindInteger(casts, "kind", INVALID_ARGUMENT, "kind");
-            Casts.kindInteger(casts, "normkind", INVALID_NORMAL_TYPE_IN_RGNKIND);
+        static {
+            Casts casts = new Casts(RNGkind.class);
+            CastsHelper.kindInteger(casts, "kind", INVALID_ARGUMENT, "kind");
+            CastsHelper.kindInteger(casts, "normkind", INVALID_NORMAL_TYPE_IN_RGNKIND);
         }
 
         @Specialization
@@ -102,8 +102,8 @@ public class RNGFunctions {
         }
     }
 
-    private static final class Casts {
-        public static void kindInteger(CastBuilder casts, String name, Message error, Object... messageArgs) {
+    private static final class CastsHelper {
+        public static void kindInteger(Casts casts, String name, Message error, Object... messageArgs) {
             casts.arg(name).mapNull(constant(RRNG.NO_KIND_CHANGE)).mustBe(numericValue(), SHOW_CALLER, error, messageArgs).asIntegerVector().findFirst();
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
index 41ed3f09e7..72ab6ad5c7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode.ReduceSemantics;
@@ -53,8 +52,8 @@ public abstract class Range extends RBuiltinNode {
     @Child private UnaryArithmeticReduceNode minReduce = UnaryArithmeticReduceNodeGen.create(minSemantics, BinaryArithmetic.MIN);
     @Child private UnaryArithmeticReduceNode maxReduce = UnaryArithmeticReduceNodeGen.create(maxSemantics, BinaryArithmetic.MAX);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Range.class);
         casts.arg("na.rm").asLogicalVector().findFirst().map(toBoolean());
         casts.arg("finite").asLogicalVector().findFirst().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
index 73efc9004d..16f4d02288 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
@@ -34,7 +34,6 @@ import java.util.function.Function;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.CmpNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.OrderVector1NodeGen;
@@ -62,20 +61,17 @@ public abstract class Rank extends RBuiltinNode {
         MIN
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        // @formatter:off
+    static {
+        Casts casts = new Casts(Rank.class);
         Function<Object, Object> typeFunc = x -> x.getClass().getSimpleName();
         casts.arg("x").mustBe(abstractVectorValue(), SHOW_CALLER, UNIMPLEMENTED_TYPE_IN_GREATER, typeFunc).mustBe(not(rawValue()), SHOW_CALLER, RError.Message.RAW_SORT);
-        // Note: in the case of no long vector support, when given anything but integer as n, GnuR behaves as if n=1,
+        // Note: in the case of no long vector support, when given anything but integer as n, GnuR
+        // behaves as if n=1,
         // we allow ourselves to be bit inconsistent with GnuR in that.
-        casts.arg("len").defaultError(NO_CALLER, INVALID_VALUE, "length(xx)").mustBe(numericValue()).
-                asIntegerVector().
-                mustBe(notEmpty()).
-                findFirst().mustBe(intNA().not().and(gte0()));
-        // Note: we parse ties.methods in the Specialization anyway, so the validation of the value is there
+        casts.arg("len").defaultError(NO_CALLER, INVALID_VALUE, "length(xx)").mustBe(numericValue()).asIntegerVector().mustBe(notEmpty()).findFirst().mustBe(intNA().not().and(gte0()));
+        // Note: we parse ties.methods in the Specialization anyway, so the validation of the value
+        // is there
         casts.arg("ties.method").defaultError(NO_CALLER, INVALID_TIES_FOR_RANK).mustBe(stringValue()).asStringVector().findFirst();
-        // @formatter:on
     }
 
     private Order.OrderVector1Node initOrderVector1() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
index 3a5414d396..4278530d54 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 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.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -53,8 +52,8 @@ public class RawFunctions {
     @RBuiltin(name = "charToRaw", kind = INTERNAL, parameterNames = "x", behavior = PURE)
     public abstract static class CharToRaw extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(CharToRaw.class);
             casts.arg("x").defaultError(RError.Message.ARG_MUST_BE_CHARACTER_VECTOR_LENGTH_ONE).mustBe(stringValue()).asStringVector().mustBe(notEmpty());
         }
 
@@ -74,8 +73,9 @@ public class RawFunctions {
 
     @RBuiltin(name = "rawToChar", kind = INTERNAL, parameterNames = {"x", "multiple"}, behavior = PURE)
     public abstract static class RawToChar extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(RawToChar.class);
             casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
             casts.arg("multiple").defaultError(RError.Message.INVALID_LOGICAL).asLogicalVector().findFirst().notNA().map(toBoolean());
         }
@@ -107,8 +107,9 @@ public class RawFunctions {
 
     @RBuiltin(name = "rawShift", kind = INTERNAL, parameterNames = {"x", "n"}, behavior = PURE)
     public abstract static class RawShift extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(RawShift.class);
             casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
             casts.arg("n").defaultError(RError.Message.MUST_BE_SMALL_INT, "shift").asIntegerVector().findFirst().notNA().mustBe(gte(-8).and(lte(8)));
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
index ec205c198a..538a0d8c68 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -37,8 +36,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 @RBuiltin(name = "rawToBits", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
 public abstract class RawToBits extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(RawToBits.class);
         casts.arg("x").mustNotBeNull(RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x").mustBe(Predef.rawValue(), RError.SHOW_CALLER,
                         RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
index f572307428..f0a6a89595 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
@@ -35,7 +35,6 @@ import java.util.Set;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.DCF;
 import com.oracle.truffle.r.runtime.RError;
@@ -52,8 +51,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "readDCF", kind = INTERNAL, parameterNames = {"conn", "fields", "keepwhite"}, behavior = IO)
 public abstract class ReadDCF extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(ReadDCF.class);
         casts.arg("conn").defaultError(Message.INVALID_CONNECTION).asIntegerVector().findFirst();
         casts.arg("fields").mapNull(emptyStringVector()).asStringVector();
         casts.arg("keepwhite").mapNull(emptyStringVector()).asStringVector();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
index 4ee6dbbd25..999f8ef7f3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
@@ -32,7 +32,6 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -42,8 +41,8 @@ import com.oracle.truffle.r.runtime.context.RContext;
 @RBuiltin(name = "readRenviron", visibility = OFF, kind = INTERNAL, parameterNames = "x", behavior = COMPLEX)
 public abstract class ReadREnviron extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(ReadREnviron.class);
         casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_STRING, "x").asStringVector().findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
index 41f4eb9edb..bc5411859c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
@@ -37,8 +36,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "readline", kind = INTERNAL, parameterNames = "prompt", behavior = IO)
 public abstract class Readline extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Readline.class);
         casts.arg("prompt").asStringVector().findFirst("");
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
index 45abdb5dbb..4c53575646 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
@@ -55,6 +55,10 @@ public abstract class Recall extends RBuiltinNode {
 
     @Child private RExplicitCallNode call = RExplicitCallNode.create();
 
+    static {
+        Casts.noCasts(Recall.class);
+    }
+
     @Specialization
     protected Object recall(VirtualFrame frame, @SuppressWarnings("unused") RArgsValuesAndNames args) {
         Frame cframe = callerFrame.execute(frame);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
index 079bd5fdcb..4703cc2b23 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -39,8 +38,9 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "reg.finalizer", kind = INTERNAL, parameterNames = {"e", "f", "onexit"}, behavior = COMPLEX)
 public abstract class RegFinalizer extends RBuiltinNode {
-    @Override
-    protected void createCasts(CastBuilder casts) {
+
+    static {
+        Casts casts = new Casts(RegFinalizer.class);
         casts.arg("e").mustBe(instanceOf(REnvironment.class).or(instanceOf(RExternalPtr.class)), RError.Message.REG_FINALIZER_FIRST);
         casts.arg("f").mustBe(instanceOf(RFunction.class), RError.Message.REG_FINALIZER_SECOND);
         casts.arg("onexit").asLogicalVector().findFirst().notNA(RError.Message.REG_FINALIZER_THIRD).map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
index e89c2645f4..5d1bd20567 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.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
@@ -26,12 +26,12 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import java.util.Arrays;
-import java.util.function.Function;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -40,7 +40,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -48,7 +47,6 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
 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.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -90,14 +88,9 @@ public abstract class Repeat extends RBuiltinNode {
         return new Object[]{RMissing.instance, 1, RRuntime.INT_NA, 1};
     }
 
-    private String argType(Object arg) {
-        return ((RTypedValue) arg).getRType().getName();
-    }
-
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        Function<Object, Object> argType = this::argType;
-        casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, argType);
+    static {
+        Casts casts = new Casts(Repeat.class);
+        casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, typeName());
         casts.arg("times").defaultError(RError.Message.INVALID_ARGUMENT, "times").mustNotBeNull().asIntegerVector();
         casts.arg("length.out").mustNotBeNull().asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out").findFirst(RRuntime.INT_NA,
                         RError.Message.FIRST_ELEMENT_USED, "length.out").mustBe(intNA().or(gte(0)));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
index 5b8a41d269..f376567ece 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
@@ -24,16 +24,15 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
-import java.util.function.Function;
 import java.util.function.IntFunction;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -44,7 +43,6 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
@@ -58,14 +56,9 @@ public abstract class RepeatInternal extends RBuiltinNode {
     private final ConditionProfile timesOneProfile = ConditionProfile.createBinaryProfile();
     private final BranchProfile errorProfile = BranchProfile.create();
 
-    private String argType(Object arg) {
-        return ((RTypedValue) arg).getRType().getName();
-    }
-
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        Function<Object, Object> argType = this::argType;
-        casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER2, RError.Message.ATTEMPT_TO_REPLICATE, argType);
+    static {
+        Casts casts = new Casts(RepeatInternal.class);
+        casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER2, RError.Message.ATTEMPT_TO_REPLICATE, typeName());
         casts.arg("times").defaultError(RError.SHOW_CALLER, RError.Message.INCORRECT_ARG_TYPE, "second").mustBe(abstractVectorValue()).asIntegerVector().mustBe(notEmpty(),
                         RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "times");
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
index 90886c168a..163552a82d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -20,7 +20,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -42,8 +41,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 @RBuiltin(name = "rep_len", kind = INTERNAL, parameterNames = {"x", "length.out"}, behavior = PURE)
 public abstract class RepeatLength extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(RepeatLength.class);
         casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER, RError.Message.ATTEMPT_TO_REPLICATE_NO_VECTOR);
         // with default error message, SHOW_CALLER does not work
         casts.arg("length.out").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "length.out").mustNotBeNull().asIntegerVector().mustBe(size(1)).findFirst().mustBe(notIntNA());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java
index 7001a7a168..4acc844bfc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java
@@ -72,6 +72,17 @@ public abstract class Return extends RBuiltinNode {
         return arguments.length == 1 ? new ReturnSpecial(arguments[0]) : null;
     }
 
+    private final BranchProfile isPromiseEvalProfile = BranchProfile.create();
+
+    static {
+        Casts.noCasts(Return.class);
+    }
+
+    @Override
+    public Object[] getDefaultParameterValues() {
+        return new Object[]{RNull.instance};
+    }
+
     static ReturnException doReturn(VirtualFrame frame, Object value, BranchProfile isPromiseEvalProfile) {
         RCaller call = RArguments.getCall(frame);
         while (call.isPromise()) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
index 74eb30e05f..544075d500 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.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
@@ -39,7 +39,6 @@ import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RError;
@@ -59,8 +58,8 @@ public abstract class Rm extends RBuiltinNode {
 
     private final BranchProfile invalidateProfile = BranchProfile.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Rm.class);
         casts.arg("list").mustBe(stringValue(), SHOW_CALLER, INVALID_FIRST_ARGUMENT);
         casts.arg("envir").mustNotBeNull(SHOW_CALLER, USE_NULL_ENV_DEFUNCT).mustBe(REnvironment.class, SHOW_CALLER, INVALID_ARGUMENT, "envir");
         casts.arg("inherits").mustBe(numericValue(), SHOW_CALLER, INVALID_ARGUMENT, "inherits").asLogicalVector().findFirst().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
index 56ee8c1890..13230809be 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -63,22 +62,13 @@ public abstract class Round extends RBuiltinNode {
         return new Object[]{RMissing.instance, 0};
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        //@formatter:off
-        casts.arg("x").
-            defaultError(this, RError.Message.NON_NUMERIC_MATH).
-            mustBe(numericValue().or(complexValue()));
+    static {
+        Casts casts = new Casts(Round.class);
+        casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(numericValue().or(complexValue()));
 
         // TODO: this should also accept vectors
         // TODO: digits argument is rounded, not simply stripped off the decimal part
-        casts.arg("digits").
-            defaultError(this, RError.Message.NON_NUMERIC_MATH).
-            mustBe(numericValue().or(complexValue())).
-            asIntegerVector().
-            findFirst();
-
-        //@formatter:on
+        casts.arg("digits").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(numericValue().or(complexValue())).asIntegerVector().findFirst();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
index a24d5c11c2..245edd7529 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -19,7 +19,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -30,8 +29,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 @RBuiltin(name = "row", kind = INTERNAL, parameterNames = {"dims"}, behavior = PURE)
 public abstract class Row extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Row.class);
         casts.arg("dims").defaultError(SHOW_CALLER, RError.Message.MATRIX_LIKE_REQUIRED, "row").mustBe(integerValue()).asIntegerVector().mustBe(size(2));
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java
index dd72109980..fc308351bf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -21,8 +21,14 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 
 // Implements .rowMeans
+@SuppressWarnings("unused")
 @RBuiltin(name = "rowMeans", kind = INTERNAL, parameterNames = {"X", "m", "n", "na.rm"}, behavior = PURE)
 public abstract class RowMeans extends RowSumsBase {
+
+    static {
+        new ColSumsCasts(RowMeans.class);
+    }
+
     @Specialization
     protected RDoubleVector rowMeans(RAbstractDoubleVector x, int rowNum, int colNum, boolean naRm) {
         return accumulateRows(x, rowNum, colNum, naRm, RowMeans::getMean, (v, nacheck, i) -> v.getDataAt(i));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java
index 4fe2545e4c..7659e933c1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -20,8 +20,14 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 
+@SuppressWarnings("unused")
 @RBuiltin(name = "rowSums", kind = INTERNAL, parameterNames = {"X", "m", "n", "na.rm"}, behavior = PURE)
 public abstract class RowSums extends RowSumsBase {
+
+    static {
+        new ColSumsCasts(RowSums.class);
+    }
+
     @Specialization
     protected RDoubleVector rowSums(RAbstractDoubleVector x, int rowNum, int colNum, boolean naRm) {
         return accumulateRows(x, rowNum, colNum, naRm, (sum, cnt) -> sum, (v, nacheck, i) -> v.getDataAt(i));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
index 207312d8a6..f476fd860d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2015,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -24,7 +24,6 @@ import java.util.HashMap;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -51,8 +50,8 @@ public class RowsumFunctions {
         private final ConditionProfile typeProfile = ConditionProfile.createBinaryProfile();
         private final NACheck na = NACheck.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Rowsum.class);
             casts.arg("x").mustBe(integerValue().or(doubleValue()), RError.Message.ROWSUM_NON_NUMERIC);
 
             casts.arg("g").asVector();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
index fe0c2dcfde..76766dbfcf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
@@ -101,6 +101,10 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
         private final ConditionProfile argMissingProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile argsValueAndNamesProfile = ConditionProfile.createBinaryProfile();
 
+        static {
+            Casts.noCasts(UseMethod.class);
+        }
+
         protected UseMethod() {
             super(false);
         }
@@ -193,6 +197,10 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
         private final ValueProfile parameterSignatureProfile = ValueProfile.createIdentityProfile();
         private final ValueProfile suppliedParameterSignatureProfile = ValueProfile.createIdentityProfile();
 
+        static {
+            Casts.noCasts(NextMethod.class);
+        }
+
         protected NextMethod() {
             super(true);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
index 128290e690..961dd4dfee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
@@ -39,7 +39,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -54,24 +53,15 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
 public abstract class Sample extends RBuiltinNode {
     private final ConditionProfile sampleSizeProfile = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        // @formatter:off
-        casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().
-                mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER, VECTOR_SIZE_NA_NAN).
-                mapIf(doubleValue(), chain(asDoubleVector()).with(findFirst().doubleElement()).
-                        with(mustBe(isFinite(), SHOW_CALLER, VECTOR_SIZE_NA_NAN)).
-                        with(mustBe(lt(4.5e15), SHOW_CALLER, VECTOR_SIZE_TOO_LARGE)).end()).
-                asIntegerVector().findFirst().mustBe(gte0());
-        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").
-                mustBe(integerValue().or(doubleValue()).or(stringValue())).
-                asIntegerVector().findFirst().
-                defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").
-                notNA().mustBe(gte0());
-        casts.arg("replace").mustBe(integerValue().or(doubleValue()).or(logicalValue())).
-                asLogicalVector().mustBe(singleElement()).findFirst().notNA().map(toBoolean());
+    static {
+        Casts casts = new Casts(Sample.class);
+        casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER, VECTOR_SIZE_NA_NAN).mapIf(doubleValue(),
+                        chain(asDoubleVector()).with(findFirst().doubleElement()).with(mustBe(isFinite(), SHOW_CALLER, VECTOR_SIZE_NA_NAN)).with(
+                                        mustBe(lt(4.5e15), SHOW_CALLER, VECTOR_SIZE_TOO_LARGE)).end()).asIntegerVector().findFirst().mustBe(gte0());
+        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().defaultError(SHOW_CALLER,
+                        INVALID_ARGUMENT, "size").notNA().mustBe(gte0());
+        casts.arg("replace").mustBe(integerValue().or(doubleValue()).or(logicalValue())).asLogicalVector().mustBe(singleElement()).findFirst().notNA().map(toBoolean());
         casts.arg("prob").asDoubleVector();
-        // @formatter:on
     }
 
     // Validation that correlates two or more argument values (note: positiveness of prob is checked
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
index 90fb10fe61..8b1ad3e4b6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetDouble;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetInt;
@@ -50,18 +49,12 @@ public abstract class Sample2 extends RBuiltinNode {
 
     private final BranchProfile errorProfile = BranchProfile.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        // @formatter:off
-        casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().
-                mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER, INVALID_FIRST_ARGUMENT).
-                asDoubleVector().findFirst().mustBe(gte(0.0)).mustBe(isFinite());
-        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").
-                mustBe(integerValue().or(doubleValue())).
-                asIntegerVector().findFirst().
-                defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").
-                notNA().mustBe(gte0());
-        // @formatter:on
+    static {
+        Casts casts = new Casts(Sample2.class);
+        casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER,
+                        INVALID_FIRST_ARGUMENT).asDoubleVector().findFirst().mustBe(gte(0.0)).mustBe(isFinite());
+        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue())).asIntegerVector().findFirst().defaultError(SHOW_CALLER, INVALID_ARGUMENT,
+                        "size").notNA().mustBe(gte0());
     }
 
     @Specialization(guards = "x > MAX_INT")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 86377c5a1a..d80ec47fd7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen;
@@ -101,8 +100,8 @@ public abstract class Scan extends RBuiltinNode {
         boolean skipNull = false;
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Scan.class);
         casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
 
         casts.arg("what").asVector();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 6bb73698a3..01d918d117 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -29,9 +29,11 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.library.utils.TypeConvert;
+import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.base.SeqFunctions.SeqInt.IsIntegralNumericNode;
 import com.oracle.truffle.r.nodes.builtin.base.SeqFunctionsFactory.GetIntegralNumericNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.SeqFunctionsFactory.IsMissingOrNumericNodeGen;
@@ -330,6 +332,10 @@ public final class SeqFunctions {
     public abstract static class SeqAlong extends RBuiltinNode {
         @Child private ClassHierarchyNode classHierarchyNode = ClassHierarchyNode.create();
 
+        static {
+            Casts.noCasts(SeqAlong.class);
+        }
+
         @Specialization(guards = "!hasClass(value)")
         protected RIntSequence seq(VirtualFrame frame, Object value,
                         @Cached("create()") RLengthNode length) {
@@ -373,8 +379,8 @@ public final class SeqFunctions {
     @RBuiltin(name = "seq_len", kind = PRIMITIVE, parameterNames = {"length.out"}, behavior = PURE)
     public abstract static class SeqLen extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SeqLen.class);
             /*
              * This is slightly different than what GNU R does as it will report coercion warning
              * for: seq_len(c("7", "b")) GNU R (presumably) gets the first element before doing a
@@ -426,6 +432,10 @@ public final class SeqFunctions {
 
         private static final double FLT_EPSILON = 1.19209290e-7;
 
+        static {
+            Casts.noCasts(SeqInt.class);
+        }
+
         protected abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith);
 
         protected SeqInt(boolean seqFastPath) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
index 6d18414e51..94ba8ac89e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
@@ -86,15 +86,16 @@ public class SerializeFunctions {
             }
         }
 
-        protected void connection(CastBuilder casts) {
+        protected static void connection(Casts casts) {
             casts.arg("con").mustBe(integerValue()).asIntegerVector().findFirst();
         }
     }
 
     @RBuiltin(name = "unserializeFromConn", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO)
     public abstract static class UnserializeFromConn extends Adapter {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(UnserializeFromConn.class);
             connection(casts);
         }
 
@@ -112,8 +113,9 @@ public class SerializeFunctions {
 
     @RBuiltin(name = "serializeToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "ascii", "version", "refhook"}, behavior = IO)
     public abstract static class SerializeToConn extends Adapter {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SerializeToConn.class);
             connection(casts);
             casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL);
             casts.arg("version").allowNull().mustBe(integerValue());
@@ -135,8 +137,9 @@ public class SerializeFunctions {
 
     @RBuiltin(name = "unserialize", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO)
     public abstract static class Unserialize extends Adapter {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(Unserialize.class);
             casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustBe(integerValue().or(rawValue())).mapIf(integerValue(),
                             asIntegerVector().setNext(findFirst().integerElement()));
         }
@@ -154,8 +157,9 @@ public class SerializeFunctions {
 
     @RBuiltin(name = "serialize", kind = INTERNAL, parameterNames = {"object", "con", "type", "version", "refhook"}, behavior = IO)
     public abstract static class Serialize extends Adapter {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(Serialize.class);
             casts.arg("con").allowNull().mustBe(integerValue()).asIntegerVector().findFirst();
             casts.arg("type").asIntegerVector().findFirst();
         }
@@ -175,8 +179,9 @@ public class SerializeFunctions {
 
     @RBuiltin(name = "serializeb", kind = INTERNAL, parameterNames = {"object", "con", "xdr", "version", "refhook"}, behavior = IO)
     public abstract static class SerializeB extends Adapter {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SerializeB.class);
             connection(casts);
             casts.arg("xdr").asLogicalVector().findFirst();
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
index 4fa28d6d07..49a67b4f48 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.objects.AsS4;
 import com.oracle.truffle.r.nodes.objects.AsS4NodeGen;
@@ -45,8 +44,8 @@ public abstract class SetS4Object extends RBuiltinNode {
 
     @Child private AsS4 asS4 = AsS4NodeGen.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(SetS4Object.class);
         casts.arg("object").asAttributable(true, true, true);
         casts.arg("flag").asLogicalVector().mustBe(singleElement(), RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "flag").findFirst().map(toBoolean());
         // "complete" can be a vector, unlike "flag"
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java
index 12b685c970..1b89fd845d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -36,8 +35,8 @@ import com.oracle.truffle.r.runtime.data.RNull;
 @RBuiltin(name = "setTimeLimit", kind = INTERNAL, parameterNames = {"cpu", "elapsed", "transient"}, visibility = OFF, behavior = COMPLEX)
 public abstract class SetTimeLimit extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(SetTimeLimit.class);
         casts.arg("cpu").asDoubleVector().findFirst();
         casts.arg("elapsed").asDoubleVector().findFirst();
         casts.arg("transient").asLogicalVector().findFirst().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
index dc905f1abf..4c4abf4a6b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
@@ -33,7 +33,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.Utils;
@@ -43,8 +42,8 @@ import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 @RBuiltin(name = "setwd", visibility = OFF, kind = INTERNAL, parameterNames = "path", behavior = IO)
 public abstract class Setwd extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Setwd.class);
         casts.arg("path").defaultError(SHOW_CALLER, CHAR_ARGUMENT).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java
index 17a035de4a..eed5de7dd1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.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
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.IntValueProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetRowNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -51,8 +50,8 @@ public abstract class ShortRowNames extends RBuiltinNode {
 
     @Child private GetRowNamesAttributeNode getRowNamesNode = GetRowNamesAttributeNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(ShortRowNames.class);
         casts.arg("type").asIntegerVector().findFirst().mustBe(gte0().and(lte(2)));
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
index 6ec1fc1d5e..5c3afc71a8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
@@ -40,7 +40,6 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.CopyAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.CopyAttributesNodeGen;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -69,8 +68,8 @@ public abstract class Signif extends RBuiltinNode {
     private final BranchProfile identity = BranchProfile.create();
     private final ConditionProfile infProfile = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Signif.class);
         casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(numericValue().or(complexValue())).mapIf(complexValue().not(),
                         asDoubleVector(true, true, true));
         // TODO: for the error messages to be consistent with GNU R we should chack for notEmpty()
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
index 85ad64c740..9ae7473c5f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
@@ -32,7 +32,6 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -43,8 +42,9 @@ import com.oracle.truffle.r.runtime.data.RNull;
 public class SinkFunctions {
     @RBuiltin(name = "sink", visibility = OFF, kind = INTERNAL, parameterNames = {"file", "closeOnExit", "type", "split"}, behavior = IO)
     public abstract static class Sink extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(Sink.class);
             casts.arg("file").mustBe(integerValue()).asIntegerVector().findFirst();
             casts.arg("closeOnExit").asLogicalVector().findFirst().notNA().map(toBoolean());
             casts.arg("type").asLogicalVector().findFirst().notNA().map(toBoolean());
@@ -78,8 +78,9 @@ public class SinkFunctions {
 
     @RBuiltin(name = "sink.number", kind = INTERNAL, parameterNames = {"type"}, behavior = IO)
     public abstract static class SinkNumber extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SinkNumber.class);
             casts.arg("type").asLogicalVector().findFirst().notNA().map(toBoolean());
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
index a01de6f6ad..b785bc5ddd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
@@ -24,7 +24,6 @@ import com.oracle.truffle.r.nodes.access.AccessSlotNode;
 import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.WrapArgumentNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -38,8 +37,8 @@ public abstract class Slot extends RBuiltinNode {
 
     @Child private AccessSlotNode accessSlotNode = AccessSlotNodeGen.create(true);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Slot.class);
         casts.arg(0).asAttributable(true, true, true);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
index 85bd174365..14ab57ffcf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
@@ -60,12 +60,12 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 public class SortFunctions {
 
     private abstract static class Adapter extends RBuiltinNode {
-        protected static void addCastForX(CastBuilder castBuilder) {
-            castBuilder.arg("x").allowNull().mustBe(abstractVectorValue(), SHOW_CALLER, ONLY_ATOMIC_CAN_BE_SORTED);
+        protected static void addCastForX(Casts casts) {
+            casts.arg("x").allowNull().mustBe(abstractVectorValue(), SHOW_CALLER, ONLY_ATOMIC_CAN_BE_SORTED);
         }
 
-        protected static void addCastForDecreasing(CastBuilder castBuilder) {
-            castBuilder.arg("decreasing").defaultError(SHOW_CALLER, INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean());
+        protected static void addCastForDecreasing(Casts casts) {
+            casts.arg("decreasing").defaultError(SHOW_CALLER, INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean());
         }
 
         @TruffleBoundary
@@ -152,8 +152,8 @@ public class SortFunctions {
     @RBuiltin(name = "sort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE)
     public abstract static class Sort extends Adapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Sort.class);
             addCastForX(casts);
             addCastForDecreasing(casts);
         }
@@ -182,8 +182,8 @@ public class SortFunctions {
     @RBuiltin(name = "qsort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE)
     public abstract static class QSort extends Adapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(QSort.class);
             addCastForX(casts);
             addCastForDecreasing(casts);
         }
@@ -202,8 +202,8 @@ public class SortFunctions {
     @RBuiltin(name = "psort", kind = INTERNAL, parameterNames = {"x", "partial"}, behavior = PURE)
     public abstract static class PartialSort extends Adapter {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(PartialSort.class);
             addCastForX(casts);
         }
 
@@ -242,8 +242,8 @@ public class SortFunctions {
     public abstract static class RadixSort extends Adapter {
         @Child private Order orderNode = OrderNodeGen.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(RadixSort.class);
             casts.arg("na.last").asLogicalVector().findFirst();
             casts.arg("decreasing").mustBe(numericValue(), SHOW_CALLER, INVALID_LOGICAL, "decreasing").asLogicalVector();
             casts.arg("retgrp").asLogicalVector().findFirst().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
index 196ccc3cfa..b43d2e7fc9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
@@ -58,6 +58,10 @@ public abstract class Split extends RBuiltinNode {
     private static final int INITIAL_SIZE = 5;
     private static final int SCALE_FACTOR = 2;
 
+    static {
+        Casts.noCasts(Split.class);
+    }
+
     public static class SplitTemplate {
         @SuppressWarnings("unused") private int[] collectResultsSize;
         @SuppressWarnings("unused") private int nLevels;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
index a18ee23a79..1a47d84f96 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
@@ -45,8 +45,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "sprintf", kind = INTERNAL, parameterNames = {"fmt", "..."}, behavior = PURE)
+
 public abstract class Sprintf extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(Sprintf.class);
+    }
+
     public abstract Object executeObject(String fmt, Object args);
 
     @Child private Sprintf sprintfRecursive;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
index a23e27aca5..9ca4d012ee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
@@ -32,10 +32,8 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyScalarNode;
-import com.oracle.truffle.r.nodes.function.ClassHierarchyScalarNodeGen;
 import com.oracle.truffle.r.nodes.objects.CollectGenericArgumentsNode;
 import com.oracle.truffle.r.nodes.objects.CollectGenericArgumentsNodeGen;
 import com.oracle.truffle.r.nodes.objects.DispatchGeneric;
@@ -68,7 +66,6 @@ public abstract class StandardGeneric extends RBuiltinNode {
     @Child private LocalReadVariableNode readSigARgs = LocalReadVariableNode.create(RRuntime.DOT_SIG_ARGS, true);
     @Child private CollectGenericArgumentsNode collectArgumentsNode;
     @Child private DispatchGeneric dispatchGeneric = DispatchGenericNodeGen.create();
-    @Child private ClassHierarchyScalarNode classNode;
 
     @Child private CastNode castIntScalar;
     @Child private CastNode castStringScalar;
@@ -80,19 +77,11 @@ public abstract class StandardGeneric extends RBuiltinNode {
     private final BranchProfile noGenFunFound = BranchProfile.create();
     private final ConditionProfile sameNamesProfile = ConditionProfile.createBinaryProfile();
 
-    private String argClass(Object arg) {
-        if (classNode == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            classNode = insert(ClassHierarchyScalarNodeGen.create());
-        }
-        return classNode.executeString(arg);
-    }
-
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(StandardGeneric.class);
         casts.arg("f").defaultError(RError.Message.GENERIC, "argument to 'standardGeneric' must be a non-empty character string").mustBe(
                         stringValue()).asStringVector().findFirst().mustBe(lengthGt(0));
-        Function<Object, Object> argClass = this::argClass;
+        Function<Object, Object> argClass = ClassHierarchyScalarNode::get;
         casts.arg("fdef").defaultError(RError.SHOW_CALLER, RError.Message.EXPECTED_GENERIC, argClass).allowMissing().asAttributable(true, true, true).mustBe(instanceOf(RFunction.class));
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
index 361eaeb24a..ac22038d7d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public class StartsEndsWithFunctions {
-    private static class Casts {
+    private static class CastsHelper {
         private static void arg(CastBuilder casts, String name) {
             casts.arg(name).mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER_OBJECTS).asStringVector();
         }
@@ -48,10 +48,12 @@ public class StartsEndsWithFunctions {
         private final NACheck naCheck = NACheck.create();
         private final ConditionProfile singlePrefixProfile = ConditionProfile.createBinaryProfile();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.arg(casts, "x");
-            Casts.arg(casts, "prefix");
+        static final class AdapterCasts extends Casts {
+            AdapterCasts(Class<? extends Adapter> extCls) {
+                super(extCls);
+                CastsHelper.arg(casts, "x");
+                CastsHelper.arg(casts, "prefix");
+            }
         }
 
         protected Object doIt(RAbstractStringVector xVec, RAbstractStringVector prefixVec, boolean startsWith) {
@@ -95,17 +97,28 @@ public class StartsEndsWithFunctions {
         }
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "startsWith", kind = INTERNAL, parameterNames = {"x", "prefix"}, behavior = PURE)
     public abstract static class StartsWith extends Adapter {
+
+        static {
+            new AdapterCasts(StartsWith.class);
+        }
+
         @Specialization
         protected Object startsWith(RAbstractStringVector x, RAbstractStringVector prefix) {
             return doIt(x, prefix, true);
         }
     }
 
+    @SuppressWarnings("unused")
     @RBuiltin(name = "endsWith", kind = INTERNAL, parameterNames = {"x", "prefix"}, behavior = PURE)
     public abstract static class EndsWith extends Adapter {
 
+        static {
+            new AdapterCasts(EndsWith.class);
+        }
+
         @Specialization
         protected Object endsWith(RAbstractStringVector x, RAbstractStringVector prefix) {
             return doIt(x, prefix, false);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java
index 44e3885490..efb1ada9f4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -38,8 +37,9 @@ import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = "stop", kind = INTERNAL, parameterNames = {"call", "message"}, behavior = COMPLEX)
 public abstract class Stop extends RBuiltinNode {
-    @Override
-    protected void createCasts(CastBuilder casts) {
+
+    static {
+        Casts casts = new Casts(Stop.class);
         casts.arg("call").asLogicalVector().findFirst().map(toBoolean());
         casts.arg("message").allowNull().mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_STRING_IN_STOP).findFirst();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
index 42746aea68..6710bae7b4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -42,8 +41,8 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 public abstract class Strrep extends RBuiltinNode {
     private final NACheck naCheck = NACheck.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Strrep.class);
         casts.arg("x").asStringVector();
         casts.arg("times").asIntegerVector();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
index ce5653198a..86e2c0b11b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -35,7 +35,6 @@ 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.api.profiles.PrimitiveValueProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -46,8 +45,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "strtoi", kind = INTERNAL, parameterNames = {"x", "base"}, behavior = PURE)
 public abstract class Strtoi extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Strtoi.class);
         casts.arg("x").mustBe(stringValue()).asStringVector();
         // base == 0 || (base >= 2 && base <= 36)
         casts.arg("base").mustBe(integerValue()).asIntegerVector().findFirst().mustBe(eq(0).or(gte(2).and(lte(36))));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
index fa27e232c3..9fb1980325 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 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.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.ToLowerOrUpper.StringMapNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -37,8 +36,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "strtrim", kind = INTERNAL, parameterNames = {"x", "width"}, behavior = PURE)
 public abstract class Strtrim extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Strtrim.class);
         casts.arg("x").defaultError(Message.REQUIRES_CHAR_VECTOR, "strtrim()").mustBe(stringValue()).asStringVector(true, true, true);
         casts.arg("width").asIntegerVector();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
index f6077ad1c6..395271e222 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
@@ -47,6 +47,10 @@ public abstract class Substitute extends RBuiltinNode {
 
     @Child private Quote quote;
 
+    static {
+        Casts.noCasts(Substitute.class);
+    }
+
     @Specialization
     protected Object doSubstitute(VirtualFrame frame, RPromise expr, @SuppressWarnings("unused") RMissing envMissing) {
         return doSubstituteWithEnv(expr, REnvironment.frameToEnvironment(frame.materialize()));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
index eec7907648..b55b50f943 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.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
@@ -47,6 +47,10 @@ public abstract class Substr extends RBuiltinNode {
     private final BranchProfile everSeenIllegalRange = BranchProfile.create();
     private final ConditionProfile naIndexesProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(Substr.class);
+    }
+
     @SuppressWarnings("unused")
     @Specialization(guards = "emptyArg(arg)")
     protected RStringVector substrEmptyArg(VirtualFrame frame, RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
index e0571ca49d..b8a914baf1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
@@ -31,7 +31,6 @@ 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.api.profiles.LoopConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticReduceNode;
@@ -59,8 +58,8 @@ public abstract class Sum extends RBuiltinNode {
 
     @Child private UnaryArithmeticReduceNode reduce = UnaryArithmeticReduceNodeGen.create(semantics, BinaryArithmetic.ADD);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Sum.class);
         casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
index 50ea531bd0..d1af871ffb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -59,6 +59,10 @@ public abstract class Switch extends RBuiltinNode {
     private final BranchProfile notIntType = BranchProfile.create();
     private final ConditionProfile noAlternativesProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(Switch.class);
+    }
+
     @Specialization
     protected Object doSwitch(VirtualFrame frame, RAbstractStringVector x, RArgsValuesAndNames optionalArgs) {
         if (x.getLength() != 1) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
index 4e845a663b..cc35e6facb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
@@ -52,7 +52,6 @@ import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinPackages;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -90,8 +89,8 @@ public class SysFunctions {
     public abstract static class SysGetenv extends RBuiltinNode {
         private final ConditionProfile zeroLengthProfile = ConditionProfile.createBinaryProfile();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(SysGetenv.class);
             casts.arg("x").mustBe(stringValue(), RError.Message.ARGUMENT_WRONG_TYPE);
             casts.arg("unset").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
         }
@@ -163,8 +162,9 @@ public class SysFunctions {
 
     @RBuiltin(name = "Sys.setenv", visibility = OFF, kind = INTERNAL, parameterNames = {"nm", "values"}, behavior = MODIFIES_STATE)
     public abstract static class SysSetEnv extends LoadNamespaceAdapter {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SysSetEnv.class);
             casts.arg("nm").mustBe(stringValue(), RError.Message.ARGUMENT_WRONG_TYPE);
             casts.arg("values").mustBe(stringValue(), RError.Message.ARGUMENT_WRONG_TYPE);
         }
@@ -192,8 +192,9 @@ public class SysFunctions {
 
     @RBuiltin(name = "Sys.unsetenv", visibility = OFF, kind = INTERNAL, parameterNames = {"x"}, behavior = READS_STATE)
     public abstract static class SysUnSetEnv extends LoadNamespaceAdapter {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SysUnSetEnv.class);
             casts.arg("x").mustBe(stringValue(), RError.Message.ARGUMENT_WRONG_TYPE);
         }
 
@@ -217,8 +218,9 @@ public class SysFunctions {
 
     @RBuiltin(name = "Sys.sleep", visibility = OFF, kind = INTERNAL, parameterNames = {"time"}, behavior = COMPLEX)
     public abstract static class SysSleep extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SysSleep.class);
             casts.arg("time").asDoubleVector().findFirst().mustBe(gte(0.0).and(eq(Double.NaN).not()));
         }
 
@@ -247,8 +249,9 @@ public class SysFunctions {
      */
     @RBuiltin(name = "Sys.readlink", kind = INTERNAL, parameterNames = {"paths"}, behavior = IO)
     public abstract static class SysReadlink extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SysReadlink.class);
             casts.arg("paths").mustBe(stringValue());
         }
 
@@ -289,8 +292,9 @@ public class SysFunctions {
 
     @RBuiltin(name = "Sys.chmod", visibility = OFF, kind = INTERNAL, parameterNames = {"paths", "octmode", "use_umask"}, behavior = IO)
     public abstract static class SysChmod extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SysChmod.class);
             casts.arg("paths").mustBe(stringValue());
             casts.arg("octmode").asIntegerVector().mustBe(notEmpty(), RError.Message.MODE_LENGTH_ONE);
             casts.arg("use_umask").asLogicalVector().findFirst().notNA().map(toBoolean());
@@ -316,8 +320,9 @@ public class SysFunctions {
     // TODO implement
     @RBuiltin(name = "Sys.umask", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"octmode"}, behavior = COMPLEX)
     public abstract static class SysUmask extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SysUmask.class);
             casts.arg("octmode").asIntegerVector().findFirst();
         }
 
@@ -366,8 +371,9 @@ public class SysFunctions {
 
     @RBuiltin(name = "Sys.glob", kind = INTERNAL, parameterNames = {"paths", "dirmask"}, behavior = IO)
     public abstract static class SysGlob extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SysGlob.class);
             casts.arg("paths").mustBe(stringValue()).asStringVector();
             casts.arg("dirmask").asLogicalVector().findFirst().notNA().map(toBoolean());
         }
@@ -394,8 +400,9 @@ public class SysFunctions {
 
     @RBuiltin(name = "setFileTime", kind = INTERNAL, parameterNames = {"path", "time"}, visibility = OFF, behavior = IO)
     public abstract static class SysSetFileTime extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(SysSetFileTime.class);
             casts.arg("path").mustBe(stringValue()).asStringVector().findFirst();
             casts.arg("time").asIntegerVector().findFirst().notNA();
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
index f6ac5b3121..bbe48d983e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -31,8 +30,8 @@ public abstract class Tabulate extends RBuiltinNode {
 
     private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Tabulate.class);
         casts.arg("bin").defaultError(RError.NO_CALLER, RError.Message.INVALID_INPUT).mustBe(integerValue()).asIntegerVector();
         casts.arg("nbins").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "nbin").asIntegerVector().findFirst().mustBe(gte(0));
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
index 1d365eb082..2bb1e17c5c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.TempPathName;
@@ -42,8 +41,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "tempfile", kind = INTERNAL, parameterNames = {"pattern", "tempdir", "fileext"}, behavior = COMPLEX)
 public abstract class TempFile extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(TempFile.class);
         casts.arg("pattern").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_FILENAME_PATTERN).mustBe(notEmpty(), RError.SHOW_CALLER, RError.Message.NO, "pattern");
         casts.arg("tempdir").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "tempdir").findFirst(RError.SHOW_CALLER, RError.Message.NO, "tempdir");
         casts.arg("fileext").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_FILE_EXT).mustBe(notEmpty(), RError.SHOW_CALLER, RError.Message.NO, "fileext");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java
index 31023607ab..92d3eb1c98 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.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
@@ -35,7 +35,6 @@ import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNodeGen;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -95,8 +94,8 @@ public abstract class ToLowerOrUpper {
 
         @Child private StringMapNode mapNode = StringMapNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(ToLower.class);
             casts.arg(0, "x").mustBe(stringValue()).asStringVector(true, true, true);
         }
 
@@ -121,8 +120,8 @@ public abstract class ToLowerOrUpper {
 
         @Child private StringMapNode mapNode = StringMapNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(ToUpper.class);
             casts.arg(0, "x").mustBe(stringValue()).asStringVector(true, true, true);
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
index 949cc82fbf..6ea603fb46 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
@@ -44,7 +44,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen;
 import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling;
@@ -70,12 +69,12 @@ public class TraceFunctions {
     private abstract static class PrimTraceAdapter extends RBuiltinNode {
         @Child private GetFunctions.Get getNode;
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            // @formatter:off
-            casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), SHOW_CALLER, Message.ARG_MUST_BE_FUNCTION).
-                    mapIf(stringValue(), chain(asStringVector()).with(findFirst().stringElement()).end());
-            // @formatter:on
+        static final class PrimTraceCasts extends Casts {
+            PrimTraceCasts(Class<? extends PrimTraceAdapter> extCls) {
+                super(extCls);
+                casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), SHOW_CALLER, Message.ARG_MUST_BE_FUNCTION).mapIf(stringValue(),
+                                chain(asStringVector()).with(findFirst().stringElement()).end());
+            }
         }
 
         protected Object getFunction(VirtualFrame frame, String funcName) {
@@ -90,6 +89,10 @@ public class TraceFunctions {
     @RBuiltin(name = ".primTrace", visibility = OFF, kind = PRIMITIVE, parameterNames = "what", behavior = COMPLEX)
     public abstract static class PrimTrace extends PrimTraceAdapter {
 
+        static {
+            new PrimTraceCasts(PrimTrace.class);
+        }
+
         @Specialization
         protected RNull primTrace(VirtualFrame frame, RAbstractStringVector funcName) {
             return primTrace((RFunction) getFunction(frame, funcName.getDataAt(0)));
@@ -110,6 +113,10 @@ public class TraceFunctions {
     @RBuiltin(name = ".primUntrace", visibility = OFF, kind = PRIMITIVE, parameterNames = "what", behavior = COMPLEX)
     public abstract static class PrimUnTrace extends PrimTraceAdapter {
 
+        static {
+            new PrimTraceCasts(PrimUnTrace.class);
+        }
+
         @Specialization
         protected RNull primUnTrace(VirtualFrame frame, RAbstractStringVector funcName) {
             return primUnTrace((RFunction) getFunction(frame, funcName.getDataAt(0)));
@@ -127,6 +134,11 @@ public class TraceFunctions {
 
     @RBuiltin(name = "traceOnOff", kind = INTERNAL, parameterNames = "state", behavior = COMPLEX)
     public abstract static class TraceOnOff extends RBuiltinNode {
+
+        static {
+            Casts.noCasts(TraceOnOff.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected byte traceOnOff(byte state) {
@@ -220,8 +232,9 @@ public class TraceFunctions {
      */
     @RBuiltin(name = "tracemem", kind = PRIMITIVE, parameterNames = "x", behavior = COMPLEX)
     public abstract static class Tracemem extends TracememBase {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(Tracemem.class);
             casts.arg("x").mustNotBeNull(Message.TRACEMEM_NOT_NULL);
         }
 
@@ -242,8 +255,8 @@ public class TraceFunctions {
 
         @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Retracemem.class);
             casts.arg("previous").defaultError(Message.INVALID_ARGUMENT, "previous").allowNullAndMissing().mustBe(stringValue());
         }
 
@@ -281,6 +294,11 @@ public class TraceFunctions {
 
     @RBuiltin(name = "untracemem", kind = PRIMITIVE, visibility = OFF, parameterNames = "x", behavior = COMPLEX)
     public abstract static class Untracemem extends TracememBase {
+
+        static {
+            Casts.noCasts(Untracemem.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected RNull execute(Object x) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java
index fca379d841..4c75e21ae3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.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
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -36,8 +35,8 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 @RBuiltin(name = "traceback", kind = INTERNAL, parameterNames = {"x"}, behavior = COMPLEX)
 public abstract class Traceback extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Traceback.class);
         casts.arg("x").mustBe(numericValue()).asIntegerVector().findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
index f264855e7e..f9c7bf4af7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
@@ -65,6 +65,10 @@ public abstract class Transpose extends RBuiltinNode {
     @Child private GetDimNamesAttributeNode getDimNamesNode = GetDimNamesAttributeNode.create();
     @Child private GetDimAttributeNode getDimNode;
 
+    static {
+        Casts.noCasts(Transpose.class);
+    }
+
     public abstract Object execute(RAbstractVector o);
 
     @FunctionalInterface
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
index 21efb2c61f..9839f2e54c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.AcosNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.AsinNodeGen;
@@ -495,8 +494,8 @@ public class TrigExpFunctions {
         private final NACheck yNACheck = NACheck.create();
         private final NACheck xNACheck = NACheck.create();
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Atan2.class);
             casts.arg(0).mapIf(numericValue(), asDoubleVector());
             casts.arg(1).mapIf(numericValue(), asDoubleVector());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
index 3d0e13e8a4..759597b4bc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
@@ -48,16 +47,10 @@ public abstract class Trunc extends RBuiltinNode {
     @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
     @Child private UnaryArithmeticNode trunc = UnaryArithmeticNodeGen.create(TRUNC, RError.Message.NON_NUMERIC_MATH, RType.Double);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
-        //@formatter:off
-        casts.arg("x").
-            defaultError(this, RError.Message.NON_NUMERIC_MATH).
-            mustNotBeNull().
-            mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).
-            mustBe(numericValue()).
-            asDoubleVector(true, true, true);
-        //@formatter:on
+    static {
+        Casts casts = new Casts(Trunc.class);
+        casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustNotBeNull().mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(true,
+                        true, true);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java
index 735a4bf0e9..1366ac09fa 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.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
@@ -36,6 +36,10 @@ public abstract class Typeof extends RBuiltinNode {
 
     @Child private TypeofNode typeofNode = TypeofNodeGen.create();
 
+    static {
+        Casts.noCasts(Typeof.class);
+    }
+
     @Specialization
     protected String typeof(Object obj) {
         return typeofNode.execute(obj).getName();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
index ce157c2c11..04288a4970 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
@@ -20,7 +20,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.RemoveClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributable;
@@ -34,8 +33,8 @@ public abstract class UnClass extends RBuiltinNode {
     private final BranchProfile objectProfile = BranchProfile.create();
     private final BranchProfile shareableProfile = BranchProfile.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UnClass.class);
         casts.arg("x").asAttributable(true, true, true);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
index b6b914319a..56cad49e98 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
@@ -34,7 +34,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSet;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetDouble;
@@ -70,8 +69,8 @@ public abstract class Unique extends RBuiltinNode {
 
     private final ConditionProfile bigProfile = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Unique.class);
         // these are similar to those in DuplicatedFunctions.java
         casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.APPLIES_TO_VECTORS, "unique()").allowNull().mustBe(abstractVectorValue()).asVector();
         // not much more can be done for incomparables as it is either a vector of incomparable
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
index 4c7d7f36ef..67b2bbd517 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.UnlistNodeGen.RecursiveLengthNodeGen;
 import com.oracle.truffle.r.nodes.unary.PrecedenceNode;
@@ -50,8 +49,8 @@ public abstract class Unlist extends RBuiltinNode {
 
     // portions of the algorithm were transcribed from GNU R
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Unlist.class);
         casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean());
         casts.arg("use.names").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index b9597aa685..a9d87f4e49 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -42,7 +42,6 @@ import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetRowNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.UpdateAttrNodeGen.InternStringNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
@@ -98,8 +97,8 @@ public abstract class UpdateAttr extends RBuiltinNode {
         }
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UpdateAttr.class);
         // Note: cannot check 'attributability' easily because atomic values, e.g int, are not
         // RAttributable.
         casts.arg("x"); // disallows null
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index da512cd398..b86a4da62e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNames
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetRowNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
@@ -72,12 +71,12 @@ public abstract class UpdateAttributes extends RBuiltinNode {
     @Child private SetRowNamesAttributeNode setRowNamesNode;
     @Child private RemoveAttributeNode removeAttrNode;
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UpdateAttributes.class);
         // Note: cannot check 'attributability' easily because atomic values, e.g int, are not
         // RAttributable.
         casts.arg("obj"); // by default disallows RNull
-        casts.arg("value").mustBe(nullValue().or(instanceOf(RList.class)), this, ATTRIBUTES_LIST_OR_NULL);
+        casts.arg("value").mustBe(nullValue().or(instanceOf(RList.class)), ATTRIBUTES_LIST_OR_NULL);
     }
 
     // it's OK for the following two methods to update attributes in-place as the container has been
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
index 120e4b10ed..7fd8850a96 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClass
 import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode;
 import com.oracle.truffle.r.nodes.binary.CastTypeNode;
 import com.oracle.truffle.r.nodes.binary.CastTypeNodeGen;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNodeGen;
@@ -51,8 +50,8 @@ public abstract class UpdateClass extends RBuiltinNode {
     @Child private TypeofNode typeof;
     @Child private SetClassAttributeNode setClassAttrNode = SetClassAttributeNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UpdateClass.class);
         casts.arg("x"); // disallows null
         casts.arg("value").asStringVector();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
index d30e638139..867c09bfd9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.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
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.RemoveFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.opt.ReuseNonSharedNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -49,10 +48,10 @@ public abstract class UpdateDim extends RBuiltinNode {
 
     @Child private ReuseNonSharedNode reuse = ReuseNonSharedNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UpdateDim.class);
         casts.arg("x"); // disallows null
-        casts.arg("value").allowNull().asIntegerVector().mustBe(notEmpty(), this, LENGTH_ZERO_DIM_INVALID);
+        casts.arg("value").allowNull().asIntegerVector().mustBe(notEmpty(), LENGTH_ZERO_DIM_INVALID);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index d521f8a0ed..439c1b4a24 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -55,6 +55,10 @@ public abstract class UpdateDimNames extends RBuiltinNode {
     @Child private CastStringNode castStringNode;
     @Child private CastToVectorNode castVectorNode;
 
+    static {
+        Casts.noCasts(UpdateDimNames.class);
+    }
+
     private Object castString(Object o) {
         if (castStringNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
index 840f1ea37e..38199269d7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
@@ -34,7 +34,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -43,15 +42,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 @RBuiltin(name = "length<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class UpdateLength extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UpdateLength.class);
         // Note: `length<-`(NULL, newLen) really works in GnuR unlike other update builtins
-        // @formatter:off
-        casts.arg("x").allowNull().mustBe(abstractVectorValue(), this, INVALID_UNNAMED_ARGUMENT);
-        casts.arg("value").defaultError(this, INVALID_UNNAMED_VALUE).
-                mustBe(integerValue().or(doubleValue()).or(stringValue())).
-                asIntegerVector().mustBe(singleElement()).findFirst();
-        // @formatter:on
+        casts.arg("x").allowNull().mustBe(abstractVectorValue(), INVALID_UNNAMED_ARGUMENT);
+        casts.arg("value").defaultError(INVALID_UNNAMED_VALUE).mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().mustBe(singleElement()).findFirst();
     }
 
     @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
index 472dc7388a..fd018457e0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
@@ -19,7 +19,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.RemoveFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -32,8 +31,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 @RBuiltin(name = "levels<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class UpdateLevels extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UpdateLevels.class);
         casts.arg("value").allowNull().asVector(false);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
index 134470c264..afefd3a53d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
@@ -46,6 +46,10 @@ public abstract class UpdateNames extends RBuiltinNode {
 
     @Child private CastStringNode castStringNode;
 
+    static {
+        Casts.noCasts(UpdateNames.class);
+    }
+
     private Object castString(Object o) {
         if (castStringNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
index 02c1ab3e72..0ba6831d05 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -48,6 +48,10 @@ public abstract class UpdateOldClass extends RBuiltinNode {
     @Child private CastStringNode castStringNode;
     @Child private SetClassAttributeNode setClassAttributeNode = SetClassAttributeNode.create();
 
+    static {
+        Casts.noCasts(UpdateOldClass.class);
+    }
+
     @Specialization(guards = "!isStringVector(className)")
     protected Object setOldClass(RAbstractContainer arg, RAbstractVector className) {
         if (className.getLength() == 0) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
index e97872b6a2..42af29b001 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
@@ -25,7 +25,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.UpdateSlotNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
@@ -56,8 +55,8 @@ public abstract class UpdateSlot extends RBuiltinNode {
     @Child private CallRFunctionNode checkAtAssignmentCall;
     private final ConditionProfile cached = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UpdateSlot.class);
         casts.arg(0).asAttributable(true, true, true);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
index 804b73b667..6901189972 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -51,6 +51,10 @@ public abstract class UpdateStorageMode extends RBuiltinNode {
 
     private final BranchProfile errorProfile = BranchProfile.create();
 
+    static {
+        Casts.noCasts(UpdateStorageMode.class);
+    }
+
     @Specialization
     protected Object update(Object x, String value,
                     @Cached("create()") ArrayAttributeNode attrAttrAccess,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
index c6cb92740a..0211c6ed55 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -50,6 +50,10 @@ public abstract class UpdateSubstr extends RBuiltinNode {
 
     private final BranchProfile everSeenIllegalRange = BranchProfile.create();
 
+    static {
+        Casts.noCasts(UpdateSubstr.class);
+    }
+
     private static boolean rangeOk(String x, int start, int stop) {
         return start <= stop && start > 0 && stop > 0 && start <= x.length() && stop <= x.length();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
index c1ba6395b1..50aa92742d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -40,8 +39,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 @RBuiltin(name = "utf8ToInt", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
 public abstract class Utf8ToInt extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Utf8ToInt.class);
         casts.arg(0, "x").defaultError(RError.SHOW_CALLER, RError.Message.ARG_MUST_BE_CHARACTER_VECTOR_LENGTH_ONE, "x").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).shouldBe(size(1),
                         RError.SHOW_CALLER, RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE).findFirst();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
index 83f99a9513..b8d5a7b81f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.Lapply.LapplyInternalNode;
 import com.oracle.truffle.r.nodes.builtin.base.LapplyNodeGen.LapplyInternalNodeGen;
@@ -95,8 +94,8 @@ public abstract class VApply extends RBuiltinNode {
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
     @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(VApply.class);
         casts.arg("X").asVector();
         casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.SHOW_CALLER, RError.Message.APPLY_NON_FUNCTION);
         // casts.arg("FUN.VALUE").mapIf(anyValue(),
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
index 1cc2146e00..ee217670d4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode;
 import com.oracle.truffle.r.nodes.attributes.TypeFromModeNodeGen;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RType;
@@ -45,8 +44,8 @@ public abstract class Vector extends RBuiltinNode {
 
     @Child private TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Vector.class);
         casts.arg("mode").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "mode").asStringVector().mustBe(singleElement()).findFirst();
         casts.arg("length").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "length").asIntegerVector().mustBe(singleElement()).findFirst();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
index bfb083d159..164019046f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RErrorHandling;
@@ -40,8 +39,8 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 @RBuiltin(name = "warning", visibility = OFF, kind = INTERNAL, parameterNames = {"call", "immediate", "nobreaks", "message"}, behavior = COMPLEX)
 public abstract class Warning extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Warning.class);
         casts.arg("call").asLogicalVector().findFirst().map(toBoolean());
         casts.arg("immediate").asLogicalVector().findFirst().map(toBoolean());
         casts.arg("nobreaks").asLogicalVector().findFirst().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
index d61abdf172..7d0478eb4d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.WhichFunctionsFactory.WhichMaxNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.WhichFunctionsFactory.WhichMinNodeGen;
@@ -54,8 +53,8 @@ public class WhichFunctions {
     @RBuiltin(name = "which", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
     public abstract static class Which extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Which.class);
             casts.arg("x").mustBe(logicalValue()).asLogicalVector();
         }
 
@@ -111,9 +110,11 @@ public class WhichFunctions {
             this.isMax = isMax;
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            casts.arg(0, "x").asDoubleVector(true, false, false);
+        static final class WhichMinMaxs extends Casts {
+            protected WhichMinMaxs(Class<? extends WhichMinMax> extCls) {
+                super(extCls);
+                casts.arg(0, "x").asDoubleVector(true, false, false);
+            }
         }
 
         @Specialization
@@ -156,6 +157,11 @@ public class WhichFunctions {
 
     @RBuiltin(name = "which.max", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
     public abstract static class WhichMax extends WhichMinMax {
+
+        static {
+            new WhichMinMaxs(WhichMax.class);
+        }
+
         protected WhichMax() {
             super(true);
         }
@@ -167,6 +173,11 @@ public class WhichFunctions {
 
     @RBuiltin(name = "which.min", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
     public abstract static class WhichMin extends WhichMinMax {
+
+        static {
+            new WhichMinMaxs(WhichMin.class);
+        }
+
         protected WhichMin() {
             super(false);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
index 5fb69cbcaa..fa52a36dfc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
@@ -92,6 +92,10 @@ public abstract class WithVisible extends RBuiltinNode {
         return RDataFactory.createList(new Object[]{value, RRuntime.asLogical(visibility.execute(frame))}, LISTNAMES);
     }
 
+    static {
+        Casts.noCasts(WithVisible.class);
+    }
+
     @Specialization
     protected RList withVisible(@SuppressWarnings("unused") RMissing x) {
         CompilerDirectives.transferToInterpreter();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java
index 1c8a3656ce..7d2c7fdfc6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -45,6 +45,10 @@ public abstract class Xtfrm extends RBuiltinNode {
 
     @Child private GetFunctions.Get getNode;
 
+    static {
+        Casts.noCasts(Xtfrm.class);
+    }
+
     @Specialization
     protected Object xtfrm(VirtualFrame frame, Object x,
                     @Cached("createBinaryProfile()") ConditionProfile createProfile) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java
index 5b13b78fd4..4f9d28cfb2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java
@@ -5,22 +5,21 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
 package com.oracle.truffle.r.nodes.builtin.base.foreign;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 public abstract class CairoProps extends RExternalBuiltinNode.Arg1 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(CairoProps.class);
         casts.arg(0).asIntegerVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 7acf32697d..c8fc0b6df1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -226,6 +226,10 @@ public class CallAndExternalFunctions {
 
         private final BranchProfile errorProfile = BranchProfile.create();
 
+        static {
+            Casts.noCasts(DotCall.class);
+        }
+
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY, RMissing.instance};
@@ -723,6 +727,10 @@ public class CallAndExternalFunctions {
 
         private final BranchProfile errorProfile = BranchProfile.create();
 
+        static {
+            Casts.noCasts(DotExternal.class);
+        }
+
         @Override
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList f) {
@@ -821,6 +829,10 @@ public class CallAndExternalFunctions {
         private static final Object OP = "op";
         private static final Object RHO = "rho";
 
+        static {
+            Casts.noCasts(DotExternal2.class);
+        }
+
         private final BranchProfile errorProfile = BranchProfile.create();
 
         @Override
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
index 3ca0f0c97d..6941258c6b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -30,6 +30,10 @@ public final class Dqrcf extends RExternalBuiltinNode {
     private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE;
     private static final RStringVector DQRCF_NAMES = RDataFactory.createStringVector(new String[]{E, E, E, E, E, E, "coef", "info"}, RDataFactory.COMPLETE_VECTOR);
 
+    static {
+        Casts.noCasts(Dqrcf.class);
+    }
+
     @Override
     public RList call(RArgsValuesAndNames args) {
         Object[] argValues = args.getArguments();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
index e63b42dd11..330ffbe41d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -32,6 +32,10 @@ public final class Dqrdc2 extends RExternalBuiltinNode {
 
     @Child private GetDimAttributeNode getDimNode = GetDimAttributeNode.create();
 
+    static {
+        Casts.noCasts(Dqrdc2.class);
+    }
+
     @Override
     public RList call(RArgsValuesAndNames args) {
         Object[] argValues = args.getArguments();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
index 23bbc0cf05..aeb884a611 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
@@ -15,7 +15,6 @@ 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.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -28,8 +27,8 @@ public abstract class Fft extends RExternalBuiltinNode.Arg2 {
     private final ConditionProfile zVecLgt1 = ConditionProfile.createBinaryProfile();
     private final ConditionProfile noDims = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Fft.class);
         casts.arg(0).mustNotBeNull().asComplexVector(false, true, false);
         casts.arg(1).mustNotBeNull().asLogicalVector().findFirst().map(Predef.toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Flushconsole.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Flushconsole.java
index 676a0d0dee..6e7ef5004d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Flushconsole.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Flushconsole.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -17,6 +17,10 @@ import com.oracle.truffle.r.runtime.data.RNull;
 
 public final class Flushconsole extends RExternalBuiltinNode {
 
+    static {
+        Casts.noCasts(Flushconsole.class);
+    }
+
     @Override
     public RNull call(RArgsValuesAndNames args) {
         return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
index 5bf8f743db..926aa8a2b3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
@@ -192,6 +192,10 @@ public class FortranAndCFunctions {
     @RBuiltin(name = ".Fortran", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX)
     public abstract static class Fortran extends CRFFIAdapter {
 
+        static {
+            Casts.noCasts(Fortran.class);
+        }
+
         @Override
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
@@ -244,6 +248,10 @@ public class FortranAndCFunctions {
     @RBuiltin(name = ".C", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX)
     public abstract static class DotC extends CRFFIAdapter {
 
+        static {
+            Casts.noCasts(DotC.class);
+        }
+
         @Override
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
index c2ffbc4f9e..4f119f7a18 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
@@ -74,6 +74,10 @@ abstract class LookupAdapter extends RBuiltinNode {
     protected static class UnimplementedExternal extends RExternalBuiltinNode {
         private final String name;
 
+        static {
+            Casts.noCasts(UnimplementedExternal.class);
+        }
+
         public UnimplementedExternal(String name) {
             this.name = name;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/MakeQuartzDefault.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/MakeQuartzDefault.java
index c0a8cbaffa..01f7905dfb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/MakeQuartzDefault.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/MakeQuartzDefault.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -17,6 +17,10 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 
 public final class MakeQuartzDefault extends RExternalBuiltinNode {
 
+    static {
+        Casts.noCasts(MakeQuartzDefault.class);
+    }
+
     @Override
     public Object call(RArgsValuesAndNames args) {
         return RRuntime.LOGICAL_FALSE;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
index e0c3cec0f8..71b34f1465 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -15,7 +15,6 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -25,8 +24,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public abstract class ReadTableHead extends RExternalBuiltinNode.Arg7 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(ReadTableHead.class);
         casts.arg(0).defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
         casts.arg(1).mustNotBeNull().asIntegerVector().findFirst();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
index 812d042353..53cbadf9d4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
@@ -18,7 +18,6 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.printer.ComplexVectorPrinter;
@@ -50,8 +49,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(WriteTable.class);
         // file
         casts.arg(1).defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
         // nrows
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
index 8e3d1fcbe3..591c9236aa 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
@@ -39,7 +39,6 @@ import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
@@ -95,8 +94,8 @@ public abstract class AccessField extends RBuiltinNode {
     private final ConditionProfile invalidAtomicVector = ConditionProfile.createBinaryProfile();
     private final BranchProfile error = BranchProfile.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(AccessField.class);
         casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT_TYPE, RType.Language.getName()).mustBe(stringValue()).asStringVector().findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java
index a8655bf30d..08d6f1a624 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.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
@@ -52,6 +52,10 @@ final class ParensSpecial extends RNode {
 @RBuiltin(name = "(", kind = PRIMITIVE, parameterNames = {""}, visibility = ON, behavior = PURE)
 public final class ParenBuiltin extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(ParenBuiltin.class);
+    }
+
     public static RNode special(ArgumentsSignature signature, RNode[] args, @SuppressWarnings("unused") boolean inReplacement) {
         if (signature == ArgumentsSignature.empty(1)) {
             return new ParensSpecial(args[0]);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index 639d98960d..176b95d29c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.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
@@ -190,6 +190,10 @@ public abstract class Subscript extends RBuiltinNode {
         // same implementation as "[[", with different dispatch
     }
 
+    static {
+        Casts.noCasts(Subscript.class);
+    }
+
     public static RNode special(ArgumentsSignature signature, RNode[] arguments, boolean inReplacement) {
         if (signature.getNonNullCount() == 0) {
             if (arguments.length == 2) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
index b36cbf5a3e..82199ccb54 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.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
@@ -37,7 +37,6 @@ import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue;
@@ -136,8 +135,8 @@ public abstract class Subset extends RBuiltinNode {
 
     @Child private ExtractVectorNode extractNode = ExtractVectorNode.create(ElementAccessMode.SUBSET, false);
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(Subset.class);
         casts.arg("drop").asLogicalVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
index aa56519590..5376735712 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.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
@@ -57,6 +57,10 @@ public abstract class Tilde extends RBuiltinNode {
 
     @Child private SetClassAttributeNode setClassAttrNode = SetClassAttributeNode.create();
 
+    static {
+        Casts.noCasts(Tilde.class);
+    }
+
     @Override
     public Object[] getDefaultParameterValues() {
         return new Object[]{RMissing.instance, RMissing.instance};
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
index b34a10d621..8723f67b6f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode;
 import com.oracle.truffle.r.nodes.unary.CastListNode;
@@ -124,8 +123,8 @@ public abstract class UpdateField extends RBuiltinNode {
 
     private final ConditionProfile coerceList = ConditionProfile.createBinaryProfile();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(UpdateField.class);
         casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT).mustBe(stringValue()).asStringVector().findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index 1488822ff5..432d1c31a5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.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
@@ -165,6 +165,10 @@ public abstract class UpdateSubscript extends RBuiltinNode {
 
     private final ConditionProfile argsLengthLargerThanOneProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(UpdateSubscript.class);
+    }
+
     public static RNode special(ArgumentsSignature signature, RNode[] args, boolean inReplacement) {
         if (SpecialsUtils.isCorrectUpdateSignature(signature) && (args.length == 3 || args.length == 4)) {
             ProfiledValue vector = profile(args[0]);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
index 4e9fd8094a..30ad8a85fc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.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
@@ -54,6 +54,10 @@ public abstract class UpdateSubset extends RBuiltinNode {
     @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSET, false);
     private final ConditionProfile argsLengthLargerThanOneProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(UpdateSubset.class);
+    }
+
     public static RNode special(ArgumentsSignature signature, RNode[] args, boolean inReplacement) {
         if (SpecialsUtils.isCorrectUpdateSignature(signature) && (args.length == 3 || args.length == 4)) {
             ProfiledValue vector = profile(args[0]);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
index a045122de6..ad08dd85ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -40,8 +39,8 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 public abstract class SystemFunction extends RBuiltinNode {
     @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(SystemFunction.class);
         casts.arg("command").mustBe(stringValue(), RError.Message.SYSTEM_CHAR_ARG).asStringVector().findFirst();
         casts.arg("intern").asLogicalVector().findFirst().notNA(RError.Message.SYSTEM_INTERN_NOT_NA).map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index de95794b29..808039cbf1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -37,7 +37,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RChannel;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
@@ -62,25 +62,25 @@ public class FastRContext {
 
     private static final String[] EMPTY = new String[0];
 
-    private static final class Casts {
-        private static void exprs(CastBuilder casts) {
+    private static final class CastsHelper {
+        private static void exprs(Casts casts) {
             casts.arg("exprs").asStringVector().mustBe(notEmpty());
         }
 
-        private static void kind(CastBuilder casts) {
+        private static void kind(Casts casts) {
             casts.arg("kind").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().notNA().mustBe(
                             equalTo(RContext.ContextKind.SHARE_NOTHING.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RW.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RO.name()))));
         }
 
-        private static void pc(CastBuilder casts) {
+        private static void pc(Casts casts) {
             casts.arg("pc").asIntegerVector().findFirst().notNA().mustBe(gt(0));
         }
 
-        private static void key(CastBuilder casts) {
+        private static void key(Casts casts) {
             casts.arg("key").asIntegerVector().mustBe(notEmpty()).findFirst();
         }
 
-        private static void id(CastBuilder casts) {
+        private static void id(Casts casts) {
             casts.arg("id").asIntegerVector().mustBe(notEmpty()).findFirst();
         }
     }
@@ -107,11 +107,11 @@ public class FastRContext {
             return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.exprs(casts);
-            Casts.pc(casts);
-            Casts.kind(casts);
+        static {
+            Casts casts = new Casts(Spawn.class);
+            CastsHelper.exprs(casts);
+            CastsHelper.pc(casts);
+            CastsHelper.kind(casts);
         }
 
         @Specialization
@@ -134,8 +134,9 @@ public class FastRContext {
 
     @RBuiltin(name = ".fastr.context.join", visibility = OFF, kind = PRIMITIVE, parameterNames = {"handle"}, behavior = COMPLEX)
     public abstract static class Join extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(Join.class);
             casts.arg("handle").asIntegerVector().mustBe(notEmpty());
         }
 
@@ -178,11 +179,11 @@ public class FastRContext {
             return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.exprs(casts);
-            Casts.pc(casts);
-            Casts.kind(casts);
+        static {
+            Casts casts = new Casts(Eval.class);
+            CastsHelper.exprs(casts);
+            CastsHelper.pc(casts);
+            CastsHelper.kind(casts);
         }
 
         @Specialization
@@ -229,8 +230,8 @@ public class FastRContext {
             return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_FALSE};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(R.class);
             casts.arg("args").allowMissing().mustBe(stringValue());
             casts.arg("env").allowMissing().mustBe(stringValue());
             casts.arg("intern").asLogicalVector().findFirst().map(toBoolean());
@@ -265,8 +266,8 @@ public class FastRContext {
             return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_FALSE};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Rscript.class);
             casts.arg("args").mustBe(stringValue(), RError.Message.GENERIC, "usage: /path/to/Rscript [--options] [-e expr [-e expr2 ...] | file] [args]").asStringVector();
             casts.arg("env").allowMissing().mustBe(stringValue());
             casts.arg("intern").asLogicalVector().findFirst().map(toBoolean());
@@ -299,9 +300,9 @@ public class FastRContext {
     @RBuiltin(name = ".fastr.channel.create", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX)
     public abstract static class CreateChannel extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.key(casts);
+        static {
+            Casts casts = new Casts(CreateChannel.class);
+            CastsHelper.key(casts);
         }
 
         @Specialization
@@ -313,9 +314,10 @@ public class FastRContext {
 
     @RBuiltin(name = ".fastr.channel.get", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX)
     public abstract static class GetChannel extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.key(casts);
+
+        static {
+            Casts casts = new Casts(GetChannel.class);
+            CastsHelper.key(casts);
         }
 
         @Specialization
@@ -327,9 +329,10 @@ public class FastRContext {
 
     @RBuiltin(name = ".fastr.channel.close", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX)
     public abstract static class CloseChannel extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.id(casts);
+
+        static {
+            Casts casts = new Casts(CloseChannel.class);
+            CastsHelper.id(casts);
         }
 
         @Specialization
@@ -342,9 +345,10 @@ public class FastRContext {
 
     @RBuiltin(name = ".fastr.channel.send", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id", "data"}, behavior = COMPLEX)
     public abstract static class ChannelSend extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.id(casts);
+
+        static {
+            Casts casts = new Casts(ChannelSend.class);
+            CastsHelper.id(casts);
         }
 
         @Specialization
@@ -357,9 +361,10 @@ public class FastRContext {
 
     @RBuiltin(name = ".fastr.channel.receive", kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX)
     public abstract static class ChannelReceive extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.id(casts);
+
+        static {
+            Casts casts = new Casts(ChannelReceive.class);
+            CastsHelper.id(casts);
         }
 
         @Specialization
@@ -371,9 +376,10 @@ public class FastRContext {
 
     @RBuiltin(name = ".fastr.channel.poll", kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX)
     public abstract static class ChannelPoll extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.id(casts);
+
+        static {
+            Casts casts = new Casts(ChannelPoll.class);
+            CastsHelper.id(casts);
         }
 
         @Specialization
@@ -385,8 +391,9 @@ public class FastRContext {
 
     @RBuiltin(name = ".fastr.channel.select", kind = PRIMITIVE, parameterNames = {"ids"}, behavior = COMPLEX)
     public abstract static class ChannelSelect extends RBuiltinNode {
-        @Override
-        protected void createCasts(CastBuilder casts) {
+
+        static {
+            Casts casts = new Casts(ChannelSelect.class);
             casts.arg("ids").mustBe(instanceOf(RList.class));
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
index e867b73ba1..6dd3870946 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -38,8 +37,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = ".fastr.debug", visibility = OFF, kind = PRIMITIVE, parameterNames = {"values"}, behavior = COMPLEX)
 public abstract class FastRDebug extends RBuiltinNode {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(FastRDebug.class);
         casts.arg("values").asStringVector();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java
index cb129360b7..5b76a6ac96 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -33,6 +33,10 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 @RBuiltin(name = ".fastr.identity", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX)
 public abstract class FastRIdentity extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(FastRIdentity.class);
+    }
+
     @Specialization
     @TruffleBoundary
     protected int typeof(Object x) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index 46df0267cc..d2cd4888e2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -48,7 +48,6 @@ import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.Source.Builder;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -66,8 +65,8 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.eval", visibility = OFF, kind = PRIMITIVE, parameterNames = {"mimeType", "source"}, behavior = COMPLEX)
     public abstract static class Eval extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Eval.class);
             casts.arg("mimeType").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
             casts.arg("source").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
         }
@@ -106,8 +105,8 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.evalFile", visibility = OFF, kind = PRIMITIVE, parameterNames = {"path", "mimeType"}, behavior = COMPLEX)
     public abstract static class EvalFile extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(EvalFile.class);
             casts.arg("path").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
             casts.arg("mimeType").allowMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
         }
@@ -146,8 +145,8 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.export", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "value"}, behavior = COMPLEX)
     public abstract static class Export extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Export.class);
             casts.arg("name").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
             casts.arg("value").boxPrimitive();
         }
@@ -178,8 +177,8 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.import", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX)
     public abstract static class Import extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(Import.class);
             casts.arg("name").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
         }
 
@@ -199,6 +198,10 @@ public class FastRInterop {
 
         @Child private Node node = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode();
 
+        static {
+            Casts.noCasts(HasSize.class);
+        }
+
         @Specialization
         public byte hasSize(VirtualFrame frame, TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendHasSize(node, frame, obj));
@@ -210,6 +213,10 @@ public class FastRInterop {
 
         @Child private Node node = com.oracle.truffle.api.interop.Message.IS_NULL.createNode();
 
+        static {
+            Casts.noCasts(IsNull.class);
+        }
+
         @Specialization
         public byte hasSize(VirtualFrame frame, TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendIsNull(node, frame, obj));
@@ -221,6 +228,10 @@ public class FastRInterop {
 
         @Child private Node node = com.oracle.truffle.api.interop.Message.IS_EXECUTABLE.createNode();
 
+        static {
+            Casts.noCasts(IsExecutable.class);
+        }
+
         @Specialization
         public byte hasSize(VirtualFrame frame, TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendIsExecutable(node, frame, obj));
@@ -230,8 +241,8 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.toBoolean", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class ToBoolean extends RBuiltinNode {
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
+        static {
+            Casts casts = new Casts(ToBoolean.class);
             casts.arg("value").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(notLogicalNA()).map(Predef.toBoolean());
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
index d072a3ad76..0306c6dc7a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
@@ -37,7 +37,6 @@ import java.nio.file.Path;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
@@ -70,8 +69,8 @@ public abstract class FastRPkgSource extends RBuiltinNode {
         return new Object[]{RNull.instance, RRuntime.LOGICAL_FALSE};
     }
 
-    @Override
-    public void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(FastRPkgSource.class);
         casts.arg("pkgs").mustBe(stringValue());
         casts.arg("verbose").asLogicalVector().findFirst().notNA().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java
index 600608775c..a9e8cee05e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -39,6 +39,10 @@ import com.oracle.truffle.r.runtime.data.RShareable;
 @RBuiltin(name = ".fastr.refcountinfo", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX)
 public abstract class FastRRefCountInfo extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(FastRRefCountInfo.class);
+    }
+
     @Specialization
     protected int refcount(Object x) {
         if (x instanceof RShareable) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
index fbc559dc1a..f2b4d2b4d5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
@@ -45,8 +44,8 @@ public abstract class FastRStackTrace extends RBuiltinNode {
         return new Object[]{RRuntime.LOGICAL_FALSE};
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(FastRStackTrace.class);
         casts.arg("print.frame.contents").asLogicalVector().findFirst().map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
index dc521a05ff..16abbd8f16 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -62,12 +62,12 @@ import com.oracle.truffle.tools.Profiler.Counter.TimeKind;
 
 public class FastRStats {
 
-    private static final class Casts {
-        private static void filename(CastBuilder casts) {
+    private static final class CastsHelper {
+        private static void filename(Casts casts) {
             casts.arg("filename").allowNull().mustBe(stringValue()).asStringVector();
         }
 
-        private static void append(CastBuilder casts) {
+        private static void append(Casts casts) {
             casts.arg("append").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean());
         }
     }
@@ -79,10 +79,10 @@ public class FastRStats {
             return new Object[]{"Rprofattr.out", RRuntime.LOGICAL_FALSE};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.filename(casts);
-            Casts.append(casts);
+        static {
+            Casts casts = new Casts(FastRProfAttr.class);
+            CastsHelper.filename(casts);
+            CastsHelper.append(casts);
         }
 
         @SuppressWarnings("unused")
@@ -164,10 +164,10 @@ public class FastRStats {
             return new Object[]{"Rproftypecounts.out", RRuntime.LOGICAL_FALSE};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.filename(casts);
-            Casts.append(casts);
+        static {
+            Casts casts = new Casts(FastRProfTypecounts.class);
+            CastsHelper.filename(casts);
+            CastsHelper.append(casts);
         }
 
         @SuppressWarnings("unused")
@@ -295,10 +295,10 @@ public class FastRStats {
             return new Object[]{"Rproffuncounts.out", RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, 0, RRuntime.LOGICAL_FALSE};
         }
 
-        @Override
-        protected void createCasts(CastBuilder casts) {
-            Casts.filename(casts);
-            Casts.append(casts);
+        static {
+            Casts casts = new Casts(FastRProfFuncounts.class);
+            CastsHelper.filename(casts);
+            CastsHelper.append(casts);
             casts.arg("timing").asLogicalVector().findFirst().notNA().map(toBoolean());
             casts.arg("threshold").asIntegerVector().findFirst().notNA();
             casts.arg("histograms").asLogicalVector().findFirst().notNA().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
index 580be8e81f..8817ee3bcf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeVisitor;
 import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags;
@@ -74,8 +73,8 @@ public abstract class FastRSyntaxTree extends RBuiltinNode {
         return new Object[]{RMissing.instance, "syntaxelement", RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE};
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(FastRSyntaxTree.class);
         casts.arg("func").mustBe(instanceOf(RFunction.class));
         casts.arg("visitMode").asStringVector().findFirst();
         casts.arg("printSource").asLogicalVector().findFirst().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
index c24b8abdd4..aa63c26945 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.JumpToTopLevelException;
 import com.oracle.truffle.r.runtime.RError;
@@ -38,8 +37,9 @@ import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = ".fastr.throw", kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX)
 public abstract class FastRThrowIt extends RBuiltinNode {
-    @Override
-    protected void createCasts(CastBuilder casts) {
+
+    static {
+        Casts casts = new Casts(FastRThrowIt.class);
         casts.arg("name").asStringVector().findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
index e2ead78ab4..96eec41e23 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
@@ -115,6 +115,10 @@ public class FastRTrace {
         @Child private CastLogicalNode castLogical;
         @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
+        static {
+            Casts.noCasts(Trace.class);
+        }
+
         @Specialization
         protected Object trace(VirtualFrame frame, Object whatObj, Object tracer, Object exit, Object at, Object printObj, Object signature, Object whereObj) {
             Object what = whatObj;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java
index 01682e5fbd..7071bb26a0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.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
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.NodeUtil;
 import com.oracle.truffle.api.nodes.RootNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -46,8 +45,8 @@ public abstract class FastRTree extends RBuiltinNode {
         return new Object[]{RMissing.instance, RRuntime.LOGICAL_FALSE};
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(FastRTree.class);
         casts.arg("func").mustBe(instanceOf(RFunction.class));
         casts.arg("verbose").asLogicalVector().findFirst().map(toBoolean());
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java
index 8ec98d89c9..45a57b1932 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java
@@ -44,6 +44,10 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 public abstract class FastRTry extends RBuiltinNode {
     @Child private RExplicitCallNode call = RExplicitCallNode.create();
 
+    static {
+        Casts.noCasts(FastRTry.class);
+    }
+
     @Specialization
     public Object tryFunc(VirtualFrame frame, RFunction func) {
         try {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
index af534f63f7..fb4cc5a0b3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
@@ -19,7 +19,6 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -43,8 +42,8 @@ public abstract class FastrDqrls extends RBuiltinNode {
     private static final String[] NAMES = new String[]{"qr", "coefficients", "residuals", "effects", "rank", "pivot", "qraux", "tol", "pivoted"};
     private static RStringVector namesVector = null;
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(FastrDqrls.class);
         casts.arg("x").asDoubleVector(true, true, true);
         casts.arg("n").asIntegerVector().findFirst();
         casts.arg("p").asIntegerVector().findFirst();
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/builtin/CastBuilderTest.java
index 531ad1205d..14bd470438 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/builtin/CastBuilderTest.java
@@ -28,6 +28,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asInteger;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
@@ -103,8 +104,11 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.REnvironment.NewEnv;
 
 /**
  * Tests the cast pipelines and also that the samples generation process matches the intended
@@ -121,6 +125,7 @@ public class CastBuilderTest {
     private static final boolean TEST_SAMPLING = false;
 
     private CastBuilder cb;
+    private CastNode castNode;
     private PreinitialPhaseBuilder arg;
 
     static {
@@ -135,6 +140,7 @@ public class CastBuilderTest {
     public void setUp() {
         cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
         arg = cb.arg("x");
+        castNode = null;
     }
 
     @After
@@ -488,6 +494,21 @@ public class CastBuilderTest {
         assertCastFail(RRuntime.INT_NA);
     }
 
+    @Test
+    public void testChain2() {
+        arg.
+        mapIf(instanceOf(RAbstractListVector.class),
+           chain(asVector()).
+              with(findFirst().objectElement()).
+              end()).mustBe(instanceOf(RList.class).or(instanceOf(REnvironment.class)));
+
+        RList l = RDataFactory.createList();
+        assertEquals(l, cast(RDataFactory.createList(new Object[]{l})));
+        NewEnv env = RDataFactory.createNewEnv("aaa");
+        assertEquals(env, cast(RDataFactory.createList(new Object[]{env})));
+        assertCastPreserves(env);
+    }
+
     public Function<InitialPhaseBuilder<Object>, InitialPhaseBuilder<Object>> nonListToBoolean() {
         return phaseBuilder -> phaseBuilder.
                         mapIf(instanceOf(RList.class).not(),
@@ -844,8 +865,7 @@ public class CastBuilderTest {
      * Casts given object using the configured pipeline in {@link #arg}.
      */
     private Object cast(Object a) {
-        CastNode argCastNode = cb.getCasts()[0];
-        NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(argCastNode, (node, args) -> node.execute(args[0]));
+        NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(getCastNode(), (node, args) -> node.execute(args[0]));
         return argCastNodeHandle.call(a);
     }
 
@@ -900,7 +920,7 @@ public class CastBuilderTest {
     }
 
     private TypeExpr resultTypes() {
-        CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cb.getCasts()[0]);
+        CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(getCastNode());
         return sampler.resultTypes();
     }
 
@@ -909,7 +929,7 @@ public class CastBuilderTest {
             return;
         }
 
-        CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cb.getCasts()[0]);
+        CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(getCastNode());
         Samples<?> samples = sampler.collectSamples();
         if (!emptyPositiveSamplesAllowed) {
             Assert.assertFalse(samples.positiveSamples().isEmpty());
@@ -917,6 +937,13 @@ public class CastBuilderTest {
         testPipeline(samples);
     }
 
+    private CastNode getCastNode() {
+        if (castNode == null) {
+            castNode = cb.getCasts()[0];
+        }
+        return castNode;
+    }
+
     private void testPipeline(Samples<?> samples) {
         if (!TEST_SAMPLING) {
             return;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
index c74cd58b07..11c58387f4 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
@@ -25,6 +25,8 @@ package com.oracle.truffle.r.nodes.test;
 import static junit.framework.TestCase.assertTrue;
 import static org.junit.Assert.assertEquals;
 
+import java.util.Optional;
+
 import org.junit.Test;
 
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter;
@@ -127,6 +129,6 @@ public class PipelineToCastNodeTests {
     private static CastNode createPipeline(PipelineStep<?, ?> lastStep) {
         PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x");
         configBuilder.setValueForwarding(false);
-        return PipelineToCastNode.convert(configBuilder.build(), lastStep);
+        return PipelineToCastNode.convert(configBuilder.build(), lastStep, Optional.empty());
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
index 62a2998e3d..e4b307888c 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
@@ -94,6 +94,13 @@ public class RBuiltinDiagnostics {
     }
 
     public static void main(String[] args) throws Throwable {
+        // TODO: Enable it when the diagnostics is rewritten using CP-IR
+        if (true) {
+            System.out.println("Temporarily disabled until the diagnostics is rewritten using CP-IR");
+            return;
+        }
+
+        @SuppressWarnings("unused")
         RBuiltinDiagnostics rbDiag = ChimneySweepingSuite.createChimneySweepingSuite(args).orElseGet(() -> createRBuiltinDiagnostics(args));
 
         List<String> bNames = Arrays.stream(args).filter(arg -> !arg.startsWith("-")).collect(Collectors.toList());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
index c1c544f750..cbf0003eec 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
@@ -29,7 +29,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.primitive.BinaryMapNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
@@ -67,8 +66,8 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
         this.unary = unaryFactory;
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(BinaryArithmeticNode.class);
         casts.arg(0).boxPrimitive();
         casts.arg(1).boxPrimitive();
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
index 1ce1356f4f..6983da07a4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.primitive.BinaryMapNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
@@ -67,8 +66,8 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         this.factory = factory;
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(BinaryBooleanNode.class);
         casts.arg(0).boxPrimitive();
         casts.arg(1).boxPrimitive();
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
index 742f104bcb..3026310ff2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
@@ -62,6 +62,10 @@ public abstract class BinaryBooleanScalarNode extends RBuiltinNode {
 
     private final BooleanOperation booleanLogic;
 
+    static {
+        Casts.noCasts(BinaryBooleanScalarNode.class);
+    }
+
     BinaryBooleanScalarNode(BooleanOperationFactory factory) {
         this.booleanLogic = factory.createOperation();
         logic = new BinaryMapBooleanFunctionNode(booleanLogic);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 8ad506b96d..4d4279b45d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -91,7 +91,6 @@ public final class CastBuilder {
     private final RBuiltin builtin;
     private final String[] argumentNames;
     private PipelineBuilder[] argumentBuilders;
-    private CastNode[] castsCache = null;
 
     public CastBuilder(RBuiltin builtin) {
         // Note: if we have the builtin metadata, we pre-allocate the arrays, builtinNode != null is
@@ -125,16 +124,14 @@ public final class CastBuilder {
      * casting, returns {@code null} as its cast node.
      */
     public CastNode[] getCasts() {
-        if (castsCache == null) {
-            castsCache = new CastNode[argumentBuilders.length];
-            for (int i = 0; i < argumentBuilders.length; i++) {
-                PipelineBuilder arg = argumentBuilders[i];
-                if (arg != null) {
-                    castsCache[i] = arg.buildNode();
-                }
+        CastNode[] castNodes = new CastNode[argumentBuilders.length];
+        for (int i = 0; i < argumentBuilders.length; i++) {
+            PipelineBuilder arg = argumentBuilders[i];
+            if (arg != null) {
+                castNodes[i] = arg.buildNode();
             }
         }
-        return castsCache;
+        return castNodes;
     }
 
     // ---------------------
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
new file mode 100644
index 0000000000..01a7e12b53
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.oracle.truffle.api.dsl.GeneratedBy;
+import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+
+public interface NodeWithArgumentCasts {
+
+    default Casts getCastHolder() {
+        Class<?> cls = Casts.getBuiltinClass(getClass());
+        Casts casts = Casts.forClass(cls);
+        assert casts != null || Casts.noCastsAllowed(getClass().getSuperclass()) : "No casts associated with builtin " + cls;
+        return casts == null ? Casts.empty : casts;
+    }
+
+    default CastNode[] getCasts() {
+        CastNode[] casts = getCastHolder().getCastNodes();
+        return casts;
+    }
+
+    class Casts {
+        private static final ConcurrentHashMap<Class<?>, Casts> castsMap = new ConcurrentHashMap<>();
+        private static final Casts empty = new Casts();
+
+        protected final CastBuilder casts;
+
+        private Casts() {
+            casts = new CastBuilder();
+        }
+
+        public Casts(Class<? extends NodeWithArgumentCasts> cls) {
+            casts = new CastBuilder(cls.getAnnotation(RBuiltin.class));
+            castsMap.put(cls, this);
+        }
+
+        public static void noCasts(Class<? extends NodeWithArgumentCasts> cls) {
+            castsMap.put(cls, new Casts(cls));
+        }
+
+        public static Casts forClass(Class<?> cls) {
+            return castsMap.get(cls);
+        }
+
+        public CastNode[] getCastNodes() {
+            return casts.getCasts();
+        }
+
+        public PreinitialPhaseBuilder arg(String argumentName) {
+            return casts.arg(argumentName);
+        }
+
+        public PreinitialPhaseBuilder arg(int argumentIndex, String argumentName) {
+            return casts.arg(argumentIndex, argumentName);
+        }
+
+        public PreinitialPhaseBuilder arg(int argumentIndex) {
+            return casts.arg(argumentIndex);
+        }
+
+        private static boolean noCastsAllowed(Class<?> cls) {
+            boolean res = RExternalBuiltinNode.Arg0.class.isAssignableFrom(cls) || UnaryArithmeticBuiltinNode.class.isAssignableFrom(cls) ||
+                            (RBuiltinNode.class.isAssignableFrom(cls) && hasNoArguments(cls));
+            return res;
+        }
+
+        private static boolean hasNoArguments(Class<?> cls) {
+            RBuiltin a = cls.getAnnotation(RBuiltin.class);
+            return a != null && a.parameterNames().length == 0;
+        }
+
+        private static Class<?> getBuiltinClass(Class<?> cls) {
+            if (cls.getAnnotation(GeneratedBy.class) != null) {
+                return cls.getSuperclass();
+            } else {
+                return cls;
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index 4449df431e..579352ce12 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.RCallNode;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
@@ -47,20 +46,10 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 
 @TypeSystemReference(RTypes.class)
-public abstract class RBuiltinNode extends RBaseNode {
+public abstract class RBuiltinNode extends RBaseNode implements NodeWithArgumentCasts {
 
     public abstract Object executeBuiltin(VirtualFrame frame, Object... args);
 
-    protected void createCasts(@SuppressWarnings("unused") CastBuilder casts) {
-        // nothing to do
-    }
-
-    public CastNode[] getCasts() {
-        CastBuilder builder = new CastBuilder(getRBuiltin());
-        createCasts(builder);
-        return builder.getCasts();
-    }
-
     /**
      * Return the default values of the builtin's formal arguments. This is only valid for builtins
      * of {@link RBuiltinKind kind} PRIMITIVE or SUBSTITUTE. Only simple scalar constants and
@@ -132,4 +121,5 @@ public abstract class RBuiltinNode extends RBaseNode {
     public String toString() {
         return (getRBuiltin() == null ? getClass().getSimpleName() : getRBuiltin().name());
     }
+
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
index 60c5f72e58..8f4ad0a026 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
@@ -48,7 +48,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @TypeSystemReference(RTypes.class)
-public abstract class RExternalBuiltinNode extends RBaseNode {
+public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWithArgumentCasts {
 
     public Object call(@SuppressWarnings("unused") VirtualFrame frame, RArgsValuesAndNames args) {
         return call(args);
@@ -56,16 +56,6 @@ public abstract class RExternalBuiltinNode extends RBaseNode {
 
     protected abstract Object call(RArgsValuesAndNames args);
 
-    protected void createCasts(@SuppressWarnings("unused") CastBuilder casts) {
-        // nothing to do
-    }
-
-    public CastNode[] getCasts() {
-        CastBuilder builder = new CastBuilder();
-        createCasts(builder);
-        return builder.getCasts();
-    }
-
     // TODO: these should be in the build nodes
     @Child private CastLogicalNode castLogical;
     @Child private CastIntegerNode castInt;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java
index 78914ee931..05e9185110 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInternalCodeBuiltinNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -48,6 +48,10 @@ public final class RInternalCodeBuiltinNode extends RExternalBuiltinNode {
     @Child private CallMatcherNode call = CallMatcherNode.create(true);
     @CompilationFinal private RFunction function;
 
+    static {
+        Casts.noCasts(RInternalCodeBuiltinNode.class);
+    }
+
     public RInternalCodeBuiltinNode(RContext context, String basePackage, Source code, String functionName) {
         this.context = context;
         this.basePackage = basePackage;
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 98cb9ac462..6d99e4f2ed 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts;
 
+import java.util.Optional;
 import java.util.function.Supplier;
 
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
@@ -63,7 +64,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.PipelineStepVisitor;
-import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardedValuesAnalyser;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult;
 import com.oracle.truffle.r.nodes.unary.BypassNode;
 import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassDoubleNodeGen;
@@ -113,11 +113,12 @@ public final class PipelineToCastNode {
         // nop: static class
     }
 
-    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep) {
-        return convert(config, firstStep, PipelineConfig.getFilterFactory(), PipelineConfig.getMapperFactory());
+    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep, Optional<ForwardingAnalysisResult> fwdAnalysisResult) {
+        return convert(config, firstStep, PipelineConfig.getFilterFactory(), PipelineConfig.getMapperFactory(), fwdAnalysisResult);
     }
 
-    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep, ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory) {
+    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep, ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory,
+                    Optional<ForwardingAnalysisResult> fwdAnalysisResult) {
         if (firstStep == null) {
             return BypassNode.create(config, null, mapperFactory, null);
         }
@@ -133,11 +134,9 @@ public final class PipelineToCastNode {
             return originalPipelineFactory.get();
         }
 
-        // TODO: the result of this analysis should be cached
-        ForwardedValuesAnalyser fwdAnalyser = new ForwardedValuesAnalyser();
-        ForwardingAnalysisResult fwdAnalytics = fwdAnalyser.analyse(firstStep);
-        if (fwdAnalytics.isAnythingForwarded()) {
-            return ValueForwardingNodeGen.create(fwdAnalytics, originalPipelineFactory);
+        ForwardingAnalysisResult fwdRes = fwdAnalysisResult.get();
+        if (fwdRes != null && fwdRes.isAnythingForwarded()) {
+            return ValueForwardingNodeGen.create(fwdRes, originalPipelineFactory);
         } else {
             return originalPipelineFactory.get();
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
index 2efd6be469..b660585cb2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
@@ -22,6 +22,10 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicReference;
+
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter;
 import com.oracle.truffle.r.nodes.builtin.casts.Mapper;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
@@ -35,6 +39,8 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep;
+import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardedValuesAnalyser;
+import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -50,13 +56,14 @@ public final class PipelineBuilder {
 
     private final PipelineConfigBuilder pcb;
     private ChainBuilder<?> chainBuilder;
+    private final AtomicReference<Optional<ForwardingAnalysisResult>> fwdAnalysisResult = new AtomicReference<>();
 
     public PipelineBuilder(String argumentName) {
         this.pcb = new PipelineConfigBuilder(argumentName);
     }
 
     public CastNode buildNode() {
-        return PipelineToCastNode.convert(pcb.build(), getFirstStep());
+        return PipelineToCastNode.convert(pcb.build(), getFirstStep(), getFwdAnalysisResult());
     }
 
     public PreinitialPhaseBuilder fluent() {
@@ -147,4 +154,24 @@ public final class PipelineBuilder {
             chainBuilder.addStep(step);
         }
     }
+
+    public Optional<ForwardingAnalysisResult> getFwdAnalysisResult() {
+        Optional<ForwardingAnalysisResult> res = fwdAnalysisResult.get();
+        if (res == null) {
+            ForwardedValuesAnalyser fwdAnalyser = new ForwardedValuesAnalyser();
+            PipelineStep<?, ?> firstStep = getFirstStep();
+            if (firstStep == null) {
+                res = Optional.empty();
+            } else {
+                res = Optional.of(fwdAnalyser.analyse(firstStep));
+            }
+            if (fwdAnalysisResult.compareAndSet(null, res)) {
+                return res;
+            } else {
+                return fwdAnalysisResult.get();
+            }
+        } else {
+            return res;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 2323cce098..427b9c1c60 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -803,7 +803,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                             arg = casts[i].execute(arg);
                         }
                     } else {
-                        assert casts.length <= i || casts[i] == null : "no casts allowed on non-evaluated arguments";
+                        assert casts.length <= i || casts[i] == null : "no casts allowed on non-evaluated arguments in builtin " + builtinDescriptor.getName();
                         if (arg instanceof RPromise || arg instanceof RMissing) {
                             if (!nonWrapSeen[i]) {
                                 CompilerDirectives.transferToInterpreterAndInvalidate();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java
index 1211e077b4..25920e4044 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java
@@ -14,7 +14,6 @@ package com.oracle.truffle.r.nodes.objects;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.builtin;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -22,8 +21,8 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 // transcribed from src/library/methods/src/utils.c
 public abstract class GetPrimName extends RExternalBuiltinNode.Arg1 {
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(GetPrimName.class);
         casts.arg(0).defaultError(RError.NO_CALLER, RError.Message.GENERIC, "'R_get_primname' called on a non-primitive").mustBe(builtin());
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
index 59f2ef25c1..44d51c9a1b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
@@ -20,7 +20,6 @@ import com.oracle.truffle.r.nodes.access.AccessSlotNode;
 import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.nodes.unary.DuplicateNode;
@@ -47,8 +46,8 @@ public abstract class NewObject extends RExternalBuiltinNode.Arg1 {
         castLogicalScalar = newCastBuilder().asLogicalVector().findFirst(RRuntime.LOGICAL_NA).buildCastNode();
     }
 
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    static {
+        Casts casts = new Casts(NewObject.class);
         // TODO: should we change the message to (incompatible) "Java level ..."?
         casts.arg(0).mustNotBeNull(RError.NO_CALLER, RError.Message.GENERIC, "C level NEW macro called with null class definition pointer");
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
index a1e52ad1f1..88d39a7818 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -55,6 +56,10 @@ public abstract class UnaryNotNode extends RBuiltinNode {
     private final NAProfile naProfile = NAProfile.create();
     private final ConditionProfile zeroLengthProfile = ConditionProfile.createBinaryProfile();
 
+    static {
+        Casts.noCasts(UnaryNotNode.class);
+    }
+
     private static byte not(byte value) {
         return (value == RRuntime.LOGICAL_TRUE ? RRuntime.LOGICAL_FALSE : RRuntime.LOGICAL_TRUE);
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
index d4f9f6d33c..730c1b5a77 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
@@ -140,6 +140,17 @@ public abstract class RBaseNode extends Node {
         Node current = this;
         while (current != null) {
             if (current instanceof RSyntaxNode && ((RSyntaxNode) current).isSyntax()) {
+                if (current instanceof RSyntaxCall) {
+                    RSyntaxCall call = (RSyntaxCall) current;
+                    if (call.getSyntaxArguments().length > 0 && call.getSyntaxLHS() instanceof RSyntaxLookup &&
+                                    ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier().equals(".Internal")) {
+                        // unwrap .Internal calls
+                        RSyntaxElement firstArg = call.getSyntaxArguments()[0];
+                        if (firstArg instanceof RSyntaxNode) {
+                            return (RSyntaxNode) firstArg;
+                        }
+                    }
+                }
                 return (RSyntaxNode) current;
             }
             current = current.getParent();
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java
index 95b6ce40cd..063819596e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -40,7 +40,7 @@ public class TestBuiltin_asfunction extends TestBase {
         assertEval("{ as.function(alist(\"foo\"))() }");
         assertEval("{ as.function(alist(7+42i))() }");
         assertEval("{ as.function(alist(as.raw(7)))() }");
-        assertEval(Output.IgnoreErrorContext, "{ .Internal(as.function.default(alist(a+b), \"foo\")) }");
+        assertEval("{ .Internal(as.function.default(alist(a+b), \"foo\")) }");
         assertEval(Output.IgnoreErrorContext, "{ .Internal(as.function.default(function() 42, parent.frame())) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
index 6ebebb950d..671161d6d8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
@@ -422,9 +422,9 @@ public class TestBuiltin_asvector extends TestBase {
         assertEval("as.vector(x~z)");
         assertEval("as.vector(file(''))");
 
-        assertEval(Output.IgnoreErrorContext, "{ as.vector(42, NULL) }");
-        assertEval(Output.IgnoreErrorContext, "{ as.vector(42, c(\"character\", \"character\")) }");
-        assertEval(Output.IgnoreErrorContext, "{ as.vector(42, character())  }");
+        assertEval("{ as.vector(42, NULL) }");
+        assertEval("{ as.vector(42, c(\"character\", \"character\")) }");
+        assertEval("{ as.vector(42, character())  }");
     }
 
     @Test
-- 
GitLab