// RUN: %target-typecheck-verify-swift -enable-objc-interop

class B { 
  init() {} 
}
class D : B {
  override init() { super.init() }
}

var seven : Double = 7

var pair : (Int, Double) = (1, 2)

var closure : (Int, Int) -> Int = { $0 + $1 }

var d_as_b : B = D()
var b_as_d = B() as! D
var bad_b_as_d : D = B()  // expected-error{{cannot convert value of type 'B' to specified type 'D'}}

var d = D()
var b = B()

var d_as_b_2 : B = d 
var b_as_d_2 = b as! D

var b_is_d:Bool = B() is D
// FIXME: Poor diagnostic below.
var bad_d_is_b:Bool = D() is B // expected-warning{{always true}}

func base_class_archetype_casts<T : B>(_ t: T) {
  var _ : B = t
  _ = B() as! T
  var _ : T = B() // expected-error{{cannot convert value of type 'B' to specified type 'T'}}

  let b = B()

  _ = b as! T

  var _:Bool = B() is T
  var _:Bool = b is T
  var _:Bool = t is B // expected-warning{{always true}}

  _ = t as! D
}

protocol P1 { func p1() }
protocol P2 { func p2() }

struct S1 : P1 {
  func p1() {}
}
class C1 : P1 {
  func p1() {}
}
class D1 : C1 {}

struct S2 : P2 {
  func p2() {}
}

struct S3 {}

struct S12 : P1, P2 {
  func p1() {}
  func p2() {}
}

func protocol_archetype_casts<T : P1>(_ t: T, p1: P1, p2: P2, p12: P1 & P2) {
  // Coercions.
  var _ : P1 = t
  var _ : P2 = t // expected-error{{value of type 'T' does not conform to specified type 'P2'}}

  // Checked unconditional casts.
  _ = p1 as! T
  _ = p2 as! T
  _ = p12 as! T

  _ = t as! S1
  _ = t as! S12
  _ = t as! C1
  _ = t as! D1

  _ = t as! S2

  _ = S1() as! T
  _ = S12() as! T
  _ = C1() as! T
  _ = D1() as! T

  _ = S2() as! T

  // Type queries.
  var _:Bool = p1 is T
  var _:Bool = p2 is T
  var _:Bool = p12 is T

  var _:Bool = t is S1
  var _:Bool = t is S12
  var _:Bool = t is C1
  var _:Bool = t is D1

  var _:Bool = t is S2
}

func protocol_concrete_casts(_ p1: P1, p2: P2, p12: P1 & P2) {
  // Checked unconditional casts.
  _ = p1 as! S1
  _ = p1 as! C1
  _ = p1 as! D1
  _ = p1 as! S12

  _ = p1 as! P1 & P2

  _ = p2 as! S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}

  _ = p12 as! S1 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S1' always fails}}
  _ = p12 as! S2 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S2' always fails}}
  _ = p12 as! S12
  _ = p12 as! S3 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S3' always fails}}

  // Type queries.
  var _:Bool = p1 is S1
  var _:Bool = p1 is C1
  var _:Bool = p1 is D1
  var _:Bool = p1 is S12

  var _:Bool = p1 is P1 & P2

  var _:Bool = p2 is S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}

  var _:Bool = p12 is S1 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S1' always fails}}
  var _:Bool = p12 is S2 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S2' always fails}}
  var _:Bool = p12 is S12
  var _:Bool = p12 is S3 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S3' always fails}}
}

func conditional_cast(_ b: B) -> D? {
  return b as? D
}

@objc protocol ObjCProto1 {}
@objc protocol ObjCProto2 {}
protocol NonObjCProto : class {}

@objc class ObjCClass {}
class NonObjCClass {}

func objc_protocol_casts(_ op1: ObjCProto1, opn: NonObjCProto) {
  _ = ObjCClass() as! ObjCProto1
  _ = ObjCClass() as! ObjCProto2
  _ = ObjCClass() as! ObjCProto1 & ObjCProto2
  _ = ObjCClass() as! NonObjCProto
  _ = ObjCClass() as! ObjCProto1 & NonObjCProto

  _ = op1 as! ObjCProto1 & ObjCProto2
  _ = op1 as! ObjCProto2
  _ = op1 as! ObjCProto1 & NonObjCProto
  _ = opn as! ObjCProto1

  _ = NonObjCClass() as! ObjCProto1
}

