1
- // ===--- Diagnostics.cpp - Redundancy and conflict diagnostics ------------===//
1
+ // ===--- Diagnostics.cpp - Requirement conflict diagnostics --- ------------===//
2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
@@ -143,20 +143,6 @@ bool swift::rewriting::diagnoseRequirementErrors(
143
143
break ;
144
144
}
145
145
146
- case RequirementError::Kind::RedundantInverseRequirement: {
147
- // We only emit redundant requirement warnings if the user passed
148
- // the -warn-redundant-requirements frontend flag.
149
- if (!ctx.LangOpts .WarnRedundantRequirements )
150
- break ;
151
-
152
- auto inverse = error.getInverse ();
153
- auto protoName = getKnownProtocolKind (inverse.getKind ());
154
- ctx.Diags .diagnose (loc, diag::redundant_inverse_constraint,
155
- inverse.subject ,
156
- getProtocolName (protoName));
157
- break ;
158
- }
159
-
160
146
case RequirementError::Kind::ConflictingInverseRequirement: {
161
147
auto inverse = error.getInverse ();
162
148
auto protoKind = getKnownProtocolKind (inverse.getKind ());
@@ -234,45 +220,6 @@ bool swift::rewriting::diagnoseRequirementErrors(
234
220
break ;
235
221
}
236
222
237
- case RequirementError::Kind::RedundantRequirement: {
238
- // We only emit redundant requirement warnings if the user passed
239
- // the -warn-redundant-requirements frontend flag.
240
- if (!ctx.LangOpts .WarnRedundantRequirements )
241
- break ;
242
-
243
- auto requirement = error.getRequirement ();
244
- if (requirement.hasError ())
245
- break ;
246
-
247
- switch (requirement.getKind ()) {
248
- case RequirementKind::SameShape:
249
- llvm_unreachable (" Same-shape requirement not supported here" );
250
-
251
- case RequirementKind::SameType:
252
- ctx.Diags .diagnose (loc, diag::redundant_same_type_to_concrete,
253
- requirement.getFirstType (),
254
- requirement.getSecondType ());
255
- break ;
256
- case RequirementKind::Conformance:
257
- ctx.Diags .diagnose (loc, diag::redundant_conformance_constraint,
258
- requirement.getFirstType (),
259
- requirement.getSecondType ());
260
- break ;
261
- case RequirementKind::Superclass:
262
- ctx.Diags .diagnose (loc, diag::redundant_superclass_constraint,
263
- requirement.getFirstType (),
264
- requirement.getSecondType ());
265
- break ;
266
- case RequirementKind::Layout:
267
- ctx.Diags .diagnose (loc, diag::redundant_layout_constraint,
268
- requirement.getFirstType (),
269
- requirement.getLayoutConstraint ());
270
- break ;
271
- }
272
-
273
- break ;
274
- }
275
-
276
223
case RequirementError::Kind::UnsupportedSameElement: {
277
224
if (error.getRequirement ().hasError ())
278
225
break ;
@@ -287,184 +234,6 @@ bool swift::rewriting::diagnoseRequirementErrors(
287
234
return diagnosedError;
288
235
}
289
236
290
- // / Determine whether this is a redundantly inheritable Objective-C protocol.
291
- // /
292
- // / A redundantly-inheritable Objective-C protocol is one where we will
293
- // / silently accept a directly-stated redundant conformance to this protocol,
294
- // / and emit this protocol in the list of "inherited" protocols. There are
295
- // / two cases where we allow this:
296
- // /
297
- // 1) For a protocol defined in Objective-C, so that we will match Clang's
298
- // / behavior, and
299
- // / 2) For an @objc protocol defined in Swift that directly inherits from
300
- // / JavaScriptCore's JSExport, which depends on this behavior.
301
- static bool isRedundantlyInheritableObjCProtocol (const ProtocolDecl *inheritingProto,
302
- const ProtocolDecl *proto) {
303
- if (!proto->isObjC ()) return false ;
304
-
305
- // Check the two conditions in which we will suppress the diagnostic and
306
- // emit the redundant inheritance.
307
- if (!inheritingProto->hasClangNode () && !proto->getName ().is (" JSExport" ))
308
- return false ;
309
-
310
- // If the inheriting protocol already has @_restatedObjCConformance with
311
- // this protocol, we're done.
312
- for (auto *attr : inheritingProto->getAttrs ()
313
- .getAttributes <RestatedObjCConformanceAttr>()) {
314
- if (attr->Proto == proto) return true ;
315
- }
316
-
317
- // Otherwise, add @_restatedObjCConformance.
318
- auto &ctx = proto->getASTContext ();
319
- const_cast <ProtocolDecl *>(inheritingProto)
320
- ->getAttrs ().add (new (ctx) RestatedObjCConformanceAttr (
321
- const_cast <ProtocolDecl *>(proto)));
322
- return true ;
323
- }
324
-
325
- // / Computes the set of explicit redundant requirements to
326
- // / emit warnings for in the source code.
327
- void RewriteSystem::computeRedundantRequirementDiagnostics (
328
- SmallVectorImpl<RequirementError> &errors) {
329
- // Collect all rule IDs for each unique requirement ID.
330
- llvm::SmallDenseMap<unsigned , llvm::SmallVector<unsigned , 2 >>
331
- rulesPerRequirement;
332
-
333
- // Collect non-explicit requirements that are not redundant.
334
- llvm::SmallDenseSet<unsigned , 2 > nonExplicitNonRedundantRules;
335
-
336
- for (unsigned ruleID = FirstLocalRule, e = Rules.size ();
337
- ruleID < e; ++ruleID) {
338
- auto &rule = getRules ()[ruleID];
339
-
340
- if (rule.isPermanent ())
341
- continue ;
342
-
343
- if (!isInMinimizationDomain (rule.getLHS ().getRootProtocol ()))
344
- continue ;
345
-
346
- // Concrete conformance rules do not map to requirements in the minimized
347
- // signature; we don't consider them to be 'non-explicit non-redundant',
348
- // so that a conformance rule (T.[P] => T) expressed in terms of a concrete
349
- // conformance (T.[concrete: C : P] => T) is still diagnosed as redundant.
350
- if (auto optSymbol = rule.isPropertyRule ()) {
351
- if (optSymbol->getKind () == Symbol::Kind::ConcreteConformance)
352
- continue ;
353
- }
354
-
355
- auto requirementID = rule.getRequirementID ();
356
-
357
- if (!requirementID.has_value ()) {
358
- if (!rule.isRedundant ())
359
- nonExplicitNonRedundantRules.insert (ruleID);
360
-
361
- continue ;
362
- }
363
-
364
- rulesPerRequirement[*requirementID].push_back (ruleID);
365
- }
366
-
367
- // Compute the set of redundant rules which transitively reference a
368
- // non-explicit non-redundant rule. This updates nonExplicitNonRedundantRules.
369
- //
370
- // Since earlier redundant paths might reference rules which appear later in
371
- // the list but not vice versa, walk the redundant paths in reverse order.
372
- for (const auto &pair : llvm::reverse (RedundantRules)) {
373
- // Pre-condition: the replacement path only references redundant rules
374
- // which we have already seen. If any of those rules transitively reference
375
- // a non-explicit, non-redundant rule, they have been inserted into the
376
- // nonExplicitNonRedundantRules set on previous iterations.
377
- unsigned ruleID = pair.first ;
378
- const auto &rewritePath = pair.second ;
379
-
380
- // Check if this rewrite path references a rule that is already known to
381
- // either be non-explicit and non-redundant, or reference such a rule via
382
- // it's redundancy path.
383
- for (auto step : rewritePath) {
384
- switch (step.Kind ) {
385
- case RewriteStep::Rule: {
386
- if (nonExplicitNonRedundantRules.count (step.getRuleID ())) {
387
- nonExplicitNonRedundantRules.insert (ruleID);
388
- continue ;
389
- }
390
-
391
- break ;
392
- }
393
-
394
- case RewriteStep::LeftConcreteProjection:
395
- case RewriteStep::Decompose:
396
- case RewriteStep::PrefixSubstitutions:
397
- case RewriteStep::Shift:
398
- case RewriteStep::Relation:
399
- case RewriteStep::DecomposeConcrete:
400
- case RewriteStep::RightConcreteProjection:
401
- break ;
402
- }
403
- }
404
-
405
- // Post-condition: If the current replacement path transitively references
406
- // any non-explicit, non-redundant rules, then nonExplicitNonRedundantRules
407
- // contains the current rule.
408
- }
409
-
410
- // We diagnose a redundancy if the rule is redundant, and if its replacement
411
- // path does not transitively involve any non-explicit, non-redundant rules.
412
- auto isRedundantRule = [&](unsigned ruleID) {
413
- const auto &rule = getRules ()[ruleID];
414
-
415
- if (!rule.isRedundant ())
416
- return false ;
417
-
418
- if (nonExplicitNonRedundantRules.count (ruleID) > 0 )
419
- return false ;
420
-
421
- if (rule.isProtocolRefinementRule (Context) &&
422
- isRedundantlyInheritableObjCProtocol (rule.getLHS ()[0 ].getProtocol (),
423
- rule.getLHS ()[1 ].getProtocol ()))
424
- return false ;
425
-
426
- return true ;
427
- };
428
-
429
- // Finally walk through the written requirements, diagnosing any that are
430
- // redundant.
431
- for (auto requirementID : indices (WrittenRequirements)) {
432
- auto requirement = WrittenRequirements[requirementID];
433
-
434
- // Inferred requirements can be re-stated without warning.
435
- if (requirement.inferred )
436
- continue ;
437
-
438
- auto pairIt = rulesPerRequirement.find (requirementID);
439
-
440
- // If there are no rules for this structural requirement, then the
441
- // requirement is unnecessary in the source code.
442
- //
443
- // This means the requirement was determined to be vacuous by
444
- // requirement lowering and produced no rules, or the rewrite rules were
445
- // trivially simplified by RewriteSystem::addRule().
446
- if (pairIt == rulesPerRequirement.end ()) {
447
- errors.push_back (
448
- RequirementError::forRedundantRequirement (requirement.req ,
449
- requirement.loc ));
450
- continue ;
451
- }
452
-
453
- // If all rules derived from this structural requirement are redundant,
454
- // then the requirement is unnecessary in the source code.
455
- //
456
- // This means the rules derived from this requirement were all
457
- // determined to be redundant by homotopy reduction.
458
- const auto &ruleIDs = pairIt->second ;
459
- if (llvm::all_of (ruleIDs, isRedundantRule)) {
460
- auto requirement = WrittenRequirements[requirementID];
461
- errors.push_back (
462
- RequirementError::forRedundantRequirement (requirement.req ,
463
- requirement.loc ));
464
- }
465
- }
466
- }
467
-
468
237
static Requirement
469
238
getRequirementForDiagnostics (Type subject, Symbol property,
470
239
const PropertyMap &map,
@@ -557,7 +326,6 @@ void RequirementMachine::computeRequirementDiagnostics(
557
326
SmallVectorImpl<RequirementError> &errors,
558
327
ArrayRef<InverseRequirement> inverses,
559
328
SourceLoc signatureLoc) {
560
- System.computeRedundantRequirementDiagnostics (errors);
561
329
System.computeConflictingRequirementDiagnostics (errors, signatureLoc, Map,
562
330
getGenericParams ());
563
331
System.computeRecursiveRequirementDiagnostics (errors, signatureLoc, Map,
0 commit comments