|
29 | 29 | #include "swift/AST/GenericEnvironment.h" |
30 | 30 | #include "swift/AST/GenericParamList.h" |
31 | 31 | #include "swift/AST/GenericSignature.h" |
| 32 | +#include "swift/AST/InverseMarking.h" |
32 | 33 | #include "swift/AST/MacroDefinition.h" |
33 | 34 | #include "swift/AST/Module.h" |
34 | 35 | #include "swift/AST/NameLookup.h" |
@@ -3360,33 +3361,66 @@ static bool usesFeatureFlowSensitiveConcurrencyCaptures(Decl *decl) { |
3360 | 3361 | return false; |
3361 | 3362 | } |
3362 | 3363 |
|
3363 | | -static bool usesFeatureMoveOnly(Decl *decl) { |
| 3364 | +/// \param isRelevantInverse the function used to inspect a mark corresponding |
| 3365 | +/// to an inverse to determine whether it "has" an inverse that we care about. |
| 3366 | +static bool hasInverseCopyable( |
| 3367 | + Decl *decl, |
| 3368 | + std::function<bool(InverseMarking const&)> isRelevantInverse) { |
| 3369 | + |
| 3370 | + auto getTypeDecl = [](Type type) -> TypeDecl* { |
| 3371 | + if (auto genericTy = type->getAnyGeneric()) |
| 3372 | + return genericTy; |
| 3373 | + if (auto gtpt = dyn_cast<GenericTypeParamType>(type)) |
| 3374 | + return gtpt->getDecl(); |
| 3375 | + return nullptr; |
| 3376 | + }; |
| 3377 | + |
3364 | 3378 | if (auto *extension = dyn_cast<ExtensionDecl>(decl)) { |
3365 | 3379 | if (auto *nominal = extension->getSelfNominalTypeDecl()) |
3366 | | - if (nominal->canBeNoncopyable()) |
| 3380 | + if (isRelevantInverse(nominal->getNoncopyableMarking())) |
3367 | 3381 | return true; |
3368 | 3382 | } |
3369 | 3383 |
|
3370 | 3384 | if (auto typeDecl = dyn_cast<TypeDecl>(decl)) { |
3371 | | - if (typeDecl->canBeNoncopyable()) |
| 3385 | + if (isRelevantInverse(typeDecl->getNoncopyableMarking())) |
3372 | 3386 | return true; |
| 3387 | + |
| 3388 | + // Check the protocol's associated types too. |
| 3389 | + if (auto proto = dyn_cast<ProtocolDecl>(decl)) { |
| 3390 | + auto hasNoncopyable = llvm::any_of(proto->getAssociatedTypeMembers(), |
| 3391 | + [&](AssociatedTypeDecl *assocTyDecl) { |
| 3392 | + return isRelevantInverse(assocTyDecl->getNoncopyableMarking()); |
| 3393 | + }); |
| 3394 | + if (hasNoncopyable) |
| 3395 | + return true; |
| 3396 | + } |
3373 | 3397 | } |
3374 | 3398 |
|
3375 | 3399 | if (auto value = dyn_cast<ValueDecl>(decl)) { |
3376 | | - // Check for move-only types in the types of this declaration. |
| 3400 | + // Check for noncopyable types in the types of this declaration. |
3377 | 3401 | if (Type type = value->getInterfaceType()) { |
3378 | | - bool hasMoveOnly = type.findIf([](Type type) { |
3379 | | - return type->isNoncopyable(); |
| 3402 | + bool hasNoncopyable = type.findIf([&](Type type) { |
| 3403 | + if (auto *typeDecl = getTypeDecl(type)) |
| 3404 | + if (isRelevantInverse(typeDecl->getNoncopyableMarking())) |
| 3405 | + return true; |
| 3406 | + |
| 3407 | + return false; |
3380 | 3408 | }); |
3381 | 3409 |
|
3382 | | - if (hasMoveOnly) |
| 3410 | + if (hasNoncopyable) |
3383 | 3411 | return true; |
3384 | 3412 | } |
3385 | 3413 | } |
3386 | 3414 |
|
3387 | 3415 | return false; |
3388 | 3416 | } |
3389 | 3417 |
|
| 3418 | +static bool usesFeatureMoveOnly(Decl *decl) { |
| 3419 | + return hasInverseCopyable(decl, [](auto &marking) -> bool { |
| 3420 | + return marking.getInverse().is(InverseMarking::Kind::LegacyExplicit); |
| 3421 | + }); |
| 3422 | +} |
| 3423 | + |
3390 | 3424 | static bool usesFeatureLazyImmediate(Decl *D) { return false; } |
3391 | 3425 |
|
3392 | 3426 | static bool usesFeatureMoveOnlyClasses(Decl *decl) { |
@@ -3424,9 +3458,17 @@ static bool usesFeatureMoveOnlyPartialConsumption(Decl *decl) { |
3424 | 3458 | } |
3425 | 3459 |
|
3426 | 3460 | static bool usesFeatureNoncopyableGenerics(Decl *decl) { |
3427 | | - // FIXME: need to look for suppressed entries on generic parameters or |
3428 | | - // inheritance clauses! |
3429 | | - return false; |
| 3461 | + return hasInverseCopyable(decl, [](auto &marking) -> bool { |
| 3462 | + switch (marking.getInverse().getKind()) { |
| 3463 | + case InverseMarking::Kind::None: |
| 3464 | + case InverseMarking::Kind::LegacyExplicit: // covered by MoveOnly |
| 3465 | + return false; |
| 3466 | + |
| 3467 | + case InverseMarking::Kind::Explicit: |
| 3468 | + case InverseMarking::Kind::Inferred: |
| 3469 | + return true; |
| 3470 | + } |
| 3471 | + }); |
3430 | 3472 | } |
3431 | 3473 |
|
3432 | 3474 | static bool usesFeatureOneWayClosureParameters(Decl *decl) { |
@@ -7207,17 +7249,29 @@ class TypePrinter : public TypeVisitor<TypePrinter> { |
7207 | 7249 | } |
7208 | 7250 |
|
7209 | 7251 | void visitProtocolCompositionType(ProtocolCompositionType *T) { |
7210 | | - if (T->getMembers().empty()) { |
7211 | | - if (T->hasExplicitAnyObject()) |
7212 | | - Printer << "AnyObject"; |
7213 | | - else |
7214 | | - Printer.printKeyword("Any", Options); |
7215 | | - } else { |
7216 | | - interleave(T->getMembers(), [&](Type Ty) { visit(Ty); }, |
7217 | | - [&] { Printer << " & "; }); |
7218 | | - if (T->hasExplicitAnyObject()) |
7219 | | - Printer << " & AnyObject"; |
7220 | | - } |
| 7252 | + interleave(T->getMembers(), [&](Type Ty) { visit(Ty); }, |
| 7253 | + [&] { Printer << " & "; }); |
| 7254 | + |
| 7255 | + bool printed = !T->getMembers().empty(); |
| 7256 | + auto printSpecial = [&](llvm::StringRef str, bool tilde=false) { |
| 7257 | + if (printed) |
| 7258 | + Printer << " & "; |
| 7259 | + |
| 7260 | + if (tilde) |
| 7261 | + Printer << "~"; |
| 7262 | + |
| 7263 | + Printer << str; |
| 7264 | + printed = true; |
| 7265 | + }; |
| 7266 | + |
| 7267 | + if (T->hasExplicitAnyObject()) |
| 7268 | + printSpecial("AnyObject"); |
| 7269 | + |
| 7270 | + for (auto ip : T->getInverses()) |
| 7271 | + printSpecial(getProtocolName(getKnownProtocolKind(ip)), true); |
| 7272 | + |
| 7273 | + if (!printed) |
| 7274 | + Printer.printKeyword("Any", Options); |
7221 | 7275 | } |
7222 | 7276 |
|
7223 | 7277 | void visitParameterizedProtocolType(ParameterizedProtocolType *T) { |
|
0 commit comments