diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index a95b7a8cb785a..fa1a9f71ac021 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -873,65 +873,37 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current, continue; } - // Signatures are the same, but interface types are not. We must - // have a type that we've massaged as part of signature - // interface type generation. - if (current->getInterfaceType()->isEqual(other->getInterfaceType())) { - if (currentDC->isTypeContext() == other->getDeclContext()->isTypeContext()) { - auto currFnTy = current->getInterfaceType()->getAs(); - auto otherFnTy = other->getInterfaceType()->getAs(); - if (currFnTy && otherFnTy && currentDC->isTypeContext()) { - currFnTy = currFnTy->getResult()->getAs(); - otherFnTy = otherFnTy->getResult()->getAs(); - } - - if (currFnTy && otherFnTy) { - ArrayRef currParams = currFnTy->getParams(); - ArrayRef otherParams = otherFnTy->getParams(); - - if (currParams.size() == otherParams.size()) { - auto diagnosed = false; - for (unsigned i : indices(currParams)) { - - bool currIsIUO = false; - bool otherIsIUO = false; - bool optionalRedecl = false; - - if (currParams[i].getPlainType()->getOptionalObjectType()) { - optionalRedecl = true; - auto *param = swift::getParameterAt(current, i); - assert(param); - if (param->isImplicitlyUnwrappedOptional()) - currIsIUO = true; - } - - if (otherParams[i].getPlainType()->getOptionalObjectType()) { - auto *param = swift::getParameterAt(other, i); - assert(param); - if (param->isImplicitlyUnwrappedOptional()) - otherIsIUO = true; - } - else { - optionalRedecl = false; - } - - if (optionalRedecl && currIsIUO != otherIsIUO) { - ctx.Diags.diagnoseWithNotes( - current->diagnose(diag::invalid_redecl, current), [&]() { - other->diagnose(diag::invalid_redecl_prev, other); - }); - current->diagnose(diag::invalid_redecl_by_optionality_note, - otherIsIUO, currIsIUO); - - current->setInvalid(); - diagnosed = true; - break; - } - } - - if (diagnosed) - break; + // Emit a custom diagnostic if the interface types match but one of the + // parameters differ in IUO-ness. + if (current->getInterfaceType()->isEqual(other->getInterfaceType()) && + currentDC->isTypeContext() == otherDC->isTypeContext()) { + auto currParams = current->getParameterList(); + auto otherParams = other->getParameterList(); + + if (currParams && otherParams && + currParams->size() == otherParams->size()) { + for (unsigned i : indices(*currParams)) { + auto *currParam = currParams->get(i); + auto *otherParam = otherParams->get(i); + + if (!currParam->getInterfaceType()->isOptional() || + !otherParam->getInterfaceType()->isOptional()) { + continue; } + + auto currIsIUO = currParam->isImplicitlyUnwrappedOptional(); + auto otherIsIUO = otherParam->isImplicitlyUnwrappedOptional(); + if (currIsIUO == otherIsIUO) + continue; + + ctx.Diags.diagnoseWithNotes( + current->diagnose(diag::invalid_redecl, current), + [&]() { other->diagnose(diag::invalid_redecl_prev, other); }); + current->diagnose(diag::invalid_redecl_by_optionality_note, + otherIsIUO, currIsIUO); + + current->setInvalid(); + return std::make_tuple(); } } } diff --git a/test/decl/overload.swift b/test/decl/overload.swift index f79d7e0b4432c..63fece91353d3 100644 --- a/test/decl/overload.swift +++ b/test/decl/overload.swift @@ -402,6 +402,16 @@ class optionalOverloads { func optional_3() -> Int? { } // expected-note{{previously declared}} func optional_3() -> Int! { } // expected-error{{invalid redeclaration of 'optional_3()'}} +var optionalFnVar: (Int?) -> Void // expected-note {{previously declared}} +var optionalFnVar: (Int?) -> Void // expected-error {{invalid redeclaration of 'optionalFnVar'}} + +enum IUORedeclarationCaseConstructor { + case foo(Int?) // expected-note{{previously declared}} + static func foo(_ x: Int!) -> Self {} + // expected-error@-1 {{invalid redeclaration of 'foo'}} + // expected-note@-2 {{implicitly unwrapped optional parameter is of same type as optional parameter}} +} + // mutating / nonmutating protocol ProtocolWithMutating { mutating func test1() // expected-note {{previously declared}}