From 9783152b4548be894c112dc7d737e3d4afe665bc Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 13 Jun 2017 14:43:32 +0200 Subject: [PATCH] Fix #2741: Handle wildcard types in unions and intersections. i2741.scala is a test case where this happens. --- compiler/src/dotty/tools/dotc/core/Types.scala | 16 +++++++++++----- tests/pos/i2741.scala | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 tests/pos/i2741.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index ac3245c37db3..97e72afb26f0 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1417,8 +1417,11 @@ object Types { /** A marker trait for types that can be types of values or prototypes of value types */ trait ValueTypeOrProto extends TermType + /** A marker trait for types that can be types of values or wildcards */ + trait ValueTypeOrWildcard extends TermType + /** A marker trait for types that can be types of values or that are higher-kinded */ - trait ValueType extends ValueTypeOrProto + trait ValueType extends ValueTypeOrProto with ValueTypeOrWildcard /** A marker trait for types that are guaranteed to contain only a * single non-null value (they might contain null in addition). @@ -2311,7 +2314,8 @@ object Types { object AndType { def apply(tp1: Type, tp2: Type)(implicit ctx: Context): AndType = { - assert(tp1.isValueType && tp2.isValueType, i"$tp1 & $tp2 / " + s"$tp1 & $tp2") + assert(tp1.isInstanceOf[ValueTypeOrWildcard] && + tp2.isInstanceOf[ValueTypeOrWildcard], i"$tp1 & $tp2 / " + s"$tp1 & $tp2") unchecked(tp1, tp2) } @@ -2334,7 +2338,8 @@ object Types { abstract case class OrType(tp1: Type, tp2: Type) extends CachedGroundType with AndOrType { - assert(tp1.isInstanceOf[ValueType] && tp2.isInstanceOf[ValueType]) + assert(tp1.isInstanceOf[ValueTypeOrWildcard] && + tp2.isInstanceOf[ValueTypeOrWildcard], s"$tp1 $tp2") def isAnd = false private[this] var myJoin: Type = _ @@ -2369,7 +2374,8 @@ object Types { unique(new CachedOrType(tp1, tp2)) } def make(tp1: Type, tp2: Type)(implicit ctx: Context): Type = - if (tp1 eq tp2) tp1 else apply(tp1, tp2) + if (tp1 eq tp2) tp1 + else apply(tp1, tp2) } // ----- ExprType and LambdaTypes ----------------------------------- @@ -3500,7 +3506,7 @@ object Types { object TryDynamicCallType extends FlexType /** Wildcard type, possibly with bounds */ - abstract case class WildcardType(optBounds: Type) extends CachedGroundType with TermType { + abstract case class WildcardType(optBounds: Type) extends CachedGroundType with ValueTypeOrWildcard { def derivedWildcardType(optBounds: Type)(implicit ctx: Context) = if (optBounds eq this.optBounds) this else if (!optBounds.exists) WildcardType diff --git a/tests/pos/i2741.scala b/tests/pos/i2741.scala new file mode 100644 index 000000000000..37bbe54507f1 --- /dev/null +++ b/tests/pos/i2741.scala @@ -0,0 +1,16 @@ +object Result { + type ResultF[F] = F | Errors + type ResultF2[F] = F & Errors + + case class Errors(msgs: Seq[String]) + + implicit class ResultFunctions[A](val res: ResultF[A]) extends AnyVal { + def map[B](f: A => B): ResultF[B] = res match { + case errs: Errors => errs + case x: A => f(x) + } + } + implicit class ResultFunctions2[A](val res: ResultF2[A]) extends AnyVal { + def map[B](f: A => B): ResultF[B] = ??? + } +}