Url1 == url2, but behavior differs

I wanted to ask about an issue I found and whether there is already a bug to track it. When dealing with security scoped URLs created via init(resolvingBookmarkData:options:relativeTo:bookmarkDataIsStale:).

Initially, when resolving bookmark data, I had a check for if resolvedURL != self.url { self.url = resolvedURL } . However, this led to permission errors. Once I removed the if condition and unconditionally set self.url = resolvedURL, the errors went away. This seems to violate Equatable semantics, which has the following guarantee: "Equality implies substitutability—any two instances that compare equally can be used interchangeably in any code that depends on their values."

If anyone wants more info I can try to distill this into a minimal example and file a bug, but I wanted to check whether such an issue was known before I went to that effort since directory bookmarks can be a little annoying to work with.

I don't know anything about this particular case, but that definition of equality is either too restrictive (e.g. ObjectIdentifier breaks this for all class instances) or you have to be careful about defining what substitutability really means in practice (i.e. some aspects are salient for equality and some aren't, e.g. Sets and Dictionaries that compare equal may iterate in different orders). I don't know if the security/permission status of the URL is/should be considered “salient” in that sense.

Maybe I’m misunderstanding what you meant, but doesn’t ObjectIdentifier only compare equal when you’re dealing with the exact same instance? I don’t see how that breaks substitutability (since the implication is uni-directional). As for Set and Dictionary, relying on their iteration order is a bug, so for all correct uses of those objects they would be substitutable. If there are other deviations from these semantics I’d love to know—those should probably be tracked as bugs as well :slight_smile:

There are going to be deviations you can find in many places. The documentation wording is overly strong: the semantic guarantee is that equivalence by == implies substitutability for all salient features, where that is determined by the type itself. Indeed that is the entire point of having a user-customizable equivalence relation.

Now, whatever the flexibility offered, in this specific case it’s pretty clear that equivalence did not imply substitutability for the principal use case of the value, so that’s clearly a bug. Since it’s an Apple-specific feature, that merits a bug report in Radar.

2 Likes

Thanks, that makes sense! Did not realize that the operating usage of Equatable differed from the documentation in that regard. It still seems like a documentation bug if that deviation is not documented, or at least on Equatable since the wording is stronger than what is done in practice.

Yes, exactly, so two instances that compare equal can have different ObjectIdentifiers, i.e. they are not substitutable in contexts that examine the object identifier.