scala编译器如何定位方差注释的位置

时间:2018-03-17 08:35:16

标签: scala

我试图理解编译器如何检查类型参数的位置是协变还是逆变。

据我所知,如果type参数是用+来注释的,那就是协变注释,那么任何方法都不能有一个用class / trait类型参数输入的输入参数。

例如,bar不能包含T类型的参数。

class Foo[+T] {
  def bar(param: T): Unit = 
    println("Hello foo bar")
}

因为bar()参数的位置被认为是负数,这意味着该位置的任何类型参数都处于逆变位置。

我很好奇Scala编译器如何能够找到类/特征中的每个位置是正面的,负面的还是中性的。似乎存在一些规则,比如在某些条件下翻转其位置但无法清楚地理解它。

另外,如果可能的话,我想知道如何定义这些规则。例如,似乎在具有协变注释的类中定义的方法的参数(如bar()类中的Foo方法)应该具有逆变类类型。为什么?

1 个答案:

答案 0 :(得分:2)

  

我很好奇Scala编译器如何找到它中的每个位置   阶级/特质是积极的,消极的或中立的。似乎那里   存在一些规则,比如在某些条件下翻转其位置但是   无法清楚地理解它。

Scala compiler有一个称为解析器的阶段(与大多数编译器一样),它遍历文本并解析出令牌。其中一个令牌称为方差。如果我们深入研究细节,那么有一个名为Parsers.typeParamClauseOpt的方法,它负责解析类型参数子句。与您的问题相关的部分是:

def typeParam(ms: Modifiers): TypeDef = {
  var mods = ms | Flags.PARAM
  val start = in.offset
  if (owner.isTypeName && isIdent) {
    if (in.name == raw.PLUS) {
      in.nextToken()
      mods |= Flags.COVARIANT
    } else if (in.name == raw.MINUS) {
      in.nextToken()
      mods |= Flags.CONTRAVARIANT
    }
  }

解析器在类型参数签名中查找+-符号,并创建一个名为TypeDef的类,该类描述了它的协变性,逆变性或不变性的类型和状态

  

另外,如果可能的话,我想知道如何定义这些规则。

方差规则具有普遍性,它们源于一个名为Category Theory的数学分支。更具体地说,它们来自Covariant and Contravariant Functors和两者之间的组合。如果您想了解有关这些规则的更多信息,那就是我要走的路。

此外,Scala编译器中有一个名为Variance的类,如果您想深入了解,它看起来像是方差规则的辅助类。