Skip to content

Commit d302860

Browse files
authored
Merge pull request swiftlang#72112 from slavapestov/ncgenerics-fixes-8
Non-copyable generics fixes, part 8
2 parents f3e288a + b067402 commit d302860

35 files changed

+237
-374
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7630,10 +7630,6 @@ NOTE(add_inverse,none,
76307630
NOTE(note_inverse_preventing_conformance,none,
76317631
"%0 has '~%1' constraint preventing implicit '%1' conformance",
76327632
(Type, StringRef))
7633-
NOTE(note_inverse_preventing_conformance_implicit,none,
7634-
"%kind0 has '~%1' constraint on a generic parameter, "
7635-
"making its '%1' conformance conditional",
7636-
(const ValueDecl *, StringRef))
76377633
NOTE(note_inverse_preventing_conformance_explicit,none,
76387634
"%kind0 has '~%1' constraint preventing '%1' conformance",
76397635
(const ValueDecl *, StringRef))

include/swift/AST/InverseMarking.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ namespace swift {
2424
struct InverseMarking {
2525
enum class Kind : uint8_t {
2626
None, // No inverse marking is present
27-
Inferred, // Inverse is inferred based on generic parameters.
2827
Explicit, // Inverse is explicitly present.
2928
LegacyExplicit, // An equivalent, explicit legacy annotation is present.
3029
};
@@ -84,25 +83,6 @@ struct InverseMarking {
8483
return Mark(k, loc);
8584
}
8685
};
87-
88-
private:
89-
Mark inverse;
90-
Mark positive;
91-
92-
public:
93-
94-
// Creates an empty marking.
95-
InverseMarking() {}
96-
97-
Mark const& getInverse() const { return inverse; }
98-
Mark const& getPositive() const { return positive; }
99-
100-
static InverseMarking forInverse(Kind kind, SourceLoc loc = SourceLoc()) {
101-
InverseMarking marking;
102-
marking.inverse.set(kind, loc);
103-
marking.positive.set(Kind::None);
104-
return marking;
105-
}
10686
};
10787

10888
}

lib/AST/ConformanceLookup.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,6 @@ getBuiltinInvertibleProtocolConformance(NominalTypeDecl *nominal,
421421
// An inverse ~Copyable prevents conformance.
422422
return ProtocolConformanceRef::forInvalid();
423423

424-
case InverseMarking::Kind::Inferred: // ignore "inferred" inverse marking
425424
case InverseMarking::Kind::None:
426425
break;
427426
}

lib/AST/Decl.cpp

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6694,9 +6694,9 @@ NominalTypeDecl::hasInverseMarking(InvertibleProtocolKind target) const {
66946694
if (!ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics))
66956695
return InverseMarking::Mark(InverseMarking::Kind::None);
66966696

6697-
// Claim that the tuple decl has an inferred ~TARGET marking.
6697+
// Claim that the tuple decl has an explicit ~TARGET marking.
66986698
if (isa<BuiltinTupleDecl>(this))
6699-
return InverseMarking::Mark(InverseMarking::Kind::Inferred);
6699+
return InverseMarking::Mark(InverseMarking::Kind::Explicit);
67006700

67016701
if (auto P = dyn_cast<ProtocolDecl>(this))
67026702
return P->hasInverseMarking(target);
@@ -6705,57 +6705,6 @@ NominalTypeDecl::hasInverseMarking(InvertibleProtocolKind target) const {
67056705
if (auto inverse = findInverseInInheritance(getInherited(), target))
67066706
return inverse;
67076707

6708-
// Check the generic parameters for an explicit ~TARGET marking
6709-
// which would result in an Inferred ~TARGET marking for this context.
6710-
auto *gpList = getParsedGenericParams();
6711-
if (!gpList)
6712-
return InverseMarking::Mark();
6713-
6714-
llvm::SmallSet<GenericTypeParamDecl *, 4> params;
6715-
6716-
// Scan the inheritance clauses of generic parameters only for an inverse.
6717-
for (GenericTypeParamDecl *param : gpList->getParams()) {
6718-
auto inverse = findInverseInInheritance(param->getInherited(), target);
6719-
6720-
// Inverse is inferred from one of the generic parameters.
6721-
if (inverse)
6722-
return inverse.with(InverseMarking::Kind::Inferred);
6723-
6724-
params.insert(param);
6725-
}
6726-
6727-
// Next, scan the where clause and return the result.
6728-
auto whereClause = getTrailingWhereClause();
6729-
if (!whereClause)
6730-
return InverseMarking::Mark();
6731-
6732-
auto requirements = whereClause->getRequirements();
6733-
for (unsigned i : indices(requirements)) {
6734-
auto requirementRepr = requirements[i];
6735-
if (requirementRepr.getKind() != RequirementReprKind::TypeConstraint)
6736-
continue;
6737-
6738-
auto *subjectRepr =
6739-
dyn_cast<UnqualifiedIdentTypeRepr>(requirementRepr.getSubjectRepr());
6740-
6741-
if (!(subjectRepr && subjectRepr->isBound()))
6742-
continue;
6743-
6744-
auto *subjectGP =
6745-
dyn_cast<GenericTypeParamDecl>(subjectRepr->getBoundDecl());
6746-
if (!subjectGP || !params.contains(subjectGP))
6747-
continue;
6748-
6749-
auto *constraintRepr =
6750-
dyn_cast<InverseTypeRepr>(requirementRepr.getConstraintRepr());
6751-
if (!constraintRepr || constraintRepr->isInvalid())
6752-
continue;
6753-
6754-
if (constraintRepr->isInverseOf(target, getDeclContext()))
6755-
return InverseMarking::Mark(InverseMarking::Kind::Inferred,
6756-
constraintRepr->getLoc());
6757-
}
6758-
67596708
return InverseMarking::Mark();
67606709
}
67616710

lib/AST/FeatureSet.cpp

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
#include "swift/AST/Decl.h"
1616
#include "swift/AST/ExistentialLayout.h"
17-
#include "swift/AST/InverseMarking.h"
17+
#include "swift/AST/NameLookup.h"
1818
#include "swift/AST/ParameterList.h"
1919
#include "swift/AST/Pattern.h"
2020
#include "clang/AST/DeclObjC.h"
@@ -33,62 +33,6 @@ static bool usesTypeMatching(Decl *decl, llvm::function_ref<bool(Type)> fn) {
3333
return false;
3434
}
3535

36-
/// \param isRelevantInverse the function used to inspect a mark corresponding
37-
/// to an inverse to determine whether it "has" an inverse that we care about.
38-
static bool hasInverse(
39-
Decl *decl, InvertibleProtocolKind ip,
40-
std::function<bool(InverseMarking::Mark const &)> isRelevantInverse) {
41-
42-
auto getTypeDecl = [](Type type) -> TypeDecl * {
43-
if (auto genericTy = type->getAnyGeneric())
44-
return genericTy;
45-
if (auto gtpt = dyn_cast<GenericTypeParamType>(type))
46-
return gtpt->getDecl();
47-
return nullptr;
48-
};
49-
50-
if (auto *extension = dyn_cast<ExtensionDecl>(decl)) {
51-
if (auto *nominal = extension->getSelfNominalTypeDecl())
52-
return hasInverse(nominal, ip, isRelevantInverse);
53-
return false;
54-
}
55-
56-
auto hasInverseInType = [&](Type type) {
57-
return type.findIf([&](Type type) -> bool {
58-
if (auto *typeDecl = getTypeDecl(type))
59-
return hasInverse(typeDecl, ip, isRelevantInverse);
60-
return false;
61-
});
62-
};
63-
64-
if (auto *TD = dyn_cast<TypeDecl>(decl)) {
65-
if (auto *alias = dyn_cast<TypeAliasDecl>(TD))
66-
return hasInverseInType(alias->getUnderlyingType());
67-
68-
if (auto *NTD = dyn_cast<NominalTypeDecl>(TD)) {
69-
if (isRelevantInverse(NTD->hasInverseMarking(ip)))
70-
return true;
71-
}
72-
73-
if (auto *P = dyn_cast<ProtocolDecl>(TD)) {
74-
// Check the protocol's associated types too.
75-
return llvm::any_of(
76-
P->getAssociatedTypeMembers(), [&](AssociatedTypeDecl *ATD) {
77-
return isRelevantInverse(ATD->hasInverseMarking(ip));
78-
});
79-
}
80-
81-
return false;
82-
}
83-
84-
if (auto *VD = dyn_cast<ValueDecl>(decl)) {
85-
if (VD->hasInterfaceType())
86-
return hasInverseInType(VD->getInterfaceType());
87-
}
88-
89-
return false;
90-
}
91-
9236
// ----------------------------------------------------------------------------
9337
// MARK: - Standard Features
9438
// ----------------------------------------------------------------------------
@@ -255,10 +199,39 @@ static bool usesFeatureExtensionMacros(Decl *decl) {
255199
}
256200

