Skip to content

fix(decompiler): unbound method-ref cast for Object methods + fixUnreachableDefaultThrow#7

Merged
VillanCh merged 1 commit into
mainfrom
fix/commons-lang3-final-clearout
Jul 15, 2026
Merged

fix(decompiler): unbound method-ref cast for Object methods + fixUnreachableDefaultThrow#7
VillanCh merged 1 commit into
mainfrom
fix/commons-lang3-final-clearout

Conversation

@VillanCh

Copy link
Copy Markdown
Contributor

Two fixes clearing commons-lang3 tree errors, zero-regression on all 8 jars.

  1. Unbound method-ref FI cast (JDEC_LAMBDA_RAW_JDK_RECV_CAST_OFF): cast method references targeting Object-inherited methods (toString/hashCode/equals) on raw Stream/Optional. Clears MethodUtils map(Method::toString). Gated to Object methods only to avoid spring/fastjson2 regression.

  2. fixUnreachableDefaultThrow (JDEC_FIX_UNREACHABLE_DEFAULT_THROW_OFF): removes unreachable throw from empty switch default when post-switch code is a real statement. Clears RandomStringUtils. Keeps throw when next line starts with } (block exit).

Results: commons-lang3 2->1, all provenClean 0, spring 28 same, guava 26 same. Test: unbound_methodref_object_method_test.go.

… + fixUnreachableDefaultThrow

Two fixes clearing commons-lang3 tree errors, zero-regression on all 8 jars.

1. Unbound method-ref FI cast for Object-inherited methods on raw JDK receivers
   (lambdaArgRawJDKReceiverCast, JDEC_LAMBDA_RAW_JDK_RECV_CAST_OFF):
   When a method reference targets a method inherited from java.lang.Object
   (toString, hashCode, equals, getClass, clone, finalize) and the receiver is a
   raw Stream/Optional, javac tries to bind the ref to Object version (0 args)
   instead of the unbound instance form (1 arg = receiver), causing "invalid
   method reference". The cast (Function<Method, String>) Method::toString
   re-targets the SAM so javac uses the unbound form. Gated by:
   - InstantiatedMtdDesc first param is a non-Object class (unbound instance ref)
   - method name is in objectInheritedMethodNames (toString/hashCode/equals/etc.)
   For methods NOT on Object (e.g. MergedAnnotation::withNonMergedAttributes),
   javac resolves the unbound form correctly and the cast is skipped (it would
   break downstream type inference). Clears commons-lang3 MethodUtils
   map(Method::toString). Zero regression: spring stays 28, fastjson2 stays 0.

2. fixUnreachableDefaultThrow (JDEC_FIX_UNREACHABLE_DEFAULT_THROW_OFF):
   Post-processing fix that removes a throw new RuntimeException() inserted by
   fixEmptySwitchDefault into an empty default: when the switch is followed by
   an ACTUAL statement (not a block-closing }). In that case the empty default
   falls through to the post-switch code, and the throw makes it unreachable
   ("unreachable statement"). The throw is only removed when the first non-blank
   line after the switch-closing } does NOT start with } (real statement like
   continue;), keeping it when the next line is }else{ or } (block exit where
   the throw is needed). Clears commons-lang3 RandomStringUtils unreachable
   statement. Zero regression: fastjson2 ToBoolean (switch close followed by
   }else{) keeps its throw.

Load-bearing test: unbound_methodref_object_method_test.go with UnboundMethodRefSeed.
Commons-lang3: 2->1 (MethodUtils and RandomStringUtils fixed; NumberUtils
missing-return-statement remains as a latent control-flow issue).
@VillanCh
VillanCh merged commit f633a5b into main Jul 15, 2026
13 checks passed
@VillanCh
VillanCh deleted the fix/commons-lang3-final-clearout branch July 15, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant