@@ -2586,7 +2586,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
2586
2586
2587
2587
// FIXME(kavon): see if these can be integrated into other parts of Sema
2588
2588
diagnoseCopyableTypeContainingMoveOnlyType (ED);
2589
- diagnoseMoveOnlyNominalDeclDoesntConformToProtocols (ED);
2589
+ diagnoseIncompatibleProtocolsForMoveOnlyType (ED);
2590
2590
2591
2591
checkExplicitAvailability (ED);
2592
2592
@@ -2645,7 +2645,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
2645
2645
// are not move only.
2646
2646
diagnoseCopyableTypeContainingMoveOnlyType (SD);
2647
2647
2648
- diagnoseMoveOnlyNominalDeclDoesntConformToProtocols (SD);
2648
+ diagnoseIncompatibleProtocolsForMoveOnlyType (SD);
2649
2649
}
2650
2650
2651
2651
// / Check whether the given properties can be @NSManaged in this class.
@@ -2747,21 +2747,53 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
2747
2747
}
2748
2748
}
2749
2749
2750
- void diagnoseMoveOnlyNominalDeclDoesntConformToProtocols (
2751
- NominalTypeDecl *nomDecl) {
2752
- if (!nomDecl->isMoveOnly ())
2753
- return ;
2750
+ // / check to see if a move-only type can ever conform to the given type.
2751
+ // / \returns true iff a diagnostic was emitted because it was not compatible
2752
+ static bool diagnoseIncompatibleWithMoveOnlyType (SourceLoc loc,
2753
+ NominalTypeDecl *moveonlyType,
2754
+ Type type) {
2755
+ assert (type && " got an empty type?" );
2756
+ assert (moveonlyType->isMoveOnly ());
2754
2757
2755
- for (auto *prot : nomDecl->getLocalProtocols ()) {
2758
+ auto canType = type->getCanonicalType ();
2759
+ if (auto prot = canType->getAs <ProtocolType>()) {
2756
2760
// Permit conformance to marker protocol Sendable.
2757
- if (prot->isSpecificProtocol (KnownProtocolKind::Sendable)) {
2758
- assert (prot->isMarkerProtocol ());
2759
- continue ;
2761
+ if (prot->getDecl ()-> isSpecificProtocol (KnownProtocolKind::Sendable)) {
2762
+ assert (prot->getDecl ()-> isMarkerProtocol ());
2763
+ return false ;
2760
2764
}
2765
+ }
2761
2766
2762
- nomDecl->diagnose (diag::moveonly_cannot_conform_to_protocol_with_name,
2763
- nomDecl->getDescriptiveKind (),
2764
- nomDecl->getBaseName (), prot->getBaseName ());
2767
+ auto &ctx = moveonlyType->getASTContext ();
2768
+ ctx.Diags .diagnose (loc,
2769
+ diag::moveonly_cannot_conform_to_type,
2770
+ moveonlyType->getDescriptiveKind (),
2771
+ moveonlyType->getBaseName (),
2772
+ type);
2773
+ return true ;
2774
+ }
2775
+
2776
+ static void diagnoseIncompatibleProtocolsForMoveOnlyType (Decl *decl) {
2777
+ if (auto *nomDecl = dyn_cast<NominalTypeDecl>(decl)) {
2778
+ if (!nomDecl->isMoveOnly ())
2779
+ return ;
2780
+
2781
+ // go over the all protocols directly conformed-to by this nominal
2782
+ for (auto *prot : nomDecl->getLocalProtocols ())
2783
+ diagnoseIncompatibleWithMoveOnlyType (nomDecl->getLoc (), nomDecl,
2784
+ prot->getDeclaredInterfaceType ());
2785
+
2786
+ } else if (auto *extension = dyn_cast<ExtensionDecl>(decl)) {
2787
+ if (auto *nomDecl = extension->getExtendedNominal ()) {
2788
+ if (!nomDecl->isMoveOnly ())
2789
+ return ;
2790
+
2791
+ // go over the all types directly conformed-to by the extension
2792
+ for (auto entry : extension->getInherited ()) {
2793
+ diagnoseIncompatibleWithMoveOnlyType (extension->getLoc (), nomDecl,
2794
+ entry.getType ());
2795
+ }
2796
+ }
2765
2797
}
2766
2798
}
2767
2799
@@ -2928,7 +2960,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
2928
2960
2929
2961
maybeDiagnoseClassWithoutInitializers (CD);
2930
2962
2931
- diagnoseMoveOnlyNominalDeclDoesntConformToProtocols (CD);
2963
+ diagnoseIncompatibleProtocolsForMoveOnlyType (CD);
2932
2964
2933
2965
// Ban non-final classes from having move only fields.
2934
2966
if (!CD->isFinal ()) {
@@ -3404,11 +3436,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
3404
3436
if (nominal->isDistributedActor ())
3405
3437
TypeChecker::checkDistributedActor (SF, nominal);
3406
3438
3407
- // If we have a move only type and allow it to extend any protocol, error.
3408
- if (nominal->isMoveOnly () && ED->getInherited ().size ()) {
3409
- ED->diagnose (diag::moveonly_cannot_conform_to_protocol,
3410
- nominal->getDescriptiveKind (), nominal->getBaseName ());
3411
- }
3439
+ diagnoseIncompatibleProtocolsForMoveOnlyType (ED);
3412
3440
3413
3441
TypeChecker::checkReflectionMetadataAttributes (ED);
3414
3442
}
0 commit comments