257201
static bool usesFeatureMoveOnly(Decl *decl) {
258-
return hasInverse(decl, InvertibleProtocolKind::Copyable,
259-
[](auto &marking) -> bool {
260-
return marking.is(InverseMarking::Kind::LegacyExplicit);
261-
});
202+
if (auto *extension = dyn_cast<ExtensionDecl>(decl)) {
203+
if (auto *nominal = extension->getExtendedNominal())
204+
return usesFeatureMoveOnly(nominal);
205+
return false;
206+
}
207+
208+
auto hasInverseInType = [&](Type type) {
209+
return type.findIf([&](Type type) -> bool {
210+
if (auto *NTD = type->getAnyNominal()) {
211+
if (NTD->getAttrs().hasAttribute<MoveOnlyAttr>())
212+
return true;
213+
}
214+
return false;
215+
});
216+
};
217+
218+
if (auto *TD = dyn_cast<TypeDecl>(decl)) {
219+
if (auto *alias = dyn_cast<TypeAliasDecl>(TD))
220+
return hasInverseInType(alias->getUnderlyingType());
221+
222+
if (auto *NTD = dyn_cast<NominalTypeDecl>(TD)) {
223+
if (NTD->getAttrs().hasAttribute<MoveOnlyAttr>())
224+
return true;
225+
}
226+
227+
return false;
228+
}
229+
230+
if (auto *VD = dyn_cast<ValueDecl>(decl)) {
231+
return hasInverseInType(VD->getInterfaceType());
232+
}
233+
234+
return false;
262235
}
263236