func dynamic_lookup_cast(_ dl: AnyObject) {
  _ = dl as! ObjCProto1
  _ = dl as! ObjCProto2
  _ = dl as! ObjCProto1 & ObjCProto2
}

// Cast to subclass with generic parameter inference
class C2<T> : B { }
class C3<T> : C2<[T]> { 
  func f(_ x: T) { }
}
var c2i : C2<[Int]> = C3()
var c3iOpt = c2i as? C3
c3iOpt?.f(5)
var b1 = c2i is C3
var c2f: C2<Float>? = b as? C2
var c2f2: C2<[Float]>? = b as! C3


// <rdar://problem/15633178>
var f: (Float) -> Float = { $0 as Float }
var f2: (B) -> Bool = { $0 is D }

func metatype_casts<T, U>(_ b: B.Type, t:T.Type, u: U.Type) {
  _ = b is D.Type
  _ = T.self is U.Type
  _ = type(of: T.self) is U.Type.Type
  _ = type(of: b) is D.Type // expected-warning{{always fails}}
  _ = b is D.Type.Type // expected-warning{{always fails}}

}

// <rdar://problem/17017851>
func forcedDowncastToOptional(_ b: B) {
  var dOpt: D? = b as! D // expected-warning{{treating a forced downcast to 'D' as optional will never produce 'nil'}}
  // expected-note@-1{{use 'as?' to perform a conditional downcast to 'D'}}{{22-23=?}}
  // expected-note@-2{{add parentheses around the cast to silence this warning}}{{18-18=(}}{{25-25=)}}
  dOpt = b as! D // expected-warning{{treating a forced downcast to 'D' as optional will never produce 'nil'}}
  // expected-note@-1{{use 'as?' to perform a conditional downcast to 'D'}}{{14-15=?}}
  // expected-note@-2{{add parentheses around the cast to silence this warning}}{{10-10=(}}{{17-17=)}}
  dOpt = (b as! D)
  _ = dOpt
}

_ = b1 as Int    // expected-error {{cannot convert value of type 'Bool' to type 'Int' in coercion}}
_ = seven as Int // expected-error {{cannot convert value of type 'Double' to type 'Int' in coercion}}

func rdar29894174(v: B?) {
  let _ = [v].compactMap { $0 as? D }
}

// When re-typechecking a solution with an 'is' cast applied,
// we would fail to produce a diagnostic.
func process(p: Any?) {
  compare(p is String)
  // expected-error@-1 {{missing argument for parameter #2 in call}} {{22-22=, <#Bool#>}}
}

func compare<T>(_: T, _: T) {} // expected-note {{'compare' declared here}}
func compare<T>(_: T?, _: T?) {}

_ = nil? as? Int?? // expected-error {{'nil' requires a contextual type}}

func test_tuple_casts_no_warn() {
  struct Foo {}

  let arr: [(Any, Any)] = [(Foo(), Foo())]
  let tup: (Any, Any) = (Foo(), Foo())

  _ = arr as! [(Foo, Foo)] // Ok
  _ = tup as! (Foo, Foo) // Ok

  _ = arr as! [(Foo, Foo, Foo)] // Ok
  _ = tup as! (Foo, Foo, Foo) // expected-warning {{cast from '(Any, Any)' to unrelated type '(Foo, Foo, Foo)' always fails}}

  _ = arr as! [(a: Foo, Foo)] // Ok
  _ = tup as! (a: Foo, Foo) // Ok
}

infix operator ^^^
func ^^^ <T> (lhs: T?, rhs: @autoclosure () -> T) -> T { lhs! }
func ^^^ <T> (lhs: T?, rhs: @autoclosure () -> T?) -> T? { lhs! }

func ohno<T>(_ x: T) -> T? { nil }

