Title: Postpone action does not correctly update expiration date for expired or never-expire submissions

**Description**
When a receiver uses the "postpone" operation on a submission, the system is expected to extend the submission's expiration date according to the context’s `tip_timetolive` setting. However, the behavior is broken for at least two important edge cases:

1. **Already-expired submissions** – If the submission’s expiration date is in the past (e.g., `1970-01-01T00:00:00Z`), the postpone call appears to succeed but the expiration date does not get updated; the API still returns the old expired timestamp.

2. **Never-expire context** – When the submission’s context has `tip_timetolive = -1` (meaning “never expire”), a postpone call should set the expiration date to the special “never” value (`3000-01-01T00:00:00Z`). In practice this does not happen—the stale date persists.

**Steps to reproduce**
- Create a submission and let it expire (or force its expiration).
- As a receiver who has the “can postpone expiration” permission, send a PUT request to `/rtips/{tip_id}` with the body `{"operation": "postpone", "args": {}}`.
- Inspect the returned RTip resource; the `expiration_date` field still shows the old expired value.
- Repeat with a context whose `tip_timetolive` is `-1`; the date still does not change to `3000-01-01T00:00:00Z`.

**Expected behaviour**
- For positive TTL values: the new expiration date must be the current time + TTL days, and must be returned in the serialised RTip.
- For TTL = -1: the expiration date must be set to `3000-01-01T00:00:00Z` (the “never” sentinel).
- In all cases the response must accurately reflect the updated expiration date.

**Impact**
Receivers can falsely believe a submission’s lifetime has been extended, while it actually remains expired and may be cleaned up by the housekeeping job. This leads to premature data loss and a misleading UI.


**Feature request: Support `&self` methods in `ConnectBuilder`**

Currently, the `ConnectBuilder` API (accessed via `TypedSignal::connect_builder`) allows connecting to methods that take a mutable receiver (`&mut self`) through `method_mut`, but there is no equivalent for methods that take an immutable receiver (`&self`). Users can work around this by using `connect_obj`, but that API does not support the builder’s extra options (custom `ConnectFlags`, a debug name via `.name()`, or, on the `experimental-threads` feature, `.sync()`).

We need `ConnectBuilder` to provide a `method_immut` method, analogous to `method_mut`, that accepts a callable with a `&self` receiver. The flow should be:

```
sig.connect_builder()
    .object(&receiver_obj)         // or .object_self()
    .method_immut(Receiver::method)
    .done();
```

Key acceptance criteria and constraints:

1. **Immutable receiver semantics**: when the signal fires, the `Gd<T>` object stored in the builder must be `bind()`-ed to obtain a shared/immutable Rust reference. No `&mut` aliasing or `bind_mut()` call should occur. The closure that bridges Godot’s variant-array call convention must invoke the user-provided callable with a `&C` receiver.

2. **`AsFunc` trait extension**: the machinery that dispatches parameter tuples to callables (`AsFunc<Receiver, Ps>`) should gain an implementation for `&C` receivers. The existing implementation for `&mut C` is a good reference. The new implementation must accept `FnMut(&C, Params...)` (note: the closure internally may still be `FnMut` for consistency, even though the instance is not mutated; this matches how `method_mut` works).

3. **Object cloning**: the builder already takes ownership of a `Gd<T>` pointer. The `method_immut` path should capture this `Gd` in a closure that calls `.bind()` each time the signal fires. Nothing should prevent the object from being used elsewhere normally.

4. **Builder stage contract**: `method_immut` must only be available in stage 2, i.e., after `object` or `object_self` has moved the builder into the “receiver object selected” state. After `method_immut` is called, the builder transitions to stage 3 where options like `.name()`, `.flags()`, and `.done()` are available.

5. **Documentation**: the builder’s doc comment (the “Builder stages” section) should be updated to list `method_immut` alongside `method_mut`, and any existing small inaccuracies (like referring to stage 2 instead of stage 1 for the precondition) should be corrected.

6. **No changes required to the `object` method’s signature**: the change should work with the existing `object(Gd<C>)` method (or whatever signature it has at the time of implementation). The feature is purely additive in terms of the builder’s public API surface.

7. **Compatibility**: connecting an `&self` method must work when the signal is emitted from both internal class code and external users (via `Gd::signals()`). The existing test suite should pass, and new uses of the builder with `method_immut` should compile and run correctly without panics or undefined behavior.

Add ConnectBuilder::method_immut() + docs


`#[export(file)]`, `#[export(global_file)]`, `#[export(dir)]`, and `#[export(global_dir)]` with array types (`Array<GString>` and `PackedStringArray`) are only supported starting from Godot 4.3.  On earlier versions those combinations should produce a compile-time error that makes it clear only `GString` is allowed prior to 4.3.  The existing error message covers the 4.3+ case but does not handle the older version.

Make the export logic conditional on the Godot API level so that array fields are accepted only when `since_api = "4.3"` and otherwise yield the version-appropriate error.  Also ensure the integration-test property templates do not generate the array variants of these exports for Godot versions older than 4.3, so that tests do not attempt to compile or run unsupported exports on those versions.

Handle @export_file on arrays only available in Godot 4.3+


Add `Variant::object_id()`, returning `Option<InstanceId>`.

- For variants holding an object, retrieve the object's instance ID from the engine, **even if the object has been freed** (dead object).
- For any non-object variant (including `Nil`), return `None`.
- Gate behind Godot 4.4 (`since_api = "4.4"`), using the engine function `variant_get_object_instance_id` (safe to call on non-object variants; returns 0).
- Document the distinction from `try_to`: this returns the ID for dead objects while `try_to` fails to extract a live instance.


```
**Bug: Generated virtual-method signatures lack return types**

When implementing a Godot virtual method (e.g., from the `NodeVirtual` trait), the generated
Rust function signature omits the return type declared in the class API. The method body contains
`unimplemented!()`, but there is no return type, so the signature is effectively `fn ... (self)`
instead of the expected `fn ... (self) -> PackedStringArray`.

**Steps to reproduce**
1. Create a custom node type that implements `NodeVirtual`.
2. Try to implement `get_configuration_warnings`. The generated signature in the trait definition
   (or the required override) looks like:
   ```rust
   fn get_configuration_warnings(&self) {
       unimplemented!()
   }
   ```
3. Attempt to provide a proper implementation that returns a `PackedStringArray`; Rust will refuse
   because the trait signature expects `()`.

**Expected behavior**
The generated virtual-method definitions should include the correct return type from the Godot API
specification. For example:
```rust
fn get_configuration_warnings(&self) -> PackedStringArray {
    unimplemented!()
}
```
This should apply to *all* virtual methods that have a non-void return type across all Godot
classes, not just `Node`.

**Actual behavior**
All virtual-method signatures are generated without a return type, making it impossible to correctly
implement the corresponding traits.

**Additional context**
- Regular (non-virtual) methods already respect the declared return type.
- The issue affects every virtual method with a non-unit return type, regardless of the engine class.
  `get_configuration_warnings` on `Node` is one concrete example; other classes (e.g.,
  `Object._get_property_list`) are similarly broken.
- This is a code-generation problem; the Godot API data already includes the return types in
  `ClassMethod::return_value`, so the necessary information is available.
```

Add return values when generating virtual methods


Title: NodePath API overhaul: panic-on-OOB accessors, subpath replacement, and polyfill

Background
The current `NodePath` methods `get_name` and `get_subname` return `Option<StringName>`, which is inconsistent with other index-based accessors in the library (e.g. `GString::unicode_at`) that use debug‑only panics for out‑of‑bounds and safe‑but‑unspecified behavior in release. The count methods `get_name_count` and `get_subname_count` return `u32` while the rest of the library uses `usize`. The existing slicing method `slice()` takes a `RangeBounds<i64>` and is both non‑idiomatic and unable to handle negative indices cleanly; it also relies on the engine’s `slice` which is buggy in Godot ≤ 4.3 regarding subname index calculation.

Goal
Redesign the `NodePath` API so that it is more Rust‑idiomatic, consistent with other builtins, and correct across all supported Godot versions.

Required changes

1. **Accessor semantics** – `get_name()` and `get_subname()` must return `StringName` (not `Option`). Out‑of‑bounds access must **debug‑panic** with a clear message; in release mode the call returns an unspecified (but safe) value, matching the pattern of `unicode_at`.

2. **Count return types** – `get_name_count()` and `get_subname_count()` must return `usize`.

3. **Convenience** – Add `get_total_count() -> usize` which sums the name and subname counts.

4. **Slicing replacement** – Remove the current `slice(impl RangeBounds<i64>)` method. Introduce a new method `subpath(begin: i32, exclusive_end: i32)` available since Godot 4.3 (`since_api = "4.3"`).
   - Negative indices resolve from the end (e.g. -1 is the last element).
   - Absolute values are clamped to `get_total_count()`.
   - The method should eventually call `self.as_inner().slice(…)` with the resolved indices.

5. **Polyfill for Godot engine bug** – Because Godot ≤ 4.3 mis‑handles subname indexing in `NodePath::slice`, the implementation must compensate. After clamping and resolving `begin` to a non‑negative value, if `begin` is greater than `get_name_count()` it must be incremented by 1 to skip over the colon separator before being passed to the engine. `exclusive_end` can be forwarded as‑is. The polyfill should be clearly marked for later removal when the fix lands in Godot 4.4.

Non‑goals / notes
- The subarray methods on `Array` and `PackedArray` are not part of this ticket, but you may add TODO comments noting that they should eventually accept `i32` indices (like `subpath`) to support negative indices.
- The old `slice` method and its `RangeBounds` imports must be removed entirely.
- The new API should be verified with appropriate integration tests (not described here).

Finalize NodePath methods + `subpath/slice` polyfill + tests


As a maintainer of the Godot Rust bindings, file a feature-request ticket for supporting Godot 4.3's `GDExtensionScriptInstanceInfo3`. The task must be framed as a concrete requirement written before the fix, describing observable behavior and contract changes, not implementation mechanics. The ticket must be concise, use the repository's naming conventions, and leave the agent to find the relevant files and symbols by exploring the codebase.

Support GDExtensionScriptInstanceInfo3 in 4.3


Feature request (backlog ticket):

**Title**: Add `GString::substr(range)` using Rust-style `RangeBounds<usize>`

**Summary**:
The Godot engine exposes `String::substr(int from, int len)` which returns a substring of length `len` starting at index `from` (with `len = -1` meaning "until end"). Currently, in `gdext`, this generated method is intentionally hidden (via special-casing in the code‑gen step). Instead, we should expose a manual, idiomatic Rust method on `GString` that accepts any `RangeBounds<usize>` and returns a `GString`.

