ExtensionMacro on a nested type does not generate extension at top level?

Hi! I'm seeing some unexpected behavior with using ExtensionMacro. According to SE-0402[1] we can expect that an ExtensionMacro applied to a nested type will generate an extension at top-level. I am testing with an ExtensionMacro example from the swift-syntax repo and I am seeing the extension generated at local scope:

struct Outer {
  @Observable
  struct Inner {}
}

Expands to:

struct Outer {
  
  struct Inner {
    
    let _registrar = ObservationRegistrar<Inner >()
    
    public nonisolated func addObserver(_ observer: some Observer<Inner >) {
      _registrar.addObserver(observer)
    }
    
    public nonisolated func removeObserver(_ observer: some Observer<Inner >) {
      _registrar.removeObserver(observer)
    }
    
    private func withTransaction<T>(_ apply: () throws -> T) rethrows -> T {
      _registrar.beginAccess()
      defer {
        _registrar.endAccess()
      }
      return try apply()
    }
    
    private struct Storage {
      
    }
    
    private var _storage = Storage()
  }
  
  extension Outer.Inner: Observable {
  }
  
}

Is this a known issue being tracked? I've searched through forums and GitHub and I didn't see this already. Is there any place I can follow along to learn more about a potential fix or workaround? Thanks!

Here is a diff on swift-syntax to repro:

diff --git a/Examples/Sources/MacroExamples/Playground/main.swift b/Examples/Sources/MacroExamples/Playground/main.swift
index 6df22c09..00df357b 100644
--- a/Examples/Sources/MacroExamples/Playground/main.swift
+++ b/Examples/Sources/MacroExamples/Playground/main.swift
@@ -84,6 +84,11 @@ print("Point storage contains only the value we set:  \(point)")
 
 // MARK: - ObservableMacro
 
+struct Outer {
+  @Observable
+  struct Inner {}
+}
+
 struct Treat {}
 
 @Observable


  1. swift-evolution/proposals/0402-extension-macros.md at main · apple/swift-evolution · GitHub ↩︎

Is this using assertMacroExpansion?

@ahoppen Ahh… good question! I apologize for not adding that I am trying to expand from Xcode Version 15.3 (15E204a) using Expand Macro and Inline Macro. Maybe this is an Xcode issue?

Ah, I see. I did remember that we fixed something for assertMacroExpansion. Could you file an issue on Sign in to GitHub · GitHub for Inline Macro putting the extension into the nested type and not at the top level?

1 Like

Ahh… interesting! I just now wrote a test using assertMacroExpansion and my test is passing… but only on latest main. That same test fails on the production 510.0.1 commit. This is expected? Would the implication be that those test failures in production are false negatives (and this code really works even when the test fails)?

Yes, that’s what I meant by remembering that we fixed something along those lines for assertMacroExpansion. I think it’s still worth filing an issue for the same issue during compilation and the Inline Macro refactoring, which uses a slightly different code path.

Edit: Just saw that you filed the issue Expand Macro and Inline Macro commands put extension macro expansion in nested type and not at top level. · Issue #73140 · apple/swift · GitHub. Thanks :pray:

1 Like