How to combine the Module Dependencies with the Dependencies of its parent Module with Mill - scala

I want to combine the Module Dependencies with the ones from the parent Module.
I have the following in my build.sc:
trait ExampleModule extends ModuleWithTests {
override def moduleDeps = Seq(camunda, cli)
}
object twitter extends ExampleModule {
override def moduleDeps = super.moduleDeps ++ Seq(twitterApi)
}
This gives me:
build.sc:222: type mismatch;
found : Seq[build.this.ModuleWithTests]
required: Seq[build.this.ModuleWithTests{def moduleDeps: Seq[build.this.ModuleWithTests]}]
override def moduleDeps = super.moduleDeps ++ Seq(twitterApi)
^
build.sc:222: `T.command` definitions must have 1 parameter list
override def moduleDeps = super.moduleDeps ++ Seq(twitterApi)
^
Compilation Failed
Is there a way to achieve this, or do I have to list the module dependencies in each child module?

Your example is almost right, but because you omitted the explicit return type of ExampleModule.moduleDeps it seems the compiler inferred a more specific type of Seq[ModuleWithTests] in this case. Looks like all your modules camunda and cli also implement this trait. Whereas twitterApi seems to not implement it.
To fix the compile error, you might try to add the explicit return type Seq[JavaModule] to ExampleModule.moduleDeps.

Related

sbt could not find implicit value for parameter valName

I'm using sbt to build some of the riscv boom from the source code, but the sbt complains that it "could not find implicit value for parameter valName: : freechips.rocketchip.diplomacy.ValName". The detailed error message are as below:
[error] F:\hiMCU\my_proj\src\main\scala\freechips\rocketchip\tile\BaseTile.scala:170:42: could not find implicit value for parameter valName: freechips.rocketchip.diplomacy.ValName
[error] Error occurred in an application involving default arguments.
[error] protected val tlMasterXbar = LazyModule(new TLXbar)
The code where sbt complains is as below:
abstract class BaseTile private (val crossing: ClockCrossingType, q: Parameters)
extends LazyModule()(q)
with CrossesToOnlyOneClockDomain
with HasNonDiplomaticTileParameters
{
// Public constructor alters Parameters to supply some legacy compatibility keys
def this(tileParams: TileParams, crossing: ClockCrossingType, lookup: LookupByHartIdImpl, p: Parameters) = {
this(crossing, p.alterMap(Map(
TileKey -> tileParams,
TileVisibilityNodeKey -> TLEphemeralNode()(ValName("tile_master")),
LookupByHartId -> lookup
)))
}
def module: BaseTileModuleImp[BaseTile]
def masterNode: TLOutwardNode
def slaveNode: TLInwardNode
def intInwardNode: IntInwardNode // Interrupts to the core from external devices
def intOutwardNode: IntOutwardNode // Interrupts from tile-internal devices (e.g. BEU)
def haltNode: IntOutwardNode // Unrecoverable error has occurred; suggest reset
def ceaseNode: IntOutwardNode // Tile has ceased to retire instructions
def wfiNode: IntOutwardNode // Tile is waiting for an interrupt
protected val tlOtherMastersNode = TLIdentityNode()
protected val tlSlaveXbar = LazyModule(new TLXbar)
protected val tlMasterXbar = LazyModule(new TLXbar)
protected val intXbar = LazyModule(new IntXbar)
....
}
The LazyModule object code is as below:
object LazyModule
{
protected[diplomacy] var scope: Option[LazyModule] = None
private var index = 0
def apply[T <: LazyModule](bc: T)(implicit valName: ValName, sourceInfo: SourceInfo): T = {
// Make sure the user put LazyModule around modules in the correct order
// If this require fails, probably some grandchild was missing a LazyModule
// ... or you applied LazyModule twice
require (scope.isDefined, s"LazyModule() applied to ${bc.name} twice ${sourceLine(sourceInfo)}")
require (scope.get eq bc, s"LazyModule() applied to ${bc.name} before ${scope.get.name} ${sourceLine(sourceInfo)}")
scope = bc.parent
bc.info = sourceInfo
if (!bc.suggestedNameVar.isDefined) bc.suggestName(valName.name)
bc
}
}
I think the sbt should find some val of type freechips.rocketchip.diplomacy.ValName, but it didn't find such kind of val.
You need to have an object of type ValName in the scope where your LazyModules are instantiated:
implicit val valName = ValName("MyXbars")
For more details on Scala's implicit please see https://docs.scala-lang.org/tutorials/tour/implicit-parameters.html.html
You generally shouldn't need to manually create a ValName, the Scala compiler can materialize them automatically based on the name of the val you're assigning the LazyModule to. You didn't include your imports in your example, but can you try importing ValName?
import freechips.rocketchip.diplomacy.ValName
In most of rocket-chip code, this is imported via wildcard importing everything in the diplomacy package
import freechips.rocketchip.diplomacy._

MappedEnum - No implicit view available

