summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorJuan Carlos <juancarlospaco@gmail.com>2021-01-15 23:56:38 -0300
committerGitHub <noreply@github.com>2021-01-15 18:56:38 -0800
commit78a99587a4ad8ad17a179a7992fcda8a6e10f25a (patch)
tree18a244e09f7db4636b3bd221130f36f5d5fb8b97 /lib/pure
parent7b632f9ccbd4d15fa9fe4ca45b6fea22b259c81d (diff)
downloadNim-78a99587a4ad8ad17a179a7992fcda8a6e10f25a.tar.gz
Deprecate TaintedString (#15423)
Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/asyncftpclient.nim18
-rw-r--r--lib/pure/cgi.nim8
-rw-r--r--lib/pure/includes/osenv.nim18
-rw-r--r--lib/pure/memfiles.nim12
-rw-r--r--lib/pure/net.nim8
-rw-r--r--lib/pure/os.nim18
-rw-r--r--lib/pure/osproc.nim14
-rw-r--r--lib/pure/parseopt.nim40
-rw-r--r--lib/pure/smtp.nim2
-rw-r--r--lib/pure/streams.nim78
-rw-r--r--lib/pure/streamwrapper.nim2
-rw-r--r--lib/pure/terminal.nim8
-rw-r--r--lib/pure/uri.nim4
13 files changed, 111 insertions, 119 deletions
diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim
index b538e10c9..5bf0c240d 100644
--- a/lib/pure/asyncftpclient.nim
+++ b/lib/pure/asyncftpclient.nim
@@ -134,9 +134,9 @@ type
 
 const multiLineLimit = 10000
 
-proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
+proc expectReply(ftp: AsyncFtpClient): Future[string] {.async.} =
   var line = await ftp.csock.recvLine()
-  result = TaintedString(line)
+  result = line
   var count = 0
   while line.len > 3 and line[3] == '-':
     ## Multi-line reply.
@@ -146,7 +146,7 @@ proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
     if count >= multiLineLimit:
       raise newException(ReplyError, "Reached maximum multi-line reply count.")
 
-proc send*(ftp: AsyncFtpClient, m: string): Future[TaintedString] {.async.} =
+proc send*(ftp: AsyncFtpClient, m: string): Future[string] {.async.} =
   ## Send a message to the server, and wait for a primary reply.
   ## ``\c\L`` is added for you.
   ##
@@ -158,9 +158,9 @@ proc send*(ftp: AsyncFtpClient, m: string): Future[TaintedString] {.async.} =
   await ftp.csock.send(m & "\c\L")
   return await ftp.expectReply()
 
-proc assertReply(received: TaintedString, expected: varargs[string]) =
+proc assertReply(received: string, expected: varargs[string]) =
   for i in items(expected):
-    if received.string.startsWith(i): return
+    if received.startsWith(i): return
   raise newException(ReplyError,
                      "Expected reply '$1' got: $2" %
                       [expected.join("' or '"), received.string])
@@ -169,7 +169,7 @@ proc pasv(ftp: AsyncFtpClient) {.async.} =
   ## Negotiate a data connection.
   ftp.dsock = newAsyncSocket()
 
-  var pasvMsg = (await ftp.send("PASV")).string.strip.TaintedString
+  var pasvMsg = (await ftp.send("PASV")).strip
   assertReply(pasvMsg, "227")
   var betweenParens = captureBetween(pasvMsg.string, '(', ')')
   var nums = betweenParens.split(',')
@@ -201,11 +201,11 @@ proc connect*(ftp: AsyncFtpClient) {.async.} =
   if ftp.pass != "":
     assertReply(await(ftp.send("PASS " & ftp.pass)), "230")
 
-proc pwd*(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
+proc pwd*(ftp: AsyncFtpClient): Future[string] {.async.} =
   ## Returns the current working directory.
   let wd = await ftp.send("PWD")
   assertReply wd, "257"
-  return wd.string.captureBetween('"').TaintedString # "
+  return wd.captureBetween('"') # "
 
 proc cd*(ftp: AsyncFtpClient, dir: string) {.async.} =
   ## Changes the current directory on the remote FTP server to ``dir``.
@@ -253,7 +253,7 @@ proc createDir*(ftp: AsyncFtpClient, dir: string, recursive = false){.async.} =
   if not recursive:
     assertReply(await(ftp.send("MKD " & dir.normalizePathSep)), "257")
   else:
-    var reply = TaintedString""
+    var reply = ""
     var previousDirs = ""
     for p in split(dir, {os.DirSep, os.AltSep}):
       if p != "":
diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim
index 3b8dad849..4810aea88 100644
--- a/lib/pure/cgi.nim
+++ b/lib/pure/cgi.nim
@@ -81,14 +81,14 @@ proc getEncodedData(allowedMethods: set[RequestMethod]): string =
     if methodNone notin allowedMethods:
       cgiError("'REQUEST_METHOD' must be 'POST' or 'GET'")
 
-iterator decodeData*(data: string): tuple[key, value: TaintedString] =
+iterator decodeData*(data: string): tuple[key, value: string] =
   ## Reads and decodes CGI data and yields the (name, value) pairs the
   ## data consists of.
   for (key, value) in uri.decodeQuery(data):
     yield (key, value)
 
 iterator decodeData*(allowedMethods: set[RequestMethod] =
-       {methodNone, methodPost, methodGet}): tuple[key, value: TaintedString] =
+       {methodNone, methodPost, methodGet}): tuple[key, value: string] =
   ## Reads and decodes CGI data and yields the (name, value) pairs the
   ## data consists of. If the client does not use a method listed in the
   ## `allowedMethods` set, a `CgiError` exception is raised.
@@ -301,10 +301,10 @@ proc setCookie*(name, value: string) =
 var
   gcookies {.threadvar.}: StringTableRef
 
-proc getCookie*(name: string): TaintedString =
+proc getCookie*(name: string): string =
   ## Gets a cookie. If no cookie of `name` exists, "" is returned.
   if gcookies == nil: gcookies = parseCookies(getHttpCookie())
-  result = TaintedString(gcookies.getOrDefault(name))
+  result = gcookies.getOrDefault(name)
 
 proc existsCookie*(name: string): bool =
   ## Checks if a cookie of `name` exists.
diff --git a/lib/pure/includes/osenv.nim b/lib/pure/includes/osenv.nim
index 55ace92f2..fef7de85b 100644
--- a/lib/pure/includes/osenv.nim
+++ b/lib/pure/includes/osenv.nim
@@ -4,7 +4,7 @@ when not declared(os) and not declared(ospaths):
   {.error: "This is an include file for os.nim!".}
 
 when defined(nodejs):
-  proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
+  proc getEnv*(key: string, default = ""): string {.tags: [ReadEnvEffect].} =
     var ret: cstring
     let key2 = key.cstring
     {.emit: "`ret` = process.env[`key2`];".}
@@ -25,7 +25,7 @@ when defined(nodejs):
     var key2 = key.cstring
     {.emit: "delete process.env[`key2`];".}
 
-  iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
+  iterator envPairs*(): tuple[key, value: string] {.tags: [ReadEnvEffect].} =
     var num: int
     var keys: RootObj
     {.emit: "`keys` = Object.keys(process.env); `num` = `keys`.length;".}
@@ -144,7 +144,7 @@ else:
         if startsWith(environment[i], temp): return i
     return -1
 
-  proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
+  proc getEnv*(key: string, default = ""): string {.tags: [ReadEnvEffect].} =
     ## Returns the value of the `environment variable`:idx: named `key`.
     ##
     ## If the variable does not exist, `""` is returned. To distinguish
@@ -165,11 +165,11 @@ else:
     else:
       var i = findEnvVar(key)
       if i >= 0:
-        return TaintedString(substr(environment[i], find(environment[i], '=')+1))
+        return substr(environment[i], find(environment[i], '=')+1)
       else:
         var env = c_getenv(key)
-        if env == nil: return TaintedString(default)
-        result = TaintedString($env)
+        if env == nil: return default
+        result = $env
 
   proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
     ## Checks whether the environment variable named `key` exists.
@@ -248,7 +248,7 @@ else:
           raiseOSError(osLastError())
       environment.delete(indx)
 
-  iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
+  iterator envPairs*(): tuple[key, value: string] {.tags: [ReadEnvEffect].} =
     ## Iterate over all `environments variables`:idx:.
     ##
     ## In the first component of the tuple is the name of the current variable stored,
@@ -262,5 +262,5 @@ else:
     getEnvVarsC()
     for i in 0..high(environment):
       var p = find(environment[i], '=')
-      yield (TaintedString(substr(environment[i], 0, p-1)),
-             TaintedString(substr(environment[i], p+1)))
+      yield (substr(environment[i], 0, p-1),
+             substr(environment[i], p+1))
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 5e6571e11..06eb2d6c2 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -428,17 +428,17 @@ iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline
     ms.data = cast[pointer](cast[int](ending) +% 1) # skip delim
     remaining = mfile.size - (ms.data -! mfile.mem)
 
-iterator lines*(mfile: MemFile, buf: var TaintedString, delim = '\l',
-    eat = '\r'): TaintedString {.inline.} =
+iterator lines*(mfile: MemFile, buf: var string, delim = '\l',
+    eat = '\r'): string {.inline.} =
   ## Replace contents of passed buffer with each new line, like
-  ## `readLine(File) <io.html#readLine,File,TaintedString>`_.
+  ## `readLine(File) <io.html#readLine,File,string>`_.
   ## `delim`, `eat`, and delimiting logic is exactly as for `memSlices
   ## <#memSlices.i,MemFile,char,char>`_, but Nim strings are returned.
   ##
   ## Example:
   ##
   ## .. code-block:: nim
-  ##   var buffer: TaintedString = ""
+  ##   var buffer: string = ""
   ##   for line in lines(memfiles.open("foo"), buffer):
   ##     echo line
 
@@ -448,7 +448,7 @@ iterator lines*(mfile: MemFile, buf: var TaintedString, delim = '\l',
       copyMem(addr string(buf)[0], ms.data, ms.size)
     yield buf
 
-iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): TaintedString {.inline.} =
+iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): string {.inline.} =
   ## Return each line in a file as a Nim string, like
   ## `lines(File) <io.html#lines.i,File>`_.
   ## `delim`, `eat`, and delimiting logic is exactly as for `memSlices
