hasAttribute only supports declaration attributes?

The codebase I'm working in compiles against both nightly and Xcode versions of Swift, which means we've recently started getting hit with the warnings about retroactive conformances on the bleeding edge compilation pipeline. In an attempt to smooth things over until Xcode catches up, we attempted to use #if hasAttribute(retroactive) (around the whole extension) to guard the use of @retroactive on the conformances we wanted to keep, only to surprisingly find that the nightly toolchain was taking the #else path. From looking at the implementation, it appears that hasAttribute is only checking against declaration attributes, though I see no mention of such a restriction in the original proposal.

It seems like this was just an oversight (i.e., bug) and that we should be checking against all attributes here, but is there something I'm missing?

cc @Douglas_Gregor


I also don't recall any discussion that hasAttribute would work only for declaration attributes.

That said, for this particular use case, the alternative of fully qualifying the conformance is backward compatible. I'm sure you're aware but just bringing it up for completeness for those following along.


You can use hasFeature(RetroactiveAttribute) instead. If you want to support swift 5.7 you need a workaround like we use in swift-nio: use feature-specific guard for @retroactive by rnro · Pull Request #2581 · apple/swift-nio · GitHub

1 Like

...you know, I had forgotten that we'd kept that option in as a backwards-compatibility kludge. I was so sure that hasAttribute should work here I totally glossed over it. :person_facepalming:

Yeah thankfully we're not supporting behind latest Xcode at this point so we get to avoid that. :slight_smile:

We found out that hasFeature(RetroactiveAttribute) doesn't actually work as expected, but $RetroactiveAttribute does. See Nightly builds have `@retroactive` but `hasFeature(RetroactiveAttribute)` is `false` · Issue #69643 · apple/swift · GitHub for more details.

1 Like

Ah yeah, meant to loop back here to ask if you were actually able to observe that working, we saw the same thing. Ended up settling on a Swift version check.