@@ -60,10 +60,8 @@ SubstitutionMap::SubstitutionMap(
6060 ArrayRef<Type> replacementTypes,
6161 ArrayRef<ProtocolConformanceRef> conformances)
6262 : storage(Storage::get(genericSig, replacementTypes, conformances)) {
63- #ifndef NDEBUG
6463 if (genericSig->getASTContext ().LangOpts .VerifyAllSubstitutionMaps )
6564 verify ();
66- #endif
6765}
6866
6967ArrayRef<ProtocolConformanceRef> SubstitutionMap::getConformances () const {
@@ -534,78 +532,109 @@ SubstitutionMap::getOverrideSubstitutions(const NominalTypeDecl *baseNominal,
534532 LookUpConformanceInOverrideSubs (info));
535533}
536534
537- void SubstitutionMap::verify () const {
538- #ifndef NDEBUG
535+ void SubstitutionMap::verify (bool allowInvalid) const {
539536 if (empty ())
540537 return ;
541538
539+ auto genericSig = getGenericSignature ();
540+ auto &ctx = genericSig->getASTContext ();
541+
542+ if (ctx.isRecursivelyConstructingRequirementMachine (
543+ genericSig.getCanonicalSignature ()))
544+ return ;
545+
542546 unsigned conformanceIndex = 0 ;
543547
544- for (const auto &req : getGenericSignature () .getRequirements ()) {
548+ for (const auto &req : genericSig .getRequirements ()) {
545549 if (req.getKind () != RequirementKind::Conformance)
546550 continue ;
547551
548552 SWIFT_DEFER { ++conformanceIndex; };
553+ auto conformance = getConformances ()[conformanceIndex];
554+
549555 auto substType = req.getFirstType ().subst (*this );
550- if (substType->isTypeParameter () ||
551- substType->is <ArchetypeType>() ||
552- substType->isTypeVariableOrMember () ||
553- substType->is <UnresolvedType>() ||
554- substType->hasError ())
555- continue ;
556556
557- auto conformance = getConformances ()[conformanceIndex];
557+ // Unwrap various strange things.
558+ substType = substType->getReferenceStorageReferent ();
559+ if (auto *selfType = substType->getAs <DynamicSelfType>())
560+ substType = selfType->getSelfType ();
558561
559- if (conformance.isInvalid ())
560- continue ;
562+ // Don't bother validating these cases.
563+ if (allowInvalid && substType->hasUnboundGenericType ())
564+ return ;
565+
566+ if (conformance.isInvalid ()) {
567+ if (!allowInvalid) {
568+ llvm::errs () << " Unexpected invalid conformance in substitution map:\n " ;
569+ dump (llvm::dbgs ());
570+ llvm::errs () << " \n " ;
571+ abort ();
572+ }
561573
562- // All of the conformances should be concrete.
563- if (!conformance.isConcrete ()) {
564- llvm::dbgs () << " Concrete type cannot have abstract conformance:\n " ;
565- substType->dump (llvm::dbgs ());
566- llvm::dbgs () << " SubstitutionMap:\n " ;
567- dump (llvm::dbgs ());
568- llvm::dbgs () << " \n " ;
569- llvm::dbgs () << " Requirement:\n " ;
570- req.dump (llvm::dbgs ());
571- llvm::dbgs () << " \n " ;
574+ continue ;
572575 }
573- assert (conformance.isConcrete () && " Conformance should be concrete" );
574-
575- if (substType->is <UnboundGenericType>())
576+
577+ if (conformance.isAbstract ()) {
578+ if (!substType->isTypeParameter () &&
579+ !substType->is <PackElementType>() &&
580+ !substType->is <ArchetypeType>() &&
581+ !substType->isTypeVariableOrMember () &&
582+ !substType->is <UnresolvedType>() &&
583+ !substType->is <PlaceholderType>() &&
584+ !substType->is <ErrorType>()) {
585+ llvm::errs () << " Unexpected abstract conformance in substitution map:\n " ;
586+ dump (llvm::errs ());
587+ llvm::errs () << " \n " ;
588+ abort ();
589+ }
590+
576591 continue ;
577-
578- auto conformanceTy = conformance.getConcrete ()->getType ();
579- if (conformanceTy->hasTypeParameter ()
580- && !substType->hasTypeParameter ()) {
581- conformanceTy = conformance.getConcrete ()->getDeclContext ()
582- ->mapTypeIntoContext (conformanceTy);
583592 }
584-
585- if (!substType->isEqual (conformanceTy)) {
586- llvm::dbgs () << " Conformance must match concrete replacement type:\n " ;
587- substType->dump (llvm::dbgs ());
588- llvm::dbgs () << " Conformance type:\n " ;
589- conformance.getConcrete ()->getType ()->dump (llvm::dbgs ());
590- llvm::dbgs () << " Conformance:\n " ;
591- conformance.dump (llvm::dbgs ());
592- llvm::dbgs () << " \n " ;
593- llvm::dbgs () << " SubstitutionMap:\n " ;
594- dump (llvm::dbgs ());
595- llvm::dbgs () << " \n " ;
596- llvm::dbgs () << " Requirement:\n " ;
597- req.dump (llvm::dbgs ());
598- llvm::dbgs () << " \n " ;
593+
594+ if (conformance.isPack ()) {
595+ // FIXME: Implement some kind of check here.
596+ continue ;
599597 }
600- assert (substType-> isEqual (conformanceTy)
601- && " conformance should match corresponding type " );
598+
599+ auto *concrete = conformance. getConcrete ( );
602600
603601 if (substType->isExistentialType ()) {
604- assert (isa<SelfProtocolConformance>(conformance.getConcrete ()) &&
605- " Existential type cannot have normal conformance" );
602+ if (req.getProtocolDecl ()->isSpecificProtocol (KnownProtocolKind::Sendable) &&
603+ isa<BuiltinProtocolConformance>(concrete)) {
604+ continue ;
605+ }
606+
607+ if (!isa<SelfProtocolConformance>(concrete)) {
608+ // A superclass-constrained self-conforming existential might conform
609+ // concretely.
610+ if (substType->getSuperclass ())
611+ continue ;
612+
613+ llvm::errs () << " Expected to find a self conformance:\n " ;
614+ substType->dump (llvm::errs ());
615+ llvm::errs () << " Substitution map:\n " ;
616+ dump (llvm::errs ());
617+ llvm::errs () << " \n " ;
618+ abort ();
619+ }
620+
621+ continue ;
622+ }
623+
624+ if (substType->isTypeParameter ())
625+ continue ;
626+
627+ if (!concrete->getType ()->isEqual (substType)) {
628+ llvm::errs () << " Conformance with wrong conforming type:\n " ;
629+ concrete->getType ()->dump (llvm::errs ());
630+ llvm::errs () << " Should be:\n " ;
631+ substType->dump (llvm::errs ());
632+ llvm::errs () << " Substitution map:\n " ;
633+ dump (llvm::errs ());
634+ llvm::errs () << " \n " ;
635+ abort ();
606636 }
607637 }
608- #endif
609638}
610639
611640void SubstitutionMap::profile (llvm::FoldingSetNodeID &id) const {
0 commit comments