Cookbook

Inner Classes and Path-Dependent Types

To instantiate path-dependent types via constructor, their prefix type must be present in the object graph:

import distage._

trait Path {
  class A
  class B
}

val path = new Path {}
// path: AnyRef with Path = repl.Session$App0$$anon$1@269017e0

val module = new ModuleDef {
  make[path.A]
  make[path.type].from[path.type](path: path.type)
}
// module: AnyRef with ModuleDef = Set(SingletonBinding({type.{java.lang.Object & repl.Session::repl.Session.App0::repl.Session.App0.Path}::repl.Session.App0.Path.A},TypeImpl({java.lang.Object & repl.Session::repl.Session.App0::repl.Session.App0.Path}::repl.Session.App0.Path.A),Set(),(cookbook.md:24)), SingletonBinding({type.repl.Session.App0.<refinement>},ProviderImpl(repl.Session.App0.<refinement>,izumi.distage.model.providers.ProviderMagnet$$$Lambda$18788/0x0000000843303840@8e795fb(): repl.Session.App0.<refinement>),Set(),(cookbook.md:25)))

The same applies to type projections:

val module1 = new ModuleDef {
  make[Path#B]
  make[Path].from(new Path {})
}
// module1: AnyRef with ModuleDef = Set(SingletonBinding({type.repl.Session::repl.Session.App0::repl.Session.App0.Path::repl.Session.App0.Path.B},TypeImpl(repl.Session::repl.Session.App0::repl.Session.App0.Path::repl.Session.App0.Path.B),Set(),(cookbook.md:33)), SingletonBinding({type.repl.Session::repl.Session.App0::repl.Session.App0.Path},ProviderImpl({java.lang.Object & repl.Session::repl.Session.App0::repl.Session.App0.Path},izumi.distage.model.providers.ProviderMagnet$$$Lambda$18788/0x0000000843303840@151ec56c(): {java.lang.Object & repl.Session::repl.Session.App0::repl.Session.App0.Path}),Set(),(cookbook.md:34)))

Function and instance bindings and also compile-time mode in distage-static module do not require the type prefix:

val module2 = new ModuleDef {
  make[Path#B].fromValue {
    val path = new Path {}
    new path.B
  }
}
// module2: AnyRef with ModuleDef = Set(SingletonBinding({type.repl.Session::repl.Session.App0::repl.Session.App0.Path::repl.Session.App0.Path.B},InstanceImpl({java.lang.Object & repl.Session::repl.Session.App0::repl.Session.App0.Path}::repl.Session.App0.Path.B,repl.Session$App0$Path$B@34ed1004),Set(),(cookbook.md:42)))

Depending on Locator

Classes can depend on the Locator (container of the final object graph):

import distage._

class A(all: LocatorRef) {
  def c = all.get.get[C]
}
class B
class C

val module = new ModuleDef {
  make[A]
  make[B]
  make[C]
}

val locator = Injector().produce(module)

assert(locator.get[A].c eq locator.get[C]) 

Locator contains metadata about the plan and the bindings from which it was ultimately created:

// Plan that created this locator
val plan: OrderedPlan = locator.plan

// Bindings from which the Plan was built
val moduleDef: ModuleBase = plan.definition