Repository: apple/swift
File: lib/IDE/SourceEntityWalker.cpp (C++)

Code before:
                           SE->isImplicit());

    if (SubscrD) {
      if (!passSubscriptReference(SubscrD, E->getLoc(), data, true))
        return Action::Stop();
    }

    // For regular subscripts (not dynamic member lookups), the index expressions
    // are always read, regardless of how the subscript is being used (read or write).
    // Do not propagate a write access kind into the subscript arguments.
    // However, for dynamic member lookup subscripts, the argument represents
    // a member being accessed, so it should reflect the access kind.
    bool isDynamicMemberLookup = false;
    if (SubscrD) {
      if (auto *args = SE->getArgs()) {
        auto &ctx = SubscrD->getASTContext();
        if (args->isUnary() &&
            args->getLabel(0) == ctx.Id_dynamicMember) {
          isDynamicMemberLookup = true;
        }
      }
    }

    if (!isDynamicMemberLookup) {
      llvm::SaveAndRestore<std::optional<AccessKind>>
          C(this->OpAccess, AccessKind::Read);
      if (!SE->getArgs()->walk(*this))
        return Action::Stop();
    } else {
      if (!SE->getArgs()->walk(*this))
        return Action::Stop();
    }

    if (SubscrD) {
      if (!passSubscriptReference(SubscrD, E->getEndLoc(), data, false))
        return Action::Stop();
    }

    // We already visited the children.
    return Action::SkipChildren(E);

  } else if (auto *KPE = dyn_cast<KeyPathExpr>(E)) {
    for (auto &component : KPE->getComponents()) {
      switch (component.getKind()) {
      case KeyPathExpr::Component::Kind::Member:
      case KeyPathExpr::Component::Kind::Subscript: {
        auto *decl = component.getDeclRef().getDecl();
        auto loc = component.getLoc();
        SourceRange range(loc, loc);
        auto Continue = passReference(
            decl, component.getComponentType(), loc, range,

Review comment (suggestion):
I don't think it matters much in practice, but I think for consistency I think this should reset back to `nullopt` rather than `Read`


```suggestion
          C(this->OpAccess, std::nullopt);
```

Code after:
                           SE->isImplicit());

    if (SubscrD) {
      if (!passSubscriptReference(SubscrD, E->getLoc(), data, true))
        return Action::Stop();
    }

    // For regular subscripts (not dynamic member lookups), the index expressions
    // are always read, regardless of how the subscript is being used (read or write).
    // Do not propagate a write access kind into the subscript arguments.
    // However, for dynamic member lookup subscripts, the argument represents
    // a member being accessed, so it should reflect the access kind.
    bool isKeyPathDynamicMemberLookup = false;
    if (auto *SD = dyn_cast_or_null<SubscriptDecl>(SubscrD)) {
      // Check if the base type has @dynamicMemberLookup
      Type baseType = SE->getBase()->getType();
      if (baseType) {
        baseType = baseType->getWithoutSpecifierType();
        if (baseType->hasDynamicMemberLookupAttribute() &&
            isValidKeyPathDynamicMemberLookup(SD)) {
          isKeyPathDynamicMemberLookup = true;
        }
      }
    }

    if (!isKeyPathDynamicMemberLookup) {
      llvm::SaveAndRestore<std::optional<AccessKind>>
          C(this->OpAccess, std::nullopt);
      if (!SE->getArgs()->walk(*this))
        return Action::Stop();
    } else {
      if (!SE->getArgs()->walk(*this))
        return Action::Stop();
    }

    if (SubscrD) {
      if (!passSubscriptReference(SubscrD, E->getEndLoc(), data, false))
        return Action::Stop();
    }

    // We already visited the children.
    return Action::SkipChildren(E);

  } else if (auto *KPE = dyn_cast<KeyPathExpr>(E)) {
    for (auto &component : KPE->getComponents()) {
      switch (component.getKind()) {
      case KeyPathExpr::Component::Kind::Member:
      case KeyPathExpr::Component::Kind::Subscript: {
        auto *decl = component.getDeclRef().getDecl();
        auto loc = component.getLoc();
        SourceRange range(loc, loc);