diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 2570aaab4f9..9eedb5e7b33 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -1584,8 +1584,10 @@ shouldOpenExistentialCallArgument( if (param->isVariadic()) return None; - // Look through an inout type on the formal type of the parameter. - auto formalParamTy = param->getInterfaceType()->getInOutObjectType(); + // Look through an inout and optional types on the formal type of the + // parameter. + auto formalParamTy = param->getInterfaceType()->getInOutObjectType() + ->lookThroughSingleOptionalType(); // If the argument is of an existential metatype, look through the // metatype on the parameter. @@ -1594,8 +1596,8 @@ shouldOpenExistentialCallArgument( paramTy = paramTy->getMetatypeInstanceType(); } - // Look through an inout type on the parameter. - paramTy = paramTy->getInOutObjectType(); + // Look through an inout and optional types on the parameter. + paramTy = paramTy->getInOutObjectType()->lookThroughSingleOptionalType(); // The parameter type must be a type variable. auto paramTypeVar = paramTy->getAs(); diff --git a/test/Constraints/opened_existentials.swift b/test/Constraints/opened_existentials.swift index 588524f0eeb..da64f77547d 100644 --- a/test/Constraints/opened_existentials.swift +++ b/test/Constraints/opened_existentials.swift @@ -161,6 +161,16 @@ func passesInOut(i: Int) { takesInOut(&p) } +func takesOptional(_ value: T?) { } +// expected-note@-1{{required by global function 'takesOptional' where 'T' = 'any P'}} + +func passesToOptional(p: any P, pOpt: (any P)?) { + takesOptional(p) // okay + takesOptional(pOpt) // expected-error{{type 'any P' cannot conform to 'P'}} + // expected-note@-1{{only concrete types such as structs, enums and classes can conform to protocols}} +} + + @available(SwiftStdlib 5.1, *) func testReturningOpaqueTypes(p: any P) { let q = p.getQ() diff --git a/test/Generics/existential_restrictions.swift b/test/Generics/existential_restrictions.swift index fd439be246d..ff08588a872 100644 --- a/test/Generics/existential_restrictions.swift +++ b/test/Generics/existential_restrictions.swift @@ -9,10 +9,7 @@ protocol CP : class { } } func fP(_ t: T?) { } -// expected-note@-1 {{required by global function 'fP' where 'T' = 'any P'}} -// expected-note@-2 {{required by global function 'fP' where 'T' = 'any OP & P'}} func fOP(_ t: T?) { } -// expected-note@-1 {{required by global function 'fOP' where 'T' = 'any OP & P'}} func fOPE(_ t: OP) { } func fSP(_ t: T?) { } func fAO(_ t: T?) { } @@ -23,7 +20,7 @@ func fAOE(_ t: AnyObject) { } func fT(_ t: T) { } func testPassExistential(_ p: P, op: OP, opp: OP & P, cp: CP, sp: SP, any: Any, ao: AnyObject) { - fP(p) // expected-error{{type 'any P' cannot conform to 'P'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}} + fP(p) fAO(p) // expected-error{{global function 'fAO' requires that 'any P' be a class type}} fAOE(p) // expected-error{{argument type 'any P' expected to be an instance of a class or class-constrained type}} fT(p) @@ -37,14 +34,14 @@ func testPassExistential(_ p: P, op: OP, opp: OP & P, cp: CP, sp: SP, any: Any, fAOE(cp) fT(cp) - fP(opp) // expected-error{{type 'any OP & P' cannot conform to 'P'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}} - fOP(opp) // expected-error{{type 'any OP & P' cannot conform to 'OP'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}} + fP(opp) + fOP(opp) fAO(opp) // expected-error{{global function 'fAO' requires that 'any OP & P' be a class type}} fAOE(opp) fT(opp) fOP(sp) - fSP(sp) // expected-error{{'any SP' cannot be used as a type conforming to protocol 'SP' because 'SP' has static requirements}} + fSP(sp) fAO(sp) fAOE(sp) fT(sp)