Scala的类型擦除如何适用于更高的kinded类型参数?

时间:2018-01-25 02:22:38

标签: scala generics type-erasure higher-kinded-types scala-compiler

我不明白 Scala会删除哪些泛型类型参数。我曾经认为它应该删除所有泛型类型参数,但似乎并非如此。

如果我错了,请纠正我:如果我在代码中实例化了Map[Int, String]类型的实例,那么在运行时,实例只知道它是Map[_, _]类型,并且对其泛型类型参数一无所知。这就是以下成功编译和执行而没有错误的原因:

val x: Map[Int, String] = Map(2 -> "a")
val y: Map[String, Int] = x.asInstanceOf[Map[String, Int]]

现在我希望所有更高级别的类型参数也被删除,也就是说,如果我有一个

class Foo[H[_, _], X, Y]

我希望Foo[Map, Int, String]类型的实例对Map一无所知。但现在考虑以下类型的类型转换"实验":

import scala.language.higherKinds

def cast1[A](a: Any): A = a.asInstanceOf[A]
def cast2[H[_, _], A, B](a: Any) = a.asInstanceOf[H[A, B]]
def cast3[F[_[_, _], _, _], H[_, _], X, Y](a: Any) = a.asInstanceOf[F[H, X, Y]]
class CastTo[H[_, _], A, B] {
  def cast(x: Any): H[A, B] = x.asInstanceOf[H[A, B]]
}

ignoreException {
  val v1 = cast1[String](List[Int](1, 2, 3))                      
  // throws ClassCastException
}

ignoreException {
  val v2 = cast2[Map, Int, Long](Map[String, Double]("a" -> 1.0)) 
  // doesn't complain at all, `A` and `B` erased
}

ignoreException {
  // right kind
  val v3 = cast2[Map, Int, Long]((x: Int) => x.toLong)            
  // throws ClassCastException
}

ignoreException {
  // wrong kind
  val v4 = cast2[Map, Int, Long]("wrong kind")                     
  // throws ClassCastException
}

ignoreException {
  class Foo[H[_, _], X, Y](h: H[X, Y])
  val x = new Foo[Function, Int, String](n => "#" * n)
  val v5 = cast3[Foo, Map, Int, Long](x)
  // nothing happens, happily replaces `Function` by `Map`
}

ignoreException {
  val v6 = (new CastTo[Map, Int, Long]).cast(List("hello?"))       
  // throws ClassCastException
}

ignoreException {
  val castToMap = new CastTo[Map, Int, Long]
  val v7 = castToMap.cast("how can it detect this?")               
  // throws ClassCastException
}

ignoreException {
  val castToMap = new CastTo[Map, Int, Long]
  val madCast = castToMap.asInstanceOf[CastTo[Function, Float, Double]]
  val v8 = madCast.cast("what does it detect at all?")
  // String cannot be cast to Function???
  // Why does it retain any information about `Function` here?
}


// --------------------------------------------------------------------
var ignoreBlockCounter = 0
/** Executes piece of code, 
  * catches an exeption (if one is thrown),
  * prints number of `ignoreException`-wrapped block,
  * prints name of the exception.
  */
def ignoreException[U](f: => U): Unit = {
  ignoreBlockCounter += 1
  try {
    f
  } catch {
    case e: Exception =>
      println("[" + ignoreBlockCounter + "]" + e)
  }
}

这是输出(scala -version 2.12.4):

[1]java.lang.ClassCastException: scala.collection.immutable.$colon$colon cannot be cast to java.lang.String
[3]java.lang.ClassCastException: Main$$anon$1$$Lambda$143/1744347043 cannot be cast to scala.collection.immutable.Map
[4]java.lang.ClassCastException: java.lang.String cannot be cast to scala.collection.immutable.Map
[6]java.lang.ClassCastException: scala.collection.immutable.$colon$colon cannot be cast to scala.collection.immutable.Map
[7]java.lang.ClassCastException: java.lang.String cannot be cast to scala.collection.immutable.Map
[8]java.lang.ClassCastException: java.lang.String cannot be cast to scala.Function1
  • 案例1,3,4表明asInstanceOf[Foo[...]]确实关心Foo,这是预期的。
  • 案例2表明asInstanceOf[Foo[X,Y]] 关心XY,这也是预期的。
  • 案例5表明asInstanceOf 关心更高级别的类型参数Map,类似于案例2,这也是预期的。

