Skip to content

Commit 41b47f4

Browse files
committed
[Sema] Fix crash in CheckRedeclarationRequest for IUO mismatch check
Make sure we only check this if both declarations have parameter lists. While here, clean up the logic a bit such that we just iterate over the parameter lists. rdar://156874925
1 parent 3595fe4 commit 41b47f4

File tree

2 files changed

+40
-58
lines changed

2 files changed

+40
-58
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 30 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -873,65 +873,37 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current,
873873
continue;
874874
}
875875

876-
// Signatures are the same, but interface types are not. We must
877-
// have a type that we've massaged as part of signature
878-
// interface type generation.
879-
if (current->getInterfaceType()->isEqual(other->getInterfaceType())) {
880-
if (currentDC->isTypeContext() == other->getDeclContext()->isTypeContext()) {
881-
auto currFnTy = current->getInterfaceType()->getAs<AnyFunctionType>();
882-
auto otherFnTy = other->getInterfaceType()->getAs<AnyFunctionType>();
883-
if (currFnTy && otherFnTy && currentDC->isTypeContext()) {
884-
currFnTy = currFnTy->getResult()->getAs<AnyFunctionType>();
885-
otherFnTy = otherFnTy->getResult()->getAs<AnyFunctionType>();
886-
}
887-
888-
if (currFnTy && otherFnTy) {
889-
ArrayRef<AnyFunctionType::Param> currParams = currFnTy->getParams();
890-
ArrayRef<AnyFunctionType::Param> otherParams = otherFnTy->getParams();
891-
892-
if (currParams.size() == otherParams.size()) {
893-
auto diagnosed = false;
894-
for (unsigned i : indices(currParams)) {
895-
896-
bool currIsIUO = false;
897-
bool otherIsIUO = false;
898-
bool optionalRedecl = false;
899-
900-
if (currParams[i].getPlainType()->getOptionalObjectType()) {
901-
optionalRedecl = true;
902-
auto *param = swift::getParameterAt(current, i);
903-
assert(param);
904-
if (param->isImplicitlyUnwrappedOptional())
905-
currIsIUO = true;
906-
}
907-
908-
if (otherParams[i].getPlainType()->getOptionalObjectType()) {
909-
auto *param = swift::getParameterAt(other, i);
910-
assert(param);
911-
if (param->isImplicitlyUnwrappedOptional())
912-
otherIsIUO = true;
913-
}
914-
else {
915-
optionalRedecl = false;
916-
}
917-
918-
if (optionalRedecl && currIsIUO != otherIsIUO) {
919-
ctx.Diags.diagnoseWithNotes(
920-
current->diagnose(diag::invalid_redecl, current), [&]() {
921-
other->diagnose(diag::invalid_redecl_prev, other);
922-
});
923-
current->diagnose(diag::invalid_redecl_by_optionality_note,
924-
otherIsIUO, currIsIUO);
925-
926-
current->setInvalid();
927-
diagnosed = true;
928-
break;
929-
}
930-
}
931-
932-
if (diagnosed)
933-
break;
876+
// Emit a custom diagnostic if the interface types match but one of the
877+
// parameters differ in IUO-ness.
878+
if (current->getInterfaceType()->isEqual(other->getInterfaceType()) &&
879+
currentDC->isTypeContext() == otherDC->isTypeContext()) {
880+
auto currParams = current->getParameterList();
881+
auto otherParams = other->getParameterList();
882+
883+
if (currParams && otherParams &&
884+
currParams->size() == otherParams->size()) {
885+
for (unsigned i : indices(*currParams)) {
886+
auto *currParam = currParams->get(i);
887+
auto *otherParam = otherParams->get(i);
888+
889+
if (!currParam->getInterfaceType()->isOptional() ||
890+
!otherParam->getInterfaceType()->isOptional()) {
891+
continue;
934892
}
893+
894+
auto currIsIUO = currParam->isImplicitlyUnwrappedOptional();
895+
auto otherIsIUO = otherParam->isImplicitlyUnwrappedOptional();
896+
if (currIsIUO == otherIsIUO)
897+
continue;
898+
899+
ctx.Diags.diagnoseWithNotes(
900+
current->diagnose(diag::invalid_redecl, current),
901+
[&]() { other->diagnose(diag::invalid_redecl_prev, other); });
902+
current->diagnose(diag::invalid_redecl_by_optionality_note,
903+
otherIsIUO, currIsIUO);
904+
905+
current->setInvalid();
906+
return std::make_tuple();
935907
}
936908
}
937909
}

test/decl/overload.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,16 @@ class optionalOverloads {
402402
func optional_3() -> Int? { } // expected-note{{previously declared}}
403403
func optional_3() -> Int! { } // expected-error{{invalid redeclaration of 'optional_3()'}}
404404

405+
var optionalFnVar: (Int?) -> Void // expected-note {{previously declared}}
406+
var optionalFnVar: (Int?) -> Void // expected-error {{invalid redeclaration of 'optionalFnVar'}}
407+
408+
enum IUORedeclarationCaseConstructor {
409+
case foo(Int?) // expected-note{{previously declared}}
410+
static func foo(_ x: Int!) -> Self {}
411+
// expected-error@-1 {{invalid redeclaration of 'foo'}}
412+
// expected-note@-2 {{implicitly unwrapped optional parameter is of same type as optional parameter}}
413+
}
414+
405415
// mutating / nonmutating
406416
protocol ProtocolWithMutating {
407417
mutating func test1() // expected-note {{previously declared}}

0 commit comments

Comments
 (0)