具有泛型类型和带装箱参数的方法的 scala 抽象类 - 类型不匹配

问题描述 投票:0回答:1

我在编译此 Scala 2 代码时遇到问题:

import chisel3._
import circt.stage.ChiselStage.emitCHIRRTL

class Box[X](val content: X)
abstract class Combination[I <: Bits, O <: Bits] {
  def fn1: I => O
  def fn2: Box[I] => I
}

object Comb1 extends Combination[SInt, SInt] {
  def fn1 = (x: SInt) => x
  def fn2 = (x: Box[SInt]) => x.content
}

object Comb2 extends Combination[UInt, UInt] {
  def fn1 = (x: UInt) => x
  def fn2 = (x: Box[UInt]) => x.content
}

val rand = new scala.util.Random
val temp = rand.nextInt(2) + 1
val comb = temp match {
  case 1 => Comb1
  case 2 => Comb2
}

class TopModule[I <: Bits, O <: Bits](comb: Combination[I, O]) extends Module

println(emitCHIRRTL(new TopModule(comb)))

但是,我得到的错误如下:

type mismatch;
 found   : Playground.Combination[_ >: chisel3.SInt with chisel3.UInt <: chisel3.Bits with chisel3.Num[_ >: chisel3.SInt with chisel3.UInt <: chisel3.Bits], _ >: chisel3.SInt with chisel3.UInt <: chisel3.Bits with chisel3.Num[_ >: chisel3.SInt with chisel3.UInt <: chisel3.Bits]]{def fn2: Playground.Box[chisel3.SInt] with Playground.Box[chisel3.UInt] => chisel3.Bits}
 required: Playground.Combination[chisel3.Bits with chisel3.Num[_ >: chisel3.SInt with chisel3.UInt <: chisel3.Bits],chisel3.Bits with chisel3.Num[_ >: chisel3.SInt with chisel3.UInt <: chisel3.Bits]]

此示例可在 Scastie 上使用:https://scastie.scala-lang.org/JersAqMWRAC3Zgykbewr5A

任何人都可以帮助我理解为什么会发生这种情况吗?我意识到这在某种程度上是包含

fn2
的效果,它使用了 Boxed 参数。因此,如果我删除
fn2
实例,此代码可以正常编译。

我的目标是使用

Combination
来参数化
TopModule
和其他类似的类。

scala generics generic-variance
1个回答
0
投票

虽然

SInt
UInt
都是
Bits
的子类型,但它们彼此不兼容。当您在
Comb1
Comb2
之间进行模式匹配时,必须为结果分配一个类型,但 Scala 无法确定满足两者的通用超类型,因为
fn2
需要
Box[SInt]
Box[UInt]
。这种不匹配导致了错误。

为了解决这个问题,我在

Combination
类中使用了路径相关类型,并且效果很好 here

import chisel3._
import circt.stage.ChiselStage.emitCHIRRTL
import chisel3.util._
import chisel3.experimental.VecLiterals._ 


class Box[X](val content: X)
abstract class Combination{
  type I <: Bits
  type O <: Bits
  def fn1: I => O
  def fn2: Box[I] => I
}

object Comb1 extends Combination {
  type I = SInt
  type O = SInt
  def fn1 = (x: I) => x
  def fn2 = (x: Box[I]) => x.content
}

object Comb2 extends Combination {
  type I = UInt
  type O = UInt
  def fn1 = (x: I) => x
  def fn2 = (x: Box[I]) => x.content
}

val rand = new scala.util.Random
val temp = rand.nextInt(2) + 1


val comb: Combination = temp match {
  case 1 => Comb1
  case 2 => Comb2
}

class TopModule(val comb: Combination) extends Module

println(emitCHIRRTL(new TopModule(comb)))
© www.soinside.com 2019 - 2024. All rights reserved.