[stdlib] Fix issue with UTF16 index(_:offsetBy:limitedBy) (#12469)

diff --git a/stdlib/public/core/StringUTF16.swift b/stdlib/public/core/StringUTF16.swift
index b848fe1..6db190d 100644
--- a/stdlib/public/core/StringUTF16.swift
+++ b/stdlib/public/core/StringUTF16.swift
@@ -167,7 +167,7 @@
     ) -> Index? {
       // FIXME: swift-3-indexing-model: range check i?
       let d = i.encodedOffset.distance(to: limit.encodedOffset)
-      if (d > 0) ? (d < n) : (d > n) {
+      if (d >= 0) ? (d < n) : (d > n) {
         return nil
       }
       return Index(encodedOffset: i.encodedOffset.advanced(by: n))
diff --git a/test/Interpreter/SDK/Foundation_test.swift b/test/Interpreter/SDK/Foundation_test.swift
index fbcb182..50dfc96 100644
--- a/test/Interpreter/SDK/Foundation_test.swift
+++ b/test/Interpreter/SDK/Foundation_test.swift
@@ -177,6 +177,14 @@
   let nsrFrom = NSRange(b..., in: s)
   expectEqual(nsrFrom.location,5)
   expectEqual(nsrFrom.length, 5)
+  
+  expectNil(Range(NSRange(location: 100, length: 0), in: s))
+  expectNil(Range(NSRange(location: 0, length: 100), in: s))
+  
+  let empty = ""
+  expectNil(Range(NSRange(location: 1, length: 0), in: empty))  
+  expectNil(Range(NSRange(location: 0, length: 1), in: empty))
+  expectNotNil(Range(NSRange(location: 0, length: 0), in: empty))
 
   // FIXME: enable once indices conform to RangeExpression
   // let nsrFull = NSRange(s.indices, in: s)
diff --git a/test/stdlib/StringTraps.swift b/test/stdlib/StringTraps.swift
index 8a0e74c..3f22129 100644
--- a/test/stdlib/StringTraps.swift
+++ b/test/stdlib/StringTraps.swift
@@ -18,7 +18,7 @@
     { _isFastAssertConfiguration() },
     reason: "this trap is not guaranteed to happen in -Ounchecked"))
   .code {
-  var s = "abc"
+  let s = "abc"
   var i = s.startIndex
   i = s.index(after: i)
   i = s.index(before: i)
@@ -31,7 +31,7 @@
     { _isFastAssertConfiguration() },
     reason: "this trap is not guaranteed to happen in -Ounchecked"))
   .code {
-  var s = "abc"
+  let s = "abc"
   var i = s.startIndex
   i = s.index(after: i)
   i = s.index(after: i)
@@ -45,13 +45,13 @@
     { _isFastAssertConfiguration() },
     reason: "this trap is not guaranteed to happen in -Ounchecked"))
   .code {
-  var s = "abc"
+  let s = "abc"
   var i = s.startIndex
   i = s.index(after: i)
   i = s.index(after: i)
   i = s.index(after: i)
   expectCrashLater()
-  s[i]
+  _ = s[i]
 }
 
 StringTraps.test("UTF8ViewEndIndexSuccessor")
@@ -59,7 +59,7 @@
     { _isFastAssertConfiguration() },
     reason: "this trap is not guaranteed to happen in -Ounchecked"))
   .code {
-  var s = "abc"
+  let s = "abc"
   var i = s.utf8.startIndex
   i = s.utf8.index(after: i)
   i = s.utf8.index(after: i)
@@ -73,13 +73,13 @@
     { _isFastAssertConfiguration() },
     reason: "this trap is not guaranteed to happen in -Ounchecked"))
   .code {
-  var s = "abc"
+  let s = "abc"
   var i = s.utf8.startIndex
   i = s.utf8.index(after: i)
   i = s.utf8.index(after: i)
   i = s.utf8.index(after: i)
   expectCrashLater()
-  s.utf8[i]
+  _ = s.utf8[i]
 }
 
 StringTraps.test("UTF16ViewSubscript/DecrementedStartIndex")
@@ -87,11 +87,11 @@
     { _isFastAssertConfiguration() },
     reason: "this trap is not guaranteed to happen in -Ounchecked"))
   .code {
-  var s = "abc"
+  let s = "abc"
   var i = s.utf16.startIndex
   expectCrashLater()
   i = s.utf16.index(before: i)
-  s.utf16[i]
+  _ = s.utf16[i]
 }
 
 StringTraps.test("UTF16ViewSubscript/endIndex")
@@ -105,7 +105,36 @@
   i = s.utf16.index(after: i)
   i = s.utf16.index(after: i)
   expectCrashLater()
-  s.utf16[i]
+  _ = s.utf16[i]
+}
+
+StringTraps.test("UTF16ViewIndex/offsetLimited")
+  .code {
+  let sa = "foo"
+  let u16a = sa.utf16
+  let s16 = sa + "🤦🏻‍♀️"
+  let u16 = s16.utf16
+
+  let iaBegin = u16a.index(sa.startIndex, offsetBy: 99, limitedBy: sa.endIndex)
+  expectNil(iaBegin)
+  let iaEnd = u16a.index(sa.endIndex, offsetBy: 99, limitedBy: sa.endIndex)
+  expectNil(iaEnd)
+  let i16Begin = u16.index(u16.startIndex, offsetBy: 99, limitedBy: u16.endIndex)
+  expectNil(i16Begin)
+  let i16End = u16.index(u16.startIndex, offsetBy: 99, limitedBy: u16.endIndex)
+  expectNil(i16End)
+}
+
+StringTraps.test("UTF16ViewIndex/offsetCrash")
+  .skip(.custom(
+    { _isFastAssertConfiguration() },
+    reason: "this trap is not guaranteed to happen in -Ounchecked"))
+  .code {
+  let s16 = "foo🤦🏻‍♀️"
+  let u16 = s16.utf16
+  expectCrashLater()
+  let i = u16.index(u16.startIndex, offsetBy: 99)
+  _ = s16.utf16[i]
 }
 
 runAllTests()