到目前为止一切顺利。但是,案例6,7,8提出了不同的行为:此处,类型CastTo[Foo, X, Y]的实例似乎由于某种原因保留有关泛型类型参数Foo的信息。更确切地说,CastTo[Map, Int, Long]似乎带有足够的信息,以便知道字符串不能被转换为Map。此外,在案例8中,由于演员表示,它似乎甚至将Map更改为Function

问题:

  1. 我的理解是否正确CastTo的第一个通用参数没有被删除,或者还有其他我不知道的东西?一些隐含的操作还是什么?
  2. 是否有描述此行为的文档?
  3. 我有什么理由这种行为?我发现它有些违反直觉,但也许只是我,而且我使用错误的工具......
  4. 感谢阅读。

    编辑:在类似的例子中探讨了2.12.4编译器的问题(参见我自己的"答案"下面),但这是一个单独的问题。 / p>

2 个答案:

答案 0 :(得分:3)

我认为你混淆了一些事情。

转换为泛型类型将推迟到类型变为具体的点。例如,拿这段代码:

class CastTo[H[_, _], A, B] {
  def cast(x: Any): H[A, B] = x.asInstanceOf[H[A, B]]
}

在字节码中,您只能转换为真正的类,因为它对泛型一无所知。所以上面的字节码大致相当于:

class CastTo {
  def cast(x: Object): Object = x
}

然后在代码中,您向方法String提供cast,编译器可以看到根据类型信息,Map[Int, Long]将会出现。但是在字节码cast中有一个已擦除的返回类型Object,因此编译器必须在cast方法的 use-site 处插入一个强制转换。这段代码

val castToMap = new CastTo[Map, Int, Long]
val v7 = castToMap.cast("how can it detect this?")
在字节码中,

将大致等同于以下(伪)代码:

val castToMap = new CastTo
val v7 = castToMap.cast("how can it detect this?").asInstanceOf[Map]

至于你的其他问题:

  1. 不是我立即知道的。
  2. 为什么想要它?您正在向String投射Map[Int, Long]。这最终肯定会崩溃。使用ClassCastException失败(相对)快可能是最安全,最友好的用户选择。

答案 1 :(得分:0)

好吧,这可能不是预期的行为。

以下是上述的随机版本:

package np.com.rotaractnepalapp;


import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.squareup.picasso.Picasso;

import np.com.rotaractnepalapp.Interface.ItemClickListener;
import np.com.rotaractnepalapp.Model.Member;
import np.com.rotaractnepalapp.ViewHolder.MemberViewHolder;

public class MemberFragment extends Fragment {

    View memFragment;
    RecyclerView listofMembers;

    RecyclerView.LayoutManager memLayoutManger;
    FirebaseRecyclerAdapter<Member, MemberViewHolder> memAdapter;

    FirebaseDatabase database;
    DatabaseReference members;

    public static MemberFragment newInstance(){
        MemberFragment memberFragment = new MemberFragment();
        return memberFragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        database = FirebaseDatabase.getInstance();
        members = database.getReference("ClubKNE");
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        memFragment = inflater.inflate(R.layout.fragment_member,container,false);

        TextView title = (TextView) memFragment.findViewById(R.id.txtClubNameTitle);
        title.setText("RAC Kathmandu North-East");

        listofMembers = (RecyclerView) memFragment.findViewById(R.id.memLists);
        listofMembers.setHasFixedSize(true);
        memLayoutManger = new LinearLayoutManager(container.getContext());
        listofMembers.setLayoutManager(memLayoutManger);

        loadMember();

        return memFragment;
    }

    private void loadMember() {
        memAdapter = new FirebaseRecyclerAdapter<Member, MemberViewHolder>(
                Member.class,
                R.layout.mem_layout,
                MemberViewHolder.class,
                members
        ) {
            @Override
            protected void populateViewHolder(MemberViewHolder viewHolder, Member model, int position) {
                viewHolder.memDesignation.setText(model.getMemDesignation());
                viewHolder.memName.setText(model.getMemName());
                viewHolder.memProfession.setText(model.getMemProfession());
                viewHolder.memEmail.setText(model.getMemEmail());
                Picasso.with(getActivity())
                        .load(model.getMemImage())
                        .into(viewHolder.memImage);
                viewHolder.setItemClickListener(new ItemClickListener() {
                    @Override
                    public void onClick(View view, int position, boolean isLongClick) {
                        AlertDialog.Builder alertDialog = new AlertDialog.Builder(view.getContext());
                        LayoutInflater factory = LayoutInflater.from(view.getContext());
                        view = factory.inflate(R.layout.member_info_layout, null);
                        alertDialog.setView(view);
                        alertDialog.setNegativeButton("Done", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        });
                        alertDialog.show();

                    }
                });
            }
        };
        memAdapter.notifyDataSetChanged();
        listofMembers.setAdapter(memAdapter);
    }
}