Can someone help me to understand what is wrong with the code below? The problem is inside the "join" method - I am not able to set "state" field. Error message is -
No implicit view available from code.model.Membership.MembershipState.Val => _14.MembershipState.Value.
[error] create.member(user).group(group).state(MembershipState.Accepted).save
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
What does _14 mean? I tried similar thing with MappedGender and it works as expected, so why MappedEnum fails?
scala 2.10
lift 2.5
Thanks
package code
package model
import net.liftweb.mapper._
import net.liftweb.util._
import net.liftweb.common._
class Membership extends LongKeyedMapper[Membership] with IdPK {
def getSingleton = Membership
object MembershipState extends Enumeration {
val Requested = new Val(1, "Requested")
val Accepted = new Val(2, "Accepted")
val Denied = new Val(3, "Denied")
}
object state extends MappedEnum(this, MembershipState)
{
override def defaultValue = MembershipState.Requested
}
object member extends MappedLongForeignKey(this, User) {
override def dbIndexed_? = true
}
object group extends MappedLongForeignKey(this, Group) {
override def dbIndexed_? = true
}
}
object Membership extends Membership with LongKeyedMetaMapper[Membership] {
def join (user : User, group : Group) = {
create.member(user).group(group).state(MembershipState.Accepted).save
}
}
Try moving your MembershipState enum outside of the MembershipClass. I was getting the same error as you until I tried this. Not sure why, but the code compiled after I did that.
_14 means a compiler-generated intermediate anonymous value. In other words, the compiler doesn't know how to express the type it's looking in a better way.
But if you look past that, you see the compiler is looking for a conversion from [...].Val to [...].Value. I would guess that changing
val Requested = new Val(1, "Requested")
to
val Requested = Value(1, "Requested")
would fix the error.
(I'm curious where you picked up the "new Val" style?)
What's strange is that Val actually extends Value. So if the outer type was known correctly (not inferred to the odd _14) Val vs. Value wouldn't be a problem. The issue here is that Lift from some reason defines the setters to take the now-deprecated view bound syntax. Perhaps this causes the compiler, rather than going in a straight line and trying to fit the input type into the expected type, instead to start from both ends, defining the starting type and the required type, and then start searching for an implicit view function that can reconcile the two.

How do I refer to enclosing "this" in a Scala macro?

The following macro, extracted from a larger example, is supposed to create a tree with nothing but a reference to this:
def echoThisImpl(c:Context): c.Expr[Any] = {
import c.universe._
val selfTree = This(c.enclosingClass.symbol)
c.Expr[AnyRef](selfTree)
}
def echoThis: Any = macro CallMacro.echoThisImpl
But a call to echoThis such as
object Testing extends App {
val thisValue = CallMacro.echoThis
println(thisValue)
}
fails to compile, with the message
[error] /home/rafael/dev/scala/goose/goose-macros/src/test/scala/Testing.scala:8: type mismatch;
[error] found : <noprefix>
[error] required: Any
[error] val thisValue = CallMacro.echoThis
If I set the -Ymacro-debug-lite flag the generated tree is This(newTermName("<local Testing>")).
There are two options of achieving what you want:
1) Use This(tpnme.EMPTY). Currently this doesn't compile, so you'll have to use This(newTypeName("")) instead, but in RC1 this will be fixed.
2) Use This(c.enclosingClass.symbol.asModule.moduleClass). Currently this doesn't work, because of https://issues.scala-lang.org/browse/SI-6394, but in RC1 this will be fixed.

Specs implicit conversion conflicts with Scala Predef

I have a type alias in my code like so:
type Time = Double
And I often in both tests and in applications pass Long values to functions that use this type. For instance:
def at(time : Time) : T = {
// Do Something
}
at(System.currentTimeMillis)
This code works fine unless run in my tests where I get the following error:
found : Long
required: com.github.oetzi.echo.Echo.Time
Note that implicit conversions are not applicable because they are ambiguous:
both method long2double in object Predef of type (x: Long)Double
and method longToDouble in trait NumericBaseMatchers of type (s: Long)Double
are possible conversion functions from Long to com.github.oetzi.echo.Echo.Time
After looking up NumericBaseMatchers it seems its part of the Specs testing framework (my tests are written in Specs 1). I tried running code to get the error in the interpreter and it was fine out side of the tests.
Is there any way I can somehow remove the ambiguity so I can pass Long to values to a Double/Time function? Why does Specs try and create its own LongToDouble conversion when Scala already provides this?
If you want to deactivate an inherited implicit conversion you can do this:
override def longToDouble(s: Long) = super.longToDouble(s)
For convenience if you add it to a new trait, you can mix-in your trait to your specification when needed:
trait NoConversion {
override def longToDouble(s: Long) = super.longToDouble(s)
}
class MySpecification extends NoConversion {
...
}
Try unimporting one of them.
import NumericBaseMatchers.{longToDouble => _}

Scala conflicting inherited method names

I am trying to write some code to test a database model. Both the test framework and the database framework use the "===" operator, and the test framework's is being given preference. How can I explicitly use one method or the other?
Example:
import org.scalatest.FunSuite
class TestDBModels extends FunSuite{
test("Test DoublePropertyEntry with a few new values") {
Schemas.doubleProperties.deleteWhere(p => (p.id === p.id)))
}
}
Error:
type mismatch;
found : Option[String]
required: org.squeryl.dsl.ast.LogicalBoolean
Schemas.doubleProperties.deleteWhere(p => (p.===(p.id, p.id)))
You have a number of options. The first and easiest is to use an explicit method call instead of the implicit conversion. For example, to explicitly use the scalatest ===:
Schemas.doubleProperties.deleteWhere(p => (convertToEqualizer(p.id) === p.id)))
If this is too long, you could shorten the name:
def toEq(left: Any) = convertToEqualizer(left: Any)
Schemas.doubleProperties.deleteWhere(p => (toEq(p.id) === p.id)))
convertToEqualizer is the implicit conversion method for scalatest. One other option is to override convertToEqualizer as a non-implicit method:
override def convertToEqualizer(left: Any) = new Equalizer(left)
This stops this particular implicit conversion happening. See the scalatest documentation for Assertions object and the same question on the scalatest-users mailing list.