Merge pull request #11881 from milseman/4_0_failable_view_init_message

[4.0][stdlib] Better message for unavailable String.init(_:UTF8Buffer)
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index 334714a..df94431 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -57,6 +57,8 @@
   ///         print(firstName)
   ///     }
   ///     // Prints "Marie"
+  @available(swift, deprecated: 3.2, message:
+    "Please use String or Substring directly")
   public struct CharacterView {
     @_versioned
     internal var _core: _StringCore
@@ -82,6 +84,8 @@
   }
 
   /// A view of the string's contents as a collection of characters.
+  @available(swift, deprecated: 3.2, message:
+    "Please use String or Substring directly")
   public var characters: CharacterView {
     get {
       return CharacterView(self)
diff --git a/stdlib/public/core/StringUTF8.swift b/stdlib/public/core/StringUTF8.swift
index cad601b..9554fc4 100644
--- a/stdlib/public/core/StringUTF8.swift
+++ b/stdlib/public/core/StringUTF8.swift
@@ -391,7 +391,10 @@
   /// slice of the `picnicGuest.utf8` view.
   ///
   /// - Parameter utf8: A UTF-8 code sequence.
-  @available(swift, deprecated: 3.2, obsoleted: 4.0)
+  @available(swift, deprecated: 3.2,
+    message: "Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)")
+  @available(swift, obsoleted: 4.0,
+    message: "Please use non-failable String.init(_:UTF8View) instead")
   public init?(_ utf8: UTF8View) {
     if utf8.startIndex._transcodedOffset != 0
     || utf8.endIndex._transcodedOffset != 0 {
@@ -420,7 +423,8 @@
   }
 
   /// Creates a string corresponding to the given sequence of UTF-8 code units.
-  @available(swift, introduced: 4.0)
+  @available(swift, introduced: 4.0, message:
+    "Please use failable String.init?(_:UTF8View) when in Swift 3.2 mode")
   public init(_ utf8: UTF8View) {
     self = String(utf8._core)
   }
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 0662c76..2858310 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -386,6 +386,10 @@
 %   View = ViewPrefix + 'View'
 %   RangeReplaceable = 'RangeReplaceable' if property == 'unicodeScalars' else ''
 extension Substring {
+  % if View == 'CharacterView':
+  @available(swift, deprecated: 3.2, message:
+    "Please use String or Substring directly")
+  % end
   public struct ${View} {
     var _slice: ${RangeReplaceable}BidirectionalSlice<String.${View}>
   }
@@ -424,6 +428,10 @@
 }
 
 extension Substring {
+  % if View == 'CharacterView':
+  @available(swift, deprecated: 3.2, message:
+    "Please use String or Substring directly")
+  % end
   public var ${property}: ${View} {
     get {
       return ${View}(_wholeString.${property}, _bounds: startIndex..<endIndex)
diff --git a/test/Constraints/generics.swift b/test/Constraints/generics.swift
index 2953770..5e66b16 100644
--- a/test/Constraints/generics.swift
+++ b/test/Constraints/generics.swift
@@ -418,7 +418,7 @@
     }
 }
 
-func rdar29633747(characters: String.CharacterView) {
+func rdar29633747(characters: String) {
   let _ = Array(characters).trimmed(["("])
 }
 
diff --git a/test/IDE/complete_at_top_level.swift b/test/IDE/complete_at_top_level.swift
index 5f7e792..263c3c1 100644
--- a/test/IDE/complete_at_top_level.swift
+++ b/test/IDE/complete_at_top_level.swift
@@ -421,7 +421,6 @@
 // rdar://21346928
 func optStr() -> String? { return nil }
 let x = (optStr() ?? "autoclosure").#^TOP_LEVEL_AUTOCLOSURE_1^#
-// AUTOCLOSURE_STRING: Decl[InstanceVar]/CurrNominal:      characters[#String.CharacterView#]
 // AUTOCLOSURE_STRING: Decl[InstanceVar]/CurrNominal:      unicodeScalars[#String.UnicodeScalarView#]
 // AUTOCLOSURE_STRING: Decl[InstanceVar]/CurrNominal:      utf16[#String.UTF16View#]
 
diff --git a/test/IDE/complete_literal.swift b/test/IDE/complete_literal.swift
index 9134e32..a5921e5 100644
--- a/test/IDE/complete_literal.swift
+++ b/test/IDE/complete_literal.swift
@@ -55,7 +55,6 @@
   return "Here's a string".#^LITERAL5^# // try .characters.count here
 }
 
-// LITERAL5-DAG:     Decl[InstanceVar]/CurrNominal:      characters[#String.CharacterView#]{{; name=.+$}}
 // LITERAL5-DAG:     Decl[InstanceVar]/CurrNominal:      endIndex[#String.Index#]{{; name=.+$}}
 // LITERAL5-DAG:     Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: reserveCapacity({#(n): Int#})[#Void#]{{; name=.+$}}
 // LITERAL5-DAG:     Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: append({#(c): Character#})[#Void#]{{; name=.+$}}
diff --git a/test/IDE/complete_value_expr.swift b/test/IDE/complete_value_expr.swift
index 18232bb..a98e05c 100644
--- a/test/IDE/complete_value_expr.swift
+++ b/test/IDE/complete_value_expr.swift
@@ -1730,7 +1730,6 @@
 
 // rdar://21346928
 // Just sample some String API to sanity check.
-// AUTOCLOSURE_STRING: Decl[InstanceVar]/CurrNominal:      characters[#String.CharacterView#]
 // AUTOCLOSURE_STRING: Decl[InstanceVar]/CurrNominal:      unicodeScalars[#String.UnicodeScalarView#]
 // AUTOCLOSURE_STRING: Decl[InstanceVar]/CurrNominal:      utf16[#String.UTF16View#]
 func testWithAutoClosure1(_ x: String?) {
diff --git a/test/SILOptimizer/definite_init_diagnostics.swift b/test/SILOptimizer/definite_init_diagnostics.swift
index 3f609b8..bf83d96 100644
--- a/test/SILOptimizer/definite_init_diagnostics.swift
+++ b/test/SILOptimizer/definite_init_diagnostics.swift
@@ -1127,7 +1127,7 @@
 
 // sr-184
 let x: String? // expected-note 2 {{constant defined here}}
-print(x?.characters.count as Any) // expected-error {{constant 'x' used before being initialized}}
+print(x?.count as Any) // expected-error {{constant 'x' used before being initialized}}
 print(x!) // expected-error {{constant 'x' used before being initialized}}
 
 
diff --git a/test/stdlib/Renames.swift b/test/stdlib/Renames.swift
index 81e1fef..d258ea4 100644
--- a/test/stdlib/Renames.swift
+++ b/test/stdlib/Renames.swift
@@ -503,7 +503,7 @@
   _ = s.joinWithSeparator(sep) // expected-error {{'joinWithSeparator' has been renamed to 'joined(separator:)'}} {{9-26=joined}} {{27-27=separator: }} {{none}}
 }
 
-func _StringCharacterView<S, C>(x: String.CharacterView, s: S, c: C, i: String.CharacterView.Index)
+func _StringCharacterView<S, C>(x: String, s: S, c: C, i: String.Index)
   where S : Sequence, S.Iterator.Element == Character, C : Collection, C.Iterator.Element == Character {
   var x = x
   x.replaceRange(i..<i, with: c) // expected-error {{'replaceRange(_:with:)' has been renamed to 'replaceSubrange'}} {{5-17=replaceSubrange}} {{none}}
diff --git a/test/stdlib/StringCompatibilityDiagnostics.swift b/test/stdlib/StringCompatibilityDiagnostics.swift
index e469d05..a26d6e0 100644
--- a/test/stdlib/StringCompatibilityDiagnostics.swift
+++ b/test/stdlib/StringCompatibilityDiagnostics.swift
@@ -3,12 +3,20 @@
 func testPopFirst() {
   var str = "abc"
   _ = str.popFirst() // expected-error{{'popFirst()' is unavailable: Please use 'first', 'dropFirst()', or 'Substring.popFirst()'}}
-  _ = str.characters.popFirst() // FIXME: deprecate CharacterView. This call currently gets paired with default popFirst from Collection :-(
+  _ = str.characters.popFirst() // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
   _ = str.unicodeScalars.popFirst() // expected-error{{'popFirst()' is unavailable: Please use 'first', 'dropFirst()', or 'Substring.UnicodeScalarView.popFirst()'}}
 
+  var charView: String.CharacterView // expected-warning{{'CharacterView' is deprecated: Please use String or Substring directly}}
+  charView = str.characters // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+  dump(charView)
+
   var substr = str[...]
   _ = substr.popFirst() // ok
-  _ = substr.characters.popFirst() // ok
+  _ = substr.characters.popFirst() // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
   _ = substr.unicodeScalars.popFirst() // ok
+
+  var charSubView: Substring.CharacterView // expected-warning{{'CharacterView' is deprecated: Please use String or Substring directly}}
+  charSubView = substr.characters // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+  dump(charSubView)
 }
 
diff --git a/test/stdlib/StringCompatibilityDiagnostics3.swift b/test/stdlib/StringCompatibilityDiagnostics3.swift
index 9f520a1..325b97f 100644
--- a/test/stdlib/StringCompatibilityDiagnostics3.swift
+++ b/test/stdlib/StringCompatibilityDiagnostics3.swift
@@ -3,15 +3,24 @@
 func testPopFirst() {
   var str = "abc"
   _ = str.popFirst() // expected-warning{{'popFirst()' is deprecated: Please use 'first', 'dropFirst()', or 'Substring.popFirst()'}}
-  _ = str.characters.popFirst() // expected-warning{{'popFirst()' is deprecated: Please use 'first', 'dropFirst()', or 'Substring.CharacterView.popFirst()'}}
-    // TODO: ^^^ deprecate the view, and update the warning here
+  _ = str.characters.popFirst() // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+    // expected-warning@-1{{'popFirst()' is deprecated: Please use 'first', 'dropFirst()', or 'Substring.CharacterView.popFirst()'}}
   _ = str.unicodeScalars.popFirst() // expected-warning{{'popFirst()' is deprecated: Please use 'first', 'dropFirst()', or 'Substring.UnicodeScalarView.popFirst()'}}
 
+  var charView: String.CharacterView // expected-warning{{'CharacterView' is deprecated: Please use String or Substring directly}}
+  charView = str.characters // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+  dump(charView)
+
   var substr = str[...]
   _ = substr.popFirst() // ok
-  _ = substr.characters.popFirst() // ok
+  _ = substr.characters.popFirst() // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
   _ = substr.unicodeScalars.popFirst() // ok
+
+  var charSubView: Substring.CharacterView // expected-warning{{'CharacterView' is deprecated: Please use String or Substring directly}}
+  charSubView = substr.characters // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+  dump(charSubView)
+
+  var _ = String(str.utf8) ?? "" // expected-warning{{'init' is deprecated: Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)}}
+  var _: String = String(str.utf8) // expected-error{{'init' is unavailable: Please use failable String.init?(_:UTF8View) when in Swift 3.2 mode}}
 }
 
-
-
diff --git a/test/stdlib/StringCompatibilityDiagnostics4.swift b/test/stdlib/StringCompatibilityDiagnostics4.swift
new file mode 100644
index 0000000..13cf2a9
--- /dev/null
+++ b/test/stdlib/StringCompatibilityDiagnostics4.swift
@@ -0,0 +1,29 @@
+// RUN: %swift -typecheck -swift-version 4 %s -verify
+
+func testPopFirst() {
+  var str = "abc"
+  _ = str.popFirst() // expected-error{{'popFirst()' is unavailable: Please use 'first', 'dropFirst()', or 'Substring.popFirst()'}}
+  _ = str.characters.popFirst() // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+  _ = str.popFirst() // expected-error{{'popFirst()' is unavailable: Please use 'first', 'dropFirst()', or 'Substring.popFirst()'}}
+  _ = str.unicodeScalars.popFirst() // expected-error{{'popFirst()' is unavailable: Please use 'first', 'dropFirst()', or 'Substring.UnicodeScalarView.popFirst()'}}
+
+  var charView: String.CharacterView // expected-warning{{'CharacterView' is deprecated: Please use String or Substring directly}}
+  charView = str.characters // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+  dump(charView)
+
+  var substr = str[...]
+  _ = substr.popFirst() // ok
+  _ = substr.characters.popFirst() // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+  _ = substr.unicodeScalars.popFirst() // ok
+
+  var charSubView: Substring.CharacterView // expected-warning{{'CharacterView' is deprecated: Please use String or Substring directly}}
+  charSubView = substr.characters // expected-warning{{'characters' is deprecated: Please use String or Substring directly}}
+  dump(charSubView)
+
+  var _ = String(str.utf8) ?? "" // expected-warning{{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}}
+  var _: String = String(str.utf8)! // expected-error{{'init' is unavailable: Please use non-failable String.init(_:UTF8View) instead}}
+  var _: String = String(str.utf8) // ok
+}
+
+
+
diff --git a/test/stdlib/StringDiagnostics.swift b/test/stdlib/StringDiagnostics.swift
index b5b2148..2712ee3 100644
--- a/test/stdlib/StringDiagnostics.swift
+++ b/test/stdlib/StringDiagnostics.swift
@@ -82,7 +82,7 @@
   acceptsBidirectionalCollection(s.unicodeScalars)
   acceptsRandomAccessCollection(s.unicodeScalars) // expected-error{{argument type 'String.UnicodeScalarView' does not conform to expected type 'RandomAccessCollection'}}
 
-  acceptsCollection(s.characters)
-  acceptsBidirectionalCollection(s.characters)
-  acceptsRandomAccessCollection(s.characters) // expected-error{{argument type 'String.CharacterView' does not conform to expected type 'RandomAccessCollection'}}
+  acceptsCollection(s)
+  acceptsBidirectionalCollection(s)
+  acceptsRandomAccessCollection(s) // expected-error{{argument type 'String' does not conform to expected type 'RandomAccessCollection'}}
 }
diff --git a/test/stdlib/StringDiagnostics_without_Foundation.swift b/test/stdlib/StringDiagnostics_without_Foundation.swift
index e2cd960..fa42189 100644
--- a/test/stdlib/StringDiagnostics_without_Foundation.swift
+++ b/test/stdlib/StringDiagnostics_without_Foundation.swift
@@ -19,9 +19,9 @@
   acceptsBidirectionalCollection(s.unicodeScalars)
   acceptsRandomAccessCollection(s.unicodeScalars) // expected-error{{argument type 'String.UnicodeScalarView' does not conform to expected type 'RandomAccessCollection'}}
 
-  acceptsCollection(s.characters)
-  acceptsBidirectionalCollection(s.characters)
-  acceptsRandomAccessCollection(s.characters) // expected-error{{argument type 'String.CharacterView' does not conform to expected type 'RandomAccessCollection'}}
+  acceptsCollection(s)
+  acceptsBidirectionalCollection(s)
+  acceptsRandomAccessCollection(s) // expected-error{{argument type 'String' does not conform to expected type 'RandomAccessCollection'}}
 }
 
 struct NotLosslessStringConvertible {}
diff --git a/test/stdlib/UnavailableStringAPIs.swift.gyb b/test/stdlib/UnavailableStringAPIs.swift.gyb
index 5b6e72b..361f835 100644
--- a/test/stdlib/UnavailableStringAPIs.swift.gyb
+++ b/test/stdlib/UnavailableStringAPIs.swift.gyb
@@ -49,7 +49,7 @@
   _ = s.distance(from: i, to: i) // OK
 }
 
-func test_CharacterView(s: String.CharacterView, i: String.CharacterView.Index, d: Int) {
+func test_CharacterView(s: String, i: String.Index, d: Int) {
   _ = s.index(after: i) // OK
   _ = s.index(before: i) // OK
   _ = s.index(i, offsetBy: d) // OK