Skip to content

Commit a59cdc5

Browse files
committed
Fix #57354: Fix-it for deprecated initializers removes the .init part from self.init
1 parent 6ca5716 commit a59cdc5

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2355,16 +2355,22 @@ static void fixItAvailableAttrRename(InFlightDiagnostic &diag,
23552355
} else if (parsed.BaseName == "init" && isa_and_nonnull<CallExpr>(call)) {
23562356
auto *CE = cast<CallExpr>(call);
23572357

2358-
// For initializers, replace with a "call" of the context type...but only
2359-
// if we know we're doing a call (rather than a first-class reference).
2358+
// If it is a call to an initializer (rather than a first-class reference):
2359+
23602360
if (parsed.isMember()) {
2361+
// replace with a "call" to the type (instead of writing `.init`)
23612362
diag.fixItReplace(CE->getFn()->getSourceRange(), parsed.ContextName);
23622363
} else if (auto *dotCall = dyn_cast<DotSyntaxCallExpr>(CE->getFn())) {
2363-
SourceLoc removeLoc = dotCall->getDotLoc();
2364-
if (removeLoc.isInvalid())
2365-
return;
2366-
2367-
diag.fixItRemove(SourceRange(removeLoc, dotCall->getFn()->getEndLoc()));
2364+
// if it's a dot call, and the left side is a type (and not `self` or
2365+
// `super`, for example), just remove the dot and the right side, again
2366+
// in order to make it a "call" to the type
2367+
if (isa<TypeExpr>(dotCall->getBase())) {
2368+
SourceLoc removeLoc = dotCall->getDotLoc();
2369+
if (removeLoc.isInvalid())
2370+
return;
2371+
2372+
diag.fixItRemove(SourceRange(removeLoc, dotCall->getFn()->getEndLoc()));
2373+
}
23682374
} else if (!isa<ConstructorRefCallExpr>(CE->getFn())) {
23692375
return;
23702376
}

test/attr/attr_availability.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,33 @@ func testFactoryMethods() {
615615
Int.factory2(other: 1) // expected-error {{'factory2(other:)' has been replaced by 'Int.init(other:)'}} {{3-15=Int}}
616616
}
617617

618+
class DeprecatedInitBase {
619+
@available(*, deprecated, renamed: "init(new:)")
620+
init(old: Int) {}
621+
622+
init(new: Int) {}
623+
624+
convenience init(testSelf: Int) {
625+
// https://github.com/apple/swift/issues/57354
626+
// The fix-it should not remove `.init`
627+
self.init(old: testSelf) // expected-warning {{'init(old:)' is deprecated: replaced by 'init(new:)'}} expected-note {{use 'init(new:)' instead}} {{15-18=new}}
628+
}
629+
630+
init(testSuper: Int) {}
631+
}
632+
633+
class DeprecatedInitSub1: DeprecatedInitBase {
634+
override init(testSuper: Int) {
635+
// https://github.com/apple/swift/issues/57354
636+
// The fix-it should not remove `.init`
637+
super.init(old: testSuper) // expected-warning {{'init(old:)' is deprecated: replaced by 'init(new:)'}} expected-note {{use 'init(new:)' instead}} {{16-19=new}}
638+
}
639+
}
640+
641+
class DeprecatedInitSub2: DeprecatedInitBase { }
642+
643+
_ = DeprecatedInitSub2(old: 0) // expected-warning {{'init(old:)' is deprecated}}
644+
618645
class Base {
619646
@available(*, unavailable)
620647
func bad() {} // expected-note {{here}}
@@ -1073,14 +1100,6 @@ struct UnavailableAccessors {
10731100
}
10741101
}
10751102

1076-
class BaseDeprecatedInit {
1077-
@available(*, deprecated) init(bad: Int) { }
1078-
}
1079-
1080-
class SubInheritedDeprecatedInit: BaseDeprecatedInit { }
1081-
1082-
_ = SubInheritedDeprecatedInit(bad: 0) // expected-warning {{'init(bad:)' is deprecated}}
1083-
10841103
// https://github.com/apple/swift/issues/51149
10851104
// Should produce no warnings.
10861105

0 commit comments

Comments
 (0)