2181 Commits
Author SHA1 Message Date
Guice Team b8cab7e4e9 Internal change
RELNOTES=n/a
PiperOrigin-RevId: 992432967
2026-10-02 11:19:30 -07:00
cpovirk bb8fb34bf9 Replace calls to Runnables.doNothing() with a do-nothing lambda, () -> {}.
`Runnables.doNothing()` exists only because Java lambdas didn't exist in 2013. `() -> {}` is shorter and more standard.

PiperOrigin-RevId: 972641734
2026-08-28 09:49:46 -07:00
Sam Berlin b22f83c890 Internal change enabling kotlin stack trace demangling.
PiperOrigin-RevId: 968613165
2026-08-21 11:51:43 -07:00
cpovirk 621416a240 Modernize cancellation configuration.
https://github.com/google/guice/commit/35173790910fd604e01c763df2ce9c4ae33e5198 probably used the best tools available in 2022. But this PR's approach, which we've been using with success [in Guava](https://github.com/google/guava/blob/0adf237b742d899d00239dfeefdd42807ff46a83/.github/workflows/ci.yml#L14-L17) and in other projects, looks to be [the recommended approach](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#example-using-a-fallback-value) nowadays.

In particular, I wonder if the current setup is over-canceling: Currently, I see reports like ["Canceling since a higher priority waiting request for ci-main-b7c7483a46afadd43a2f04935aaee5ff0cd09145 exists"](https://github.com/google/guice/actions/runs/30832661591/job/91750157428) on a large number of jobs, causing GitHub to report the overall CI status as "failure."

RELNOTES=n/a
PiperOrigin-RevId: 958535716
2026-08-03 13:07:48 -07:00
cpovirk b7c7483a46 Bump JSpecify to 1.0.1.
RELNOTES=n/a
PiperOrigin-RevId: 958418513
2026-08-03 09:32:49 -07:00
cpovirk 676edd7a6e Address zizmor findings:
- [`persist-credentials: false`](https://docs.zizmor.sh/audits/#artipacked)
- [excessive permissions](https://docs.zizmor.sh/audits/#excessive-permissions)

There may be other findings, but these are the easy ones.

RELNOTES=n/a
PiperOrigin-RevId: 958407678
2026-08-03 09:08:35 -07:00
cpovirk 174317a08a [Migrate](https://bazel.build/external/migration) to Bazel's ["new" module system](https://bazel.build/external/overview).
My immediate win is that this includes migrating off the old version of bazel-common that includes `google_common_workspace_rules()`: Calling `google_common_workspace_rules()` leads to trouble under macos-latest (as previously in https://github.com/google/guice/commit/17011080a118fc2d23314ccf0d5546ce53e8b650):

```
  ERROR: /Users/runner/work/guice/guice/WORKSPACE:26:30: fetching android_sdk_repository rule //external:androidsdk: Android SDK api level 34 was requested but it is not installed in the Android SDK at /Users/runner/Library/Android/sdk. The api levels found were [36, 35]. Please choose an available api level or install api level 34 from the Android SDK Manager.
  ERROR: Analysis of target '//tools:osgi_wrapper' failed; build aborted: Android SDK api level 34 was requested but it is not installed in the Android SDK at /Users/runner/Library/Android/sdk. The api levels found were [36, 35]. Please choose an available api level or install api level 34 from the Android SDK Manager.
```

RELNOTES=n/a
PiperOrigin-RevId: 957370304
2026-07-31 15:50:31 -07:00
Tobias Werth 05d1d4526f Internal change
PiperOrigin-RevId: 941516950
2026-07-02 00:17:08 -07:00
Liam Miller-Cushon 55a2b68ebe Move DeclaredMembers sorting later
This change optimizes DeclaredMembers sorting of methods and fields by first
filtering for the fields or methods with relevant annotations, and then only
sorting the members of interest.

PiperOrigin-RevId: 904608829
2026-04-23 13:27:08 -07:00
Liam Miller-Cushon 6682b69d08 Automated Code Change
PiperOrigin-RevId: 838817837
2025-12-01 09:50:12 -08:00
Liam Miller-Cushon 74adac007a Automated Code Change
PiperOrigin-RevId: 830474625
2025-11-10 09:21:59 -08:00
Guice Team 8eb1cc4d20 Add a function in Guice Elements SPI that returns a list of modules installed by the input module.
PiperOrigin-RevId: 828084529
2025-11-04 12:25:36 -08:00
Guice Team c6839995f3 Tweak Guice to suggest toProvider(() -> null) rather than toProvider(Providers.of(null)).
PiperOrigin-RevId: 780105053
2025-07-07 07:39:55 -07:00
cpovirk 2a1d0fb47c Prepare for changes in how Truth prints class names.
Truth will soon:
- print only the simple name for some well-known classes (e.g., print "NullPointerException" instead of "java.lang.NullPointerException")
- print the canonical name where available instead of the binary name (e.g., print "com.google.Foo.BarException" instead of "com.google.Foo$BarException"

This CL updates callers to accept both versions.

RELNOTES=n/a
PiperOrigin-RevId: 775721999
2025-06-25 09:29:31 -07:00
Liam Miller-Cushon 5e17283ce6 Prepare MethodInterceptionTest for an upcoming JDK version
PiperOrigin-RevId: 755050401
2025-05-05 13:22:15 -07:00
Chaoren Lin 28526f0f49 Annotate Guice *BindingBuilder#to* APIs with @CanIgnoreReturnValue.
PiperOrigin-RevId: 752841257
2025-04-29 12:37:08 -07:00
Sam Berlin 9fc2417be2 Remove the word "experimental" from the MethodHandles flag.
PiperOrigin-RevId: 752352166
2025-04-28 10:10:15 -07:00
Sam Berlin b82cc7bbdf Eagerly ensure that user-supplied providers always return the expected type. Historically this was implicitly validated upon injection into whatever used the provider (via reflection magic). However, with the shift to MethodHandles, that particular signature check becomes harder to isolate/replicate without adding a bunch of unnecessary overhead. Thus, we instead change this to validate user-supplied providers when they provide the value (which is the soonest it can go wrong).
PiperOrigin-RevId: 752295067
2025-04-28 07:14:26 -07:00
Kurt Alfred Kluever 73ed742b8a Encourage a lambda over Provider.of(T).
PiperOrigin-RevId: 751215993
2025-04-24 18:17:48 -07:00
Luke Sandberg 33232b41cc Finish the experimental method handle support
This series addresses known issues in the experimental method handle implementation

  - MethodHandles produced by InternalFactory.getHandle are now cached.  This should speed up linking and reduce the number of 'lambda forms' we generate.
      - Doing this required demoting `Dependency` from the `getHandle` to be a runtime method parameter and changing InternalFactory to be an abstract class
  - We no longer generate custom `Provider` subclasses to hold `invokedynamic` instructions and instead use a simple hand written Provider class that lazily allocates a `MethodHandle` and calls invokeExact.
       - This should greatly speed up injector creation at the cost of a slightly more expensive `invokeExact` call.
   - requestStaticInjection and MembersInjectors are now fully supported with MethodHandles.

 I imagine there are some as yet undiscovered issues but this should unblock broader experimentation.

Fixes #1894

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/guice/pull/1894 from lukesandberg:method_handles 2166e1275e
PiperOrigin-RevId: 745281859
2025-04-08 14:00:42 -07:00
Luke Sandberg 59a54e1551 Fix some scalabilitiy issues in method handles
* avoid `asCollector` when the size is not bound by an existing method
    - otherwise we can easily hit limits in the number of method arguments that java allows which is 255.  This was a problem for some of our multibinders since multibinders can easily have hundres or thousands of entries
* be careful about deep `foldArguments` chains, method handles use a tail-call pattern which can lead to stack overflow, so instead use simple divide and conquor techniques.
* detect when we are binding to very high arity methods and bail out.  `MethodHandle` infra reserves 1 or two parameters and thus limits the methods/constructors we can bind to to those with _only_ 253 or 254 parameters (WHAT IS THIS, A VM FOR ANTS!).
    - This should probably become a guice error, but for the time being we just back off.

PiperOrigin-RevId: 741507607
2025-03-28 06:41:35 -07:00
Luke Sandberg fba0e102c2 Add a regression test for a bug from an earlier iteration of the MethodHandles implementation
If a `javax.inject.Provider` was bound in a scope, we would enforce that it was a `com.google.inject.Provider` which was wrong.  This is due to logic in `MoreTypes.canonicalizeForKey` which canonicalizes `javax.inject.Provider` to the guice interface.

This behavior makes sense for injection points since guice only ever hands out `com.google.inject.Provider` instances but we don't always canonicalize them at every phase of injection which is what lead to the bug.  Now we no longer use `Dependency` objects to enforce types so we don't risk this issue anymore

PiperOrigin-RevId: 741155148
2025-03-27 08:02:38 -07:00
Luke Sandberg 17aa84c3ce Simplify the 'factory' MethodHandle signatures to drop 'dependency' types from them
I thought modeling native types would be better but on reflection it just adds complexity for little gain.  So turn all generated factories into `(InternalContext)->Object` types.  This eliminates a bunch of `asType` adapters and should improve linkage performance a bit (not that this is a huge concern), but the major benefit is just simplicity.

Performance is an interesting question here.  In principle we are just adding 'no op' cast to `Object` on constructor and provides method invocations, and then `checkCast` instructions at constructor and method parameter injection points.  So the waste is those extra `cast` operations.  However, in the JVM those are nearly free (simple pointer check, can often be elided as part of normal invocation type checking). So my guess is that this is a no-op performance wise.  Some limited benchmarking of `@Provides` and `@Inject` constructors bears this out.

PiperOrigin-RevId: 740791709
2025-03-26 09:13:15 -07:00
Luke Sandberg b8dc8844ea Add MethodHandle support to @Inject constructors/field/methods.
This is the most complicated one since it uses a long tail of rarer features (InjectionListeners, member injection). But mostly it builds on established patterns so the trickiest part was actually getting the exception handling correct, luckily this is pretty well tested!

With this there is enough to start broad based testing.  Beyond this there are open questions about how to handle various member injection APIs for which I have left some TODOs

PiperOrigin-RevId: 740475465
2025-03-25 13:59:15 -07:00
Luke Sandberg 2257657495 Add MethodHandle support to the ProviderToInternalFactoryAdapter
This follows the pattern of how `InjectorImpl.getProvider` works and calls into the same method for generating a provider subtype.  There are 2 critical differences

1. We always set the `linked` flag to `true` for these 'Scoped' providers.
2. The `dependency` is inferred from the `InternalContext.getDependency` method

The latter point adds some non-trivial complexity since `getHandle` accepts `Dependency` as a parameter and generally specializes behavior on it (checks if it is nullable, used in error messages, raw types are used for proxies and error messages).  So we use the 'callsite' trick to bind the implementation to a patchable callsite that we can update whenever we see a new dependency.

The callsite will be implemented as a `tableSwitch` when possible and a hashmap holding method handles otherwise (<jdk17).

PiperOrigin-RevId: 740381461
2025-03-25 09:44:24 -07:00
Luke Sandberg 2138d2403f Remove dependencies on InjectorOptions from the method handle API
Previously I had assumed that the 'current injector options' would be static for a particular `InternalFactory` and thus we could optimize code generation based on it (drop some if-statements, eliminate some field writes).  However, this is not true when factories are shared across parent and child injectors.  There is no simple way to detect this so we simply back off.

Remove `InjectorOptions` from LinkageContext to account for this and eliminate the downstream dependencies on it.  Add a test to show how options can flip both ways at runtime.

PiperOrigin-RevId: 740365320
2025-03-25 08:51:51 -07:00
Luke Sandberg b303a624d7 Fix how InternalProviderInstanceBindings are shared across injectors.
To support 'native-multibinders' we have specialized the construction and initialization of subtypes of `InternalProviderInstanceBindingImpl.Factory`, however this creates some ambiguity when such providers are shared across injectors.  To resolve that, we exclusively 'bind' each factory to a single injector and any injector that fails to do so simply treats it as a normal `ProviderInstanceBinding`.  As far as I can tell this issue has been around for a very long time (2016?!), but only becomes problematic as we attempt to specialize more of the implementation on the `disableCircularProxies` flag.

This simplifies future efforts to specialize the implementations of Provider methods and multibinders.

PiperOrigin-RevId: 740107103
2025-03-24 16:14:34 -07:00
Luke Sandberg a7104775f9 Add methodhandle support to InternalFactoryToScopedProviderAdapter
We can take advantage of the fact that `setDependency` is a no-op when `disableCircularProxies` is set, but otherwise this is a pretty straightforward translation.

For Singleton scoped factories, we can follow the pattern of `Initializable` and create a 'patchable' callsite which should enable constant folding of resolved singletons.

PiperOrigin-RevId: 739912256
2025-03-24 06:13:59 -07:00
Luke Sandberg 6c33cd3a07 Rolling back, broke some tests.
PiperOrigin-RevId: 738791595
2025-03-20 07:24:06 -07:00
Luke Sandberg 3806c462ff Add method handle support to InternalProviderInstanceBindingImpl and subtypes.
This includes multibinders and provider methods.  Many of the multibinders were pretty straightforward if tedious.  The ProviderMethod implementation raises some interesting API questions:

* Should `skipfastclassgeneration` apply to the methodhandle implementation?
  * I decided "no" out of simplicity.  Constructing the methodhandle implementation should be very cheap compared to a fast-class.
* How should non-public members be handled?
  * I decided to follow the pattern of the `ReflectionProviderMethod` and just call `setAccessible`.  This is not the best solution so I wrote a copious note about better solutions.

PiperOrigin-RevId: 738411883
2025-03-19 08:39:34 -07:00
Luke Sandberg 34c84e975d Make InternalContext.setDependency a no-op when cyclic proxies are disabled
This will save a tiny bit of memory and time and should simplify the `MethodHandle` implementations when we get there.  Behavior is nearly perfectly concerned, but as the `CircularDependencyTest` points out, error messages will change when failing with cycles that go through scoped bindings.

PiperOrigin-RevId: 738385449
2025-03-19 07:16:37 -07:00
Luke Sandberg efb55f0228 Add an implementation of getHandle for the null ConstantFactory
PiperOrigin-RevId: 737997930
2025-03-18 07:32:42 -07:00
Luke Sandberg ab1ef98c11 Introduce LinkageContext to resolve cycles that occur during getHandle calls.
If 2 `InternalFactory` objects get linked to each other recursively we need to handle and detect cycles to prevent `StackOverflow`

For `get` calls this is managed by `InternalContext` and it is extremely performance sensitive.

For `getHandle` calls, this is currently unhandled which can lead to StackOverflow as more InternalFactory types are migrated.  This change addresses that via a new class `LinkageContext` which can detect and automatically resolve a cycle.

The specific strategy is to use a `MutableCallSite` as a layer of indirection to link back to the original method handle once it is done being constructed.  This constructs a recursive `MethodHandle`, much in the same way the normal cycle resolution uses a `Proxy` for that same layer of indirection.

See also [The farnsworth parabox](https://en.wikipedia.org/wiki/The_Farnsworth_Parabox).

Testing this scenario right now is difficult since we don't support many kinds of factories, but the next change introducing provider methods requires this.

PiperOrigin-RevId: 737708332
2025-03-17 12:20:34 -07:00
Luke Sandberg b87d055c0a Add helper method handle combinators to construct ImmutableMap and ImmutableSet instances.
These will be useful implementing multibinders.  The approach is to just construct method handles that developers would normally write.

PiperOrigin-RevId: 737694837
2025-03-17 11:44:52 -07:00
Luke Sandberg c27590d5d8 Add methodhandle support support for ProviderInternalFactory and its subtypes
This required supporting a number of 'standard features'

 * Initializables
 * null checking for injection points
 * ProvisionListeners
 * implementing the cyclic dependency protocol.

The ProvisionListener implementation is simpler/slower than it might be since the ideal solution would be to generate classes for each ProvisionCallback, instead I am 'manually constructing' them and calling `invokeExact` myself.  As these are rare the slightly higher overhead of this approach is justifiable imho (or could be separately addressed in the future).

PiperOrigin-RevId: 737658072
2025-03-17 10:10:36 -07:00
Luke Sandberg 0b0c2a8899 Add methodhandle implementations for our simplest internal factories supporting constants and links.
Next will be handling circular factories.

PiperOrigin-RevId: 735831614
2025-03-11 11:39:00 -07:00
Luke Sandberg d59f714477 Add basic support for generating Provider instances based on MethodHandles
This is hidden behind a new system property `-Dguice_use_experimental_method_handles=YES` enables it (`NO` is the default).  This is also conditioned on `BytecodeGeneration` being enabled.

For now the providers simply delegate to `InternalFactory.get` and thus are not very useful so this just proves out some of the basic mechanisms.

There were a few interesting details to work out.

* A new method was added to `ClassDefining` to always create these new `Provider` subtypes in a way that allows them to be garbage collected.
    - This was necessary to preserve some behavior with child injectors and the WeakKeySet, otherwise the fact that we bind references to factories via invokedynamic would leak injectors.

* To actually install a generated `MethodHandle` into class we need to use `invokedynamic` and some custom bytecode generation.
   - This should be the only bytecode generation required.
   - We use `invokedynamic` plus a lazy `Supplier` to actually construct the `MethodHandle` objects.  This means everything is lazily computed on the first call.

PiperOrigin-RevId: 735805730
2025-03-11 10:31:33 -07:00
cpovirk cdf076c99e Annotate toProvider(..) methods to specify that providers can return null.
This doesn't change any Guice behavior; it just lets nullness checkers (like Kotlin and the Checker Framework) allow you to bind to such providers more easily.

Guice's handling of `null` is not entirely principled, and this CL doesn't attempt to "solve" that, nor does it attempt to thoroughly annotate for nullness, let alone enable a nullness checker for the Guice codebase. Rather, it aims only to remove a restriction that I don't think is serving any particular purpose and that no on "intended"; I think it just kind of happened because the Checker Framework treats unannotated code leniently and strictly at different times, and this happens to be one of the strict cases. (We might also have once had the hope of cracking down on injection of `null`?)

The immediate motivation for this CL is https://github.com/google/inject-common/pull/26: Soon, nullness checkers will know that `Providers.of(null)` returns *gasp* a `Provider` that can return `null`. That makes `bind(Foo.class).to(Providers.of(null))` an error. This CL lets those callers continue to compile.

PiperOrigin-RevId: 734755975
2025-03-07 19:00:18 -08:00
Guice Team e88bc7991e Do not include exact type matches when showing suggestions for similar bindings that only differ in variance.
PiperOrigin-RevId: 723973423
2025-02-06 09:52:16 -08:00
Luke Sandberg 41e8c06f6f Improve the performance of isCircularProxy
The map implementation used by `MapMaker` is fairly old and requires 2 levels of indirection (segments->table).  Switching to `ConcurrentHashMap` would be better but this will still be redundant with logic inside of `Proxy` so instead we just use that.  Based on some simple benchmarks this is about 5X as fast, and should save a bit memory.

A number of alternatives were considered

* adding a marker interface to the list of proxy interfaces
  This is a completely ideal solution but fails due to our need to support proxying interfaces from all `ClassLoaders` and it isn't possible to proxy interfaces that cannot mutually 'see' each other.  So we would need to 'inject' our interface into the Bootstrap classloader which seems impossible and risky, or create special 'child' classloaders that can bridge it, but this triggers issues with proxying package-private interfaces... sigh.
* using a `ClassValue`, bootstrapping the value is tricky and while this is faster than the status quo, it would allocate an entry for every class we queried which could add up in a large application, and the approach in this change is faster.
* using `Proxy.isProxyInstance` this works but is slower than an `instanceof` query.

PiperOrigin-RevId: 721984180
2025-01-31 19:03:43 -08:00
Luke Sandberg 9e4df6fd6c Allow factories to customize their generated Providers
This enables a few optimizations

- A number of implementations can avoid `InternalContext` overheads addressing https://github.com/google/guice/issues/1802
  - `ConstantBindings`, one time bindings like `Initializable` and `@Singleton` bound values, and a number of multibinder bindings in particular.
- We can leverage the cache within `BindingImpl` to share provider instances.

The tricky part is about multibindings, which have complex multi-phase initialization semantics, so we need to be defensive about `makeProvider` getting called prior to being initialized.  To help manage this I
* reordered the `LookupProcessor` to run _after_ multibinders.
  - The comment justifying its current location in initialization is obsolete since multibinders were rewritten to be 'native'.
  - This ensures lookups get optimized providers!
* made the `SyntheticProviderFactory` allocate its delegate lazily.
* make `OptionalBinder` explicitly initialize their delegate bindings and also be defensive against recursive and duplicate initialization.  This is necessary to force initialization to be correct when our `getExistingBinding` query ends up delegating to another multibinder.
* be defensive about initialization failing to complete due to errors

PiperOrigin-RevId: 721080468
2025-01-29 13:03:21 -08:00
Luke Sandberg 54f53e812e Fix javacopts for guice tests to also set --source 11
PiperOrigin-RevId: 721030889
2025-01-29 10:40:57 -08:00
Luke Sandberg 2a17feb94d Have ProviderLookups and MemberInjectorLookups create their dependent bindings early and satisfy delegates later on during initialization
This ensures that other phases can see the jit bindings they create, notably this is important for `OptionalBinder` which queries for bindings using `getExistingBinding`

This will allow us to optimize the way `Provider` instances are created in a later change.

PiperOrigin-RevId: 720621327
2025-01-28 10:20:29 -08:00
Luke Sandberg a376396a7a Add a test for an optional binder linking to a jit binding due to a getProvider call.
PiperOrigin-RevId: 720198330
2025-01-27 09:27:34 -08:00
Luke Sandberg b673643f6a Resolve an old TODO in ExposedKeyFactory by supplying a source about the exposed binding to thrown exceptions
PiperOrigin-RevId: 716798470
2025-01-17 14:20:38 -08:00
Luke Sandberg 325ac9c863 Simplify the ProvisionCallback API.
Every implementation needs access to the current `InternalContext` so we can save a bit of memory by just passing it.

This is pretty minor since `ProvisionListeners` are rare, but it satisfies a long running TODO and allows us to eliminate some allocations from the normal provisioning path.

PiperOrigin-RevId: 715467849
2025-01-14 11:52:53 -08:00
Luke Sandberg c4401b8f98 Simplify the protocols for 'constant' bindings
* accept an `InternalContext` parameter from `Initializable.get` which all callers can provide.
  - This speeds up the `injectAll` phrase of injector creation since we no longer need to create an `InternalContext` object for each instance binding.
* for 'constant' bindings with no injection points use a simpler set of `InternalFactory` types.
   - This provides some immediate benefits by eliminating indirection (though admittedly the impacts are minor), but when we adopt method handles this will enable a cheaper implementation there as well.

PiperOrigin-RevId: 715093467
2025-01-13 13:44:15 -08:00
Luke Sandberg 6a3557ec28 Adopt java 11 in guice builds
Use `var` in a few places to prove it out.

PiperOrigin-RevId: 715002121
2025-01-13 09:41:09 -08:00
Liam Miller-Cushon 1152193259 Use @Keep to hint to static analysis that a field is used reflectively
PiperOrigin-RevId: 714976142
2025-01-13 08:25:38 -08:00
Luke Sandberg c5e7d93796 When constructing cyclic proxies share an invocation handler across all allocated proxies.
Additionally optimize the implementation of DelegatingInvocationHandler to eliminate an unnecessary field

With these two optimizations in place, the maximum size of a leak from resolving multithreaded lock cycles in SingletonScope is now a single tiny object, so instead of eagerly clearing out proxies to avoid a leak we can just wait to satisfy them if someone attempts to construct the singleton a second time, and if we don't we just won't sweat these 16 bytes.

PiperOrigin-RevId: 714082982
2025-01-10 09:46:51 -08:00