@@ -460,7 +460,7 @@ iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): TaintedString {.inlin
   ##   for line in lines(memfiles.open("foo")):
   ##     echo line
 
-  var buf = TaintedString(newStringOfCap(80))
+  var buf = newStringOfCap(80)
   for line in lines(mfile, buf, delim, eat):
     yield buf
 
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 7b92a5e0d..057acb8fb 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -840,7 +840,7 @@ when defineSsl:
     if sidCtx.len > 32:
       raiseSSLError("sessionIdContext must be shorter than 32 characters")
     SSL_CTX_set_session_id_context(ctx.context, sidCtx, sidCtx.len)
-  
+
 proc getSocketError*(socket: Socket): OSErrorCode =
   ## Checks ``osLastError`` for a valid error. If it has been reset it uses
   ## the last error stored in the socket object.
@@ -1490,7 +1490,7 @@ proc peekChar(socket: Socket, c: var char): int {.tags: [ReadIOEffect].} =
         return
     result = recv(socket.fd, addr(c), 1, MSG_PEEK)
 
-proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
+proc readLine*(socket: Socket, line: var string, timeout = -1,
                flags = {SocketFlag.SafeDisconn}, maxLength = MaxLineLength) {.
   tags: [ReadIOEffect, TimeEffect].} =
   ## Reads a line of data from ``socket``.
@@ -1548,7 +1548,7 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
 
 proc recvLine*(socket: Socket, timeout = -1,
                flags = {SocketFlag.SafeDisconn},
-               maxLength = MaxLineLength): TaintedString =
+               maxLength = MaxLineLength): string =
   ## Reads a line of data from ``socket``.
   ##
   ## If a full line is read ``\r\L`` is not
