Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

encountered unrecoverable cycle resolving import #3123

Open
james-s-w-clark opened this issue Apr 16, 2024 · 1 comment
Open

encountered unrecoverable cycle resolving import #3123

james-s-w-clark opened this issue Apr 16, 2024 · 1 comment

Comments

@james-s-w-clark
Copy link
Contributor

james-s-w-clark commented Apr 16, 2024

This build.sc works OK:

import mill._
import mill.define.{Module}
import mill.eval.Evaluator

def sayHi(): Command[Unit]  = utils.sayThing("hi")

object utils extends mill.Module {

  def sayThing(thing: String): Command[Unit] =
    T.command {
      println(s"saying $thing")
    }
}

This build.sc hits the titular issue:

import mill._
import mill.define.{Module}
import mill.eval.Evaluator

import utils._
def sayProblem(): Command[Unit]  = sayThing("encountered unrecoverable cycle resolving import")

object utils extends mill.Module {
  def sayThing(thing: String): Command[Unit] =
    T.command {
      println(s"saying $thing")
    }
}

[info] compiling 1 Scala source to /Users/James.Clark/IdeaProjects/mill-cycle-module-import/out/mill-build/compile.dest/classes ...
[error] /Users/James.Clark/IdeaProjects/mill-cycle-module-import/build.sc:7:8: encountered unrecoverable cycle resolving import.
[error] Note: this is often due in part to a class depending on a definition nested within its companion.
[error] If applicable, you may wish to try moving some members into another object.
[error] import utils._
[error] ^
[error] /Users/James.Clark/IdeaProjects/mill-cycle-module-import/build.sc:11:27: Modules, Targets and Commands can only be defined within a mill Module
[error] object utils extends mill.Module {
[error] ^
[error] two errors found
1 targets failed
compile Compilation failed

In this short example you're pointed in the right direction (but, at least to me, it's not clear that the solution is to not have this import as in the first example).


If you move the imports around, the error changes too. Just by reordering, you could get e.g.

import utils._
import mill._
import mill.define.{Module}
import mill.eval.Evaluator

def sayProblem(): Command[Unit]  = sayThing("encountered unrecoverable cycle resolving import")

object utils extends mill.Module {
  def sayThing(thing: String): Command[Unit] =
    T.command {
      println(s"saying $thing")
    }
}

[error] import mill._
[error] ^
[error] /Users/James.Clark/IdeaProjects/mill-cycle-module-import/build.sc:1:8: encountered unrecoverable cycle resolving import.
[error] Note: this is often due in part to a class depending on a definition nested within its companion.
[error] If applicable, you may wish to try moving some members into another object.
[error] import utils._

That's still not too bad, it still talks about utils at least.


What if you have a bunch more imports?

import mill._
import mill.define.{Module}
import mill.eval.Evaluator
import utils._
import mill.contrib.jmh.JmhModule
import $ivy.`com.lihaoyi::mill-contrib-jmh:`
import mill.scalalib._
import mill.util.Jvm

def sayProblem(): Command[Unit]  = sayThing("encountered unrecoverable cycle resolving import")

object utils extends mill.Module {
  def sayThing(thing: String): Command[Unit] =
    T.command {
      println(s"saying $thing")
    }
}

[build.sc] [49/53] compile
[info] compiling 1 Scala source to /Users/James.Clark/IdeaProjects/mill-cycle-module-import/out/mill-build/compile.dest/classes ...
[error] /Users/James.Clark/IdeaProjects/mill-cycle-module-import/build.sc:7:13: encountered unrecoverable cycle resolving import.
[error] Note: this is often due in part to a class depending on a definition nested within its companion.
[error] If applicable, you may wish to try moving some members into another object.
[error] import mill.scalalib._
[error] ^
[error] /Users/James.Clark/IdeaProjects/mill-cycle-module-import/build.sc:6:8: encountered unrecoverable cycle resolving import.
[error] Note: this is often due in part to a class depending on a definition nested within its companion.
[error] If applicable, you may wish to try moving some members into another object.
[error] import root._
[error] ^
[error] two errors found
1 targets failed
compile Compilation failed

We've lost the guidance towards this bad import.


How did we arrive at this bad import?

In mill 0.10.n, this is OK:

import mill._
import mill.define.{Module}
import mill.eval.Evaluator
import utils._
import mill.contrib.jmh.JmhModule
import $ivy.`com.lihaoyi::mill-contrib-jmh:`
import mill.scalalib._
import mill.util.Jvm

 
def sayProblem(): Command[Unit]  = sayThing("encountered unrecoverable cycle resolving import")

object utils {
  def sayThing(thing: String): Command[Unit] =
    T.command {
      println(s"saying $thing")
    }
}

But in 0.11.m, you get:

mill-cycle-module-import mill sayProblem
No mill version specified.
You should provide a version via '.mill-version' file or --mill-version option.
Using mill version 0.11.7
[build.sc] [47/53] zincReportCachedProblems
Unknown ctx of target sayThing: millbuild.build$utils$@747a0827

I added extends mill.Module as that error lead to this suggestion at #2888 (comment)


I couldn't find an issue when searching for encountered unrecoverable cycle resolving import, so at least this should help anyone who comes across the same 👍

@lefou
Copy link
Member

lefou commented May 16, 2024

I guess re-using public targets and commands defined elsewhere is never a good idea. Instead, you should define a new command with T.command { .. } and call (meaning: depend on) the other command from there. E.g.:

def sayProblem(): Command[Unit]  = T.command {
  sayThing("encountered unrecoverable cycle resolving import")()
}

Even, better, make the sayThing command an annonymous task with T.task { .. }.

Unfortunately, the types are correct, therefore the compiler will not call our implicit conversions here. The proper definition of a command should always contain the T.commnad { .. } on the left hand side, which is not the case in the definition of sayProblem in all of your examples. That means, the commands context isn't correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants