Skip to content

Commit a6d79de

Browse files
authored
Merge pull request #66113 from beccadax/implementation-warnings-5.9
Soften @objcImpl errors into warnings in 5.9
2 parents c9cdb72 + 8caa90c commit a6d79de

File tree

3 files changed

+47
-35
lines changed

3 files changed

+47
-35
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,11 @@ NOTE(objc_implementation_one_matched_requirement,none,
16601660
"'@objc(%4)' to use it}3",
16611661
(DescriptiveDeclKind, ValueDecl *, ObjCSelector, bool, StringRef))
16621662

1663+
WARNING(wrap_objc_implementation_will_become_error,none,
1664+
"%0; this will become an error before '@_objcImplementation' is "
1665+
"stabilized",
1666+
(DiagnosticInfo *))
1667+
16631668
ERROR(cdecl_not_at_top_level,none,
16641669
"@_cdecl can only be applied to global functions", ())
16651670
ERROR(cdecl_empty_name,none,

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2874,9 +2874,16 @@ namespace {
28742874
class ObjCImplementationChecker {
28752875
DiagnosticEngine &diags;
28762876

2877-
template<typename ...ArgTypes>
2878-
InFlightDiagnostic diagnose(ArgTypes &&...Args) {
2879-
auto diag = diags.diagnose(std::forward<ArgTypes>(Args)...);
2877+
template<typename Loc, typename ...ArgTypes>
2878+
InFlightDiagnostic diagnose(Loc loc, Diag<ArgTypes...> diagID,
2879+
typename detail::PassArgument<ArgTypes>::type... Args) {
2880+
auto diag = diags.diagnose(loc, diagID, std::forward<ArgTypes>(Args)...);
2881+
2882+
// WORKAROUND (5.9): Soften newly-introduced errors to make things easier
2883+
// for early adopters.
2884+
if (diags.declaredDiagnosticKindFor(diagID.ID) == DiagnosticKind::Error)
2885+
diag.wrapIn(diag::wrap_objc_implementation_will_become_error);
2886+
28802887
return diag;
28812888
}
28822889

@@ -3115,13 +3122,13 @@ class ObjCImplementationChecker {
31153122
}
31163123

31173124
// Ambiguous match (many requirements match one candidate)
3118-
cand->diagnose(diag::objc_implementation_multiple_matching_requirements,
3125+
diagnose(cand, diag::objc_implementation_multiple_matching_requirements,
31193126
cand->getDescriptiveKind(), cand);
31203127

31213128
bool shouldOfferFix = !candExplicitObjCName;
31223129
for (auto req : matchedRequirements.matches) {
31233130
auto diag =
3124-
cand->diagnose(diag::objc_implementation_one_matched_requirement,
3131+
diagnose(cand, diag::objc_implementation_one_matched_requirement,
31253132
req->getDescriptiveKind(), req,
31263133
*req->getObjCRuntimeName(), shouldOfferFix,
31273134
req->getObjCRuntimeName()->getString(scratch));
@@ -3164,14 +3171,14 @@ class ObjCImplementationChecker {
31643171
cast<IterableDeclContext>(req->getDeclContext()->getAsDecl());
31653172
auto ext =
31663173
cast<ExtensionDecl>(reqIDC->getImplementationContext());
3167-
ext->diagnose(diag::objc_implementation_multiple_matching_candidates,
3174+
diagnose(ext, diag::objc_implementation_multiple_matching_candidates,
31683175
req->getDescriptiveKind(), req,
31693176
*req->getObjCRuntimeName());
31703177

31713178
for (auto cand : cands.matches) {
31723179
bool shouldOfferFix = !unmatchedCandidates[cand];
31733180
auto diag =
3174-
cand->diagnose(diag::objc_implementation_candidate_impl_here,
3181+
diagnose(cand, diag::objc_implementation_candidate_impl_here,
31753182
cand->getDescriptiveKind(), cand, shouldOfferFix,
31763183
req->getObjCRuntimeName()->getString(scratch));
31773184

@@ -3182,7 +3189,7 @@ class ObjCImplementationChecker {
31823189
}
31833190
}
31843191

3185-
req->diagnose(diag::objc_implementation_requirement_here,
3192+
diagnose(req, diag::objc_implementation_requirement_here,
31863193
req->getDescriptiveKind(), req);
31873194
}
31883195

test/decl/ext/objc_implementation.swift

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
@_objcImplementation extension ObjCClass {
55
// expected-note@-1 {{previously implemented by extension here}}
6-
// expected-error@-2 {{extension for main class interface should provide implementation for instance method 'method(fromHeader4:)'}}
7-
// expected-error@-3 {{extension for main class interface should provide implementation for property 'propertyFromHeader9'}}
8-
// FIXME: give better diagnostic expected-error@-4 {{extension for main class interface should provide implementation for property 'propertyFromHeader8'}}
9-
// FIXME: give better diagnostic expected-error@-5 {{extension for main class interface should provide implementation for property 'propertyFromHeader7'}}
10-
// FIXME: give better diagnostic expected-error@-6 {{extension for main class interface should provide implementation for instance method 'method(fromHeader3:)'}}
6+
// expected-warning@-2 {{extension for main class interface should provide implementation for instance method 'method(fromHeader4:)'; this will become an error before '@_objcImplementation' is stabilized}}
7+
// expected-warning@-3 {{extension for main class interface should provide implementation for property 'propertyFromHeader9'; this will become an error before '@_objcImplementation' is stabilized}}
8+
// FIXME: give better diagnostic expected-warning@-4 {{extension for main class interface should provide implementation for property 'propertyFromHeader8'; this will become an error before '@_objcImplementation' is stabilized}}
9+
// FIXME: give better diagnostic expected-warning@-5 {{extension for main class interface should provide implementation for property 'propertyFromHeader7'; this will become an error before '@_objcImplementation' is stabilized}}
10+
// FIXME: give better diagnostic expected-warning@-6 {{extension for main class interface should provide implementation for instance method 'method(fromHeader3:)'; this will become an error before '@_objcImplementation' is stabilized}}
1111

1212
func method(fromHeader1: CInt) {
1313
// OK, provides an implementation for the header's method.
@@ -19,7 +19,7 @@
1919

2020
func categoryMethod(fromHeader3: CInt) {
2121
// FIXME: should emit expected-DISABLED-error@-1 {{instance method 'categoryMethod(fromHeader3:)' should be implemented in extension for category 'PresentAdditions', not main class interface}}
22-
// FIXME: expected-error@-2 {{instance method 'categoryMethod(fromHeader3:)' does not match any instance method declared in the headers for 'ObjCClass'; did you use the instance method's Swift name?}}
22+
// FIXME: expected-warning@-2 {{instance method 'categoryMethod(fromHeader3:)' does not match any instance method declared in the headers for 'ObjCClass'; did you use the instance method's Swift name?; this will become an error before '@_objcImplementation' is stabilized}}
2323
// FIXME: expected-note@-3 {{add 'private' or 'fileprivate' to define an Objective-C-compatible instance method not declared in the header}} {{3-3=private }}
2424
// FIXME: expected-note@-4 {{add 'final' to define a Swift instance method that cannot be overridden}} {{3-3=final }}
2525
}
@@ -33,7 +33,7 @@
3333
}
3434

3535
func methodNot(fromHeader3: CInt) {
36-
// expected-error@-1 {{instance method 'methodNot(fromHeader3:)' does not match any instance method declared in the headers for 'ObjCClass'; did you use the instance method's Swift name?}}
36+
// expected-warning@-1 {{instance method 'methodNot(fromHeader3:)' does not match any instance method declared in the headers for 'ObjCClass'; did you use the instance method's Swift name?; this will become an error before '@_objcImplementation' is stabilized}}
3737
// expected-note@-2 {{add 'private' or 'fileprivate' to define an Objective-C-compatible instance method not declared in the header}} {{3-3=private }}
3838
// expected-note@-3 {{add 'final' to define a Swift instance method that cannot be overridden}} {{3-3=final }}
3939
}
@@ -94,7 +94,7 @@
9494
}
9595

9696
internal var propertyNotFromHeader1: CInt
97-
// expected-error@-1 {{property 'propertyNotFromHeader1' does not match any property declared in the headers for 'ObjCClass'; did you use the property's Swift name?}}
97+
// expected-warning@-1 {{property 'propertyNotFromHeader1' does not match any property declared in the headers for 'ObjCClass'; did you use the property's Swift name?; this will become an error before '@_objcImplementation' is stabilized}}
9898
// expected-note@-2 {{add 'private' or 'fileprivate' to define an Objective-C-compatible property not declared in the header}} {{3-3=private }}
9999
// expected-note@-3 {{add 'final' to define a Swift property that cannot be overridden}} {{3-3=final }}
100100

@@ -135,33 +135,33 @@
135135
}
136136

137137
func classMethod2(_: CInt) {
138-
// expected-error@-1 {{instance method 'classMethod2' does not match class method declared in header}} {{3-3=class }}
138+
// expected-warning@-1 {{instance method 'classMethod2' does not match class method declared in header; this will become an error before '@_objcImplementation' is stabilized}} {{3-3=class }}
139139
}
140140

141141
func instanceMethod1(_: CInt) {
142142
// OK
143143
}
144144

145145
class func instanceMethod2(_: CInt) {
146-
// expected-error@-1 {{class method 'instanceMethod2' does not match instance method declared in header}} {{3-9=}}
146+
// expected-warning@-1 {{class method 'instanceMethod2' does not match instance method declared in header; this will become an error before '@_objcImplementation' is stabilized}} {{3-9=}}
147147
}
148148
}
149149

150150
@_objcImplementation(PresentAdditions) extension ObjCClass {
151151
// expected-note@-1 {{previously implemented by extension here}}
152-
// expected-error@-2 {{extension for category 'PresentAdditions' should provide implementation for instance method 'categoryMethod(fromHeader4:)'}}
153-
// FIXME: give better diagnostic expected-error@-3 {{extension for category 'PresentAdditions' should provide implementation for instance method 'categoryMethod(fromHeader3:)'}}
152+
// expected-warning@-2 {{extension for category 'PresentAdditions' should provide implementation for instance method 'categoryMethod(fromHeader4:)'; this will become an error before '@_objcImplementation' is stabilized}}
153+
// FIXME: give better diagnostic expected-warning@-3 {{extension for category 'PresentAdditions' should provide implementation for instance method 'categoryMethod(fromHeader3:)'; this will become an error before '@_objcImplementation' is stabilized}}
154154

155155
func method(fromHeader3: CInt) {
156156
// FIXME: should emit expected-DISABLED-error@-1 {{instance method 'method(fromHeader3:)' should be implemented in extension for main class interface, not category 'PresentAdditions'}}
157-
// FIXME: expected-error@-2 {{instance method 'method(fromHeader3:)' does not match any instance method declared in the headers for 'ObjCClass'; did you use the instance method's Swift name?}}
157+
// FIXME: expected-warning@-2 {{instance method 'method(fromHeader3:)' does not match any instance method declared in the headers for 'ObjCClass'; did you use the instance method's Swift name?; this will become an error before '@_objcImplementation' is stabilized}}
158158
// FIXME: expected-note@-3 {{add 'private' or 'fileprivate' to define an Objective-C-compatible instance method not declared in the header}} {{3-3=private }}
159159
// FIXME: expected-note@-4 {{add 'final' to define a Swift instance method that cannot be overridden}} {{3-3=final }}
160160
}
161161

162162
var propertyFromHeader7: CInt {
163163
// FIXME: should emit expected-DISABLED-error@-1 {{property 'propertyFromHeader7' should be implemented in extension for main class interface, not category 'PresentAdditions'}}
164-
// FIXME: expected-error@-2 {{property 'propertyFromHeader7' does not match any property declared in the headers for 'ObjCClass'; did you use the property's Swift name?}}
164+
// FIXME: expected-warning@-2 {{property 'propertyFromHeader7' does not match any property declared in the headers for 'ObjCClass'; did you use the property's Swift name?; this will become an error before '@_objcImplementation' is stabilized}}
165165
// FIXME: expected-note@-3 {{add 'private' or 'fileprivate' to define an Objective-C-compatible property not declared in the header}} {{3-3=private }}
166166
// FIXME: expected-note@-4 {{add 'final' to define a Swift property that cannot be overridden}} {{3-3=final }}
167167
get { return 1 }
@@ -184,7 +184,7 @@
184184
}
185185

186186
func categoryMethodNot(fromHeader3: CInt) {
187-
// expected-error@-1 {{instance method 'categoryMethodNot(fromHeader3:)' does not match any instance method declared in the headers for 'ObjCClass'; did you use the instance method's Swift name?}}
187+
// expected-warning@-1 {{instance method 'categoryMethodNot(fromHeader3:)' does not match any instance method declared in the headers for 'ObjCClass'; did you use the instance method's Swift name?; this will become an error before '@_objcImplementation' is stabilized}}
188188
// expected-note@-2 {{add 'private' or 'fileprivate' to define an Objective-C-compatible instance method not declared in the header}} {{3-3=private }}
189189
// expected-note@-3 {{add 'final' to define a Swift instance method that cannot be overridden}} {{3-3=final }}
190190
}
@@ -209,45 +209,45 @@
209209
}
210210

211211
@_objcImplementation(SwiftNameTests) extension ObjCClass {
212-
// expected-error@-1 {{extension for category 'SwiftNameTests' should provide implementation for instance method 'methodSwiftName6B()'}}
212+
// expected-warning@-1 {{extension for category 'SwiftNameTests' should provide implementation for instance method 'methodSwiftName6B()'; this will become an error before '@_objcImplementation' is stabilized}}
213213

214214
func methodSwiftName1() {
215-
// expected-error@-1 {{selector 'methodSwiftName1' for instance method 'methodSwiftName1()' not found in header; did you mean 'methodObjCName1'?}} {{3-3=@objc(methodObjCName1) }}
215+
// expected-warning@-1 {{selector 'methodSwiftName1' for instance method 'methodSwiftName1()' not found in header; did you mean 'methodObjCName1'?; this will become an error before '@_objcImplementation' is stabilized}} {{3-3=@objc(methodObjCName1) }}
216216
}
217217

218218
@objc(methodObjCName2) func methodSwiftName2() {
219219
// OK
220220
}
221221

222222
func methodObjCName3() {
223-
// expected-error@-1 {{selector 'methodObjCName3' used in header by an instance method with a different name; did you mean 'methodSwiftName3()'?}} {{8-23=methodSwiftName3}} {{3-3=@objc(methodObjCName3) }}
223+
// expected-warning@-1 {{selector 'methodObjCName3' used in header by an instance method with a different name; did you mean 'methodSwiftName3()'?; this will become an error before '@_objcImplementation' is stabilized}} {{8-23=methodSwiftName3}} {{3-3=@objc(methodObjCName3) }}
224224
// FIXME: probably needs an @objc too, since the name is not explicit
225225
}
226226

227227
@objc(methodWrongObjCName4) func methodSwiftName4() {
228-
// expected-error@-1 {{selector 'methodWrongObjCName4' for instance method 'methodSwiftName4()' not found in header; did you mean 'methodObjCName4'?}} {{9-29=methodObjCName4}}
228+
// expected-warning@-1 {{selector 'methodWrongObjCName4' for instance method 'methodSwiftName4()' not found in header; did you mean 'methodObjCName4'?; this will become an error before '@_objcImplementation' is stabilized}} {{9-29=methodObjCName4}}
229229
}
230230

231231
@objc(methodObjCName5) func methodWrongSwiftName5() {
232-
// expected-error@-1 {{selector 'methodObjCName5' used in header by an instance method with a different name; did you mean 'methodSwiftName5()'?}} {{31-52=methodSwiftName5}}
232+
// expected-warning@-1 {{selector 'methodObjCName5' used in header by an instance method with a different name; did you mean 'methodSwiftName5()'?; this will become an error before '@_objcImplementation' is stabilized}} {{31-52=methodSwiftName5}}
233233
}
234234

235235
@objc(methodObjCName6A) func methodSwiftName6B() {
236-
// expected-error@-1 {{selector 'methodObjCName6A' used in header by an instance method with a different name; did you mean 'methodSwiftName6A()'?}} {{32-49=methodSwiftName6A}}
236+
// expected-warning@-1 {{selector 'methodObjCName6A' used in header by an instance method with a different name; did you mean 'methodSwiftName6A()'?; this will become an error before '@_objcImplementation' is stabilized}} {{32-49=methodSwiftName6A}}
237237
}
238238
}
239239

240240
@_objcImplementation(AmbiguousMethods) extension ObjCClass {
241-
// expected-error@-1 {{found multiple implementations that could match instance method 'ambiguousMethod4(with:)' with selector 'ambiguousMethod4WithCInt:'}}
241+
// expected-warning@-1 {{found multiple implementations that could match instance method 'ambiguousMethod4(with:)' with selector 'ambiguousMethod4WithCInt:'; this will become an error before '@_objcImplementation' is stabilized}}
242242

243243
@objc func ambiguousMethod1(with: CInt) {
244-
// expected-error@-1 {{instance method 'ambiguousMethod1(with:)' could match several different members declared in the header}}
244+
// expected-warning@-1 {{instance method 'ambiguousMethod1(with:)' could match several different members declared in the header; this will become an error before '@_objcImplementation' is stabilized}}
245245
// expected-note@-2 {{instance method 'ambiguousMethod1(with:)' (with selector 'ambiguousMethod1WithCInt:') is a potential match; insert '@objc(ambiguousMethod1WithCInt:)' to use it}} {{8-8=(ambiguousMethod1WithCInt:)}}
246246
// expected-note@-3 {{instance method 'ambiguousMethod1(with:)' (with selector 'ambiguousMethod1WithCChar:') is a potential match; insert '@objc(ambiguousMethod1WithCChar:)' to use it}} {{8-8=(ambiguousMethod1WithCChar:)}}
247247
}
248248

249249
func ambiguousMethod1(with: CChar) {
250-
// expected-error@-1 {{instance method 'ambiguousMethod1(with:)' could match several different members declared in the header}}
250+
// expected-warning@-1 {{instance method 'ambiguousMethod1(with:)' could match several different members declared in the header; this will become an error before '@_objcImplementation' is stabilized}}
251251
// expected-note@-2 {{instance method 'ambiguousMethod1(with:)' (with selector 'ambiguousMethod1WithCInt:') is a potential match; insert '@objc(ambiguousMethod1WithCInt:)' to use it}} {{3-3=@objc(ambiguousMethod1WithCInt:) }}
252252
// expected-note@-3 {{instance method 'ambiguousMethod1(with:)' (with selector 'ambiguousMethod1WithCChar:') is a potential match; insert '@objc(ambiguousMethod1WithCChar:)' to use it}} {{3-3=@objc(ambiguousMethod1WithCChar:) }}
253253
}
@@ -258,11 +258,11 @@
258258

259259
func ambiguousMethod2(with: CChar) {
260260
// FIXME: OK, matches -ambiguousMethod2WithCChar: because the WithCInt: variant has been eliminated
261-
// FIXME: expected-error@-2 {{selector 'ambiguousMethod2With:' for instance method 'ambiguousMethod2(with:)' not found in header; did you mean 'ambiguousMethod2WithCChar:'?}}
261+
// FIXME: expected-warning@-2 {{selector 'ambiguousMethod2With:' for instance method 'ambiguousMethod2(with:)' not found in header; did you mean 'ambiguousMethod2WithCChar:'?; this will become an error before '@_objcImplementation' is stabilized}}
262262
}
263263

264264
func ambiguousMethod3(with: CInt) {
265-
// expected-error@-1 {{instance method 'ambiguousMethod3(with:)' could match several different members declared in the header}}
265+
// expected-warning@-1 {{instance method 'ambiguousMethod3(with:)' could match several different members declared in the header; this will become an error before '@_objcImplementation' is stabilized}}
266266
// expected-note@-2 {{instance method 'ambiguousMethod3(with:)' (with selector 'ambiguousMethod3WithCInt:') is a potential match; insert '@objc(ambiguousMethod3WithCInt:)' to use it}} {{3-3=@objc(ambiguousMethod3WithCInt:) }}
267267
// expected-note@-3 {{instance method 'ambiguousMethod3(with:)' (with selector 'ambiguousMethod3WithCChar:') is a potential match; insert '@objc(ambiguousMethod3WithCChar:)' to use it}} {{3-3=@objc(ambiguousMethod3WithCChar:) }}
268268
}
@@ -292,7 +292,7 @@
292292
}
293293

294294
@_objcImplementation(Conformance) extension ObjCClass {
295-
// expected-error@-1 {{extension for category 'Conformance' should provide implementation for instance method 'requiredMethod2()'}}
295+
// expected-warning@-1 {{extension for category 'Conformance' should provide implementation for instance method 'requiredMethod2()'; this will become an error before '@_objcImplementation' is stabilized}}
296296
// no-error concerning 'optionalMethod2()'
297297

298298
func requiredMethod1() {}

0 commit comments

Comments
 (0)