Skip to content

Commit d6719d5

Browse files
committed
Systematically use cast in compiler
Replace all instances of compiler-generated type casts by calls to `Any_typeCast` via `tpd.cast`. This will assume that all these calls are pure.
1 parent e28841f commit d6719d5

12 files changed

+22
-15
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -875,13 +875,20 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
875875
tree.select(defn.Any_asInstanceOf).appliedToType(tp)
876876
}
877877

878-
/** `tree.asInstanceOf[tp]` (or its box/unbox/cast equivalent when after
878+
/** cast tree to `tp`, assuming no exception is raised, i.e the operation is pure */
879+
def cast(tp: Type)(implicit ctx: Context): Tree = {
880+
assert(tp.isValueType, i"bad cast: $tree.asInstanceOf[$tp]")
881+
tree.select(if (ctx.erasedTypes) defn.Any_asInstanceOf else defn.Any_typeCast)
882+
.appliedToType(tp)
883+
}
884+
885+
/** cast `tree` to `tp` (or its box/unbox/cast equivalent when after
879886
* erasure and value and non-value types are mixed),
880887
* unless tree's type already conforms to `tp`.
881888
*/
882889
def ensureConforms(tp: Type)(implicit ctx: Context): Tree =
883890
if (tree.tpe <:< tp) tree
884-
else if (!ctx.erasedTypes) asInstance(tp)
891+
else if (!ctx.erasedTypes) cast(tp)
885892
else Erasure.Boxing.adaptToType(tree, tp)
886893

887894
/** `tree ne null` (might need a cast to be type correct) */

compiler/src/dotty/tools/dotc/transform/CrossCastAnd.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class CrossCastAnd extends MiniPhase {
2323
lazy val qtype = tree.qualifier.tpe.widen
2424
val sym = tree.symbol
2525
if (sym.is(Flags.Private) && qtype.typeSymbol != sym.owner)
26-
cpy.Select(tree)(tree.qualifier.asInstance(AndType(qtype.baseType(sym.owner), tree.qualifier.tpe)), tree.name)
26+
cpy.Select(tree)(tree.qualifier.cast(AndType(qtype.baseType(sym.owner), tree.qualifier.tpe)), tree.name)
2727
else tree
2828
}
2929
}

compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ExplicitSelf extends MiniPhase {
3737
case Select(thiz: This, name) if name.isTermName =>
3838
val cls = thiz.symbol.asClass
3939
if (cls.givenSelfType.exists && !cls.derivesFrom(tree.symbol.owner))
40-
cpy.Select(tree)(thiz.asInstance(AndType(cls.classInfo.selfType, thiz.tpe)), name)
40+
cpy.Select(tree)(thiz.cast(AndType(cls.classInfo.selfType, thiz.tpe)), name)
4141
else tree
4242
case _ => tree
4343
}

compiler/src/dotty/tools/dotc/transform/FunctionXXLForwarders.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ class FunctionXXLForwarders extends MiniPhase with IdentityDenotTransformer {
3434
var idx = -1
3535
val argss = receiver.tpe.widenDealias.paramInfoss.map(_.map { param =>
3636
idx += 1
37-
argsApply.appliedToArgs(List(Literal(Constant(idx)))).asInstance(param)
37+
argsApply.appliedToArgs(List(Literal(Constant(idx)))).cast(param)
3838
})
39-
ref(receiver.symbol).appliedToArgss(argss).asInstance(defn.ObjectType)
39+
ref(receiver.symbol).appliedToArgss(argss).cast(defn.ObjectType)
4040
}
4141

4242
val forwarders =

compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ object PatternMatcher {
330330
swapBind(tree) match {
331331
case Typed(pat, tpt) =>
332332
TestPlan(TypeTest(tpt), scrutinee, tree.span,
333-
letAbstract(ref(scrutinee).asInstance(tpt.tpe)) { casted =>
333+
letAbstract(ref(scrutinee).cast(tpt.tpe)) { casted =>
334334
nonNull += casted
335335
patternPlan(casted, pat, onSuccess)
336336
})

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ class ReifyQuotes extends MacroTransform {
282282
val argTpe =
283283
if (tree.isType) defn.QuotedTypeType.appliedTo(tpw)
284284
else defn.QuotedExprType.appliedTo(tpw)
285-
val selectArg = arg.select(nme.apply).appliedTo(Literal(Constant(i))).asInstance(argTpe)
285+
val selectArg = arg.select(nme.apply).appliedTo(Literal(Constant(i))).cast(argTpe)
286286
val capturedArg = SyntheticValDef(UniqueName.fresh(tree.symbol.name.toTermName).toTermName, selectArg)
287287
i += 1
288288
embedded.addTree(tree, capturedArg.symbol)

compiler/src/dotty/tools/dotc/transform/Staging.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class Staging extends MacroTransform {
169169
*/
170170
protected def addSpliceCast(tree: Tree)(implicit ctx: Context): Tree = {
171171
val tp = checkType(tree.sourcePos).apply(tree.tpe.widenTermRefExpr)
172-
tree.asInstance(tp).withSpan(tree.span)
172+
tree.cast(tp).withSpan(tree.span)
173173
}
174174

175175
/** If `tree` refers to a locally defined symbol (either directly, or in a pickled type),

compiler/src/dotty/tools/dotc/transform/SyntheticMethods.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
173173
val matchExpr = Match(that, List(matchingCase, defaultCase))
174174
if (isDerivedValueClass(clazz)) matchExpr
175175
else {
176-
val eqCompare = This(clazz).select(defn.Object_eq).appliedTo(that.asInstance(defn.ObjectType))
176+
val eqCompare = This(clazz).select(defn.Object_eq).appliedTo(that.cast(defn.ObjectType))
177177
eqCompare or matchExpr
178178
}
179179
}

compiler/src/dotty/tools/dotc/typer/Deriving.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ trait Deriving { this: Typer =>
409409
case caseType =>
410410
val args =
411411
for ((elemTp, idx) <- elems.zipWithIndex)
412-
yield paramRef.select(nme.apply).appliedTo(Literal(Constant(idx))).asInstance(elemTp)
412+
yield paramRef.select(nme.apply).appliedTo(Literal(Constant(idx))).cast(elemTp)
413413
New(caseType, args)
414414
}
415415
shape match {

compiler/src/dotty/tools/dotc/typer/Dynamic.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ trait Dynamic { self: Typer with Applications =>
159159

160160
fun.tpe.widen match {
161161
case tpe: ValueType =>
162-
structuralCall(nme.selectDynamic, Nil).asInstance(tpe)
162+
structuralCall(nme.selectDynamic, Nil).cast(tpe)
163163

164164
case tpe: MethodType =>
165165
def isDependentMethod(tpe: Type): Boolean = tpe match {
@@ -176,7 +176,7 @@ trait Dynamic { self: Typer with Applications =>
176176
else {
177177
val ctags = tpe.paramInfoss.flatten.map(pt =>
178178
implicitArgTree(defn.ClassTagType.appliedTo(pt.widenDealias :: Nil), fun.span.endPos))
179-
structuralCall(nme.applyDynamic, ctags).asInstance(tpe.finalResultType)
179+
structuralCall(nme.applyDynamic, ctags).cast(tpe.finalResultType)
180180
}
181181

182182
// (@allanrenucci) I think everything below is dead code

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2611,7 +2611,7 @@ class Typer extends Namer
26112611
// I suspect, but am not 100% sure that this might affect inferred types,
26122612
// if the expected type is a supertype of the GADT bound. It would be good to come
26132613
// up with a test case for this.
2614-
tree.select(defn.Any_typeCast).appliedToType(pt)
2614+
tree.cast(pt)
26152615
else
26162616
tree
26172617
}

tests/run/tasty-extractors-2.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Type.SymRef(IsClassSymbol(<scala.Unit>), Type.ThisType(Type.SymRef(IsPackageSymb
4949
Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil)), Nil, None, List(DefDef("a", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(0))))))), Term.Literal(Constant.Unit())))
5050
Type.SymRef(IsClassSymbol(<scala.Unit>), Type.ThisType(Type.SymRef(IsPackageSymbol(<scala>), NoPrefix())))
5151

52-
Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Product"), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, None, List(DefDef("hashCode", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Literal(Constant.Int(394005536)))), DefDef("equals", Nil, List(List(ValDef("x$0", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.Apply(Term.Select(Term.This(Some(Id("Foo"))), "eq"), List(Term.TypeApply(Term.Select(Term.Ident("x$0"), "asInstanceOf"), List(TypeTree.Inferred())))), "||"), List(Term.Match(Term.Ident("x$0"), List(CaseDef(Pattern.Bind("x$0", Pattern.TypeTest(TypeTree.Inferred())), None, Term.Literal(Constant.Boolean(true))), CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Literal(Constant.Boolean(false))))))))), DefDef("toString", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Ident("_toString"), List(Term.This(Some(Id("Foo"))))))), DefDef("canEqual", Nil, List(List(ValDef("that", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.TypeApply(Term.Select(Term.Ident("that"), "isInstanceOf"), List(TypeTree.Inferred())))), DefDef("productArity", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(0)))), DefDef("productPrefix", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.String("Foo")))), DefDef("productElement", Nil, List(List(ValDef("n", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Match(Term.Ident("n"), List(CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Apply(Term.Ident("throw"), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), List(Term.Apply(Term.Select(Term.Ident("n"), "toString"), Nil)))))))))), DefDef("productElementName", Nil, List(List(ValDef("x$1", TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Int"), None))), TypeTree.Select(Term.Select(Term.Ident("java"), "lang"), "String"), Some(Term.Match(Term.Ident("x$1"), List(CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Apply(Term.Ident("throw"), List(Term.Apply(Term.Select(Term.New(TypeTree.Select(Term.Select(Term.Ident("java"), "lang"), "IndexOutOfBoundsException")), "<init>"), List(Term.Apply(Term.Select(Term.Select(Term.Select(Term.Ident("java"), "lang"), "String"), "valueOf"), List(Term.Ident("x$1")))))))))))), DefDef("copy", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil))))), ValDef("Foo", TypeTree.Ident("Foo$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo$")), "<init>"), Nil))), ClassDef("Foo$", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil), TypeTree.Applied(TypeTree.Inferred(), List(TypeTree.Inferred())), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo")), None)), List(DefDef("apply", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil))), DefDef("unapply", Nil, List(List(ValDef("x$1", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Literal(Constant.Boolean(true))))))), Term.Literal(Constant.Unit())))
52+
Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Product"), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, None, List(DefDef("hashCode", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Literal(Constant.Int(394005536)))), DefDef("equals", Nil, List(List(ValDef("x$0", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.Apply(Term.Select(Term.This(Some(Id("Foo"))), "eq"), List(Term.TypeApply(Term.Select(Term.Ident("x$0"), "$asInstanceOf$"), List(TypeTree.Inferred())))), "||"), List(Term.Match(Term.Ident("x$0"), List(CaseDef(Pattern.Bind("x$0", Pattern.TypeTest(TypeTree.Inferred())), None, Term.Literal(Constant.Boolean(true))), CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Literal(Constant.Boolean(false))))))))), DefDef("toString", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Ident("_toString"), List(Term.This(Some(Id("Foo"))))))), DefDef("canEqual", Nil, List(List(ValDef("that", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.TypeApply(Term.Select(Term.Ident("that"), "isInstanceOf"), List(TypeTree.Inferred())))), DefDef("productArity", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(0)))), DefDef("productPrefix", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.String("Foo")))), DefDef("productElement", Nil, List(List(ValDef("n", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Match(Term.Ident("n"), List(CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Apply(Term.Ident("throw"), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), List(Term.Apply(Term.Select(Term.Ident("n"), "toString"), Nil)))))))))), DefDef("productElementName", Nil, List(List(ValDef("x$1", TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Int"), None))), TypeTree.Select(Term.Select(Term.Ident("java"), "lang"), "String"), Some(Term.Match(Term.Ident("x$1"), List(CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Apply(Term.Ident("throw"), List(Term.Apply(Term.Select(Term.New(TypeTree.Select(Term.Select(Term.Ident("java"), "lang"), "IndexOutOfBoundsException")), "<init>"), List(Term.Apply(Term.Select(Term.Select(Term.Select(Term.Ident("java"), "lang"), "String"), "valueOf"), List(Term.Ident("x$1")))))))))))), DefDef("copy", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil))))), ValDef("Foo", TypeTree.Ident("Foo$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo$")), "<init>"), Nil))), ClassDef("Foo$", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil), TypeTree.Applied(TypeTree.Inferred(), List(TypeTree.Inferred())), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo")), None)), List(DefDef("apply", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil))), DefDef("unapply", Nil, List(List(ValDef("x$1", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Literal(Constant.Boolean(true))))))), Term.Literal(Constant.Unit())))
5353
Type.SymRef(IsClassSymbol(<scala.Unit>), Type.ThisType(Type.SymRef(IsPackageSymbol(<scala>), NoPrefix())))
5454

5555
Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo1", DefDef("<init>", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil)), Nil, None, List(ValDef("a", TypeTree.Inferred(), None)))), Term.Literal(Constant.Unit())))

0 commit comments

Comments
 (0)