2323#include " swift/AST/Module.h"
2424#include " swift/AST/Types.h"
2525#include " swift/Basic/Assertions.h"
26+ #include " RequirementMachine/RequirementLowering.h"
2627
2728using namespace swift ;
2829
@@ -364,10 +365,51 @@ InvertibleProtocolKind InverseRequirement::getKind() const {
364365 return *getInvertibleProtocolKind (*(protocol->getKnownProtocolKind ()));
365366}
366367
368+ // / Do these two ArrayRefs alias any of the same memory?
369+ template <typename T>
370+ bool arrayrefs_overlap (ArrayRef<T> A, ArrayRef<T> B) {
371+ if (A.empty () || B.empty ())
372+ return false ;
373+
374+ const T *ABegin = A.data ();
375+ const T *AEnd = ABegin + A.size ();
376+ const T *BBegin = B.data ();
377+ const T *BEnd = BBegin + B.size ();
378+
379+ return ABegin < BEnd && BBegin < AEnd;
380+ }
381+
367382void InverseRequirement::expandDefaults (
368383 ASTContext &ctx,
369384 ArrayRef<Type> gps,
370- SmallVectorImpl<StructuralRequirement> &result) {
385+ ArrayRef<StructuralRequirement> existingReqs,
386+ SmallVectorImpl<StructuralRequirement> &result,
387+ SmallVectorImpl<Type> &expandedGPs) {
388+ // If there are no subjects, there's nothing to expand.
389+ if (gps.empty ())
390+ return ;
391+
392+ // Vectors can reallocate, so we mustn't be looking at an ArrayRef pointing
393+ // into the same span of memory that we're also mutating!
394+ ASSERT (!arrayrefs_overlap (existingReqs, {result.data (), result.size ()}) &&
395+ " requirements are aliasing!" );
396+ ASSERT (!arrayrefs_overlap (gps, {expandedGPs.data (), expandedGPs.size ()}) &&
397+ " types are aliasing!" );
398+
399+ auto expandFor = [&](Type gp) {
400+ expandedGPs.push_back (gp);
401+ for (auto ip : InvertibleProtocolSet::allKnown ()) {
402+ auto proto = ctx.getProtocol (getKnownProtocolKind (ip));
403+
404+ result.push_back ({{RequirementKind::Conformance, gp,
405+ proto->getDeclaredInterfaceType ()},
406+ SourceLoc ()});
407+ }
408+ };
409+
410+ // Used for further expansion of defaults for dependent type members of gps.
411+ // Contains the root generic parameters of the ones we were asked to expand.
412+ llvm::SmallSetVector<CanType, 8 > seenRoots;
371413 for (auto gp : gps) {
372414 // Value generics never have inverses (or the positive thereof).
373415 if (auto gpTy = gp->getAs <GenericTypeParamType>()) {
@@ -376,11 +418,57 @@ void InverseRequirement::expandDefaults(
376418 }
377419 }
378420
379- for (auto ip : InvertibleProtocolSet::allKnown ()) {
380- auto proto = ctx.getProtocol (getKnownProtocolKind (ip));
381- result.push_back ({{RequirementKind::Conformance, gp,
382- proto->getDeclaredInterfaceType ()},
383- SourceLoc ()});
421+ // Each generic parameter is inferred to have a conformance requirement
422+ // to all invertible protocols, regardless of what other requirements exist.
423+ // We later cancel them out in applyInverses.
424+ expandFor (gp);
425+ seenRoots.insert (gp->getDependentMemberRoot ()->getCanonicalType ());
426+ }
427+
428+ // Look for structural requirements stating type parameter G conforms to P.
429+ // If P has a primary associatedtype P.A, infer default requirements for G.A
430+ // For example, given protocol,
431+ //
432+ // protocol P<A>: ~Copyable { associatedtype A: ~Copyable }
433+ //
434+ // For an initial gp [T] and structural requirements [T: P, T.A: P],
435+ // we proceed with one pass over the original structural requirements:
436+ //
437+ // 1. Expand new requirement 'T: Copyable' (already done earlier)
438+ // 2. Because of requirement 'T: P', infer requirement [T.A: Copyable]
439+ // 4. Because of requirement 'T.A: P', infer requirement [T.A.A: Copyable]
440+ // 5. Expansion stops, as no other structural requirements are relevant.
441+ // Because Copyable & Escapable don't have associated types, we're done.
442+ if (ctx.LangOpts .hasFeature (Feature::SuppressedAssociatedTypesWithDefaults)) {
443+ // Help avoid duplicate expansions of the same member type.
444+ llvm::SmallSetVector<CanType, 8 > dmtsExpanded;
445+
446+ for (auto const & sreq : existingReqs) {
447+ auto &req = sreq.req ;
448+ if (req.getKind () != RequirementKind::Conformance)
449+ continue ;
450+
451+ // Is this subject rooted in one we did expand defaults for?
452+ auto subject = req.getFirstType ();
453+ auto subjectRoot = subject->getDependentMemberRoot ()->getCanonicalType ();
454+ if (!seenRoots.contains (subjectRoot))
455+ continue ;
456+
457+ // Given a structural requirement `Subject: P`,
458+ // for each primary associated type A of P, expand defaults for Subject.A
459+ auto *proto = req.getProtocolDecl ();
460+ for (auto *ATD : proto->getPrimaryAssociatedTypes ()) {
461+ auto dmt = DependentMemberType::get (subject, ATD);
462+ auto cleanDMT =
463+ rewriting::stripBoundDependentMemberTypes (dmt)->getCanonicalType ();
464+
465+ // Did we already expand for the same DMT?
466+ if (dmtsExpanded.contains (cleanDMT))
467+ continue ;
468+
469+ expandFor (dmt);
470+ dmtsExpanded.insert (cleanDMT);
471+ }
384472 }
385473 }
386474}
0 commit comments