崩溃了2.12.4编译器。 Dotty没有问题。

编辑更短,自包含的示例:

导入scala.language.higherKinds

ignoreException {
  class Foo[X, Y]
  class Bar[X, Y]

  val castToMap = new CastTo[Map, Int, Long]
  val madderCast = if (math.random() > 0.5) {
    println("Foo")
    castToMap.asInstanceOf[CastTo[Foo, Float, Double]]
  } else {
    println("Bar")
    castToMap.asInstanceOf[CastTo[Bar, String, Any]]
  }
  val v9 = madderCast.cast("crash 'dis serva, awww yeah!")
  // crashes the compile server for scala 2.12.4
  // dotty 0.4.0-RC1 doesn't complain at all (as expected!)
}

崩溃:

class Foo[X]
class Bar[X]
class CrashIt[A[_]] {
  def cast(a: Any): A[Int] = a.asInstanceOf[A[Int]]
}
val c = if (true) new CrashIt[Foo] else new CrashIt[Bar]
val x = c.cast("")

铸造步骤似乎至关重要。如果删除java.util.NoSuchElementException: head of empty list at scala.collection.immutable.Nil$.head(List.scala:428) at scala.collection.immutable.Nil$.head(List.scala:425) at scala.tools.nsc.typechecker.ContextErrors$InferencerContextErrors$InferErrorGen$. NotWithinBoundsErrorMessage(ContextErrors.scala:1045) at scala.tools.nsc.typechecker.ContextErrors$InferencerContextErrors$InferErrorGen$. NotWithinBoundsContextErrors.scala:1052) at scala.tools.nsc.typechecker.Infer$Inferencer.issueBoundsError$1(Infer.scala:881) at scala.tools.nsc.typechecker.Infer$Inferencer.check$1(Infer.scala:887) at scala.tools.nsc.typechecker.Infer$Inferencer.checkBounds(Infer.scala:891) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkBounds(RefChecks.scala:1203) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkTypeRef(RefChecks.scala:1384) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transform$4(RefChecks.scala:1668) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transform$4$adapted(RefChecks.scala:1659) at scala.reflect.internal.tpe.TypeMaps$ForEachTypeTraverser.traverse(TypeMaps.scala:1102) at scala.reflect.internal.Types$Type.foreach(Types.scala:787) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1407) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107) at scala.reflect.internal.Trees.$anonfun$itransform$1(Trees.scala:1369) at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600) at scala.reflect.internal.Trees.itransform(Trees.scala:1368) at scala.reflect.internal.Trees.itransform$(Trees.scala:1348) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStat(RefChecks.scala:1186) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transformStats$1(RefChecks.scala:1169) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:1169) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:107) at scala.reflect.internal.Trees.itransform(Trees.scala:1416) at scala.reflect.internal.Trees.itransform$(Trees.scala:1348) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107) at scala.reflect.api.Trees$Transformer.transformTemplate(Trees.scala:2563) at scala.reflect.internal.Trees.$anonfun$itransform$4(Trees.scala:1420) at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600) at scala.reflect.internal.Trees.itransform(Trees.scala:1419) at scala.reflect.internal.Trees.itransform$(Trees.scala:1348) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStat(RefChecks.scala:1198) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transformStats$1(RefChecks.scala:1169) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:1169) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:107) at scala.reflect.internal.Trees.itransform(Trees.scala:1378) at scala.reflect.internal.Trees.itransform$(Trees.scala:1348) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107) at scala.reflect.internal.Trees.$anonfun$itransform$2(Trees.scala:1375) at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600) at scala.reflect.internal.Trees.itransform(Trees.scala:1373) at scala.reflect.internal.Trees.itransform$(Trees.scala:1348) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStat(RefChecks.scala:1198) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transformStats$1(RefChecks.scala:1169) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:1169) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:107) at scala.reflect.internal.Trees.itransform(Trees.scala:1416) at scala.reflect.internal.Trees.itransform$(Trees.scala:1348) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107) at scala.reflect.api.Trees$Transformer.transformTemplate(Trees.scala:2563) at scala.reflect.internal.Trees.$anonfun$itransform$5(Trees.scala:1425) at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600) at scala.reflect.internal.Trees.itransform(Trees.scala:1424) at scala.reflect.internal.Trees.itransform$(Trees.scala:1348) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStat(RefChecks.scala:1198) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transformStats$1(RefChecks.scala:1169) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:1169) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:107) at scala.reflect.internal.Trees.$anonfun$itransform$7(Trees.scala:1438) at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600) at scala.reflect.internal.Trees.itransform(Trees.scala:1438) at scala.reflect.internal.Trees.itransform$(Trees.scala:1348) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16) at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751) at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107) at scala.tools.nsc.ast.Trees$Transformer.transformUnit(Trees.scala:140) at scala.tools.nsc.transform.Transform$Phase.apply(Transform.scala:30) at scala.tools.nsc.Global$GlobalPhase.$anonfun$applyPhase$1(Global.scala:436) at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:429) at scala.tools.nsc.Global$GlobalPhase.$anonfun$run$1(Global.scala:400) at scala.tools.nsc.Global$GlobalPhase.$anonfun$run$1$adapted(Global.scala:400) at scala.collection.Iterator.foreach(Iterator.scala:929) at scala.collection.Iterator.foreach$(Iterator.scala:929) at scala.collection.AbstractIterator.foreach(Iterator.scala:1417) at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:400) at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1452) at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1436) at scala.tools.nsc.Global$Run.compileSources(Global.scala:1429) at scala.tools.nsc.Global$Run.compile(Global.scala:1545) at scala.tools.nsc.StandardCompileServer.session(CompileServer.scala:150) at scala.tools.util.SocketServer.$anonfun$doSession$2(SocketServer.scala:80) at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12) at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58) at scala.Console$.withOut(Console.scala:163) at scala.tools.util.SocketServer.$anonfun$doSession$1(SocketServer.scala:80) at scala.tools.util.SocketServer.$anonfun$doSession$1$adapted(SocketServer.scala:75) at scala.tools.nsc.io.Socket.applyReaderAndWriter(Socket.scala:49) at scala.tools.util.SocketServer.doSession(SocketServer.scala:75) at scala.tools.util.SocketServer.loop$1(SocketServer.scala:91) at scala.tools.util.SocketServer.run(SocketServer.scala:103) at scala.tools.nsc.CompileServer$.$anonfun$execute$3(CompileServer.scala:216) at scala.runtime.java8.JFunction0$mcZ$sp.apply(JFunction0$mcZ$sp.java:12) at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58) at scala.Console$.withOut(Console.scala:163) at scala.tools.nsc.CompileServer$.$anonfun$execute$2(CompileServer.scala:211) at scala.runtime.java8.JFunction0$mcZ$sp.apply(JFunction0$mcZ$sp.java:12) at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58) at scala.Console$.withErr(Console.scala:192) at scala.tools.nsc.CompileServer$.main(CompileServer.scala:211) at scala.tools.nsc.CompileServer.main(CompileServer.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at scala.reflect.internal.util.ScalaClassLoader.$anonfun$run$2(ScalaClassLoader.scala:99) at scala.reflect.internal.util.ScalaClassLoader.asContext(ScalaClassLoader.scala:34) at scala.reflect.internal.util.ScalaClassLoader.asContext$(ScalaClassLoader.scala:30) at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:125) at scala.reflect.internal.util.ScalaClassLoader.run(ScalaClassLoader.scala:99) at scala.reflect.internal.util.ScalaClassLoader.run$(ScalaClassLoader.scala:91) at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:125) at scala.tools.nsc.CommonRunner.run(ObjectRunner.scala:22) at scala.tools.nsc.CommonRunner.run$(ObjectRunner.scala:21) at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39) at scala.tools.nsc.CommonRunner.runAndCatch(ObjectRunner.scala:29) at scala.tools.nsc.CommonRunner.runAndCatch$(ObjectRunner.scala:28) at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39) at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:66) at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:85) at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96) at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101) at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 的调用,则不会发生任何事情。

如果参数cast不是更高的,则不会发生这种情况,因此例如对于Aclass CrashIt[A],编译器不会抱怨。

EDIT-2 :找不到这个确切的错误(或明显的概括),在此处报告:https://github.com/scala/bug/issues/10700