@@ -1566,7 +1566,7 @@ proc recvLine*(socket: Socket, timeout = -1,
   ## that can be read. The result is truncated after that.
   ##
   ## **Warning**: Only the ``SafeDisconn`` flag is currently supported.
-  result = "".TaintedString
+  result = ""
   readLine(socket, result, timeout, flags, maxLength)
 
 proc recvFrom*(socket: Socket, data: var string, length: int,
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 77499deea..83e60cf77 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -2670,7 +2670,7 @@ when defined(nimdoc):
     ##   else:
     ##     # Do something else!
 
-  proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} =
+  proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
     ## Returns the `i`-th `command line argument`:idx: given to the application.
     ##
     ## `i` should be in the range `1..paramCount()`, the `IndexDefect`
@@ -2704,7 +2704,7 @@ when defined(nimdoc):
 
 elif defined(nimscript): discard
 elif defined(nintendoswitch) or weirdTarget:
-  proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} =
+  proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
     raise newException(OSError, "paramStr is not implemented on Nintendo Switch")
 
   proc paramCount*(): int {.tags: [ReadIOEffect].} =
@@ -2727,17 +2727,17 @@ elif defined(windows):
       ownParsedArgv = true
     result = ownArgv.len-1
 
-  proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1",
+  proc paramStr*(i: int): string {.rtl, extern: "nos$1",
     tags: [ReadIOEffect].} =
     # Docstring in nimdoc block.
     if not ownParsedArgv:
       ownArgv = parseCmdLine($getCommandLine())
       ownParsedArgv = true
-    if i < ownArgv.len and i >= 0: return TaintedString(ownArgv[i])
+    if i < ownArgv.len and i >= 0: return ownArgv[i]
     raise newException(IndexDefect, formatErrorIndexBound(i, ownArgv.len-1))
 
 elif defined(genode):
-  proc paramStr*(i: int): TaintedString =
+  proc paramStr*(i: int): string =
     raise newException(OSError, "paramStr is not implemented on Genode")
 
   proc paramCount*(): int =
@@ -2750,9 +2750,9 @@ elif not defined(createNimRtl) and
     cmdCount {.importc: "cmdCount".}: cint
     cmdLine {.importc: "cmdLine".}: cstringArray
 
