Skip to content

Commit 08ccfad

Browse files
committed
Sema: Handle the edge case of in-out metatype parameter in canOpenExistentialCallArgument
1 parent 9bad133 commit 08ccfad

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

lib/Sema/OpenedExistentials.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -649,10 +649,11 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
649649
if (param->isVariadic())
650650
return std::nullopt;
651651

652-
// Look through an inout and optional types on the formal type of the
653-
// parameter.
652+
// Look through an inout and an optional type on the parameter types.
654653
auto formalParamTy = param->getInterfaceType()->getInOutObjectType()
655654
->lookThroughSingleOptionalType();
655+
// Look through an inout and optional types on the parameter.
656+
paramTy = paramTy->getInOutObjectType()->lookThroughSingleOptionalType();
656657

657658
// If the argument is of an existential metatype, look through the
658659
// metatype on the parameter.
@@ -661,9 +662,6 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
661662
paramTy = paramTy->getMetatypeInstanceType();
662663
}
663664

664-
// Look through an inout and optional types on the parameter.
665-
paramTy = paramTy->getInOutObjectType()->lookThroughSingleOptionalType();
666-
667665
// The parameter type must be a type variable.
668666
auto paramTypeVar = paramTy->getAs<TypeVariableType>();
669667
if (!paramTypeVar)

test/Constraints/opened_existentials.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,3 +483,18 @@ do {
483483
// CHECK-NOT: open_existential_expr {{.*}} location={{.*}}:[[@LINE+1]]:{{[0-9]+}} range=
484484
nestedMetatypeCallee(t)
485485
}
486+
487+
do {
488+
protocol P {}
489+
490+
func foo<T: P>(_ m: inout T.Type) {}
491+
492+
// expected-note@+1 {{change 'let' to 'var' to make it mutable}}
493+
let rValueP: P.Type
494+
var lValueP: P.Type
495+
496+
// expected-error@+1 {{cannot pass immutable value as inout argument: 'rValueP' is a 'let' constant}}
497+
foo(&rValueP)
498+
// CHECK: open_existential_expr {{.*}} location={{.*}}:[[@LINE+1]]:{{[0-9]+}} range=
499+
foo(&lValueP)
500+
}

0 commit comments

Comments
 (0)