mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Diagnostics] Do not offer a mutating fix-it if we have a mutating protocol requirement
Do not offer a mutating fix-it if we have a mutating protocol requirement and we're assigning to it from an implicitly nonmutating setter inside a protocol extension
This commit is contained in:
@@ -5689,7 +5689,8 @@ ObjCSelector VarDecl::getDefaultObjCSetterSelector(ASTContext &ctx,
|
||||
/// If this is a simple 'let' constant, emit a note with a fixit indicating
|
||||
/// that it can be rewritten to a 'var'. This is used in situations where the
|
||||
/// compiler detects obvious attempts to mutate a constant.
|
||||
void VarDecl::emitLetToVarNoteIfSimple(DeclContext *UseDC) const {
|
||||
void VarDecl::emitLetToVarNoteIfSimple(DeclContext *UseDC,
|
||||
ValueDecl *Anchor) const {
|
||||
// If it isn't a 'let', don't touch it.
|
||||
if (!isLet()) return;
|
||||
|
||||
@@ -5703,12 +5704,31 @@ void VarDecl::emitLetToVarNoteIfSimple(DeclContext *UseDC) const {
|
||||
if (FD && !FD->isMutating() && !FD->isImplicit() && FD->isInstanceMember()&&
|
||||
!FD->getDeclContext()->getDeclaredInterfaceType()
|
||||
->hasReferenceSemantics()) {
|
||||
// Do not suggest the fix it in implicit getters
|
||||
// Do not suggest the fix-it in implicit getters
|
||||
if (auto AD = dyn_cast<AccessorDecl>(FD)) {
|
||||
if (AD->isGetter() && !AD->getAccessorKeywordLoc().isValid())
|
||||
return;
|
||||
|
||||
// Do not suggest the fix-it if we have an implicitly nonmutating
|
||||
// setter in a protocol extension and we're assigning to a mutating
|
||||
// protocol requirement.
|
||||
if (Anchor && Anchor->isProtocolRequirement() && isa<VarDecl>(Anchor)) {
|
||||
auto requirementVar = cast<VarDecl>(Anchor);
|
||||
auto innermostTyCtx = AD->getInnermostTypeContext();
|
||||
bool isRequirementSetterMutating = requirementVar->isSetterMutating();
|
||||
bool isProtoExtension =
|
||||
innermostTyCtx
|
||||
? innermostTyCtx->getExtendedProtocolDecl() != nullptr
|
||||
: false;
|
||||
bool isImplicitlyNonMutatingSetter =
|
||||
AD->isSetter() && AD->isNonMutating() &&
|
||||
!AD->getAttrs().hasAttribute<NonMutatingAttr>();
|
||||
if (isRequirementSetterMutating && isProtoExtension &&
|
||||
isImplicitlyNonMutatingSetter)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto &d = getASTContext().Diags;
|
||||
d.diagnose(FD->getFuncLoc(), diag::change_to_mutating,
|
||||
isa<AccessorDecl>(FD))
|
||||
|
||||
Reference in New Issue
Block a user