-  proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} =
+  proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
     # Docstring in nimdoc block.
-    if i < cmdCount and i >= 0: return TaintedString($cmdLine[i])
+    if i < cmdCount and i >= 0: return $cmdLine[i]
     raise newException(IndexDefect, formatErrorIndexBound(i, cmdCount-1))
 
   proc paramCount*(): int {.tags: [ReadIOEffect].} =
@@ -2760,7 +2760,7 @@ elif not defined(createNimRtl) and
     result = cmdCount-1
 
 when declared(paramCount) or defined(nimdoc):
-  proc commandLineParams*(): seq[TaintedString] =
+  proc commandLineParams*(): seq[string] =
     ## Convenience proc which returns the command line parameters.
     ##
     ## This returns **only** the parameters. If you want to get the application
@@ -2789,7 +2789,7 @@ when declared(paramCount) or defined(nimdoc):
     for i in 1..paramCount():
       result.add(paramStr(i))
 else:
-  proc commandLineParams*(): seq[TaintedString] {.error:
+  proc commandLineParams*(): seq[string] {.error:
   "commandLineParams() unsupported by dynamic libraries".} =
     discard
 
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index bc447eb67..5f6dfb461 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -75,7 +75,7 @@ const poDemon* {.deprecated.} = poDaemon ## Nim versions before 0.20
 proc execProcess*(command: string, workingDir: string = "",
     args: openArray[string] = [], env: StringTableRef = nil,
     options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}):
-  TaintedString {.rtl, extern: "nosp$1",
+  string {.rtl, extern: "nosp$1",
                   tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
   ## A convenience procedure that executes ``command`` with ``startProcess``
   ## and returns its output as a string.
@@ -504,13 +504,13 @@ when not defined(useNimRtl):
       args: openArray[string] = [], env: StringTableRef = nil,
       options: set[ProcessOption] = {poStdErrToStdOut, poUsePath,
           poEvalCommand}):
-    TaintedString =
+    string =
 
     var p = startProcess(command, workingDir = workingDir, args = args,
         env = env, options = options)
     var outp = outputStream(p)
-    result = TaintedString""
-    var line = newStringOfCap(120).TaintedString
+    result = ""
+    var line = newStringOfCap(120)
     while true:
       # FIXME: converts CR-LF to LF.
       if outp.readLine(line):
@@ -1572,7 +1572,7 @@ elif not defined(useNimRtl):
 proc execCmdEx*(command: string, options: set[ProcessOption] = {
                 poStdErrToStdOut, poUsePath}, env: StringTableRef = nil,
                 workingDir = "", input = ""): tuple[
-                output: TaintedString,
+                output: string,
                 exitCode: int] {.tags:
                 [ExecIOEffect, ReadIOEffect, RootEffect], gcsafe.} =
   ## A convenience proc that runs the `command`, and returns its `output` and
@@ -1619,8 +1619,8 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
     inputStream(p).write(input)
   close inputStream(p)
 
-  result = (TaintedString"", -1)
-  var line = newStringOfCap(120).TaintedString
+  result = ("", -1)
+  var line = newStringOfCap(120)
   while true:
     if outp.readLine(line):
       result[0].string.add(line.string)
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index 94df5ea40..7916cebba 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -172,7 +172,7 @@ type
     cmds: seq[string]
     idx: int
     kind*: CmdLineKind           ## The detected command line token
-    key*, val*: TaintedString    ## Key and value pair; the key is the option
+    key*, val*: string           ## Key and value pair; the key is the option
                                  ## or the argument, and the value is not "" if
                                  ## the option was given a value
 
@@ -231,10 +231,10 @@ when declared(os.paramCount):
         result.cmds[i-1] = os.paramStr(i).string
 
     result.kind = cmdEnd
-    result.key = TaintedString""
-    result.val = TaintedString""
+    result.key = ""
+    result.val = ""
 
-  proc initOptParser*(cmdline: seq[TaintedString], shortNoVal: set[char] = {},
+  proc initOptParser*(cmdline: seq[string], shortNoVal: set[char] = {},
                       longNoVal: seq[string] = @[];
                       allowWhitespaceAfterColon = true): OptParser =
     ## Initializes the command line parser.
@@ -245,7 +245,7 @@ when declared(os.paramCount):
     ## <#initOptParser,string,set[char],seq[string]>`_.
     ##
     ## See also:
-    ## * `getopt iterator<#getopt.i,seq[TaintedString],set[char],seq[string]>`_
+    ## * `getopt iterator<#getopt.i,seq[string],set[char],seq[string]>`_
     runnableExamples:
       var p = initOptParser()
       p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"])
@@ -267,8 +267,8 @@ when declared(os.paramCount):
       for i in countup(1, os.paramCount()):
         result.cmds[i-1] = os.paramStr(i).string
     result.kind = cmdEnd
-    result.key = TaintedString""
-    result.val = TaintedString""
+    result.key = ""
+    result.val = ""
 
 proc handleShortOption(p: var OptParser; cmd: string) =
   var i = p.pos
@@ -286,7 +286,7 @@ proc handleShortOption(p: var OptParser; cmd: string) =
       inc(i)
     p.inShortState = false
     while i < cmd.len and cmd[i] in {'\t', ' '}: inc(i)
-    p.val = TaintedString substr(cmd, i)
+    p.val = substr(cmd, i)
     p.pos = 0
     inc p.idx
   else:
@@ -349,12 +349,12 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
           inc p.idx
           i = 0
         if p.idx < p.cmds.len:
-          p.val = TaintedString p.cmds[p.idx].substr(i)
+          p.val = p.cmds[p.idx].substr(i)
       elif len(p.longNoVal) > 0 and p.key.string notin p.longNoVal and p.idx+1 < p.cmds.len:
-        p.val = TaintedString p.cmds[p.idx+1]
+        p.val = p.cmds[p.idx+1]
         inc p.idx
       else:
-        p.val = TaintedString""
+        p.val = ""
       inc p.idx
       p.pos = 0
     else:
@@ -362,11 +362,11 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
       handleShortOption(p, p.cmds[p.idx])
   else:
     p.kind = cmdArgument
-    p.key = TaintedString p.cmds[p.idx]
+    p.key =  p.cmds[p.idx]
     inc p.idx
     p.pos = 0
 
-proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} =
+proc cmdLineRest*(p: OptParser): string {.rtl, extern: "npo$1".} =
   ## Retrieves the rest of the command line that has not been parsed yet.
   ##
   ## See also:
@@ -382,9 +382,9 @@ proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} =
   ##       break
   ##     else: continue
   ##   doAssert p.cmdLineRest == "foo.txt bar.txt"
