Repository: apple/swift
File: lib/Sema/TypeCheckConcurrency.cpp (C++)

Code before:
    if (conformance->getKind() == ProtocolConformanceKind::Inherited &&
        ctx.LangOpts.hasFeature(Feature::GlobalActorIsolatedTypesUsability)) {
      continue;
    }

    auto *proto = conformance->getProtocol();
    switch (auto protoIsolation = getActorIsolation(proto)) {
    case ActorIsolation::ActorInstance:
    case ActorIsolation::Unspecified:
    case ActorIsolation::Nonisolated:
    case ActorIsolation::CallerIsolationInheriting:
    case ActorIsolation::NonisolatedUnsafe:
      break;

    case ActorIsolation::Erased:
      llvm_unreachable("protocol cannot have erased isolation");

    case ActorIsolation::GlobalActor:
      if (!foundIsolation) {
        foundIsolation = {
          protoIsolation,
          IsolationSource(proto, IsolationSource::Conformance)
        };
        continue;
      }

      if (foundIsolation->isolation != protoIsolation)
        return std::nullopt;

      break;
    }
  }

  return foundIsolation;
}

/// Compute the isolation of a protocol
static std::optional<InferredActorIsolation>
getIsolationFromInheritedProtocols(ProtocolDecl *protocol) {
  std::optional<InferredActorIsolation> foundIsolation;
  bool conflict = false;

  auto inferIsolation = [&](ValueDecl *decl) {
    switch (auto protoIsolation = getActorIsolation(decl)) {
    case ActorIsolation::ActorInstance:
    case ActorIsolation::Unspecified:
    case ActorIsolation::Nonisolated:
    case ActorIsolation::CallerIsolationInheriting:
    case ActorIsolation::NonisolatedUnsafe:
      return;


Review comment (suggestion):
Is `@MainActor` still inferred for `S` below?

```swift
nonisolated protocol P1 {}
@MainActor protocol P2: P1 {}

do {
  struct S: P2 {
    func f() {}
  }

  nonisolated func test() {
    S().f()
  }
}
```

Code after:
  auto &ctx = nominal->getASTContext();

  if (isa<ProtocolDecl>(nominal))
    return std::nullopt;

  std::optional<InferredActorIsolation> foundIsolation;
  for (auto conformance :
       nominal->getLocalConformances(ConformanceLookupKind::NonStructural)) {

    // Don't include inherited conformances. If a conformance is inherited
    // from a superclass, the isolation of the subclass should be inferred
    // from the superclass, which is done directly in ActorIsolationRequest.
    // If the superclass has opted out of global actor inference, such as
    // by conforming to the protocol in an extension, then the subclass should
    // not infer isolation from the protocol.
    //
    // Gate this change behind an upcoming feature flag; isolation inference
    // changes can break source in language modes < 6.
    if (conformance->getKind() == ProtocolConformanceKind::Inherited &&
        ctx.LangOpts.hasFeature(Feature::GlobalActorIsolatedTypesUsability)) {
      continue;
    }

    auto *proto = conformance->getProtocol();
    auto inferredIsolation = getInferredActorIsolation(proto);
    auto protoIsolation = inferredIsolation.isolation;
    switch (protoIsolation) {
    case ActorIsolation::ActorInstance:
    case ActorIsolation::Unspecified:
    case ActorIsolation::CallerIsolationInheriting:
    case ActorIsolation::NonisolatedUnsafe:
      break;
    case ActorIsolation::Nonisolated:
      if (inferredIsolation.source.kind == IsolationSource::Kind::Explicit) {
        if (!foundIsolation) {
          // We found an explicitly 'nonisolated' protocol.
          foundIsolation = {
              protoIsolation,
              IsolationSource(proto, IsolationSource::Conformance)};
        }
        continue;
      } else {
        break;
      }

    case ActorIsolation::Erased:
      llvm_unreachable("protocol cannot have erased isolation");

    case ActorIsolation::GlobalActor:
      // If we encountered an explicit globally isolated conformance, allow it
      // to override the nonisolated isolation kind.