1- // ===--- Diagnostics.cpp - Redundancy and conflict diagnostics ------------===//
1+ // ===--- Diagnostics.cpp - Requirement conflict diagnostics --- ------------===//
22//
33// This source file is part of the Swift.org open source project
44//
@@ -143,20 +143,6 @@ bool swift::rewriting::diagnoseRequirementErrors(
143143 break ;
144144 }
145145
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-
160146 case RequirementError::Kind::ConflictingInverseRequirement: {
161147 auto inverse = error.getInverse ();
162148 auto protoKind = getKnownProtocolKind (inverse.getKind ());
@@ -234,45 +220,6 @@ bool swift::rewriting::diagnoseRequirementErrors(
234220 break ;
235221 }
236222
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-
276223 case RequirementError::Kind::UnsupportedSameElement: {
277224 if (error.getRequirement ().hasError ())
278225 break ;
@@ -287,184 +234,6 @@ bool swift::rewriting::diagnoseRequirementErrors(
287234 return diagnosedError;
288235}
289236
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-
468237static Requirement
469238getRequirementForDiagnostics (Type subject, Symbol property,
470239 const PropertyMap &map,
@@ -557,7 +326,6 @@ void RequirementMachine::computeRequirementDiagnostics(
557326 SmallVectorImpl<RequirementError> &errors,
558327 ArrayRef<InverseRequirement> inverses,
559328 SourceLoc signatureLoc) {
560- System.computeRedundantRequirementDiagnostics (errors);
561329 System.computeConflictingRequirementDiagnostics (errors, signatureLoc, Map,
562330 getGenericParams ());
563331 System.computeRecursiveRequirementDiagnostics (errors, signatureLoc, Map,
0 commit comments