**Desired behavior**
- `GString::substr(range: impl RangeBounds<usize>) -> GString`
- The range must be mapped to an `(from: i64, len: i64)` pair according to the following rules:
  - **Start bound**:
    - `Included(n)` → `from = n as i64`
    - `Excluded(n)` → `from = (n as i64) + 1`
    - `Unbounded` → `from = 0`
  - **End bound**:
    - `Excluded(n)` → `len = (n as i64) - from`
    - `Included(n)` → `len = ((n as i64) + 1) - from`
    - `Unbounded` → `len = -1` (Godot interprets -1 as "rest of the string")

  After computing `(from, len)` the implementation should delegate to the underlying Godot `substr` method (the one currently hidden in the generated API).

- The raw `substr(from, len)` must **not** be exposed as a public method. Therefore:
  - Remove the `("String", "substr")` entry from the builtin‑method special‑case exclusion list (so the generated method stays hidden but we don't accidentally generate it again).
  - Do **not** re‑expose the generated version.

- For `StringName`:
  - Also remove its `("StringName", "substr")` exclusion (so the generated method remains hidden).
  - Adding `StringName::substr(range)` is optional for now; if the underlying operation returns a `GString` rather than a `StringName`, leave a comment noting the limitation (future work). The important thing is that the raw `(from, len)` form is not publicly accessible.

- The method should be documented (doc comment).

**Edge cases & invariants**
- An empty range (`n..n`) should yield an empty string.
- The mapping for `Excluded` start must correctly handle `Excluded(0)` → `from = 1`.
- Out‑of‑bounds ranges (indices larger than string length) should behave as Godot does (usually clamping); we do not need to add special validation.

**Acceptance criteria**
1. `GString::substr` exists and takes `impl RangeBounds<usize>`.
2. The generated `substr(from, len)` is no longer accessible.
3. Common range styles work as expected (e.g. `"stable".substr(1..)` returns `"table"`; `..4` returns `"stab"`; `2..=4` returns `"abl"`; `..` returns the whole string).
4. The `StringName` generated `substr` is hidden, no duplicate public method appears.


Currently, exported Rust integer properties of type `i8`, `i16`, `i32`, `u8`, `u16`, `u32` cause the Godot editor to panic when a user enters a value outside the type's valid range. This happens because Godot’s editor stores integers as `i64` and does not restrict the input; the value is later downcast and panics if it exceeds the Rust type’s bounds.

To fix this, generate `@export_range(min, max)` annotations for these integer types, with `min`/`max` derived from the Rust type’s `MIN`/`MAX` constants. This will make the editor UI enforce the valid range automatically. The `#[export]` attribute should produce the appropriate hint, while `#[var]` semantics and the export of `i64`, `f32`, `f64`, and other non-integer types remain unchanged.

Note: direct assignments from GDScript or other runtime code will still panic on out-of-range values; that is acceptable. The change is only about editor-enforced export behaviour.

Export for i8, u32, etc: limit to valid inputs using @export_range


**Title:** Deprecate `global::instance_from_id`, `is_instance_valid`, `is_instance_id_valid` in favor of `Gd`/`InstanceId` methods

**Background**
The `godot::global` module re-exports several instance-checking utilities from the generated bindings: `instance_from_id`, `is_instance_valid`, and `is_instance_id_valid`. These treat instance IDs as raw `i64`s and accept `Variant`, which makes the public API less type-safe and harder to discover. The preferred way to work with instances is through the methods on `Gd` and `InstanceId` (e.g., `Gd::try_from_instance_id`, `InstanceId::lookup_validity`, `Gd::is_instance_valid`). We want to deprecate the global free functions and guide users toward the typed alternatives.

**What to do**
1. In `godot-core/src/global/mod.rs`, add deprecated forwarding wrappers for the three functions. The wrappers should carry a descriptive deprecation message pointing users to `Gd` and `InstanceId` methods, and include a link to the relevant pull request for context (#892). The bodies should delegate to the underlying generated utilities (`crate::gen::utilities`).
2. The internal code must not call these deprecated functions from new code. In particular, `RawGd::is_instance_valid` currently calls `global::is_instance_id_valid`; replace that call with the equivalent `InstanceId::lookup_validity()` (available on the `InstanceId` stored in the cached RTTI).
3. The existing integration tests that still exercise the global functions should continue to compile without deprecation warnings. Add the minimal scope `#[allow(deprecated)]` attributes to maintain clean CI output.

**Acceptance criteria**
- The three global functions are marked `#[deprecated(...)]` and still work as before.
- `RawGd::is_instance_valid` uses `InstanceId::lookup_validity()` instead of the global function.
- The `gdext` crate compiles without deprecation warnings from the new internal deprecations.
- The affected integration tests (`itest/rust/src`) pass cleanly.

Deprecate global::instance_from_id(), is_instance_valid(), is_instance_id_valid()


**Title:** `Callable` cannot represent static engine/class methods

**Affected API:** `godot_core::builtin::Callable`

**Observed behavior:**
The current `Callable` API provides constructors for object-bound methods (`from_object_method`) and custom Rust closures (`from_local_fn`, `from_sync_fn`), but there is no way to create a `Callable` that invokes a **static** method of a Godot class (e.g., static functions registered with `#[func]` or engine class statics). Passing a static function to any Godot API that uses `Callable` (signals, timers, tweens, etc.) forces developers to either work around via GDScript or create unnecessary object instances.

**Expected behavior:**
A new constructor `from_local_static(class_name, function_name)` should return a `Callable` that, when called, invokes the named static method on the given engine class. It should forward arguments and return the result. The callable must work across the supported Godot 4.x version range. Because no object is involved, `object()`, `object_id()`, and `method_name()` may return arbitrary values – that is acceptable as long as they don’t cause unsoundness or panics, and the documentation should note that those methods are unspecified for static callables. The constructor should be single-threaded (like `from_local_fn`).

**Implementation hints / constraints:**
- Godot 4.4 introduced native support for static callable creation via `ClassDB::class_call_static`. Use that path when available.
- For Godot 4.3 and earlier, a polyfill is needed. A proven approach is to dynamically construct a short GDScript snippet that creates the static callable and then extract it.
- The feature should not break existing import hygiene; the `Callable` module may need to import `crate::classes` and use `meta::AsArg` explicitly.

**Impact:**
Without this, library users cannot use `Callable` with static methods, which is a common pattern when connecting signals or scheduling deferred calls, and forces either writing GDScript glue or opening object instances unnecessarily.


Make the `Inherits` trait reflexive and derive `GodotClass` from it

Currently `T: Inherits<Base>` never holds when `T == Base`, which makes it impossible to write a generic function that accepts any `Node` *including* `Node` itself – you have to write separate signatures or force the caller to always upcast.  The trait also has no supertrait, so a bound that mentions only `Inherits<Base>` does not let you call `Gd<T>` methods that need `T: GodotClass` (like `upcast`, `free`, etc.).

Change `Inherits` so that:
- `T: Inherits<T>` is always satisfied.
- `Inherits<Base>: GodotClass` is a supertrait, removing the need for a separate `GodotClass` bound.

Make sure that reflexive upcasts and downcasts (e.g. `node.upcast::<Node3D>()` where `node` is already `Gd<Node3D>`) work correctly, and that transitivity across indirect bases (like `Node3D: Inherits<Object>`) continues to function.

Separately, the debug assertion in the FFI layer that checks whether Godot is running currently prints "unchecked access to Option::None", which is unhelpful when it fires in unit/doc tests.  Change it to say explicitly that Godot is not available.

Make Inherits<T> reflexive, with implied GodotClass bound


Split `GodotExtensionClass` into separate traits for method registration and virtual-method/toString support.

The current `GodotExtensionClass` trait forces every class to implement `virtual_call`, `register_methods`, and `to_string` in a single impl. Decouple them:

- One trait for registering user method binds (the `register_methods` function).
- One trait for virtual methods and toString control: provide default `virtual_call` returning `None` and a static `has_to_string` that defaults to `false`. This trait should not contain the actual `to_string` method; that remains in `GodotMethods` and the dispatch in `register_class` will call `GodotMethods::to_string` when `has_to_string` is true.

Update `register_class` to require all three traits (`GodotMethods` + the two new traits) so that each concern is independently satisfied.

Adjust the `#[godot_api]` proc macro:

- For inherent impls marked with `#[godot_api]`, generate an impl of the method-registration trait that calls the appropriate registration macros.
- For `impl GodotMethods for X` blocks annotated with `#[godot_api]`, generate an impl of the virtual-methods trait with the default `virtual_call` logging the class and method name.

All concrete classes (`IntegrationTests`, `Entity` in the demo, `ObjPayload`, `Tracker`, `VirtualMethodTest`) need to be updated to implement the new traits separately instead of the old combined trait.

Also, in the itest GDScript `FfiTests.gd`, the `test_to_string` test should instantiate `VirtualMethodTest` instead of the typo `VirtualMethods`.


We need to restrict which types can appear in `#[opt(default = ...)]` parameters. Currently any
type is allowed, but if a default value like `Array<i32>` is shared across multiple calls and a
caller mutates it, that mutation leaks into subsequent invocations – the classic mutable-default
bug.

**Requirements:**

* Only truly immutable types should be accepted as default argument values.
* For `Array<T>` (and any other container that can be made read-only), the default must
  automatically become read-only at the point where Godot stores it.
* As a temporary safety measure, stop allowing `Gd<T>` and `Option<Gd<T>>` defaults. They can
  be re‑enabled later once a safe story (e.g. ref‑counted ownership) is in place.
* If a user tries to use an ineligible type in `#[opt(default)]`, they should get a clear
  compile‑time error explaining that the type is not immutable.

The conversion to `Variant` already goes through `AsArg`; the immutability step should happen
after that conversion and before the value is handed to the engine.

Let the proc‑macro code invoke a single helper from godot‑core that:
1. converts the argument via `AsArg`,
2. applies any required runtime‑immutability logic,
3. produces a `Variant`.

No other user‑visible API changes are needed.

Add `GodotImmutable` to constrain `#[opt(default)]` types


Fix undefined behavior in dynamic `#[func]` calls when argument count mismatches.

When a Rust `#[func]` method is invoked dynamically (for example via `Object::call` or `Callable::callv`) and the caller passes fewer arguments than the function declares parameters, the current dispatch reads past the valid end of the argument array, which is undefined behavior.

Add a guard that checks the argument count against the declared parameter count before any arguments are extracted. On mismatch, panic with a clear error message. This should also reject calls that supply *more* arguments than the function expects, rather than silently ignoring the extras.

The panic is a temporary safeguard; later we may allow user code to recover from these errors, but for now the only goal is to eliminate UB.

Fix UB for inbound varcalls, if argument count mismatches


**Title:** Unify GString char access under a single safe `chars()` method when building for Godot ≥4.1

### Problem
`GString` currently exposes two ways to get the underlying `&[char]`:

- `chars_checked()` – safe, validates UTF-32 validity at runtime (O(n)).
- `chars_unchecked()` – `unsafe`, assumes the string is valid UTF-32 without checking, because older Godot versions could contain invalid Unicode scalar values.

Godot 4.1 (godotengine/godot#74760) guarantees that all engine strings are valid UTF-32. This makes the unsafe variant always safe for ≥4.1, and the checked validation in `chars_checked()` redundant. Having both methods is confusing and the `unsafe` version encourages unnecessary `unsafe` usage.

### Expected behavior
When the library is built with `since_api = "4.1"` (i.e., targeting Godot ≥4.1), there should be a single safe method:

- `pub fn chars(&self) -> &[char]` – returns the underlying character slice without separate validation.

The existing methods should be **deprecated** (only for `since_api = "4.1"`) with a message pointing users to `chars()`, so that older API consumers still compile but are guided toward the new API. For API levels *before* 4.1, `chars_checked` and `chars_unchecked` should remain available as before.

### Impact
This cleans up the public API, removes an `unsafe` wart, and simplifies common operations. Internal callers (such as the `Display` implementation for `GString`) should switch to `chars()` when building for ≥4.1, while keeping the old code path for earlier versions. This requires version-gated conditional compilation (`#[cfg(since_api = "4.1")]` / `#[cfg(before_api = "4.1")]`).

### Additional notes
- The new `chars()` can delegate internally to the old `chars_unchecked()` (since that is now safe under Godot 4.1).
- Empty strings must be handled correctly (the underlying FFI may return a null buffer; the method must still yield an empty slice).
- The deprecation attributes and version gates must respect the existing `#[cfg_attr(since_api = "…", deprecated = …)]` pattern already used elsewhere in the codebase.

<brief_note_supplement>The request references a `Display` implementation as a likely internal caller to update (easily discoverable by searching for `chars_checked` usage). The empty-string edge case is relevant to a previously reported null-pointer regression (#228) and tests. No test details are prescribed, but updating any existing internal call sites is part of the work.</brief_note_supplement>

Replace `GString::chars_checked`/`GString::chars_unchecked` with `GString::chars` for 4.1


Add `Variant::try_to_relaxed()`, a lenient variant-to-value conversion that uses Godot’s internal strict conversion rules (the same rules GDScript applies when coercing arguments to a declared parameter type). The existing `try_to` only succeeds for exact type matches; this new method should allow conversions between numeric, string, geometry, array, and object types as permitted by `variant_can_convert_strict` and the variant→type constructors.

Key behavioral invariants:
- When the source and target types are identical, fall back to the exact conversion for consistency (avoid unnecessary FFI round-trips).
- Forbid conversion to `NIL` (except when the target type is `Variant` itself). Godot’s C++ `variant_can_convert_strict` reports that non-`NIL` types can convert to `NIL`, but that makes no sense from a Rust type perspective (nil is unit, not never) and should be disallowed.
- The FFI conversion constructor produces the Godot FFI type (e.g., `i64`, `GString`, etc.). For Rust user types that differ from the Godot FFI type (e.g., `i8`, `u32`, custom newtypes), the conversion must still succeed: go through the `Via` representation, use the FFI constructor, then call `try_from_ffi` and `try_from_godot` so that narrowing or validation failures are handled.
- Return `ConvertError` (with `FromVariantError::BadType`) when the source type is not convertible.

The method should be added on `Variant` and behave identically to GDScript’s argument coercion. Ensure it works with all Godot variant types and does not introduce undefined behavior when calling into the GDExtension interface.


Add a `node` key to the `#[init]` attribute.

The `node` key is allowed only on fields of type `OnReady<Gd<T>>` where `T: Inherits<Node>`.
It takes a single NodePath string literal, e.g. `#[init(node = "ChildPath")]`.
It is mutually exclusive with the existing `default` key in the same `#[init]` annotation.

Semantically, `#[init(node = "...")]` is equivalent to `#[init(default = OnReady::node("..."))]` – the field is automatically initialized before `_ready()` with the node found at the given path.

Implementation requirements:
- The `OnReady` auto‑initialization must provide the owning `Gd<Node>` to the initializer closure, because `OnReady::node` resolves the path relative to the owning node.
  Therefore, the closure type used by auto‑prepared `OnReady` fields should accept `&Gd<Node>` (i.e., signature `FnOnce(&Gd<Node>) -> T`).
  `OnReady::new(...)` closures that previously took no arguments should continue to work without changes.
- The proc‑macro that emits auto‑init calls must pass the owning node’s `Gd<Node>` reference when invoking `auto_init`.
- Classes that use the `node` key (or, more generally, any `OnReady` initializer that accesses the base) must include an explicit `Base` field: `base: Base<Node>`.
- The key must be validated at compile time: if used on a non‑`OnReady` field, or together with `default`, a helpful error should be emitted.

The overall goal is a more ergonomic way to declare on‑ready node references, similar to GDScript’s `@onready var node = $NodePath`, without requiring users to write the equivalent `default` closure by hand.

Implements the `node` key for attribute #[init]


## Feature Request: Simplify Native-Structure Object-Pointer Accessors

**Background**
Godot native structures (e.g., `PhysicsServer2DExtensionShapeResult`) have fields that hold object pointers (`collider`, etc.). The generated accessor methods for these fields currently expose an `increment_refcount` parameter and use an inconsistent getter name without the `get_` prefix.

**Request**
Improve the usability of object-pointer fields in native structures in two ways:

1. **Consistent getter naming** – rename the getter from `collider()` to `get_collider()`, matching the `get_` prefix already used by other generated accessors.
2. **Remove the `increment_refcount` parameter from the setter** – the setter should accept a `Gd<T>` (where `T` inherits `Object`) and store the underlying raw pointer without influencing the reference count. The previous boolean parameter is removed; ref-count management for native structures is deferred to a future design.

**Observable behavior**

- For any native structure object-pointer field, the getter is named `get_<field>` (e.g., `get_collider()`) and returns `Option<Gd<Object>>`. It behaves as before: returns `Some` if the object instance ID is still valid, `None` otherwise.
- The setter is named `set_<field>` and accepts a single argument `obj: Gd<T>` where `T: Inherits<Object>`. It automatically upcasts to `Object`, asserts that the object is valid, and stores the raw pointer along with the instance ID. No reference count increment is performed.
- User code that previously called `result.set_collider(obj.clone().upcast(), true)` or `result.set_collider(obj, false)` must now call `result.set_collider(obj)`.
- The `increment_refcount` functionality is completely removed from the generated setter and the public API surface of `Gd`/`RawGd` that supported it.
- Existing working behavior for manually-managed objects (e.g., `Node3D`) must remain correct: storing a pointer and retrieving it while the object is alive returns the same object; after `free()` the getter returns `None`.
- Ref-counted objects (`RefCounted`) are *not* kept alive by the native structure. The test that previously exercised ref-count increment/decrement is skipped with an `#[itest(skip)]` annotation, because correct ref-count handling is postponed. A TODO comment near the codegen logic for native structures should indicate that encapsulation of object pointers (including eventual `Drop` with refcount decrement) is planned for later.

**Edge cases / constraints**

- The setter must panic (or at least assert) if the provided `Gd` is dead (instance invalid).
- The setter must be generic to avoid requiring manual `.upcast()` calls from user code; the upcast must happen automatically.
- The getter must remain unchanged in its logic for resolving an `InstanceId` from the stored identifier.
- The change must not alter the layout or FFI representation of the native structures themselves.

Postpone the ref-counting problem for native structures


```
Feature: Rename Callable methods to match original Godot names and fix get_bound_arguments_count return type

The gdext `Callable` type exposes two methods that differ from Godot's own naming:
- `arg_len()`
- `bound_args_len()`

These should be renamed to their original Godot equivalents:
- `get_argument_count()`
- `get_bound_arguments_count()`

`get_bound_arguments_count()` currently returns `i64`. In Godot versions before 4.4, the underlying engine call can return a negative value when arguments are unbound (upstream bug). The method must instead return `usize`, and any negative value from the engine should be clamped to 0 so that callers always observe a non-negative count.
(This is already fixed upstream for Godot >= 4.4, but our binding should ensure the `usize` invariant regardless of engine version.)

Additionally, `Callable::method_name()` already uses the Godot name but lacks a doc alias. Add `#[doc(alias = "get_method")]` so that users searching for the Godot getter can find it.

The old method names must be removed (no deprecated shims needed). Update all internal call sites and tests to use the new names and the new `usize` return behavior for `get_bound_arguments_count`.
```

Callable: rename arg_len() etc. to their original Godot names


**Ticket: Heuristic to const-qualify Godot getters**

*Component:* godot-codegen (method constness mapping)

**Problem**
Many Godot getter methods (names starting with `get_`, `is_`, `has_`) are incorrectly advertised as mutable in the GDExtension API. Because the codegen currently respects the advertised mutability, this forces Rust users to needlessly hold `mut` bindings for objects that are only being read. The current approach of adding explicit per-method overrides to fix individual getters is not scaling.

**Desired change**
Implement a heuristic in the constness-mapping logic that automatically treats methods whose names begin with `get_`, `is_`, or `has_` as const (`&self` in Rust) by default. This rule must be overridden for a known set of methods that genuinely mutate state despite the naming convention (e.g., reading from a stream advances a cursor). The heuristic should only apply to methods that are:
- **not** already declared const in the JSON API,
- **not** static,
- **not** virtual.

**Exceptions – methods that must remain `&mut self`**
The following getter-like methods should be added to a deny-list (forced mutable) because they have observable side effects. This list includes, at minimum:

- `FileAccess`: all numeric read methods (`get_8`, `get_16`, `get_32`, `get_64`, `get_half`, `get_float`, `get_double`, `get_real`), `get_var`, `get_line`, `get_csv_line`, `get_buffer`, `get_pascal_string`.
- `StreamPeer`: all `get_*` read methods (`get_8`, `get_16`, `get_32`, `get_64`, `get_u8`, `get_u16`, `get_u32`, `get_u64`, `get_half`, `get_float`, `get_double`, `get_string`, `get_utf8_string`, `get_data`, `get_partial_data`, `get_var`).
- `PacketPeer`: `get_packet`, `get_var`.
- `DirAccess`: `get_next`.
- `NavigationAgent2D` and `NavigationAgent3D`: `get_next_path_position` (updates internal path logic).
- `GridMap`: `get_bake_meshes` (may trigger mesh baking as side effect).
- `Node3D`: `get_global_transform_interpolated` (creates interpolation pump on first call).

**Cleanup of existing special cases**
Once the heuristic is in place, the explicit per-method `Some(true)` overrides for `MultiplayerApi` getters (`has_multiplayer_peer`, `get_multiplayer_peer`, `get_unique_id`, `is_server`, `get_remote_sender_id`, `get_peers`, `get_default_interface`) can be removed; they will be correctly handled by the new heuristic. The existing forced-const override for `Object::to_string` and the forced-mutable override for `EditorImportPlugin::_import` should remain untouched.

**Acceptance criteria**
- All non-virtual, non-static methods starting with `get_`, `is_`, or `has_` are mapped to `&self` in Rust unless they appear in the exception list.
- The exceptions listed above remain `&mut self`.
- The heuristic does not alter the mutability of virtual methods, static methods, or methods that are already const in the JSON API.


Remove the deprecated `instance_from_id`, `is_instance_valid`, and `is_instance_id_valid` functions from `godot::global`. These have dedicated replacements on `Gd` and `InstanceId` (`Gd::from_instance_id`, `Gd::try_from_instance_id`, `Gd::is_instance_valid`, `InstanceId::lookup_validity`). The old public functions were deprecated in earlier versions and should now be fully deleted.

The underlying Godot utility functions `is_instance_valid` and `is_instance_id_valid` are still needed internally by `Gd::is_instance_valid` and `InstanceId::lookup_validity`, but must not appear in the public API of `godot::global`. Make them available only inside the crate (e.g., `pub(crate)`) and update the internal callers to use that non-public path.

Add a documentation section to the `godot::global` module that lists the removed functions and points users to the new APIs on `Gd` and `InstanceId`. The code generation for utility functions may need to support marking specific utilities as crate-private so they are excluded from the public re-export but still accessible internally.

Utilities around instance ID: remove from public API + document


**Title:** `Glyph` native‑struct layout mismatch on Godot < 4.6

**Background**
Godot 4.6 added a `span_index` field to the native `Glyph` struct (godotengine/godot#108369). The JSON extension API shipped with earlier Godot versions does not include this field, so the Rust struct generated by our codegen does not match the actual C++ binary layout when using those older engine versions. This causes memory corruption and crashes.

**Task**
Backport the corrected `Glyph` struct definition into our codegen so that the generated Rust struct contains the `span_index` field even when the JSON doesn’t.

**Details**
- The corrected field is `int span_index = -1` (type `int`, default `-1`).
- The override should be applied unconditionally for now – we can add a version guard later once the upstream PR is merged. A `TODO` comment referring to `#[cfg(before_api = "4.6")]` would be nice.
- Follow the existing pattern for native‑struct special‑cases: add an override function in `godot-codegen/src/special_cases/special_cases.rs` and use it in `NativeStructure::from_json` (`godot-codegen/src/models/domain_mapping.rs`). Provide the complete corrected format string as a replacement.
- The integration tests that construct `Glyph` values (in `itest/rust/src/engine_tests/native_structures_test.rs`) must be updated to set `span_index` to `-1` as well, otherwise they will fail to compile after the codegen change.

**Acceptance criteria**
- `Glyph` struct generated from a pre‑4.6 JSON includes `span_index: i32` with a default of `-1`.
- Existing tests pass after the necessary test‑site updates.

Backport Godot fix for incorrect `Glyph` native-struct


Feature request: `Gd::upcast_ref()` and `Gd::upcast_mut()` (non‑consuming upcasts)
===================================================================================================

### Motivation
The existing `Gd<T>::upcast()` consumes `self` and returns `Gd<Base>`.
In generic code that only has a `&Gd<T>` or `&mut Gd<T>` (e.g. `T: Inherits<Node>`) it is currently impossible to call base‑class methods without taking ownership.
Users need borrowing, non‑owning variants of `upcast()`:

- `upcast_ref(&self) -> &Base`
- `upcast_mut(&mut self) -> &mut Base`

These methods should be available on `Gd<T>` for any `T` that inherits from a Godot class `Base`.

### Desired signatures and semantics
```rust
// On impl<T: GodotClass> Gd<T>

pub fn upcast_ref<Base>(&self) -> &Base
where
    Base: GodotClass,
    T: Inherits<Base>;

pub fn upcast_mut<Base>(&mut self) -> &mut Base
where
    Base: GodotClass,
    T: Inherits<Base>;
```

- They **do not** consume the `Gd<T>`. After the call the original `Gd` remains usable.
- `upcast_ref` and `upcast_mut` must **respect Rust’s aliasing rules**: `&mut` references must be exclusive.
- For valid, non‑null objects the methods **must not panic**.
- Null or otherwise invalid `Gd` instances should be rejected (following the existing practice in `Gd::deref()` / `upcast()`).

The upcast must work for both **engine classes** and **user‑defined** (script‑side) classes, in any generic context where `T: Inherits<Base>`.

### Trait bound tightening
To guarantee that `Base` is a real Godot class, the `Inherits` trait should require `Base: GodotClass`:

```rust
pub trait Inherits<Base: GodotClass>: GodotClass {}
```

This is a **backward‑compatible** change because every existing implementation of `Inherits` already satisfies that bound (the base is always `Self` or a Godot engine/user class).
Without this bound the new methods could be instantiated with a `Base` that lacks the necessary class metadata, which would be unsound.

### Acceptance criteria
1. `Gd<T>` exposes `upcast_ref` and `upcast_mut` as described.
2. Given `T: Inherits<Node>`:
   - `node.upcast_ref::<Node>().get_name()` compiles and returns the node’s name.
   - `node.upcast_mut::<Node>().set_name(…)` compiles and mutates the node.
3. The original `Gd<T>` is **not** consumed by either call; it can be used afterwards.
4. `Inherits<Base>` trait visibly documents and enforces `Base: GodotClass`.
5. All existing uses of `upcast()` continue to compile and behave correctly.


```
Title: Merge duplicate `RectSide` enum into `godot::engine::global::Side`

Description:
The Rust bindings currently expose two separate enums for the sides of a rectangle: `RectSide` (with variants `Left`, `Top`, `Right`, `Bottom`) and the `Side` enum from the engine’s global scope (`godot::engine::global::Side`). They represent the same concept and are duplicates. To reduce API surface and maintenance cost, unify them.

Acceptance criteria:
1. The public type `RectSide` becomes a deprecated type alias for `Side` (existing code using `RectSide` must still compile but trigger a deprecation warning).
2. The old variant-style names `RectSide::Left`, `RectSide::Top`, `RectSide::Right`, `RectSide::Bottom` remain accessible as deprecated associated constants on `Side` (mapping to `Side::LEFT`, `Side::TOP`, `Side::RIGHT`, `Side::BOTTOM` respectively), so that existing usage paths continue to compile with deprecation warnings.
3. The methods `Rect2::grow_side` and `Rect2i::grow_side` must accept `Side` instead of `RectSide` as the side parameter.
4. All existing tests (unit tests and integration tests) that exercise `grow_side` or reference `RectSide` must be updated to use the `Side` enum directly and continue to pass.
5. No other breaking changes to the public API should occur (the old `RectSide` variants disappear only after the deprecation cycle).
```


**Title:** Expose public owned/borrowed helpers to construct `impl AsArg<T>` generically

**Background**
We have the `AsArg<T>` trait that allows passing both by-value types (`T` for `i32`, `Vector3`, …) and by-reference types (`&T` for `GString`, `Array`, …) into Godot APIs. In generic code, a user may have an arbitrary `T: ToGodot` and either an owned value or a shared reference, but they cannot easily turn it into `impl AsArg<T>` without knowing whether `T` itself implements `AsArg<T>` or only `&T` does. Currently, an internal hidden helper (`val_into_arg` in `meta::args`) takes an owned `T` and wraps it in `CowArg::Owned`, returning `impl AsArg<T>`. There is no public equivalent that works with a borrowed `&T`.

**Request**
1. Add two public helper functions in the `godot::meta::args` module (re-exported via `godot::meta`):
   - One that takes an **owned value** and returns `impl AsArg<T>`. It should move the value into a `CowArg::Owned`.
   - One that takes a **shared reference** and returns `impl AsArg<T>`. It should wrap it as `CowArg::Borrowed`.
2. Remove the existing hidden helper `val_into_arg` (it is only used internally) and replace its usages with the new owned-helper.
3. The new functions must be generic over `T: ToGodot` and must enforce correct lifetimes: the owned version should work for any `'r` (the returned impl cannot outlive the input by construction), and the borrowed version must tie the returned `impl AsArg`’s lifetime to the input reference.
4. Document the new functions with doc-tests showing generic usage with `Array::push` or similar APIs. Mention when to prefer each (use owned if you no longer need the value; use ref if you have a borrow and want to avoid cloning).
5. Update the `AsArg` trait documentation to point to these new helpers as the recommended way to bridge `T`/`&T` into `impl AsArg<T>` in generic contexts.

**Constraints**
- Do not change the public `AsArg` trait or its existing implementations (e.g., `impl AsArg<T> for T` for by-value types, `impl AsArg<T> for &T` for by-ref types). The helpers should simply produce a `CowArg` that already implements `AsArg<T>`.
- The owned helper must compile even for non-`Copy` types (it moves).
- The borrowed helper must not require `T: Clone`; it just borrows.
- Existing internal call-sites (e.g., in `Array::bsearch_by` and `Extend` implementation) must be updated to the new owned helper.

**Acceptance criteria**
- The two public functions are available under `godot::meta` and can be used in generic code like `arr.push(helpers::owned_into_arg(my_val))` and `arr.push(helpers::ref_to_arg(&my_val))`.
- The old hidden `val_into_arg` is removed.
- Integration tests pass (including any new tests that verify correct behavior for both by-value and by-ref types).

Add `owned_into_arg()` + `ref_to_arg()` helpers


Fix `GdCell::borrow_mut` to block on main thread when a shared reference is held on another thread

The `GdCell` blocking API (in `godot-cell`) is supposed to make `borrow_mut()` block until no immutable borrow (`RefGuard`) exists on any thread.  However, if the main thread (or whatever thread first initialized the cell) calls `borrow_mut()` while a different thread already holds a shared borrow, the main thread **panics instead of blocking**.  The blocking mechanism is present but is being skipped because the thread-tracker incorrectly believes the main thread is still the designated “mutable-thread” when in fact another thread has become the first to acquire an immutable borrow.

Expected behavior:
- When a thread calls `borrow_mut()` and some other thread holds a `RefGuard`, the caller must block (parked on the condition variable) until that shared borrow is dropped.
- No thread should be able to bypass the block and enter a conflicting borrow state that leads to a runtime panic.

The core invariant that needs to be enforced:
- The `ThreadTracker` maintains which thread currently has the right to attempt a mutable borrow.
- When the **first** immutable borrow is taken (while no mutable borrow is active), the tracker must treat the borrowing thread as the new “mutable thread.”  This ensures that any subsequent `borrow_mut()` from a *different* thread will see that it is not the current mutable thread and will correctly block on the condition variable.
- Today, `ThreadTracker::mut_thread` is only updated when a mutable borrow is taken, never when the first immutable borrow is taken by a thread that is not the current `mut_thread`.  Consequently the old `mut_thread` (often the main thread) is still considered the mutable owner and attempts `borrow_mut` without blocking, immediately hitting a borrow conflict and panicking.

The fix should adjust the immutable-borrow path so that the thread tracker’s “mutable thread” is reassigned appropriately when the first immutable borrow is taken on a thread that does not already own the mutable slot.  The mutable-borrow path already updates the mutable thread; it should remain correct.  The change must not introduce new deadlocks (the thread that already holds the immutable borrow should never block on its own `borrow_mut` — that is already handled, but the logic must be preserved).  No external API surface is changed; only the internal blocking protocol in `godot-cell/src/blocking_cell.rs` needs to be fixed.

GdCell::borrow_mut should block on main thread if shared ref exists


Title: Variadic utility functions like `str` and `print` should accept zero arguments

**Description**

Several Godot global-scope utility functions (`str`, `print`, `print_rich`, `printt`, `prints`, `printerr`, `printraw`, etc.) are variadic and should accept any number of `Variant` arguments, including zero. In GDScript you can write `str()` to get an empty string, or `print()` to output a blank line.

The current generated Rust bindings for these functions do not allow zero arguments – they require at least one fixed parameter. This makes common calls like `str()` or `print()` impossible without ugly workarounds[^1]. Only `print` and `print_rich` have manual workarounds (in `godot-core/src/global/print.rs`), but other functions such as `str` are left broken, leading to an inconsistent API.

**Expected behavior**

All variadic utility functions that have no required parameters in Godot should generate a Rust signature that accepts a single `&[Variant]` slice and works with zero, one, or multiple arguments, similar to how `print` is currently manually implemented. The macros that wrap them (e.g., `godot_print!`) should continue to work, and the underlying generated functions should become usable directly.

Once the generator handles these functions correctly, the manual `print` and `print_rich` implementations should no longer be necessary and can be removed.

---

[^1]: **Why this happens**: Godot’s extension API JSON marks these functions as vararg but still includes a bogus fixed argument (like `{"name": "arg1", "type": "Variant"}`). The bindings generator currently treats that as a mandatory parameter instead of recognizing the combination of `is_vararg` with a single placeholder argument and converting the function to pure variadic.

Utility functions with "arg1" parameter are now full vararg


**Feature request: `TypedSignal::connect_obj` – connect a signal to a method on another user-defined object**

Currently `TypedSignal` provides `connect` for static functions/closures and `connect_self` for the owner’s own `&mut self` methods. There is no equally ergonomic way to wire a signal to a method on a *different* object instance (the “receiver”). The only workaround is to manually capture a clone of the other object in a closure and call `bind_mut` there, which is verbose, error-prone, and obscures the intent.

Desired API: `sig.connect_obj(&other_obj, OtherType::handler)` where `handler` is a method that takes `&mut self` plus the signal’s argument tuple. Example:

```rust
let receiver = Receiver::new_alloc();
emitter.signals().some_signal().connect_obj(&receiver, Receiver::on_event);
```

When the signal is emitted the receiver’s method should be called with a mutable reference to the receiver object, exactly as `connect_self` provides the sender’s `&mut self`. The `Gd` pointer to the receiver must be cloned into the underlying callable to keep the object alive for the lifetime of the connection; the `&Gd` argument at connect-time is only used for setup, not retained.

**Behavioral contract / edge cases:**

- The receiver method’s first parameter must be `&mut self` (mutable access to the receiver). The signal parameters follow as in `connect_self`.
- The connection must not require the receiver to be the same object as the signal owner.
- The receiver object should continue to work if it is alive when the signal fires, even if the local `Gd` used at connect-time goes out of scope (the callable holds its own clone).
- The feature should work for user-defined Godot classes that support `bind_mut` (the typical use case); compatibility with engine classes is less critical but follow what the `Gd` API already allows for mutable access.

**Why this matters:** Game code often needs an object to react to events from another object without manual closure plumbing. Without this method, developers resort to ad‑hoc closures that are hard to read and easy to get wrong regarding lifetimes or type mismatches. Adding a dedicated `connect_obj` would round out the signal connection API and match the patterns already established by `connect` and `connect_self`.

Add TypedSignal::connect_obj() to connect to other user objects


**Feature: Improve `#[export]` attribute ergonomics and safety for the `GodotClass` derive macro**

The current `#[export]` attribute on struct fields in `GodotClass` requires explicit `getter`/`setter` string literals, even when users just want a trivial field-backed property. It also silently allows referencing getter/setter function names that don't exist, leading to confusing Godot runtime errors. The API should be more concise, aligned with GDScript conventions, and reject bad references at compile time.

**Acceptance criteria**

1. **Renamed keys**
   The `#[export]` attribute arguments `getter` and `setter` are renamed to `get` and `set`. Any existing usage of `getter`/`setter` should be rejected with a clear compile error (i.e., only `get` and `set` are recognized).

2. **Default generated accessor pair**
   When no `get` or `set` argument is provided (plain `#[export]`), the macro automatically generates a trivial getter named `get_<field>` and a trivial setter named `set_<field>`. Both generated methods must be registered with Godot so they are available from GDScript.

3. **Bare `get` / `set` for generated accessors**
   The arguments `get` and `set` may be specified without a value, like `#[export(get)]` or `#[export(set)]`. Each bare key independently means "generate the trivial accessor". The generated method names follow the same `get_`/`set_` prefix convention as above (no custom name).

4. **One-sided accessors**
   Specifying only `get` (or only `set`) creates a read-only (or write-only) property. The other accessor is not generated and not registered with Godot.
   - `#[export(get)]` → read-only with auto-generated getter, no setter.
   - `#[export(get, set = "my_setter")]` → auto-generated getter, custom setter.
   - `#[export(set)]` → write-only with auto-generated setter (rare but valid).

5. **Custom accessors with compile-time existence check**
   When a string value is given for `get` or `set` (e.g., `#[export(get = "my_getter")]`), the macro must produce a **compile error** if no function with that name exists on the struct. This prevents the cryptic runtime "invalid get/set index" error that Godot would otherwise emit.

6. **Remove unused `property` argument**
   If there is any `property` argument accepted by `#[export]` that is unused, it should be removed. (Check the implementation; its presence may be a leftover.)

7. **Document the derive macro**
   The doc comment on the `GodotClass` derive macro must cover the `#[export]` attribute behavior described above, including the default behavior, bare keys, custom accessors, and the interaction with `#[func]`. The existing inline examples for the derive macro should be updated or expanded to show these patterns.

8. **Integration tests**
   Ensure that the updated behavior is covered by integration tests, exercising all combinations: auto-generated, custom, read-only, write-only, and mixed. Tests should verify correct values are read and written through GDScript properties, not just Rust‑side code.

**Edge cases and constraints**

- The trivial getter must return a copy of the field. The trivial setter must assign the field directly.
- If a custom accessor name is provided, it must be a string literal (not an identifier), matching the existing convention.
- The compile-time existence check should not prevent the struct from having other methods; it must only check that the referenced name resolves as a function on the struct.
- The implementation should not change the behavior of `#[export]` with `hint` and `hint_desc` except as needed to support the new getter/setter logic.
- The existing integration test file `itest/rust/src/export_test.rs` and its GDScript counterpart `itest/godot/ManualFfiTests.gd` must be updated to match the new API and cover the new behavior.


**Request: Support `#[cfg]` attribute on `#[signal]` declarations**

Currently, applying `#[cfg(...)]` to a signal declared with `#[signal]` inside a `#[godot_api] impl` block either causes compilation errors or unconditionally registers the signal regardless of the cfg predicate. This prevents using standard Rust conditional compilation for signals, even though the same pattern works for `#[func]` methods.

We need the following behavior:

1. **Conditional registration** — a signal definition with `#[cfg(condition)]` (whether placed above or below `#[signal]`) must only be registered with Godot when the condition is true. If the condition is false, the entire definition is ignored, exactly as it would be for any other `#[cfg]`-gated item.

2. **Handling duplicate signal names across cfg branches** — it must be possible to have multiple `#[signal]` declarations with the same signal name, as long as their `#[cfg]` attributes ensure that at most one of them is active in a single compilation. The code generator must not emit a compile error about duplicate signal registration in such cases.

3. **Attribute ordering** — `#[cfg]` must be respected whether it appears before `#[signal]` or after it (both `#[cfg(X)] #[signal] fn foo();` and `#[signal] #[cfg(X)] fn foo();`).

4. **Non-regression** — signals without a `#[cfg]` attribute continue to work as before. No change in Godot class database for any existing signal definition.

The observable end-goal: a developer can conditionally compile signals in a Rust Godot class using `#[cfg]`, mirroring the support already available for `#[func]` methods.


**Title:** Extend `Varifier` to recommend `var` for `unused` variables and `assertThrows` results

**Background:**
The `Varifier` bug checker already suggests `var` for local variables whose initializers make the explicit type redundant (casts, constructors with diamond, builders, factory methods, etc.). The goal is to reduce visual boilerplate without loss of clarity.

**Request:**
Add two more patterns where `Varifier` should recommend replacing the explicit type with `var`:

1. **Variables named `unused`**
   Any local variable whose name is exactly `unused` (case-sensitive) should use `var`. The convention of naming a variable `unused` signals that the value is intentionally ignored; spelling out the type adds no useful information.

2. **Variables initialized by `assertThrows`**
   JUnit’s `org.junit.Assert.assertThrows(Class<T>, Executable)` returns exactly `T` – the exception type passed as the first argument. When a local variable’s initializer is a call to this method (including through a static import), the explicit type on the left-hand side is pure ceremony: `MyException e = assertThrows(MyException.class, ...)`. In those cases, `Varifier` should suggest `var e = assertThrows(MyException.class, ...)`.

**Constraints & Safety:**
- Both cases should only apply to *local variables* (not fields or parameters).
- The existing safeguards must remain: no suggestion if the variable already uses `var` or has an implicit type.
- For `assertThrows`, the match must be exact: the static method `org.junit.Assert.assertThrows`. No other overloads or similarly named methods should trigger the suggestion.
- The suggestion is a pure refactor; it must not alter semantics.

**Expected Behavior:**
Given:
```java
String unused = someExpression();
NullPointerException thrown = assertThrows(NullPointerException.class, () -> nil.toString());
```
The checker should report the explicit type can be replaced with `var`, fixing both declarations to:
```java
var unused = someExpression();
var thrown = assertThrows(NullPointerException.class, () -> nil.toString());
```

Recommend using `var` for `var unused = ...;` and `var thrown = assertThrows(MyException.class, () -> ...);`


The `AlwaysThrows` check currently detects several runtime-failure patterns, but it does not flag constructions of `ImmutableMap` and `ImmutableBiMap` that are guaranteed to throw (e.g., `IllegalArgumentException` from duplicate keys). At the same time, some of these duplicates are reported by `DistinctVarargsChecker`, but only as warnings and with limited context (builder chains are not covered).

Extend `AlwaysThrows` to report errors for ImmutableMap/ImmutableBiMap creations that will always fail at runtime due to repeated keys or (for bimaps) repeated values.

**Acceptance criteria**

1. **Builder chain detection**
   For `ImmutableMap.Builder.put(key, value)` and `ImmutableBiMap.Builder.put(key, value)`, walk the chain of preceding `.put(…)` calls on the same builder. If any key (for `ImmutableMap`) or value (for `ImmutableBiMap`) is repeated among the accumulated constant arguments, the final `.buildOrThrow()` (or equivalent) call is not needed; flag the **duplicate** `.put(…)` call that introduces the conflict.
   The check must handle chains that span multiple statements (e.g., builder stored in a local variable) and must not be confused by nested builder invocations.

2. **Static factory method detection**
   For `ImmutableMap.of(k1, v1, k2, v2, …)` and `ImmutableBiMap.of(k1, v1, k2, v2, …)`, flag the invocation when:
   - two even-indexed arguments (keys) are equal, for both `Map` and `BiMap`
   - two odd-indexed arguments (values) are equal, **only** for `ImmutableBiMap` (since bimap rejects duplicate values)

3. **Constant value resolution**
   Equality must be determined at compile time using constant folding. The following should be considered constant:
   - Literals (strings, primitives, boxed types)
   - `enum` constants
   - `static final` fields (effectively final variables)
   - Other compile-time constants as resolved by standard Java constant evaluation
   Variables that are not provably constant should be ignored (no false positives).

4. **Removal from `DistinctVarargsChecker`**
   `ImmutableMap.of` and `ImmutableBiMap.of` should no longer be matched by `DistinctVarargsChecker`. Only `ImmutableSortedMap.of` and other vararg methods that have distinctness constraints not already covered by `AlwaysThrows` should remain.

5. **Error severity and message**
   Findings must be reported at `ERROR` severity (consistent with the existing `AlwaysThrows` check). The diagnostic message should clearly indicate that the construction will throw, and list the duplicate keys (or values) in a human-readable form (e.g., simple names for variables/enums, string representation for literals).

**Non-goals**
- Dynamic or flow-dependent duplicate detection (e.g., variables that are only conditionally assigned the same value) is out of scope.
- Methods other than `ImmutableMap`/`ImmutableBiMap` builders and `of()` factories are not required.

AlwaysThrows: handle ImmutableMap constructions guaranteed to throw.


Efficiently apply `Replacements` in forward order to avoid repeated tail-shifting.

`Replacements.descending()` is used to apply edits back-to-front so each edit does not disturb already-applied positions. However, this forces the entire suffix of the source to be shifted for every edit, making the overall application O(n²) in the number of edits. Using ascending order and applying all changes in a single forward pass avoids that cost.

1. Add a method `SourceFile.makeReplacements(Replacements)` that:
   - uses `replacements.ascending()`
   - handles zero, exactly one, or many replacements
   - applies all replacements in a single pass, building the new source from the original linearly
   - still replaces the backing `StringBuilder` in a way that preserves any live `CharSequence` views of the content

2. Update `DescriptionBasedDiff.applyDifferences` to call `sourceFile.makeReplacements(replacements)` instead of iterating over `replacements.descending()` and calling `replaceChars` for each.

3. Change `SuggestedFix.getReplacements` to return `replacements.ascending()` so all callers naturally work in ascending order.

4. Deprecate `Replacements.descending()` and document that `ascending()` is preferred for applying changes.

No overlapping replacements are expected; the existing `Replacements` invariants (non-overlapping, coalesced where necessary) remain unchanged.

Migrate callers of descending() to ascending()


Expand the `ImmutableMemberCollection` check to cover additional JDK collection interfaces. Currently it only looks at `List` fields; extend it to also handle private final fields declared as `Set`, `SortedSet`, `NavigableSet`, `Map`, `SortedMap`, `ListMultimap`, and `SetMultimap`. When all assignments to such a field (including inline initializers, constructor assignments, and static block assignments) use a compatible Guava immutable type (`ImmutableSet`, `ImmutableSortedSet`, `ImmutableMap`, `ImmutableSortedMap`, `ImmutableListMultimap`, `ImmutableSetMultimap`), the check should suggest replacing the declared interface type with the corresponding immutable class and adding the import. If any assignment initializes with a mutable collection, the check must remain silent.

Expand ImmutableMemberCollection to more JDK collections.


Add a new Error Prone check, `FloggerLogString`, that verifies the argument to `LoggingApi.log(String)` is a compile-time constant (or a parameter annotated `@CompileTimeConstant`). The check should emit an error with a descriptive message, including recommendations to use Flogger’s formatting log methods (`log(String, Object...)`) where possible.

Additionally, adjust `FloggerFormatString` so that it no longer flags single-argument `log(String)` calls when `FloggerLogString` is active, avoiding duplicate errors. Introduce a flag, `FloggerLogStringDisabled`, to optionally retain the old behavior of `FloggerFormatString` and suppress the new check during rollout.

The new check must handle typical non-constant patterns:
- variable references and non-constant string expressions
- string concatenations with non-constant parts

It should accept:
- string literals
- `final` local variables initialized with constant values
- `static final` constants
- parameters annotated `@CompileTimeConstant`
- null literals cast to `String`

The error message should be:
`"Arguments to log(String) must be compile-time constants or parameters annotated with @CompileTimeConstant. If possible, use Flogger's formatting log methods instead."`

Add a check that ensures that args to `LoggingApi.log(String)` are compile-time


The `FieldMissingNullable` and `ParameterMissingNullable` checks generate suggested fixes that place `@Nullable` incorrectly when the project uses type-use annotations (e.g., `org.checkerframework.checker.nullness.qual.Nullable`).

For type-use annotations the fix must attach the annotation to the **type**, not to the declaration.
- For a field like `private final Object obj;` the fix should produce `private final @Nullable Object obj;`, but currently produces `@Nullable private final Object obj;`.
- For a parameter like `java.lang.Integer i` the fix should produce `java.lang.@Nullable Integer i`, but currently produces `@Nullable java.lang.Integer i`.

The `ReturnMissingNullable` check already handles this correctly for return types, but `FieldMissingNullable` and `ParameterMissingNullable` still use the old declaration‑only placement.

**Expected behavior:**
When a type-use annotation is the preferred `@Nullable` to insert, the suggested fix for fields and parameters must insert the annotation at the correct syntactic position on the type, consistent with the existing behavior for return types. Annotation placement should also work correctly for array types and nested/annotated types.

**Impact:**
Users of type-use annotations get a suggested fix that leads to invalid or misleading annotation placement, requiring manual editing to place the annotation on the type. This is especially noticeable for fully‑qualified type names, where the declaration placement is syntactically wrong.

Put type-use annotations in the right place, this time for FieldMissingNullable and ParameterMissingNullable.


We need a new Error Prone check that catches public methods named `stream()` when their return type doesn't look like a stream. Users reading such an API reasonably expect a stream return, so a method like `public int stream()` or `public String stream()` is misleading. The check should fire on any public method (including abstract, static, and interface default methods) whose simple unqualified return-type name does not end with `Stream`. It should not fire on private/package-private/protected methods, methods with a different name, or methods where the return type’s name does end with `Stream` (e.g., `java.util.stream.Stream`, `MyCustomStream`, etc.). Severity should be SUGGESTION, with a message like “Public methods named stream() are generally expected to return a type whose name ends with Stream. Consider choosing a different method name instead.” The check should be registered as an available, but not enabled-by-default, check in the built-in scanner suppliers.

Discourage public Foo stream() where Foo does _not_ end with "Stream"


We need a way to optionally allow certain overrides in `Java8ApiChecker` that are only present in JDK 9+ but whose parent API exists in JDK 8. The checker’s static API-diff currently flags methods like `java.nio.ByteBuffer.position(int)` and `java.util.zip.Checksum.update(byte[])` when the compile-time classpath is JDK 9+. This causes false positives in builds that compile against JDK 9+ for tooling but later use a JDK 8 bootclasspath to produce a JDK 8-compatible jar. In such builds those methods are not actually available to application code, so flagging them adds noise.

Add two boolean checker flags that default to `true` (preserving current behavior) but can be set to `false` to suppress these checks:

- `Java8ApiChecker:checkBuffer` – when `false`, do not report uses of any method on classes matching `java/nio/.*Buffer`.
- `Java8ApiChecker:checkChecksum` – when `false`, do not report uses of any method on `java/util/zip/Checksum`.

The flags should be read from `ErrorProneFlags` and applied by filtering the loaded API-diff before the checker runs. No other behavioral changes are required.

Optionally allow a couple of methods in Java8ApiChecker


## Feature Request: Flag overriding implementations of well-known nullable-return methods

The `ReturnMissingNullable` check should identify methods that override certain collection or utility APIs known to commonly return `null`, and suggest annotating them with `@Nullable`. Currently the check only inspects method bodies for explicit `null` returns. This leads to false negatives when a method’s contract permits returning `null` by virtue of the interface it implements, even if the implementation doesn’t contain a direct `null` return statement.

### Acceptance Criteria

1. **Trigger on override of recognized methods**
   If a method overrides (exact signature, proper inheritance) any of the following well-known methods, and the overriding method is not already annotated with a recognized `@Nullable`, the check shall emit a warning and provide a fix suggestion to add `@Nullable` to the return type.

   - `java.util.Map`: `get`, `put`, `putIfAbsent`, `remove` (1 parameter), `replace` (2 parameters)
   - `com.google.common.collect.BiMap`: `forcePut`
   - `com.google.common.collect.Table`: `get`, `put`, `remove`
   - `com.google.common.cache.Cache`: `getIfPresent`
   - `java.util.Queue`: `poll`, `peek`
   - `java.util.Deque`: `pollFirst`, `peekFirst`, `pollLast`, `peekLast`
   - `java.util.NavigableSet`: `lower`, `floor`, `ceiling`, `higher`, `pollFirst`, `pollLast`
   - `java.util.NavigableMap`: `lowerEntry`, `floorEntry`, `ceilingEntry`, `higherEntry`, `lowerKey`, `floorKey`, `ceilingKey`, `higherKey`, `firstEntry`, `lastEntry`, `pollFirstEntry`, `pollLastEntry`
   - `java.util.Spliterator`: `trySplit`

2. **Exact override matching**
   The check shall use standard override resolution. Two methods with the same name but different parameter counts (e.g., `remove(Object)` vs `remove(Object,Object)`) must be distinguished; only the signature matching the known nullable return contract is flagged. Similarly, methods that do not actually override a listed interface (e.g., a method named `get` in a class that does not extend or implement `Map`) shall not be flagged.

3. **Already annotated methods unchanged**
   If the overriding method’s return type is already annotated with a `@Nullable` annotation (e.g., `javax.annotation.Nullable`, `org.checkerframework.checker.nullness.qual.Nullable`, or any custom annotation recognized by the check’s nullness propagation), no warning is emitted.

4. **Multiple interface overrides**
   If a method overrides two or more interfaces, and at least one override target is in the recognized set, the check should flag it. Conversely, if all overridden ancestors are outside the set (e.g., user-defined interfaces with the same method name), no warning is produced.

5. **Fix suggestion**
   The suggested fix should add an appropriate `@Nullable` annotation (based on the existing imports and annotation scoping) to the method’s return type, inserting it in the correct position before the return type.

### Constraints / Non-goals

- Only the methods explicitly listed above should trigger the override detection. No heuristic guessing based on method names alone.
- The feature does not alter the existing body-analysis logic; it supplements it.
- The feature must not require the overriding method to carry the `@Override` annotation.
- No new configuration flags are needed; the behavior is always active.

This enhancement reduces manual work when adding correct nullability annotations to implementations of common collection abstractions, aligning the static analysis with the de facto nullable contract of those interfaces.

Recognize that implementations of Map.get, etc. have a @Nullable return type.


We need a new Error Prone check that bans direct use of Java APIs that can load arbitrary bytecode from potentially untrusted sources. These APIs are a common vector for remote code execution when the input is attacker-controlled.

The check must flag any invocations of the following methods as an error:
- `java.lang.ClassLoader#defineClass` (including overrides in subclasses)
- `java.lang.ClassLoader#findClass` (including overrides in subclasses, especially in `URLClassLoader`)
- `java.lang.invoke.MethodHandles.Lookup#defineClass`
- `java.rmi.server.RMIClassLoader#loadClass` and `#loadProxyClass`
- `java.rmi.server.RMIClassLoaderSpi#loadClass` and `#loadProxyClass`

The severity must be `ERROR`, and the diagnostic message should explain the risk: "Using dangerous ClassLoader APIs may deserialize untrusted user input into bytecode, leading to remote code execution vulnerabilities."

To avoid disrupting existing codebases, the check must be **disabled by default**—users must opt in explicitly. When enabled, the check should **skip test-only targets** (i.e., compilation units that Error Prone identifies as test code) so it does not fire in test scenarios.

ErrorProne checker to ban APIs that lead to dangerous class loading operations.


The `NotJavadoc` checker currently does not flag `/**…*/` or `///` style comments that are placed on record components, but record components cannot carry Javadoc. Documentation belongs in `@param` tags on the record declaration. We should extend the checker to detect these cases and report a clear message.

**Desired behavior:**

- When a Javadoc comment (either `/** … */` block or `///` line style) appears immediately before a record component, flag it with a message directing the user to move the documentation to an `@param` tag on the record class.
- For classic Javadoc block comments (`/** … */`), offer an automatic fix that converts the comment to a regular block comment (`/* … */`) by deleting the leading asterisk(s) after the opening `/**` marker. Handle multi-asterisk starters like `/****` correctly.
- For Markdown Javadoc line comments (`///`), flag the comment but do not provide an automatic fix at this time.

**Safety / invariants:**

- Only flag comments that are directly “seemingly javadocable” on record components. Do not flag legitimate Javadoc on the record class itself or on methods/constructors inside the record.
- Comments that are already on allowed javadoc locations (classes, methods, fields of non-record classes, etc.) must remain untouched.
- Existing messages for local classes and methods inside local classes must not change accidentally.
- Record components must no longer be considered valid javadoc targets in the internal javadoc-able-tree map (they were previously not added, but the map should explicitly exclude them to avoid future regressions).


Extend `UnnecessaryParentheses` to also flag annotation uses that end with an empty argument list (e.g., `@Deprecated()`, `@Override()`) and suggest removing the parentheses to leave just `@Deprecated`, `@Override`, etc. The check should apply to any annotation regardless of whether it has attributes, as long as the source text ends with `()` — the parentheses are unnecessary and can be stripped.

Strip unnecessary trailing parens from annotations (e.g., `@Deprecated()` -> `@Deprecated`, `@Override()` -> `@Override`).


In `@InlineMe` validation (`InlinabilityResult`), extend the guard against argument-evaluation-timing changes: when any method parameter is referenced inside a branch of a conditional expression (`?:`) that is not the top-level expression, refuse to inline the method. The concern is that the corresponding argument expression would be conditionally skipped after inlining, which can silently drop side effects. Accomplish this by generalizing the existing lambda-capture check to also scan conditional expression branches. Rename the relevant error reason from `LAMBDA_CAPTURES_PARAMETER` to `BODY_WOULD_EVALUATE_DIFFERENTLY` and update the message to cover both lambdas and conditionals.

Additionally, treat a method whose entire body is a single top-level conditional expression as a complex statement and reject it with `COMPLEX_STATEMENT`, since direct inlining would embed an unparenthesized ternary at the call site. Make sure the scanner handles nested conditionals correctly.

When an inlined method refers to method arguments in the true or false


The `MockIllegalThrows` check only inspects the first exception argument passed to `thenThrow(...)`. When multiple exceptions are supplied (e.g. `thenThrow(new IllegalArgumentException(), new Exception())`), any illegal checked exception appearing after the first position is silently ignored and no finding is reported. The rule should verify every exception argument, not just `getArguments().get(0)`. Additionally, calls to `thenThrow()` with zero arguments must not cause a failure; they should simply yield no match.

**Expected behavior:** For each exception argument to `thenThrow` that is a checked exception, the check should traverse the receiver chain and, if the exception is not throwable by the mocked method, report a finding. The check should stop after reporting the first such violation for a given `thenThrow` invocation (i.e., no duplicate reports for later arguments of the same call).

Handle multiple arguments in `thenThrow`.


The `try/fail`-to-`assertThrows` refactoring incorrectly includes full assignment and variable declaration statements in the generated lambda body, producing broken or misleading code. When the last statement before `fail()` is a local variable declaration with an initializer (e.g., `int age = getAge();`) or an assignment to an already-declared variable (`age = getAge();`), the current suggested fix emits the entire statement inside the lambda:

- `assertThrows(IllegalArgumentException.class, () -> int age = getAge());` (invalid syntax)
- `assertThrows(IllegalArgumentException.class, () -> age = getAge());` (assignment that never executes)

The lambda should contain only the expression that is expected to throw, i.e., the right-hand side of the assignment or the initializer expression.

**Expected behavior**
- If the variable is declared inside the `try` block (and not used afterward), the entire declaration should be removed from the surrounding code, and the lambda should contain just the initializer: `() -> getAge()`.
- If the variable declaration appears before the `try` block, the declaration must remain, but the lambda should again only contain the right-hand-side expression: `() -> getAge()`.
- The transformation must not break scoping and must preserve the semantics that the assignment never actually occurs (the statement throws before assignment).

**Impact**
A significant number of existing `try/fail` patterns assign the result to a variable that is never used because the expected exception is thrown. Until this is fixed, those cases cannot be automatically migrated to `assertThrows`, forcing manual cleanup and leaving the codebase with unnecessary suppression or stale patterns.

Please update the `tryFailToAssertThrows` logic in `AssertThrowsUtils` so that when the last throwing statement is an `AssignmentTree` or a `VariableTree` with an initializer, the fix extracts and uses only the expression from the right-hand side/initializer, and adjusts the retained source text accordingly.

Remove assignments from `assertThrows()` lambdas. A large percentage of remaining usages of the try/fail pattern assign the result of the statement to a variable, only to never use it (the assignment never happens because the statement throws).


Add a `WARNING` check, enabled by default, that rewrites `Optional.map(...)` to `Optional.ifPresent(...)` when the return value is unused (the expression is a statement) and the argument is void-compatible.

**Match conditions:**
- The method is `java.util.Optional.map`.
- The invocation is a direct expression statement (result not returned, assigned, or chained via another call).
- The argument is a void-compatible target:
  - method references, and
  - expression lambdas whose body is a method invocation.

**Fix:**
Rename the invocation from `map` to `ifPresent`. No other changes are needed.

**Non-goals (do not flag):**
- Cases where the result of `map` is used (e.g., `return optional.map(...)`, assigned to a variable, or chained like `.map(...).orElse(...)`).
- Lambdas that are not obviously a method invocation (e.g., `v -> v + 1`), since their void-compatibility cannot be trivially determined. (More precise JLS 15.12.2.1 compatibility checking can be added later.)

Register the checker in the built-in scanner so it is part of the default warning set.

Crate a check that rewrites Optional.map to Optional.ifPresent if the result value is unused.


**Title:** `InvalidLink` should warn on qualified Javadoc method references where the class exists but the member is missing or malformed

**Description:**

The `InvalidLink` check currently does not flag broken qualified method links when the class portion of the link resolves to a known type, but the referenced member does not exist. For example, the following Javadoc tag silently passes without any diagnostic:

```java
/**
 * {@link java.util.List#nonExistent()}
 */
void foo();
```

Since `java.util.List` is available, the checker should verify the member and warn that the method reference `#nonExistent()` does not resolve.

**Expected behavior:**

- If a link contains `#` and the class part can be resolved, the checker must inspect the member reference. If the method (or field) does not exist, emit a warning like:
  "The reference `%s` to a method doesn't resolve to anything. Is it misspelled, or is the parameter list not correct? See … for documentation on how to form method links."

- If the member reference uses generic type arguments (e.g., `{@link List#add(List<String>)}`), the warning should additionally include a note that the erasure should be used: "Note, in particular, that the erasure of generic types should be used (for example, List rather than List<Foo>)."

- Links that are fully-qualified type references *without* a `#` (e.g., `{@link java.util.List}`) should continue to be ignored, because they may refer to types not yet on the classpath at compile time. The current blanket skip for any reference containing a dot should be narrowed to only skip fully-qualified names that have no `#` member separator.

- If the class part itself cannot be resolved, the checker should not emit a spurious method-resolution warning (the link may be intended for an external library or a different compile-time environment).

- The checker must handle internal javac `NullPointerException`/`AssertionError` safely when resolving elements, avoiding crashes that could propagate to the build.

**Impact:**

Users currently have no compile-time signal that a qualified method link points to a non-existent member, leading to broken Javadoc output that can be confusing for readers. This improvement would make the `InvalidLink` check more thorough and consistent with how it already handles unqualified `#method` links.

Improve InvalidLink to better handle qualified method references.


We want a new Warning-level checker, `AlreadyChecked`, that finds boolean conditions which are already guaranteed to be `true` or `false` by an enclosing check. This helps surface dead code and unnecessary re-evaluation.

**Behavior:**
- When an `if` statement’s condition or a ternary’s condition is redundant given what is already known to be true/false at that point, report a diagnostic.
- In the `then` branch of `if (a)`, the expression `a` is vacuously `true` and `!a` is vacuously `false`. Similarly, in the `else` branch, `a` is vacuously `false` and `!a` is vacuously `true`.
- For nested `if`s, ternaries, and `else if` chains, the checker should track the accumulated certainties.
- Conjunctions (`&&`) in the outer condition make each conjunct known‑true inside the `then` branch: after `if (a && b)` both `a` and `b` are known `true` inside that block.

**Constraints and edge cases:**
- Only track **effectively final** boolean variables (no reassignment) to avoid false positives from mutation.
- Handle logical complement (`!`) correctly.
- **For this first implementation, keep the analysis simple:** only decompose identifier leaves joined by `&&` with optional `!`. Any use of `||` or other operators should cause that expression to be treated as opaque and not contribute to known truths/falsehoods. This avoids incorrect warnings on complex expressions.
- The checker should not warn across disjoint top‑level `if` statements (i.e., independent checks that are not nested or part of the same chain).

**Integration:**
- Add the checker as a `WARNING` (enabled by default) to `BuiltInCheckerSuppliers`, following the existing model of compile‑tree matchers.
- Diagnostic message should state whether the condition is vacuously true or false, and mention the relevant variable(s).

This is a starting point; later we can consider handling non‑final variables with flow analysis or richer expressions.

AlreadyChecked: scan for boolean conditions which have already been checked at each point.


**Title: Make `ImmutableRefactoring` permissive for mixed-class compilation units**

**Background**
The `ImmutableRefactoring` check currently operates on an all-or-nothing basis: it only proposes a fix (replace `javax.annotation.concurrent.Immutable` with `com.google.errorprone.annotations.Immutable`) if *every* class annotated with the JSR `@Immutable` passes the immutability analysis performed by `ImmutableChecker`. If any annotated class fails the check, `Description.NO_MATCH` is returned and no import replacement or annotation changes are offered. This prevents automated refactoring of files that contain a mix of provably-immutable and non-immutable classes.

**Requested Change**
Update `ImmutableRefactoring` so that the import replacement is always applied when any class uses the JSR `@Immutable`, and the handling becomes class‑by‑class:

1. **Import replacement**: In every compilation unit where a JSR `@Immutable` import exists and is the annotation used, replace the import with `com.google.errorprone.annotations.Immutable`.
2. **Per-class annotation handling**: For each class (top‑level or nested) annotated with the JSR `@Immutable`:
   - If the class passes the immutability analysis (`ImmutableChecker.matchClass` returns `NO_MATCH`), leave the `@Immutable` annotation token as‑is (it will now resolve to the Error Prone annotation due to the import change).
   - If the class **fails** the immutability analysis, **remove** the `@Immutable` annotation from that class, and **prepend** a comment line immediately before the class declaration stating that the class was annotated with `javax.annotation.concurrent.Immutable` but did not appear to be provably immutable.

**Edge Cases & Safety**
- Nested classes (including static inner classes) should be evaluated independently.
- The removal must target only the annotation with the simple name `Immutable` on that specific class, leaving any other annotations untouched.
- The comment must be placed directly before the class definition (i.e., prefixing the `ClassTree`), not before any enclosing class or file header.
- The import removal must not interfere with other uses of the same javax package; only the exact import of `javax.annotation.concurrent.Immutable` should be removed.
- The refactoring must produce a single `SuggestedFix` that combines all operations: import add/remove, annotation deletions, and comment insertions, so that the entire change is applied atomically.

**Acceptance Criteria**
- Files where *some* annotated classes are immutable and some are not receive a fix that replaces the import, keeps `@Immutable` on the immutable classes, and comments out the annotation on the non‑immutable classes.
- Files where *no* classes are immutable still receive the import replacement and annotate each class with the explanatory comment.
- Files where all classes are immutable behave roughly as before, but the fix generation is now class‑by‑class (the import is still replaced).
- The `ImmutableChecker` analysis must be used consistently, preserving its current severity and error reporting semantics for the purpose of deciding immutability.

ImmutableRefactoring: replace JSR @Immutable uses on non-immutable classes with comments.


**Title:** Flag compile‑time‑constant bitwise AND expressions that evaluate to zero

**Problem**
Developers occasionally mix up bitwise AND (`&`) with bitwise OR (`|`). When combining disjoint bit flags with `&`, the result is `0` – a value that is almost certainly unintended and indicates a coding mistake.
```java
int flags = 1 & 2;   // constant 0, probably meant 1 | 2
long mask = 8L & 3L; // constant 0L
```
Such expressions compile without errors but are dead/useless code. If the zero were intentional, the code is clearer and safer when written as a plain literal `0` rather than as an obscure computation.

**Expected behavior**
A static analysis check should detect any binary `&` expression whose compile‑time constant value is `0` (or `0L`) and issue a warning. The warning should:
- explain that the expression evaluates to zero and is likely a bitwise‑operator mistake,
- suggest replacing `&` with `|` as the intended fix,
- mention that if zero is really desired, the developer should just write a literal `0`.

The check should be conservative: it should only fire when the entire `&` expression is a compile‑time constant zero (e.g., `1 & 2`, `(1+2) & 4`, etc.). It should **not** fire on non‑constant operands or on other bitwise operators (like `|` or `^`).

**Impact**
- Prevents a subtle class of logic errors where intended flag combinations silently become zero.
- Improves code clarity by nudging intentional‑zero uses toward a literal `0`.
- Should be enabled by default as a warning so that it catches mistakes early.

Flag binary expressions involving & which results in a constant 0.


**Title:** `FloggerRequiredModifiers` suggests illegal modifier fixes for logger fields in interfaces

**Description:**
When the `FloggerRequiredModifiers` checker runs with the default (or any) “Goal” configuration, it evaluates logger field declarations inside `interface` types and may attempt to add `private`, `static`, and `final` modifiers. Fields in interfaces are implicitly `public static final`; applying `private` produces a compile error and the other modifiers are unnecessary. The checker should not propose modifier changes for fields whose enclosing type is an interface.

Additionally, the checker exposes an internal “Goal” flag (`FloggerRequiredModifiers:Goal`) that allows selectively enabling subsets of the checks. In production this flag is always left at the `DEFAULT_ALL_GOALS` value, so the variability only adds maintenance overhead and hides the fact that tests may not be exercising real behaviour. This complexity has allowed the interface-modifier bug to persist and should be removed so that the checker always applies all its checks without configuration.

**Steps to reproduce:**
1. Declare a FluentLogger field in an interface, e.g.:
   ~~~java
   interface MyInterface {
     FluentLogger logger = FluentLogger.forEnclosingClass();
     default void logSomething() { logger.atInfo().log("test"); }
   }
   ~~~
2. Run Error Prone with `FloggerRequiredModifiers` enabled (any Goal).
3. Observe the suggested fix.

**Actual behavior:**
The checker flags the field and suggests applying `private static final` modifiers, resulting in an invalid fix that would break compilation.

**Expected behavior:**
- No modifier-related fixes are proposed for logger fields declared directly in interfaces.
- The checker should still apply other applicable checks (e.g., hoisting constant expressions, relocating loggers from interfaces) when relevant.
- The internal `Goal` configuration should be eliminated; the checker should always run in its “all checks” mode, matching the effective production configuration.

**Impact:**
Users who follow the suggested fix will introduce compile errors. The presence of the `Goal` complexity also makes it harder to verify that the checker behaves correctly in all scenarios, potentially masking other edge cases.

Remove the `Goal` complexity from `FloggerRequriedModifiers`.


Add an Error Prone check (`VoidUsed`, warning) that flags any read of a `java.lang.Void`-typed variable (fields, local variables, parameters). Since such variables can only be `null`, the read can be replaced with the literal `null`. Exclude the left-hand side of assignments (where the variable is being written).

`VoidUsed`: flag `Void` variables being _used_, where they can simply be replaced with a literal `null`.


Add a new Error Prone check, `ZoneIdOfZ`, that rejects `java.time.ZoneId.of("Z")` and suggests `java.time.ZoneOffset.UTC` as the replacement.

- Match calls to `ZoneId.of` where the argument is the constant string `"Z"` (case-sensitive; `"z"` is not flagged).
- Support constant propagation so static final `String` fields whose value is `"Z"` are also caught.
- Exclude call sites inside `java.*` and `tck.java.*` packages to avoid false positives in JDK internals and test infrastructure.
- Emit a suggested fix that replaces the entire invocation expression with `ZoneOffset.UTC`, adding an import for `java.time.ZoneOffset` if it is not already present.
- Add the check to the enabled (error) checks in `BuiltInCheckerSuppliers`.

Add a check that bans `ZoneId.of("Z")` (currently demoted to `WARN`, pending global cleanup).