You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While there isn't an "official" way to share information, it is possible to access some FIR elements from IR using the metadata property:
val IrClass.firClass: FirClass? get() = (metadata as? FirMetadataSource.Class)?.fir
Combine that with the ability to add custom data to FIR declarations, you should be able to store information in FIR and access it from IR:
class CustomData(...)
object CustomDataAttribute : FirDeclarationDataKey()
var FirClass.customData: CustomData? by FirDeclarationDataRegistry.data(CustomDataAttribute)
val IrClass.customData: CustomData? get() = (metadata as? FirMetadataSource.Class)?.fir?.customData
Dumped this into an LLM for some inspo in case anyone wants to take some cracks at this
Plan: FIR Attribute Migration for Metro Compiler
This document outlines a plan to use FIR attributes (FirDeclarationDataKey / FirDeclarationDataRegistry) to share precomputed analysis data between the FIR and IR phases of the Metro compiler. This will eliminate redundant scanning and analysis, improving performance and consistency.
Tier 1: High-Impact Candidates
These candidates involve core models that are currently fully recomputed in IR or are accessed extremely frequently.
1. MetroAnnotations Extraction
Description: The structured representation of Metro-specific annotations (e.g., @Provides, @Inject, @Scope).
Current State: Extensively parsed in AggregationChecker, BindingContainerCallableChecker, and all generators. Re-parsed in DependencyGraphTransformer and BindingLookup using IR annotations.
Benefit: Storing MetroAnnotations<MetroFirAnnotation> on FirCallableDeclaration and FirClass eliminates repeated filtering and analysis of the annotations list across both phases.
2. InjectedClass Model & Inject Constructor Resolution
Description: Information about constructor-injected classes: which constructor is injectable, assisted injection status, and member injection sites.
Current State:findInjectConstructor() is called multiple times across FIR checkers and IR transformers. The InjectedClass model is re-derived in IR with explicit "TODO" comments in InjectConstructorTransformer and MembersInjectorTransformer.
Benefit: Centralizes the "injectability" model. IR can simply look up the attribute to find the constructor and members without re-scanning all class declarations.
3. ContextualTypeKey / WrappedType Analysis
Description: The "contextual" view of a type, distinguishing between the canonical type and its wrapping layers (e.g., Provider<Lazy<T>>).
Current State:asFirContextualTypeKey and asContextualTypeKey perform nearly identical recursive analysis in FIR and IR respectively.
Benefit: Attaching the resolved contextual key/WrappedType structure to parameters and return types avoids repeated structural analysis of complex generic types.
4. BindingContainer & Provider Callable Metadata
Description: Metadata for @BindingContainer classes and their provider callables, including includes, should-generate-object flags, and parameter type keys.
Current State: Re-scanned in BindingContainerTransformer and IrBindingContainerResolver to build transitive closures. Currently uses a synthetic @CallableMetadata annotation for some bridging.
Benefit: Pre-identifying containers and their contents in FIR speeds up IR graph construction and eliminates the need for IR member scans.
Tier 2: Medium-Impact Candidates
These candidates involve specific metadata resolution that is currently duplicated but has a more localized impact.
Description: Unified representation of a callable's parameters, including FirTypeKey, assisted identifiers, and flags.
Current State: Computed in generators to scaffold declarations and re-derived in IR to implement bodies.
Benefit: Carrying the Parameters model ensures consistency and avoids re-resolving "contextual" types or assisted strings.
6. Contribution & Scope Metadata
Description: Resolved scope ClassIds, rank, and replaces targets for @ContributesBinding and related annotations.
Current State: Resolution often requires a custom type resolver. Doing this once in FIR and storing it simplifies the complex merging logic in IrContributionMerger.
Benefit: Avoids re-reading scope annotations and re-resolving target classes in IR.
7. GraphNode Categorization & Creator Info
Description: Classification of graph members (accessors, injectors, extensions) and SAM function signatures for creators.
Current State: Analyzed in FIR for diagnostics and re-scanned from all class members in GraphNodes.Builder.build in IR.
Benefit: Storing the member category as an attribute on the callable symbol avoids a full re-scan of graph members in IR.
8. Qualifier Annotation
Description: Resolved qualifier meta-annotations.
Current State: Searched in fir.kt and re-extracted during IrTypeKey construction.
Binding Container Status: Recursive check for isBindingContainer() can be cached as a boolean.
Include/Exclusion Lists: Pre-resolved ClassId lists for @DependencyGraph includes/excludes.
Member Injection Map: Already partially bridged via MemberInjectClass.toProto() for cross-compilation, but FIR attributes would help the in-compilation path.
Recommended Implementation Order
InjectedClass (Tier 1, Basic component processing #2): Highest priority as IR code already has TODO comments requesting this and it touches core injection logic.
Inject Constructor Resolution: Simple attribute shape (single constructor reference) with high frequency of use.
From @bnorm in kotlinlang
Dumped this into an LLM for some inspo in case anyone wants to take some cracks at this
Plan: FIR Attribute Migration for Metro Compiler
This document outlines a plan to use FIR attributes (
FirDeclarationDataKey/FirDeclarationDataRegistry) to share precomputed analysis data between the FIR and IR phases of the Metro compiler. This will eliminate redundant scanning and analysis, improving performance and consistency.Tier 1: High-Impact Candidates
These candidates involve core models that are currently fully recomputed in IR or are accessed extremely frequently.
1. MetroAnnotations Extraction
@Provides,@Inject,@Scope).AggregationChecker,BindingContainerCallableChecker, and all generators. Re-parsed inDependencyGraphTransformerandBindingLookupusing IR annotations.MetroAnnotations<MetroFirAnnotation>onFirCallableDeclarationandFirClasseliminates repeated filtering and analysis of the annotations list across both phases.2. InjectedClass Model & Inject Constructor Resolution
findInjectConstructor()is called multiple times across FIR checkers and IR transformers. TheInjectedClassmodel is re-derived in IR with explicit "TODO" comments inInjectConstructorTransformerandMembersInjectorTransformer.3. ContextualTypeKey / WrappedType Analysis
Provider<Lazy<T>>).asFirContextualTypeKeyandasContextualTypeKeyperform nearly identical recursive analysis in FIR and IR respectively.4. BindingContainer & Provider Callable Metadata
@BindingContainerclasses and their provider callables, including includes, should-generate-object flags, and parameter type keys.BindingContainerTransformerandIrBindingContainerResolverto build transitive closures. Currently uses a synthetic@CallableMetadataannotation for some bridging.Tier 2: Medium-Impact Candidates
These candidates involve specific metadata resolution that is currently duplicated but has a more localized impact.
5. Parameters & Parameter Models (including Assisted Keys)
FirTypeKey, assisted identifiers, and flags.Parametersmodel ensures consistency and avoids re-resolving "contextual" types or assisted strings.6. Contribution & Scope Metadata
ClassIds, rank, andreplacestargets for@ContributesBindingand related annotations.IrContributionMerger.7. GraphNode Categorization & Creator Info
GraphNodes.Builder.buildin IR.8. Qualifier Annotation
fir.ktand re-extracted duringIrTypeKeyconstruction.Tier 3: Lower Priority / Already Partially Handled
isBindingContainer()can be cached as a boolean.ClassIdlists for@DependencyGraphincludes/excludes.MemberInjectClass.toProto()for cross-compilation, but FIR attributes would help the in-compilation path.Recommended Implementation Order
Implementation Pattern
1. Define the attribute key
2. Store in FIR (during generator or checker)
declaration.injectedClassData = computedInjectedClass3. Read in IR