// SR-12369: Make sure we don't drop the coercion constraint.
func test_coercions_with_overloaded_operator(str: String, optStr: String?, veryOptString: String????) {
  _ = (str ?? "") as String // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}}
  _ = (optStr ?? "") as String

  _ = (str ?? "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
  _ = (optStr ?? "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
  _ = (optStr ?? "") as Int? // expected-error {{'String' is not convertible to 'Int?'}}
  // expected-note@-1 {{did you mean to use 'as!' to force downcast?}} {{22-24=as!}}

  _ = (str ^^^ "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
  _ = (optStr ^^^ "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
  _ = (optStr ^^^ "") as Int? // expected-error {{'String' is not convertible to 'Int?'}}
  // expected-note@-1 {{did you mean to use 'as!' to force downcast?}} {{23-25=as!}}

  _ = ([] ?? []) as String // expected-error {{cannot convert value of type '[Any]' to type 'String' in coercion}}
  _ = ([""] ?? []) as [Int: Int] // expected-error {{cannot convert value of type '[String]' to type '[Int : Int]' in coercion}}
  _ = (["": ""] ?? [:]) as [Int] // expected-error {{cannot convert value of type '[String : String]' to type '[Int]' in coercion}}
  _ = (["": ""] ?? [:]) as Set<Int> // expected-error {{cannot convert value of type '[String : String]' to type 'Set<Int>' in coercion}}
  _ = (["": ""] ?? [:]) as Int? // expected-error {{cannot convert value of type '[String : String]' to type 'Int?' in coercion}}

  _ = ("" ?? "" ?? "") as String // expected-warning 2{{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}}
  _ = ((veryOptString ?? "") ?? "") as String??
  _ = ((((veryOptString ?? "") ?? "") ?? "") ?? "") as String

  _ = ("" ?? "" ?? "") as Float // expected-error {{cannot convert value of type 'String' to type 'Float' in coercion}}
  _ = ((veryOptString ?? "") ?? "") as [String] // expected-error {{cannot convert value of type 'String??' to type '[String]' in coercion}}
  _ = ((((veryOptString ?? "") ?? "") ?? "") ?? "") as [String] // expected-error {{cannot convert value of type 'String' to type '[String]' in coercion}}

  _ = ohno(ohno(ohno(str))) as String???
  _ = ohno(ohno(ohno(str))) as Int // expected-error {{cannot convert value of type 'String???' to type 'Int' in coercion}}
}

func id<T>(_ x: T) -> T { x }

func test_compatibility_coercions(_ arr: [Int], _ optArr: [Int]?, _ dict: [String: Int], _ set: Set<Int>) {
  // Successful coercions don't raise a warning.
  _ = arr as [Any]?
  _ = dict as [String: Int]?
  _ = set as Set<Int>

  // Don't fix the simple case where no type variable is introduced, that was
  // always disallowed.
  _ = arr as [String] // expected-error {{cannot convert value of type '[Int]' to type '[String]' in coercion}}
  // expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
  _ = dict as [String: String] // expected-error {{cannot convert value of type '[String : Int]' to type '[String : String]' in coercion}}
  // expected-note@-1 {{arguments to generic parameter 'Value' ('Int' and 'String') are expected to be equal}}
  _ = dict as [String: String]? // expected-error {{'[String : Int]' is not convertible to '[String : String]?'}}
  // expected-note@-1 {{did you mean to use 'as!' to force downcast?}} {{12-14=as!}}
  _ = (dict as [String: Int]?) as [String: Int] // expected-error {{value of optional type '[String : Int]?' must be unwrapped to a value of type '[String : Int]'}}
  // expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
  // expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
  _ = set as Set<String>  // expected-error {{cannot convert value of type 'Set<Int>' to type 'Set<String>' in coercion}}
   // expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}

  // Apply the compatibility logic when a type variable is introduced. It's
  // unfortunate that this means we'll temporarily accept code we didn't before,
  // but it at least means we shouldn't break compatibility with anything.
  _ = id(arr) as [String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}

  _ = (arr ?? []) as [String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
  // expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
  _ = (arr ?? [] ?? []) as [String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
  // expected-warning@-1 2{{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
  _ = (optArr ?? []) as [String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}

  // Allow the coercion to increase optionality.
  _ = (arr ?? []) as [String]? // expected-warning {{coercion from '[Int]' to '[String]?' may fail; use 'as?' or 'as!' instead}}
  // expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
  _ = (arr ?? []) as [String?]? // expected-warning {{coercion from '[Int]' to '[String?]?' may fail; use 'as?' or 'as!' instead}}
  // expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
  _ = (arr ?? []) as [String??]?? // expected-warning {{coercion from '[Int]' to '[String??]??' may fail; use 'as?' or 'as!' instead}}
  // expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
  _ = (dict ?? [:]) as [String: String?]? // expected-warning {{coercion from '[String : Int]' to '[String : String?]?' may fail; use 'as?' or 'as!' instead}}
  // expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[String : Int]', so the right side is never used}}
  _ = (set ?? []) as Set<String>?? // expected-warning {{coercion from 'Set<Int>' to 'Set<String>??' may fail; use 'as?' or 'as!' instead}}
  // expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type 'Set<Int>', so the right side is never used}}

  // Allow the coercion to decrease optionality.
  _ = ohno(ohno(ohno(arr))) as [String] // expected-warning {{coercion from '[Int]???' to '[String]' may fail; use 'as?' or 'as!' instead}}
  _ = ohno(ohno(ohno(arr))) as [Int] // expected-warning {{coercion from '[Int]???' to '[Int]' may fail; use 'as?' or 'as!' instead}}
  _ = ohno(ohno(ohno(Set<Int>()))) as Set<String> // expected-warning {{coercion from 'Set<Int>???' to 'Set<String>' may fail; use 'as?' or 'as!' instead}}
  _ = ohno(ohno(ohno(["": ""]))) as [Int: String] // expected-warning {{coercion from '[String : String]???' to '[Int : String]' may fail; use 'as?' or 'as!' instead}}
  _ = ohno(ohno(ohno(dict))) as [String: Int] // expected-warning {{coercion from '[String : Int]???' to '[String : Int]' may fail; use 'as?' or 'as!' instead}}

  // In this case the array literal can be inferred to be [String], so totally
  // valid.
  _ = ([] ?? []) as [String] // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[String]', so the right side is never used}}
  _ = (([] as Optional) ?? []) as [String]

  // The array can also be inferred to be [Any].
  _ = ([] ?? []) as Array // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[Any]', so the right side is never used}}
}

// SR-13088
protocol JSON { }
protocol JSONLeaf: JSON {}
extension Int: JSONLeaf { }
extension Array: JSON where Element: JSON { }

protocol SR13035Error: Error {}
class ChildError: SR13035Error {}

protocol AnyC {
  func foo()
}

protocol AnyEvent {}

protocol A {
  associatedtype C: AnyC
}

protocol EventA: A {
  associatedtype Event
}

typealias Container<Namespace>
  = (event: Namespace.Event, c: Namespace.C) where Namespace: EventA

enum ConcreteA: EventA {
  struct C: AnyC {
    func foo() {}
  }

  enum Event: AnyEvent {
    case test
  }
}

protocol ProtocolP1 {}
protocol ProtocolQ1 {}
typealias Composition = ProtocolP1 & ProtocolQ1

protocol ProtocolP {}
protocol ProtocolQ {}

class ConcreteP: ProtocolP {}
class ConcreteQ: ProtocolQ {}
class ConcretePQ: ProtocolP, ProtocolQ {}
class ConcreteCPQ: ConcreteP, ProtocolQ {}

class ConcreteP1: ProtocolP1 {}
class ConcretePQ1: ProtocolP1, ProtocolQ1 {}

class ConcretePPQ1: ProtocolP, ProtocolP1, ProtocolQ1 {}
class NotConforms {}
struct StructNotComforms {}
final class NotConformsFinal {}

func tests_SR13088_false_positive_always_fail_casts() {
  // SR-13081
  let x: JSON = [4] // [4]
  _ = x as? [Any] // Ok

  // SR-13035
  func SR13035<SomeError: SR13035Error>(_ child: Result<String, ChildError>, _: Result<String, SomeError>) {
    let _ = child as? Result<String, SomeError> // Ok
  }

  func SR13035_1<SomeError: SR13035Error, Child: ChildError>(_ child: Result<String, Child>, parent: Result<String, SomeError>) {
    _ = child as? Result<String, SomeError> // Ok
    _ = parent as? Result<String, Child> // OK
  }

  // SR-11434 and SR-12321
  func encodable(_ value: Encodable) {
    _ = value as! [String : Encodable] // Ok
    _ = value as? [String: Encodable] // Ok
  }   

  // SR-13025
  func coordinate(_ event: AnyEvent, from c: AnyC) {
    switch (event, c) {
    case let container as Container<ConcreteA>: // OK
      container.c.foo()
    default:
      break
    }
  }

  // SR-7187
  let a: [Any] = [String?.some("hello") as Any, String?.none as Any]
  let b: [AnyObject] = [String?.some("hello") as AnyObject, String?.none as AnyObject]

  _ = a is [String?] // Ok
  _ = a as? [String?] as Any // OK
  _ = b is [String?] // Ok
  _ = b as? [String?] as AnyObject // OK

  // SR-6192
  let items = [String]()
  let dict = [String: Any]()
  let set = Set<String>()

  _ = items is [Int] // Ok
  _ = items as? [Int] as Any // Ok
  _ = items as! [Int] // Ok

  _ = dict is [Int: Any] // Ok
  _ = dict as? [Int: Any] as Any // Ok
  _ = dict as! [Int: Any] as Any // Ok

  _ = set is Set<Int> // Ok
  _ = set as? Set<Int> as Any // Ok
  _ = set as! Set<Int> // Ok

}

// Protocol composition
func protocol_composition(_ c: ProtocolP & ProtocolQ, _ c1: ProtocolP & Composition) {
  _ = c as? ConcretePQ // Ok
  _ = c as? ConcreteCPQ // Ok
  _ = c as? ConcreteP // Ok
  _ = c as? NotConforms // Ok
  _ = c as? StructNotComforms // expected-warning {{cast from 'ProtocolP & ProtocolQ' to unrelated type 'StructNotComforms' always fails}}
  _ = c as? NotConformsFinal // expected-warning {{cast from 'ProtocolP & ProtocolQ' to unrelated type 'NotConformsFinal' always fails}}
  _ = c1 as? ConcreteP // Ok
  _ = c1 as? ConcreteP1 // OK
  _ = c1 as? ConcretePQ1 // OK
  _ = c1 as? ConcretePPQ1 // Ok
  _ = c1 as? NotConforms // Ok
  _ = c1 as? StructNotComforms // expected-warning {{cast from 'ProtocolP & Composition' (aka 'ProtocolP & ProtocolP1 & ProtocolQ1') to unrelated type 'StructNotComforms' always fails}}
  _ = c1 as? NotConformsFinal // expected-warning {{cast from 'ProtocolP & Composition' (aka 'ProtocolP & ProtocolP1 & ProtocolQ1') to unrelated type 'NotConformsFinal' always fails}}
}

// SR-13899
class SR13899_Base {}
class SR13899_Derived: SR13899_Base {}

protocol SR13899_P {}
class SR13899_A: SR13899_P {}

typealias DA = SR13899_Derived
typealias BA = SR13899_Base
typealias ClosureType = (SR13899_Derived) -> Void

let blockp = { (_: SR13899_A) in }
let block = { (_: SR13899_Base) in }
let derived = { (_: SR13899_Derived) in }

let blockalias =  { (_: BA) in  }
let derivedalias =  { (_: DA) in  }

let _ = block is ClosureType // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to 'ClosureType' (aka '(SR13899_Derived) -> ()') is not supported; 'is' test always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-17=as}}
let _ = blockalias is (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(SR13899_Base) -> ()') to '(SR13899_Derived) -> Void' is not supported; 'is' test always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{20-22=as}}
let _ = block is (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; 'is' test always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-17=as}}
let _ = block is (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; 'is' test always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-17=as}}

let _ = block as! ClosureType // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to 'ClosureType' (aka '(SR13899_Derived) -> ()') is not supported; cast always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}}
let _ = blockalias as! (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(SR13899_Base) -> ()') to '(SR13899_Derived) -> Void' is not supported; cast always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{20-23=as}}
let _ = block as! (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; cast always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}}
let _ = block as! (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; cast always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}}

let _ = block as? ClosureType // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to 'ClosureType' (aka '(SR13899_Derived) -> ()') is not supported; cast always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}}
let _ = blockalias as? (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(BA) -> ()' (aka '(SR13899_Base) -> ()') to '(SR13899_Derived) -> Void' is not supported; cast always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{20-23=as}}
let _ = block as? (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; cast always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}}
let _ = block as? (SR13899_Derived) -> Void // expected-warning{{runtime conversion from '(SR13899_Base) -> ()' to '(SR13899_Derived) -> Void' is not supported; cast always fails}}
// expected-note@-1 {{consider using 'as' coercion instead}} {{15-18=as}}


let _ = derived is (SR13899_Base) -> Void // expected-warning{{always fails}}
let _ = blockp is (SR13899_P) -> Void // expected-warning{{always fails}}

// Types are trivially equal.
let _ = block is (SR13899_Base) -> Void // expected-warning{{'is' test is always true}}
let _ = block is (SR13899_Base) throws -> Void // expected-warning{{'is' test is always true}}
let _ = derivedalias is (SR13899_Derived) -> Void // expected-warning{{'is' test is always true}}
let _ = derivedalias is (SR13899_Derived) throws -> Void // expected-warning{{'is' test is always true}}
let _ = derived is (SR13899_Derived) -> Void // expected-warning{{'is' test is always true}}
let _ = derived is (SR13899_Derived) throws -> Void // expected-warning{{'is' test is always true}}
let _ = blockp is (SR13899_A) -> Void //expected-warning{{'is' test is always true}}
let _ = blockp is (SR13899_A) throws -> Void //expected-warning{{'is' test is always true}}

protocol PP1 { }
protocol PP2: PP1 { }
extension Optional: PP1 where Wrapped == PP2 { }

nil is PP1 // expected-error {{'nil' requires a contextual type}}

// SR-15039
enum ChangeType<T> {
  case initial(T)
  case delta(previous: T, next: T)
  case unset

  var delta: (previous: T?, next: T)? { nil }
}

extension ChangeType where T == String? {
  var foo: String? { return self.delta?.previous as? String } // OK
  var bar: String? { self.delta?.next }
}

// SR-15038
protocol ExperimentDeserializable {
  static func deserializeExperiment(_ value: Any) -> Self?
}

extension String: ExperimentDeserializable {
  static func deserializeExperiment(_ value: Any) -> String? { value as? String }
}

extension Int: ExperimentDeserializable {
  static func deserializeExperiment(_ value: Any) -> Int? { value as? Int }
}

class Constant<T> {
  private init(getUnderlyingValue: @escaping () -> T) {
    print(getUnderlyingValue())
  }
}

struct Thing {
  let storage: [String: Any]
}

extension Constant where T: Sequence, T.Element: ExperimentDeserializable {
  static func foo<U>(thing: Thing, defaultValue: T) -> T where T == [U] {
    guard let array = thing.storage["foo"] as? [Any] else {
      fatalError()
    }

    let value = array.map(T.Element.deserializeExperiment) as? [T.Element] ?? defaultValue // OK
    return value
  }
}

// Array
func decodeStringOrInt<T: FixedWidthInteger>() -> [T] {
  let stringWrapped = [String]()
  if let values = stringWrapped.map({ $0.isEmpty ? 0 : T($0) }) as? [T] { // OK
    return values
  } else {
    fatalError()
  }
}

// Set 
func decodeStringOrIntSet<T: FixedWidthInteger>() -> Set<T> {
  let stringWrapped = [String]()
  if let values = Set(stringWrapped.map({ $0.isEmpty ? 0 : T($0) })) as? Set<T> { // OK
    return values
  } else {
    fatalError()
  }
}

// Dictionary
func decodeStringOrIntDictionary<T: FixedWidthInteger>() -> [Int: T] {
  let stringWrapped = [String]()
  if let values = Dictionary(uniqueKeysWithValues: stringWrapped.map({ $0.isEmpty ? (0, 0) : (0, T($0)) })) as? [Int: T] { // OK
    return values
  } else {
    fatalError()
  }
}


// SR-15281
struct SR15281_A { }
struct SR15281_B {
  init(a: SR15281_A) { }
}

struct SR15281_S {
  var a: SR15281_A? = SR15281_A()

  var b: SR15281_B {
    a.flatMap(SR15281_B.init(a:)) // expected-error{{cannot convert return expression of type 'SR15281_B?' to return type 'SR15281_B'}} {{34-34=!}}
  }

  var b1: SR15281_B {
    a.flatMap(SR15281_B.init(a:)) as! SR15281_B 
    // expected-warning@-1 {{forced cast from 'SR15281_B?' to 'SR15281_B' only unwraps optionals; did you mean to use '!'?}} {{34-34=!}} {{34-48=}}
  }
}

class SR15281_AC {}
class SR15281_BC {
  init(a: SR15281_AC) { }
}
class SR15281_CC: SR15281_BC {}

struct SR15281_SC {
  var a: SR15281_AC? = SR15281_AC()

  var b: SR15281_BC {
    a.flatMap(SR15281_BC.init(a:)) // expected-error{{cannot convert return expression of type 'SR15281_BC?' to return type 'SR15281_BC'}} {{35-35=!}}
  }

  var c: SR15281_BC {
    a.flatMap(SR15281_CC.init(a:)) // expected-error{{cannot convert return expression of type 'SR15281_CC?' to return type 'SR15281_BC'}} {{35-35=!}}
  }
}

// SR-15562
func test_SR_15562() {
  let foo: [Int: Int] = [:]
  let bar = [1, 2, 3, 4]

  for baz in bar {
    foo[baz] as! Int += 1 // expected-warning{{forced cast from 'Int?' to 'Int' only unwraps optionals; did you mean to use '!'?}}
    // expected-error@-1{{left side of mutating operator has immutable type 'Int'}}
  }
}