-  result = p.cmds[p.idx .. ^1].quoteShellCommand.TaintedString
+  result = p.cmds[p.idx .. ^1].quoteShellCommand
 
-proc remainingArgs*(p: OptParser): seq[TaintedString] {.rtl, extern: "npo$1".} =
+proc remainingArgs*(p: OptParser): seq[string] {.rtl, extern: "npo$1".} =
   ## Retrieves a sequence of the arguments that have not been parsed yet.
   ##
   ## See also:
@@ -401,10 +401,10 @@ proc remainingArgs*(p: OptParser): seq[TaintedString] {.rtl, extern: "npo$1".} =
   ##     else: continue
   ##   doAssert p.remainingArgs == @["foo.txt", "bar.txt"]
   result = @[]
-  for i in p.idx..<p.cmds.len: result.add TaintedString(p.cmds[i])
+  for i in p.idx..<p.cmds.len: result.add p.cmds[i]
 
 iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
-    val: TaintedString] =
+    val: string] =
   ## Convenience iterator for iterating over the given
   ## `OptParser<#OptParser>`_.
   ##
@@ -443,9 +443,9 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
     yield (p.kind, p.key, p.val)
 
 when declared(initOptParser):
-  iterator getopt*(cmdline: seq[TaintedString] = commandLineParams(),
+  iterator getopt*(cmdline: seq[string] = commandLineParams(),
                    shortNoVal: set[char] = {}, longNoVal: seq[string] = @[]):
-             tuple[kind: CmdLineKind, key, val: TaintedString] =
+             tuple[kind: CmdLineKind, key, val: string] =
     ## Convenience iterator for iterating over command line arguments.
     ##
     ## This creates a new `OptParser<#OptParser>`_. If no command line
@@ -460,7 +460,7 @@ when declared(initOptParser):
     ## There is no need to check for ``cmdEnd`` while iterating.
     ##
     ## See also:
-    ## * `initOptParser proc<#initOptParser,seq[TaintedString],set[char],seq[string]>`_
+    ## * `initOptParser proc<#initOptParser,seq[string],set[char],seq[string]>`_
     ##
     ## **Examples:**
     ##
diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim
index 66d181d40..625c783c9 100644
--- a/lib/pure/smtp.nim
+++ b/lib/pure/smtp.nim
@@ -86,7 +86,7 @@ proc debugSend*(smtp: Smtp | AsyncSmtp, cmd: string) {.multisync.} =
     echo("C:" & cmd)
   await smtp.sock.send(cmd)
 
-proc debugRecv*(smtp: Smtp | AsyncSmtp): Future[TaintedString] {.multisync.} =
+proc debugRecv*(smtp: Smtp | AsyncSmtp): Future[string] {.multisync.} =
   ## Receives a line of data from the socket connected to the
   ## SMTP server.
   ##
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 62a074bd8..55a4e1b85 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -96,8 +96,6 @@
 
 import std/private/since
 
-const taintMode = compileOption("taintmode")
-
 proc newEIO(msg: string): owned(ref IOError) =
   new(result)
   result.msg = msg
@@ -124,7 +122,7 @@ type
     readDataStrImpl*: proc (s: Stream, buffer: var string, slice: Slice[int]): int
       {.nimcall, raises: [Defect, IOError, OSError], tags: [ReadIOEffect], gcsafe.}
 
-    readLineImpl*: proc(s: Stream, line: var TaintedString): bool
+    readLineImpl*: proc(s: Stream, line: var string): bool
       {.nimcall, raises: [Defect, IOError, OSError], tags: [ReadIOEffect], gcsafe.}
 
     readDataImpl*: proc (s: Stream, buffer: pointer, bufLen: int): int
@@ -216,7 +214,7 @@ proc getPosition*(s: Stream): int =
 
 proc readData*(s: Stream, buffer: pointer, bufLen: int): int =
   ## Low level proc that reads data into an untyped `buffer` of `bufLen` size.
-  ## 
+  ##
   ## **JS note:** `buffer` is treated as a ``ptr string`` and written to between
   ## ``0..<bufLen``.
   runnableExamples:
@@ -293,7 +291,7 @@ when (NimMajor, NimMinor) >= (1, 3) or not defined(js):
 proc peekData*(s: Stream, buffer: pointer, bufLen: int): int =
   ## Low level proc that reads data into an untyped `buffer` of `bufLen` size
   ## without moving stream position.
-  ## 
+  ##
   ## **JS note:** `buffer` is treated as a ``ptr string`` and written to between
   ## ``0..<bufLen``.
   runnableExamples:
@@ -309,7 +307,7 @@ proc peekData*(s: Stream, buffer: pointer, bufLen: int): int =
 proc writeData*(s: Stream, buffer: pointer, bufLen: int) =
   ## Low level proc that writes an untyped `buffer` of `bufLen` size
   ## to the stream `s`.
-  ## 
+  ##
   ## **JS note:** `buffer` is treated as a ``ptr string`` and read between
   ## ``0..<bufLen``.
   runnableExamples:
@@ -921,26 +919,20 @@ proc peekFloat64*(s: Stream): float64 =
 
   peek(s, result)
 
-template untaint(s: var TaintedString): var string =
-  when taintMode: # for VM, bug #12282
-    s.string
-  else:
-    s
-
-proc readStrPrivate(s: Stream, length: int, str: var TaintedString) =
-  if length > len(str): setLen(str.untaint, length)
+proc readStrPrivate(s: Stream, length: int, str: var string) =
+  if length > len(str): setLen(str, length)
   when defined(js):
     let L = readData(s, addr(str), length)
   else:
     let L = readData(s, cstring(str.string), length)
-  if L != len(str): setLen(str.untaint, L)
+  if L != len(str): setLen(str, L)
 
-proc readStr*(s: Stream, length: int, str: var TaintedString) {.since: (1, 3).} =
+proc readStr*(s: Stream, length: int, str: var string) {.since: (1, 3).} =
   ## Reads a string of length `length` from the stream `s`. Raises `IOError` if
   ## an error occurred.
   readStrPrivate(s, length, str)
 
-proc readStr*(s: Stream, length: int): TaintedString =
+proc readStr*(s: Stream, length: int): string =
   ## Reads a string of length `length` from the stream `s`. Raises `IOError` if
   ## an error occurred.
   runnableExamples:
@@ -950,23 +942,23 @@ proc readStr*(s: Stream, length: int): TaintedString =
     doAssert strm.readStr(2) == "e"
     doAssert strm.readStr(2) == ""
     strm.close()
-  result = newString(length).TaintedString
+  result = newString(length)
   readStrPrivate(s, length, result)
 
-proc peekStrPrivate(s: Stream, length: int, str: var TaintedString) =
-  if length > len(str): setLen(str.untaint, length)
+proc peekStrPrivate(s: Stream, length: int, str: var string) =
+  if length > len(str): setLen(str, length)
   when defined(js):
     let L = peekData(s, addr(str), length)
   else:
     let L = peekData(s, cstring(str.string), length)
-  if L != len(str): setLen(str.untaint, L)
+  if L != len(str): setLen(str, L)
 
-proc peekStr*(s: Stream, length: int, str: var TaintedString) {.since: (1, 3).} =
+proc peekStr*(s: Stream, length: int, str: var string) {.since: (1, 3).} =
   ## Peeks a string of length `length` from the stream `s`. Raises `IOError` if
   ## an error occurred.
   peekStrPrivate(s, length, str)
 
-proc peekStr*(s: Stream, length: int): TaintedString =
+proc peekStr*(s: Stream, length: int): string =
   ## Peeks a string of length `length` from the stream `s`. Raises `IOError` if
   ## an error occurred.
   runnableExamples:
@@ -977,10 +969,10 @@ proc peekStr*(s: Stream, length: int): TaintedString =
     doAssert strm.readStr(2) == "ab"
     doAssert strm.peekStr(2) == "cd"
     strm.close()
-  result = newString(length).TaintedString
+  result = newString(length)
   peekStrPrivate(s, length, result)
 
-proc readLine*(s: Stream, line: var TaintedString): bool =
+proc readLine*(s: Stream, line: var string): bool =
   ## Reads a line of text from the stream `s` into `line`. `line` must not be
   ## ``nil``! May throw an IO exception.
   ##
@@ -992,7 +984,7 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
   ## See also:
   ## * `readLine(Stream) proc <#readLine,Stream>`_
   ## * `peekLine(Stream) proc <#peekLine,Stream>`_
-  ## * `peekLine(Stream, TaintedString) proc <#peekLine,Stream,TaintedString>`_
+  ## * `peekLine(Stream, string) proc <#peekLine,Stream,string>`_
   runnableExamples:
     var strm = newStringStream("The first line\nthe second line\nthe third line")
     var line = ""
@@ -1010,7 +1002,7 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
     result = s.readLineImpl(s, line)
   else:
     # fallback
-    line.untaint.setLen(0)
+    line.setLen(0)
     while true:
       var c = readChar(s)
       if c == '\c':
@@ -1020,10 +1012,10 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
       elif c == '\0':
         if line.len > 0: break
         else: return false
-      line.untaint.add(c)
+      line.add(c)
     result = true
 
-proc peekLine*(s: Stream, line: var TaintedString): bool =
+proc peekLine*(s: Stream, line: var string): bool =
   ## Peeks a line of text from the stream `s` into `line`. `line` must not be
   ## ``nil``! May throw an IO exception.
   ##
@@ -1034,7 +1026,7 @@ proc peekLine*(s: Stream, line: var TaintedString): bool =
   ##
   ## See also:
   ## * `readLine(Stream) proc <#readLine,Stream>`_
-  ## * `readLine(Stream, TaintedString) proc <#readLine,Stream,TaintedString>`_
+  ## * `readLine(Stream, string) proc <#readLine,Stream,string>`_
   ## * `peekLine(Stream) proc <#peekLine,Stream>`_
   runnableExamples:
     var strm = newStringStream("The first line\nthe second line\nthe third line")
@@ -1054,15 +1046,15 @@ proc peekLine*(s: Stream, line: var TaintedString): bool =
   defer: setPosition(s, pos)
   result = readLine(s, line)
 
-proc readLine*(s: Stream): TaintedString =
+proc readLine*(s: Stream): string =
   ## Reads a line from a stream `s`. Raises `IOError` if an error occurred.
   ##
   ## **Note:** This is not very efficient.
   ##
   ## See also:
-  ## * `readLine(Stream, TaintedString) proc <#readLine,Stream,TaintedString>`_
+  ## * `readLine(Stream, string) proc <#readLine,Stream,string>`_
   ## * `peekLine(Stream) proc <#peekLine,Stream>`_
-  ## * `peekLine(Stream, TaintedString) proc <#peekLine,Stream,TaintedString>`_
+  ## * `peekLine(Stream, string) proc <#peekLine,Stream,string>`_
   runnableExamples:
     var strm = newStringStream("The first line\nthe second line\nthe third line")
     doAssert strm.readLine() == "The first line"
@@ -1071,7 +1063,7 @@ proc readLine*(s: Stream): TaintedString =
     doAssertRaises(IOError): discard strm.readLine()
     strm.close()
 
-  result = TaintedString""
+  result = ""
   if s.atEnd:
     raise newEIO("cannot read from stream")
   while true:
@@ -1082,17 +1074,17 @@ proc readLine*(s: Stream): TaintedString =
     if c == '\L' or c == '\0':
       break
     else:
-      result.untaint.add(c)
+      result.add(c)
 
-proc peekLine*(s: Stream): TaintedString =
+proc peekLine*(s: Stream): string =
   ## Peeks a line from a stream `s`. Raises `IOError` if an error occurred.
   ##
   ## **Note:** This is not very efficient.
   ##
   ## See also:
   ## * `readLine(Stream) proc <#readLine,Stream>`_
-  ## * `readLine(Stream, TaintedString) proc <#readLine,Stream,TaintedString>`_
-  ## * `peekLine(Stream, TaintedString) proc <#peekLine,Stream,TaintedString>`_
+  ## * `readLine(Stream, string) proc <#readLine,Stream,string>`_
+  ## * `peekLine(Stream, string) proc <#peekLine,Stream,string>`_
   runnableExamples:
     var strm = newStringStream("The first line\nthe second line\nthe third line")
     doAssert strm.peekLine() == "The first line"
@@ -1106,13 +1098,13 @@ proc peekLine*(s: Stream): TaintedString =
   defer: setPosition(s, pos)
   result = readLine(s)
 
-iterator lines*(s: Stream): TaintedString =
+iterator lines*(s: Stream): string =
   ## Iterates over every line in the stream.
   ## The iteration is based on ``readLine``.
   ##
   ## See also:
   ## * `readLine(Stream) proc <#readLine,Stream>`_
-  ## * `readLine(Stream, TaintedString) proc <#readLine,Stream,TaintedString>`_
+  ## * `readLine(Stream, string) proc <#readLine,Stream,string>`_
   runnableExamples:
     var strm = newStringStream("The first line\nthe second line\nthe third line")
     var lines: seq[string]
@@ -1121,7 +1113,7 @@ iterator lines*(s: Stream): TaintedString =
     doAssert lines == @["The first line", "the second line", "the third line"]
     strm.close()
 
-  var line: TaintedString
+  var line: string
   while s.readLine(line):
     yield line
 
@@ -1187,7 +1179,7 @@ when (NimMajor, NimMinor) < (1, 3) and defined(js):
       if readBytes < bufferSize:
         break
 
-else: # after 1.3 or JS not defined  
+else: # after 1.3 or JS not defined
   proc ssAtEnd(s: Stream): bool =
     var s = StringStream(s)
     return s.pos >= s.data.len
@@ -1333,7 +1325,7 @@ proc fsWriteData(s: Stream, buffer: pointer, bufLen: int) =
   if writeBuffer(FileStream(s).f, buffer, bufLen) != bufLen:
     raise newEIO("cannot write to stream")
 
-proc fsReadLine(s: Stream, line: var TaintedString): bool =
+proc fsReadLine(s: Stream, line: var string): bool =
   result = readLine(FileStream(s).f, line)
 
 proc newFileStream*(f: File): owned FileStream =
diff --git a/lib/pure/streamwrapper.nim b/lib/pure/streamwrapper.nim
index b99982f1b..24cccda0d 100644
--- a/lib/pure/streamwrapper.nim
+++ b/lib/pure/streamwrapper.nim
@@ -26,7 +26,7 @@ type
     baseReadLineImpl: typeof(StreamObj.readLineImpl)
     baseReadDataImpl: typeof(StreamObj.readDataImpl)
 
-proc posReadLine[T](s: Stream, line: var TaintedString): bool =
+proc posReadLine[T](s: Stream, line: var string): bool =
   var s = PipeOutStream[T](s)
   assert s.baseReadLineImpl != nil
 
diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim
index 3bda5b7aa..03c387d8e 100644
--- a/lib/pure/terminal.nim
+++ b/lib/pure/terminal.nim
@@ -771,7 +771,7 @@ proc getch*(): char =
 when defined(windows):
   from unicode import toUTF8, Rune, runeLenAt
 
-  proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
+  proc readPasswordFromStdin*(prompt: string, password: var string):
                               bool {.tags: [ReadIOEffect, WriteIOEffect].} =
     ## Reads a `password` from stdin without printing it. `password` must not
     ## be ``nil``! Returns ``false`` if the end of the file has been reached,
@@ -797,7 +797,7 @@ when defined(windows):
 else:
   import termios
 
-  proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
+  proc readPasswordFromStdin*(prompt: string, password: var string):
                             bool {.tags: [ReadIOEffect, WriteIOEffect].} =
     password.string.setLen(0)
     let fd = stdin.getFileHandle()
@@ -811,9 +811,9 @@ else:
     stdout.write "\n"
     discard fd.tcSetAttr(TCSADRAIN, old.addr)
 
-proc readPasswordFromStdin*(prompt = "password: "): TaintedString =
+proc readPasswordFromStdin*(prompt = "password: "): string =
   ## Reads a password from stdin without printing it.
-  result = TaintedString("")
+  result = ""
   discard readPasswordFromStdin(prompt, result)
 
 
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index c8ed28536..852965861 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -160,7 +160,7 @@ func encodeQuery*(query: openArray[(string, string)], usePlus = true,
       result.add('=')
       result.add(encodeUrl(val, usePlus))
 
-iterator decodeQuery*(data: string): tuple[key, value: TaintedString] =
+iterator decodeQuery*(data: string): tuple[key, value: string] =
   ## Reads and decodes query string `data` and yields the `(key, value)` pairs
   ## the data consists of. If compiled with `-d:nimLegacyParseQueryStrict`, an
   ## error is raised when there is an unencoded `=` character in a decoded
@@ -197,7 +197,7 @@ iterator decodeQuery*(data: string): tuple[key, value: TaintedString] =
         i = parseData(data, i, value, '=')
       else:
         i = parseData(data, i, value, '&')
-    yield (name.TaintedString, value.TaintedString)
+    yield (name, value)
     if i < data.len:
       when defined(nimLegacyParseQueryStrict):
         if data[i] != '&':