264237
static bool usesFeatureMoveOnlyResilientTypes(Decl *decl) {
@@ -525,22 +498,49 @@ static bool usesFeatureRawLayout(Decl *decl) {
525498
UNINTERESTING_FEATURE(Embedded)
526499

527500
static bool usesFeatureNoncopyableGenerics(Decl *decl) {
528-
auto checkInverseMarking = [](auto &marking) -> bool {
529-
switch (marking.getKind()) {
530-
case InverseMarking::Kind::None:
531-
case InverseMarking::Kind::LegacyExplicit: // covered by other checks.
532-
return false;
501+
if (auto *valueDecl = dyn_cast<ValueDecl>(decl)) {
502+
if (isa<StructDecl, EnumDecl, ClassDecl>(decl)) {
503+
auto *nominalDecl = cast<NominalTypeDecl>(valueDecl);
533504

534-
case InverseMarking::Kind::Explicit:
535-
case InverseMarking::Kind::Inferred:
536-
return true;
505+
InvertibleProtocolSet inverses;
506+
bool anyObject = false;
507+
getDirectlyInheritedNominalTypeDecls(nominalDecl, inverses, anyObject);
508+
if (!inverses.empty())
509+
return true;
537510
}
538-
};
539511

540-
return hasInverse(decl, InvertibleProtocolKind::Copyable,
541-
checkInverseMarking) ||
542-
hasInverse(decl, InvertibleProtocolKind::Escapable,
543-
checkInverseMarking);
512+
if (isa<AbstractFunctionDecl>(valueDecl) ||
513+
isa<AbstractStorageDecl>(valueDecl)) {
514+
if (valueDecl->getInterfaceType().findIf([&](Type type) -> bool {
515+
if (auto *nominalDecl = type->getAnyNominal()) {
516+
if (isa<StructDecl, EnumDecl, ClassDecl>(nominalDecl))
517+
return usesFeatureNoncopyableGenerics(nominalDecl);
518+
}
519+
return false;
520+
})) {
521+
return true;
522+
}
523+
}
524+
}
525+
526+
if (auto *ext = dyn_cast<ExtensionDecl>(decl)) {
527+
if (auto *nominal = ext->getExtendedNominal())
528+
if (usesFeatureNoncopyableGenerics(nominal))
529+
return true;
530+
}
531+
532+
SmallVector<Requirement, 2> reqs;
533+
SmallVector<InverseRequirement, 2> inverseReqs;
534+
535+
if (auto *proto = dyn_cast<ProtocolDecl>(decl)) {
536+
proto->getRequirementSignature().getRequirementsWithInverses(
537+
proto, reqs, inverseReqs);
538+
} else if (auto *genCtx = decl->getAsGenericContext()) {
539+
if (auto genericSig = genCtx->getGenericSignature())
540+
genericSig->getRequirementsWithInverses(reqs, inverseReqs);
541+
}
542+
543+
return !inverseReqs.empty();
544544
}
545545

546546
static bool usesFeatureStructLetDestructuring(Decl *decl) {

lib/AST/RequirementMachine/KnuthBendix.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,8 @@ RewriteSystem::computeCriticalPair(ArrayRef<Symbol>::const_iterator from,
325325
return true;
326326
}
327327

328-
/// Computes the confluent completion using the Knuth-Bendix algorithm and
329-
/// returns a status code.
330-
///
331-
/// The first element of the pair is a status.
328+
/// Runs the Knuth-Bendix algorithm and returns a pair consisting of a
329+
/// status code and code-specific result.
332330
///
333331
/// The status is CompletionResult::MaxRuleCount if we add more than
334332
/// \p maxRuleCount rules.
@@ -341,8 +339,8 @@ RewriteSystem::computeCriticalPair(ArrayRef<Symbol>::const_iterator from,
341339
/// Otherwise, the status is CompletionResult::Success and the second element
342340
/// is zero.
343341
std::pair<CompletionResult, unsigned>
344-
RewriteSystem::computeConfluentCompletion(unsigned maxRuleCount,
345-
unsigned maxRuleLength) {
342+
RewriteSystem::performKnuthBendix(unsigned maxRuleCount,
343+
unsigned maxRuleLength) {
346344
assert(Initialized);
347345
assert(!Minimized);
348346
assert(!Frozen);

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ RequirementMachine::computeCompletion(RewriteSystem::ValidityPolicy policy) {
449449
unsigned ruleCount = System.getRules().size();
450450

451451
// First, run the Knuth-Bendix algorithm to resolve overlapping rules.
452-
auto result = System.computeConfluentCompletion(MaxRuleCount, MaxRuleLength);
452+
auto result = System.performKnuthBendix(MaxRuleCount, MaxRuleLength);
453453

454454
unsigned rulesAdded = (System.getRules().size() - ruleCount);
455455

@@ -492,7 +492,7 @@ RequirementMachine::computeCompletion(RewriteSystem::ValidityPolicy policy) {
492492
return std::make_pair(CompletionResult::MaxRuleLength,
493493
ruleCount + i);
494494
}
495-
if (newRule.getNesting() > MaxConcreteNesting) {
495+
if (newRule.getNesting() > MaxConcreteNesting + System.getDeepestInitialRule()) {
496496
return std::make_pair(CompletionResult::MaxConcreteNesting,
497497
ruleCount + i);
498498
}

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ RewriteSystem::RewriteSystem(RewriteContext &ctx)
3333
Frozen = 0;
3434
RecordLoops = 0;
3535
LongestInitialRule = 0;
36+
DeepestInitialRule = 0;
3637
}
3738

3839
RewriteSystem::~RewriteSystem() {
@@ -88,6 +89,7 @@ void RewriteSystem::initialize(
8889

8990
for (const auto &rule : getLocalRules()) {
9091
LongestInitialRule = std::max(LongestInitialRule, rule.getDepth());
92+
DeepestInitialRule = std::max(DeepestInitialRule, rule.getNesting());
9193
}
9294
}
9395

0 commit comments

Comments
 (0)