[Experimental] Opt-in @Environment resolution to prevent warnings during inspection - #416
Draft
garry-jeromson wants to merge 1 commit into
Draft
Conversation
garry-jeromson
force-pushed
the
feature/environment-resolution
branch
2 times, most recently
from
March 2, 2026 00:04
f5c27da to
bfd3438
Compare
garry-jeromson
marked this pull request as draft
March 2, 2026 00:15
…ing inspection When ViewInspector evaluates a custom view's body, @Environment properties in .keyPath state trigger "Accessing Environment<T>'s value outside of being installed on a View" warnings. This adds opt-in resolution that transitions @Environment fields from .keyPath to .value state before body evaluation. Key features: - Opt-in via ViewInspectorConfig.resolveEnvironmentValues or env var - Supports standard SwiftUI keys and custom EnvironmentKey types - Honors .environment() modifier overrides from test code - Thread-safe: values flow through the call chain, no mutable statics - Skips action/closure-based environment values (ARC safety) Technical approach: - EnvironmentResolvable protocol for type-erased generic resolution - AnyWritableEnvironmentKeyPath protocol for type-erased modifier application - Raw byte manipulation of @Frozen @Environment<Value> enum layout - Keypath-pointer-only matching to handle Mirror spare byte divergence Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
garry-jeromson
force-pushed
the
feature/environment-resolution
branch
from
March 2, 2026 00:36
bfd3438 to
2583e6d
Compare
Owner
|
This is very interesting, thanks for the PR! I hope I'll get some free time soon to explore this more and merge. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When ViewInspector evaluates a custom view's
body, any@Environmentproperties still in their.keyPathstate trigger:In large test suites this can produce thousands of warnings (e.g. ~4,000 in ours), making it difficult to spot real issues in test output.
Related issues: #131, #167, #338
Solution
This PR adds opt-in
@Environmentresolution that transitions fields from.keyPathto.valuestate beforebodyevaluation, eliminating the warnings entirely.Enabling
Custom environment values
Test code using
.environment()modifiers is automatically honored during resolution — both standard SwiftUI keys and customEnvironmentKeytypes:Technical approach
EnvironmentResolvableprotocol — conformance onEnvironment<Value>enables type-erased generic resolution via_resolve(using:)AnyWritableEnvironmentKeyPathprotocol — conformance onWritableKeyPath<EnvironmentValues, T>enables type-erased application of.environment()modifier overrides@frozen@Environment<Value>enum layout (.keyPath→.valuestate transition)sizeof(Value) > sizeof(KeyPath), Mirror-extracted copies have divergent spare payload bytes; matching only the keypath pointer (which is unique per field) avoids false negativesbuildValueStateBytesuses raw memory allocation to avoid corrupting reference-counted keypath fieldsThis is an experimental approach that relies on
@Environment's@frozenABI-stable layout. It works reliably in our test suite but should be considered carefully before broader adoption:@frozendependency — the implementation assumes@Environment<Value>uses a two-case enum (keyPath/value) with a specific byte layout. This is ABI-stable but not a public API contract.Value types only — resolution is skipped for
@Environmentvalues that contain reference types (closures, classes). Action-type environments like\.dismissand\.openURLare safely ignored.Resolved values are defaults unless overridden — without
.environment()modifiers, values come fromEnvironmentValues()(SwiftUI defaults). Custom keys use theirEnvironmentKey.defaultValue.Files changed
EnvironmentInjection.swiftViewInspectorConfig,EnvironmentResolvable,AnyWritableEnvironmentKeyPathContentExtraction.swiftcopy.body/copy.body(), threadenvironmentModifiersparameterCustomView.swiftmedium.environmentModifiersthrough toextractContentEnvironmentInjectionTests.swiftTest coverage
@Environmentfields@Environment+@EnvironmentObject@Environment.environment()modifierEnvironmentKeyoverride via.environment()modifier@EnvironmentObjectinjection unaffected