siom79 commented on PR #1888:
URL: https://github.com/apache/maven-resolver/pull/1888#issuecomment-4557249511

   ### Root Cause
   
   The errors stem from two independent changes that interact with each other:
   
   **1. A deliberate API change in `GenericVersionScheme` (February 2023, 
commit `7872699c`, PR #242)**
   
   The three methods were changed from returning the abstract interface types 
to returning their
   concrete implementations (covariant return types):
   
   | Method | Old return type | New return type |
   |---|---|---|
   | `parseVersion(String)` | `Version` | `GenericVersion` |
   | `parseVersionRange(String)` | `VersionRange` | `GenericVersionRange` |
   | `parseVersionConstraint(String)` | `VersionConstraint` | 
`GenericVersionConstraint` |
   
   The motivation was explicitly documented in the commit message: *"generic 
scheme creates
   generic components: usually is directly instantiated, this just made a lot 
of casting issues."*
   This is a legitimate and intentional improvement.
   
   **2. A bug fix in japicmp 0.25.7 (issue #507, PR #508)**
   
   Prior to 0.25.7, japicmp incorrectly matched non-bridge methods against 
compiler-generated
   bridge methods when comparing class versions. This caused the covariant 
return type change
   above to go undetected for years. The fix in 0.25.7 corrected the 
bridge-method matching
   logic, which now surfaces the 2023 change as `METHOD_RETURN_TYPE_CHANGED`.
   
   ### Is This a Real Binary Incompatibility?
   
   **No.** Covariant return types are explicitly supported by the Java Language 
Specification
   (JLS ยง8.4.5) and are designed to be backward-compatible. When 
`GenericVersionScheme`
   declares `GenericVersion parseVersion(String)`, the Java compiler 
automatically generates
   a bridge method:
   ```
   // real method (new callers use this)
   public GenericVersion parseVersion(String) { ... }
   // compiler-generated bridge (preserves binary compatibility for old callers)
   public synthetic bridge Version parseVersion(String) {
   return this.parseVersion(String);  // delegates to real method
   }
   ```
   Any code compiled against the old API that calls `Version v = 
scheme.parseVersion(...)` will
   find the bridge method at runtime and continue to work without 
recompilation. A
   `NoSuchMethodError` cannot occur.
   
   The only scenario where this change can cause a real (silent) breakage is 
**subclassing**:
   if a third party extends `GenericVersionScheme` and overrides `parseVersion` 
with the old
   `Version` return type, that override no longer overrides the non-bridge 
method. This is a
   legitimate concern, but it is a different and narrower category than a full 
binary
   incompatibility.
   
   ### Relationship to japicmp
   
   The detection itself is correct โ€” the API *did* change in 2023 and japicmp 
0.25.6 was
   silently missing it due to its own bug. However, japicmp classifies 
covariant return type
   changes in the same category as genuinely incompatible return type changes, 
which is
   overly strict.
   
   A dedicated issue has been filed with the japicmp project to introduce a 
separate, less
   severe classification for this pattern 
(`METHOD_RETURN_TYPE_COVARIANT_CHANGED`), treated
   as compatible by default:
   ๐Ÿ‘‰ https://github.com/siom79/japicmp/issues/522
   
   ### Recommended Fix for This Project
   
   Until japicmp handles covariant return type changes natively, the 
appropriate fix on the
   maven-resolver side is to add explicit exclusion rules in the japicmp 
configuration for
   these three methods. The 2023 change was intentional, well-motivated, and 
binary-safe:
   
   ```xml
   <excludes>
     <exclude>
       
org.eclipse.aether.util.version.GenericVersionScheme#parseVersion(java.lang.String)
     </exclude>
     <exclude>
       
org.eclipse.aether.util.version.GenericVersionScheme#parseVersionRange(java.lang.String)
     </exclude>
     <exclude>
       
org.eclipse.aether.util.version.GenericVersionScheme#parseVersionConstraint(java.lang.String)
     </exclude>
   </excludes>
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to