From 647a760038fe372edb671a8a14e06c0a978bb2e9 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 12 Feb 2013 14:24:15 -0800 Subject: [refactor] type analysis consolidation move instanceOfTpImplies out of CodeGen into TypeAnalysis --- .../tools/nsc/transform/patmat/MatchAnalysis.scala | 18 ++++++++++++++++++ .../tools/nsc/transform/patmat/MatchCodeGen.scala | 22 +--------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index 5c8c377655..0abdea7c9c 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -30,6 +30,24 @@ trait TypeAnalysis extends Debugging { import debugging.patmatDebug + // we use subtyping as a model for implication between instanceof tests + // i.e., when S <:< T we assume x.isInstanceOf[S] implies x.isInstanceOf[T] + // unfortunately this is not true in general: + // SI-6022 expects instanceOfTpImplies(ProductClass.tpe, AnyRefClass.tpe) + def instanceOfTpImplies(tp: Type, tpImplied: Type) = { + val tpValue = tp.typeSymbol.isPrimitiveValueClass + + // pretend we're comparing to Any when we're actually comparing to AnyVal or AnyRef + // (and the subtype is respectively a value type or not a value type) + // this allows us to reuse subtyping as a model for implication between instanceOf tests + // the latter don't see a difference between AnyRef, Object or Any when comparing non-value types -- SI-6022 + val tpImpliedNormalizedToAny = + if (tpImplied =:= (if (tpValue) AnyValClass.tpe else AnyRefClass.tpe)) AnyClass.tpe + else tpImplied + + tp <:< tpImpliedNormalizedToAny + } + trait CheckableTypeAnalysis { val typer: Typer diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala index ad79562362..a22d35a6b4 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala @@ -72,26 +72,6 @@ trait CodeGen { self: PatternMatching => def codegen: AbsCodegen - def typesConform(tp: Type, pt: Type) = ((tp eq pt) || (tp <:< pt)) - - // we use subtyping as a model for implication between instanceof tests - // i.e., when S <:< T we assume x.isInstanceOf[S] implies x.isInstanceOf[T] - // unfortunately this is not true in general: - // SI-6022 expects instanceOfTpImplies(ProductClass.tpe, AnyRefClass.tpe) - def instanceOfTpImplies(tp: Type, tpImplied: Type) = { - val tpValue = tp.typeSymbol.isPrimitiveValueClass - - // pretend we're comparing to Any when we're actually comparing to AnyVal or AnyRef - // (and the subtype is respectively a value type or not a value type) - // this allows us to reuse subtyping as a model for implication between instanceOf tests - // the latter don't see a difference between AnyRef, Object or Any when comparing non-value types -- SI-6022 - val tpImpliedNormalizedToAny = - if (tpImplied =:= (if (tpValue) AnyValClass.tpe else AnyRefClass.tpe)) AnyClass.tpe - else tpImplied - - tp <:< tpImpliedNormalizedToAny - } - abstract class CommonCodegen extends AbsCodegen { import CODE._ def fun(arg: Symbol, body: Tree): Tree = Function(List(ValDef(arg)), body) def tupleSel(binder: Symbol)(i: Int): Tree = (REF(binder) DOT nme.productAccessorName(i)) // make tree that accesses the i'th component of the tuple referenced by binder @@ -100,7 +80,7 @@ trait CodeGen { self: PatternMatching => def _equals(checker: Tree, binder: Symbol): Tree = checker MEMBER_== REF(binder) // NOTE: checker must be the target of the ==, that's the patmat semantics for ya // the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly) - def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else gen.mkCastPreservingAnnotations(REF(b), tp) + def _asInstanceOf(b: Symbol, tp: Type): Tree = if (b.info <:< tp) REF(b) else gen.mkCastPreservingAnnotations(REF(b), tp) def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false) // duplicated out of frustration with cast generation -- cgit v1.2.3