diff --git a/src/dotty/tools/dotc/TypeErasure.scala b/src/dotty/tools/dotc/TypeErasure.scala index a45e29287f3d..807fd33f1a4b 100644 --- a/src/dotty/tools/dotc/TypeErasure.scala +++ b/src/dotty/tools/dotc/TypeErasure.scala @@ -38,7 +38,7 @@ object TypeErasure { case JavaArrayType(elem) => isErasedType(elem) case AnnotatedType(_, tp) => - isErasedType(tp) + false case ThisType(tref) => isErasedType(tref) case tp: MethodType => @@ -105,7 +105,7 @@ object TypeErasure { /** The erasure of a top-level reference. Differs from normal erasure in that * TermRefs are kept instead of being widened away. */ - def erasedRef(tp: Type)(implicit ctx: Context): Type = tp match { + def erasedRef(tp: Type)(implicit ctx: Context): Type = tp.stripAnnots match { case tp: TermRef => assert(tp.symbol.exists, tp) val tp1 = ctx.makePackageObjPrefixExplicit(tp) @@ -160,7 +160,7 @@ object TypeErasure { * as upper bound and that is not Java defined? Arrays of such types are * erased to `Object` instead of `ObjectArray`. */ - def isUnboundedGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match { + def isUnboundedGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias.stripAnnots match { case tp: TypeRef => !tp.symbol.isClass && !tp.derivesFrom(defn.ObjectClass) && @@ -186,14 +186,14 @@ object TypeErasure { * come after S. * (the reason to pick last is that we prefer classes over traits that way). */ - def erasedLub(tp1: Type, tp2: Type)(implicit ctx: Context): Type = tp1 match { + def erasedLub(tp1: Type, tp2: Type)(implicit ctx: Context): Type = tp1.stripAnnots match { case JavaArrayType(elem1) => - tp2 match { + tp2.stripAnnots match { case JavaArrayType(elem2) => JavaArrayType(erasedLub(elem1, elem2)) case _ => defn.ObjectType } case _ => - tp2 match { + tp2.stripAnnots match { case JavaArrayType(_) => defn.ObjectType case _ => val cls2 = tp2.classSymbol @@ -216,14 +216,14 @@ object TypeErasure { * - subtypes over supertypes, unless isJava is set * - real classes over traits */ - def erasedGlb(tp1: Type, tp2: Type, isJava: Boolean)(implicit ctx: Context): Type = tp1 match { + def erasedGlb(tp1: Type, tp2: Type, isJava: Boolean)(implicit ctx: Context): Type = tp1.stripAnnots match { case JavaArrayType(elem1) => - tp2 match { + tp2.stripAnnots match { case JavaArrayType(elem2) => JavaArrayType(erasedGlb(elem1, elem2, isJava)) case _ => tp1 } case _ => - tp2 match { + tp2.stripAnnots match { case JavaArrayType(_) => tp2 case _ => val tsym1 = tp1.typeSymbol @@ -346,7 +346,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild else JavaArrayType(this(elemtp)) } - def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context) = tp match { + def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context) = tp.stripAnnots match { case ExprType(rt) => if (sym is Param) apply(tp) // Note that params with ExprTypes are eliminated by ElimByName, @@ -365,7 +365,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild (if (cls.owner is Package) normalizeClass(cls) else cls).typeRef } - private def eraseResult(tp: Type)(implicit ctx: Context): Type = tp match { + private def eraseResult(tp: Type)(implicit ctx: Context): Type = tp.stripAnnots match { case tp: TypeRef => val sym = tp.typeSymbol if (sym eq defn.UnitClass) sym.typeRef diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index 3d633c58d59a..5f851cd20c7d 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -359,7 +359,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => /** Is symbol potentially a getter of a mutable variable? */ def mayBeVarGetter(sym: Symbol)(implicit ctx: Context): Boolean = { - def maybeGetterType(tpe: Type): Boolean = tpe match { + def maybeGetterType(tpe: Type): Boolean = tpe.stripAnnots match { case _: ExprType | _: ImplicitMethodType => true case tpe: PolyType => maybeGetterType(tpe.resultType) case _ => false diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala index 846c661f5352..3dec85dfc1a9 100644 --- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala +++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala @@ -89,7 +89,7 @@ final class TreeTypeMap( case tree1 => tree1.withType(mapType(tree1.tpe)) match { case id: Ident if tpd.needsSelect(id.tpe) => - ref(id.tpe.asInstanceOf[TermRef]).withPos(id.pos) + ref(id.tpe.stripAnnots.asInstanceOf[TermRef]).withPos(id.pos) case ddef @ DefDef(name, tparams, vparamss, tpt, rhs) => val (tmap1, tparams1) = transformDefs(ddef.tparams) val (tmap2, vparamss1) = tmap1.transformVParamss(vparamss) diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 8fdc4a9db282..a6d51d48d6e8 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -177,14 +177,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { polyDefDef(sym, Function.const(rhsFn)) def polyDefDef(sym: TermSymbol, rhsFn: List[Type] => List[List[Tree]] => Tree)(implicit ctx: Context): DefDef = { - val (tparams, mtp) = sym.info match { + val (tparams, mtp) = sym.info.stripAnnots match { case tp: PolyType => val tparams = ctx.newTypeParams(sym, tp.paramNames, EmptyFlags, tp.instantiateBounds) (tparams, tp.instantiate(tparams map (_.typeRef))) case tp => (Nil, tp) } - def valueParamss(tp: Type): (List[List[TermSymbol]], Type) = tp match { + def valueParamss(tp: Type): (List[List[TermSymbol]], Type) = tp.stripAnnots match { case tp @ MethodType(paramNames, paramTypes) => def valueParam(name: TermName, info: Type): TermSymbol = ctx.newSymbol(sym, name, TermParam, info) @@ -256,7 +256,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { // ------ Making references ------------------------------------------------------ def prefixIsElidable(tp: NamedType)(implicit ctx: Context) = { - def test(implicit ctx: Context) = tp.prefix match { + def test(implicit ctx: Context) = tp.prefix.stripAnnots match { case NoPrefix => true case pre: ThisType => @@ -273,7 +273,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } } - def needsSelect(tp: Type)(implicit ctx: Context) = tp match { + def needsSelect(tp: Type)(implicit ctx: Context) = tp.stripAnnots match { case tp: TermRef => !prefixIsElidable(tp) case _ => false } @@ -282,7 +282,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def ref(tp: NamedType)(implicit ctx: Context): Tree = if (tp.isType) TypeTree(tp) else if (prefixIsElidable(tp)) Ident(tp) - else tp.prefix match { + else tp.prefix.stripAnnots match { case pre: SingletonType => singleton(pre).select(tp) case pre => SelectFromTypeTree(TypeTree(pre), tp) } // no checks necessary @@ -290,7 +290,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def ref(sym: Symbol)(implicit ctx: Context): Tree = ref(NamedType(sym.owner.thisType, sym.name, sym.denot)) - def singleton(tp: Type)(implicit ctx: Context): Tree = tp match { + def singleton(tp: Type)(implicit ctx: Context): Tree = tp.stripAnnots match { case tp: TermRef => ref(tp) case tp: ThisType => This(tp.cls) case SuperType(qual, _) => singleton(qual) @@ -759,6 +759,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { Ident(defn.ScalaRuntimeModule.requiredMethod(name).termRef).appliedToArgs(args) } + /** An extractor that pulls out type arguments */ + object MaybePoly { + def unapply(tree: Tree): Option[(Tree, List[Tree])] = tree match { + case TypeApply(tree, targs) => Some(tree, targs) + case _ => Some(tree, Nil) + } + } + /** A traverser that passes the enlcosing class or method as an argumenr * to the traverse method. */ diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index cd585dea1cae..39f10dc21c3a 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -382,7 +382,7 @@ object Denotations { final def signature(implicit ctx: Context): Signature = { if (isType) Signature.NotAMethod // don't force info if this is a type SymDenotation - else info match { + else info.stripAnnots match { case info: MethodicType => try info.signature catch { // !!! DEBUG diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index c8fbb3d03977..ac66e2d9795a 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -510,7 +510,7 @@ object SymDenotations { /** Is `pre` the same as C.thisThis, where C is exactly the owner of this symbol, * or, if this symbol is protected, a subclass of the owner? */ - def isCorrectThisType(pre: Type): Boolean = pre match { + def isCorrectThisType(pre: Type): Boolean = pre.stripAnnots match { case pre: ThisType => (pre.cls eq owner) || (this is Protected) && pre.cls.derivesFrom(owner) case pre: TermRef => @@ -573,7 +573,7 @@ object SymDenotations { !( this.isTerm || this.isStaticOwner || ctx.erasedTypes - || (pre eq NoPrefix) || (pre eq thisType) + || (pre.stripAnnots eq NoPrefix) || (pre.stripAnnots eq thisType.stripAnnots) ) /** Is this symbol concrete, or that symbol deferred? */ @@ -617,7 +617,7 @@ object SymDenotations { /** The class implementing this module, NoSymbol if not applicable. */ final def moduleClass(implicit ctx: Context): Symbol = if (this is ModuleVal) - myInfo match { + myInfo.stripAnnots match { case info: TypeRef => info.symbol case ExprType(info: TypeRef) => info.symbol // needed after uncurry, when module terms might be accessor defs case info: LazyType => info.moduleClass @@ -626,7 +626,7 @@ object SymDenotations { else NoSymbol /** The module implemented by this module class, NoSymbol if not applicable. */ - final def sourceModule(implicit ctx: Context): Symbol = myInfo match { + final def sourceModule(implicit ctx: Context): Symbol = myInfo.stripAnnots match { case ClassInfo(_, _, _, _, selfType: TermRef) if this is ModuleClass => selfType.symbol case info: LazyType => @@ -1363,6 +1363,7 @@ object SymDenotations { case tp: TypeVar => tp.inst.exists && inCache(tp.inst) case tp: TypeProxy => inCache(tp.underlying) case tp: AndOrType => inCache(tp.tp1) && inCache(tp.tp2) + case tp: AnnotatedType => isCachable(tp.tpe) case _ => true } diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index e59c6095945b..5ea656349443 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -250,9 +250,9 @@ class TypeApplications(val self: Type) extends AnyVal { */ final def baseTypeWithArgs(base: Symbol)(implicit ctx: Context): Type = ctx.traceIndented(s"btwa ${self.show} wrt $base", core, show = true) { def default = self.baseTypeRef(base).appliedTo(baseArgInfos(base)) - self match { + self.stripAnnots match { case tp: TypeRef => - tp.info match { + tp.info.stripAnnots match { case TypeBounds(_, hi) => hi.baseTypeWithArgs(base) case _ => default } @@ -285,7 +285,7 @@ class TypeApplications(val self: Type) extends AnyVal { */ def underlyingIfRepeated(isJava: Boolean)(implicit ctx: Context): Type = if (self.isRepeatedParam) { - val seqClass = if(isJava) defn.ArrayClass else defn.SeqClass + val seqClass = if (isJava) defn.ArrayClass else defn.SeqClass translateParameterized(defn.RepeatedParamClass, seqClass) } else self @@ -297,7 +297,7 @@ class TypeApplications(val self: Type) extends AnyVal { */ final def argInfos(interpolate: Boolean)(implicit ctx: Context): List[Type] = { var tparams: List[TypeSymbol] = null - def recur(tp: Type, refineCount: Int): mutable.ListBuffer[Type] = tp.stripTypeVar match { + def recur(tp: Type, refineCount: Int): mutable.ListBuffer[Type] = tp.stripTypeVar.stripAnnots match { case tp @ RefinedType(tycon, name) => val buf = recur(tycon, refineCount + 1) if (buf == null) null @@ -352,7 +352,7 @@ class TypeApplications(val self: Type) extends AnyVal { * * for a contravariant type-parameter becomes L. */ - final def argInfo(tparam: Symbol, interpolate: Boolean = true)(implicit ctx: Context): Type = self match { + final def argInfo(tparam: Symbol, interpolate: Boolean = true)(implicit ctx: Context): Type = self.stripAnnots match { case self: TypeAlias => self.alias case TypeBounds(lo, hi) => if (interpolate) { @@ -367,14 +367,14 @@ class TypeApplications(val self: Type) extends AnyVal { } /** The element type of a sequence or array */ - def elemType(implicit ctx: Context): Type = self match { + def elemType(implicit ctx: Context): Type = self.stripAnnots match { case defn.ArrayType(elemtp) => elemtp case JavaArrayType(elemtp) => elemtp case _ => firstBaseArgInfo(defn.SeqClass) } def containsSkolemType(target: Type)(implicit ctx: Context): Boolean = { - def recur(tp: Type): Boolean = tp.stripTypeVar match { + def recur(tp: Type): Boolean = tp.stripTypeVar.stripAnnots match { case SkolemType(tp) => tp eq target case tp: NamedType => @@ -434,7 +434,7 @@ class TypeApplications(val self: Type) extends AnyVal { for (sym <- boundSyms) yield TypeRef(SkolemType(rt), correspondingParamName(sym)) - def rewrite(tp: Type): Type = tp match { + def rewrite(tp: Type): Type = tp.stripAnnots match { case tp @ RefinedType(parent, name: TypeName) => if (correspondingNames contains name) rewrite(parent) else RefinedType( @@ -482,7 +482,7 @@ class TypeApplications(val self: Type) extends AnyVal { //println(i"lambda abstract $self wrt $boundSyms%, % --> $res") res } - self match { + self.stripAnnots match { case self @ TypeBounds(lo, hi) => self.derivedTypeBounds(lo, expand(TypeBounds.upper(hi))) case _ => diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 9d6acee71496..f9c7b11ab14d 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -200,7 +200,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi case tp2: LazyRef => isSubType(tp1, tp2.ref) case tp2: AnnotatedType => - isSubType(tp1, tp2.tpe) // todo: refine? + isSubType(tp1.stripAnnots, tp2.stripAnnots) // todo: refine? case tp2: ThisType => def compareThis = { val cls2 = tp2.cls @@ -282,7 +282,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi case tp1: LazyRef => isSubType(tp1.ref, tp2) case tp1: AnnotatedType => - isSubType(tp1.tpe, tp2) + isSubType(tp1.stripAnnots, tp2.stripAnnots) case OrType(tp11, tp12) => isSubType(tp11, tp2) && isSubType(tp12, tp2) case ErrorType => @@ -416,7 +416,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi } isSubType(hi1, tp2) || compareGADT case _ => - def isNullable(tp: Type): Boolean = tp.dealias match { + def isNullable(tp: Type): Boolean = tp.dealias.stripAnnots match { case tp: TypeRef => tp.symbol.isNullableClass case RefinedType(parent, _) => isNullable(parent) case AndType(tp1, tp2) => isNullable(tp1) && isNullable(tp2) @@ -453,7 +453,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi case JavaArrayType(elem2) => isSubType(elem1, elem2) case _ => tp2 isRef ObjectClass } - compareJavaArray + compareJavaArray + case tp1: AnnotatedType => + isSubType(tp1.stripAnnots, tp2.stripAnnots) case _ => false } @@ -599,7 +601,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi } /** Defer constraining type variables when compared against prototypes */ - def isMatchedByProto(proto: ProtoType, tp: Type) = tp.stripTypeVar match { + def isMatchedByProto(proto: ProtoType, tp: Type) = tp.stripTypeVar.stripAnnots match { case tp: PolyParam if constraint contains tp => true case _ => proto.isMatchedBy(tp) } @@ -644,45 +646,34 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi // Tests around `matches` /** A function implementing `tp1` matches `tp2`. */ - final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = tp1 match { + final def matchesType(tp1: Type, tp2: Type, relaxed: Boolean): Boolean = tp1.widen.stripAnnots match { case tp1: MethodType => - tp2 match { + tp2.widen.stripAnnots match { case tp2: MethodType => tp1.isImplicit == tp2.isImplicit && matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) && - matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), alwaysMatchSimple) - case tp2: ExprType => - tp1.paramNames.isEmpty && - matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple) - case _ => - false - } - case tp1: ExprType => - tp2 match { - case tp2: MethodType => - tp2.paramNames.isEmpty && - matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple) - case tp2: ExprType => - matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple) - case _ => - false // was: matchesType(tp1.resultType, tp2, alwaysMatchSimple) + matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) + case tp2 => + relaxed && tp1.paramNames.isEmpty && + matchesType(tp1.resultType, tp2, relaxed) } case tp1: PolyType => - tp2 match { + tp2.widen.stripAnnots match { case tp2: PolyType => sameLength(tp1.paramNames, tp2.paramNames) && - matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), alwaysMatchSimple) + matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) case _ => false } case _ => - tp2 match { - case _: MethodType | _: PolyType => + tp2.widen.stripAnnots match { + case _: PolyType => false - case tp2: ExprType => - false // was: matchesType(tp1, tp2.resultType, alwaysMatchSimple) - case _ => - alwaysMatchSimple || isSameType(tp1, tp2) + case tp2: MethodType => + relaxed && tp2.paramNames.isEmpty && + matchesType(tp1, tp2.resultType, relaxed) + case tp2 => + relaxed || isSameType(tp1, tp2) } } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 3e04eb037537..855c5bf833e3 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -18,7 +18,7 @@ trait TypeOps { this: Context => if ((pre eq NoType) || (pre eq NoPrefix) || (cls is PackageClass)) tp else if (thiscls.derivesFrom(cls) && pre.baseTypeRef(thiscls).exists) - pre match { + pre.stripAnnots match { case SuperType(thispre, _) => thispre case _ => pre } @@ -236,7 +236,7 @@ trait TypeOps { this: Context => case _ => tpe } - tpe.prefix match { + tpe.prefix.stripAnnots match { case pre: ThisType if pre.cls is Package => tryInsert(pre.cls) case pre: TermRef if pre.symbol is Package => tryInsert(pre.symbol.moduleClass) case _ => tpe @@ -255,7 +255,7 @@ trait TypeOps { this: Context => * unless a definition for `argSym` already exists in the current scope. */ def forwardRef(argSym: Symbol, from: Symbol, to: TypeBounds, cls: ClassSymbol, decls: Scope) = - argSym.info match { + argSym.info.stripAnnots match { case info @ TypeBounds(lo2 @ TypeRef(_: ThisType, name), hi2) => if (name == from.name && (lo2 eq hi2) && @@ -290,7 +290,7 @@ trait TypeOps { this: Context => * (2) X is not yet defined in current scope. This "short-circuiting" prevents * long chains of aliases which would have to be traversed in type comparers. */ - def forwardRefs(from: Symbol, to: Type, prefs: List[TypeRef]) = to match { + def forwardRefs(from: Symbol, to: Type, prefs: List[TypeRef]) = to.stripAnnots match { case to @ TypeBounds(lo1, hi1) if lo1 eq hi1 => for (pref <- prefs) for (argSym <- pref.decls) @@ -302,7 +302,7 @@ trait TypeOps { this: Context => // println(s"normalizing $parents of $cls in ${cls.owner}") // !!! DEBUG var refinements: SimpleMap[TypeName, Type] = SimpleMap.Empty var formals: SimpleMap[TypeName, Symbol] = SimpleMap.Empty - def normalizeToRef(tp: Type): TypeRef = tp match { + def normalizeToRef(tp: Type): TypeRef = tp.stripAnnots match { case tp @ RefinedType(tp1, name: TypeName) => val prevInfo = refinements(name) refinements = refinements.updated(name, @@ -357,7 +357,7 @@ trait TypeOps { this: Context => if (!(lo <:< hiBound)) violations += ((arg, "upper", hiBound)) if (!(bounds.lo <:< hi)) violations += ((arg, "lower", bounds.lo)) } - arg.tpe match { + arg.tpe.stripAnnots match { case TypeBounds(lo, hi) => checkOverlapsBounds(lo, hi) case tp => checkOverlapsBounds(tp, tp) } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index ef8aa78b63dd..398da4b32c49 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -94,6 +94,7 @@ object Types { case tp: TermRef => tp.termSymbol.isStable case _: SingletonType => true case NoPrefix => true + case tp: AnnotatedType => tp.tpe.isStable case _ => false } @@ -103,7 +104,7 @@ object Types { * It makes no sense for it to be an alias type because isRef would always * return false in that case. */ - def isRef(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar match { + def isRef(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar.stripAnnots match { case this1: TypeRef => this1.info match { // see comment in Namer#typeDefSig case TypeAlias(tp) => tp.isRef(sym) @@ -126,7 +127,7 @@ object Types { } /** Is this type an instance of a non-bottom subclass of the given class `cls`? */ - final def derivesFrom(cls: Symbol)(implicit ctx: Context): Boolean = this match { + final def derivesFrom(cls: Symbol)(implicit ctx: Context): Boolean = stripAnnots match { case tp: TypeRef => val sym = tp.symbol if (sym.isClass) sym.derivesFrom(cls) else tp.underlying.derivesFrom(cls) @@ -162,7 +163,7 @@ object Types { classSymbol is ModuleClass /** Is this type produced as a repair for an error? */ - final def isError(implicit ctx: Context): Boolean = stripTypeVar match { + final def isError(implicit ctx: Context): Boolean = stripTypeVar.stripAnnots match { case ErrorType => true case tp => (tp.typeSymbol is Erroneous) || (tp.termSymbol is Erroneous) } @@ -187,7 +188,7 @@ object Types { /** Is this the type of a method that has a repeated parameter type as * last parameter type? */ - def isVarArgsMethod(implicit ctx: Context): Boolean = this match { + def isVarArgsMethod(implicit ctx: Context): Boolean = stripAnnots match { case tp: PolyType => tp.resultType.isVarArgsMethod case MethodType(_, paramTypes) => paramTypes.nonEmpty && paramTypes.last.isRepeatedParam case _ => false @@ -202,7 +203,7 @@ object Types { * the same class are counted as equal for this purpose. */ def refines(prefix: Type)(implicit ctx: Context): Boolean = { - val prefix1 = prefix.dealias + val prefix1 = prefix.dealias.stripAnnots def loop(tp: Type): Boolean = (tp eq prefix1) || { tp match { @@ -246,13 +247,13 @@ object Types { new NamedPartsAccumulator(p).apply(mutable.LinkedHashSet(), this) /** Map function `f` over elements of an AndType, rebuilding with function `g` */ - def mapReduceAnd[T](f: Type => T)(g: (T, T) => T)(implicit ctx: Context): T = stripTypeVar match { + def mapReduceAnd[T](f: Type => T)(g: (T, T) => T)(implicit ctx: Context): T = stripTypeVar.stripAnnots match { case AndType(tp1, tp2) => g(tp1.mapReduceAnd(f)(g), tp2.mapReduceAnd(f)(g)) case _ => f(this) } /** Map function `f` over elements of an OrType, rebuilding with function `g` */ - final def mapReduceOr[T](f: Type => T)(g: (T, T) => T)(implicit ctx: Context): T = stripTypeVar match { + final def mapReduceOr[T](f: Type => T)(g: (T, T) => T)(implicit ctx: Context): T = stripTypeVar.stripAnnots match { case OrType(tp1, tp2) => g(tp1.mapReduceOr(f)(g), tp2.mapReduceOr(f)(g)) case _ => f(this) } @@ -414,7 +415,7 @@ object Types { case tp: TypeRef => tp.denot.findMember(name, pre, excluded) case tp: TermRef => - go (tp.underlying match { + go (tp.underlying.stripAnnots match { case mt: MethodType if mt.paramTypes.isEmpty && (tp.symbol is Stable) => mt.resultType case tp1 => tp1 @@ -582,7 +583,7 @@ object Types { * either type. */ final def overrides(that: Type)(implicit ctx: Context) = { - def result(tp: Type): Type = tp match { + def result(tp: Type): Type = tp.stripAnnots match { case ExprType(_) | MethodType(Nil, _) => tp.resultType case _ => tp } @@ -593,22 +594,26 @@ object Types { } /** Is this type close enough to that type so that members - * with the two type would override each other?d + * with the two type would override each other? * This means: * - Either both types are polytypes with the same number of * type parameters and their result types match after renaming * corresponding type parameters - * - Or both types are (possibly nullary) method types with equivalent parameter types - * and matching result types - * - Or both types are equivalent - * - Or phase.erasedTypes is false and both types are neither method nor - * poly types. + * - Or both types are method types with =:=-equivalent(*) parameter types + * and matching result types after renaming corresponding parameter types + * if the method types are dependent. + * - Or both types are =:=-equivalent + * - Or phase.erasedTypes is false, and neither type takes + * term or type parameters. + * + * (*) when matching with a Java method, we also regard Any and Object as equivalent + * parameter types. */ def matches(that: Type)(implicit ctx: Context): Boolean = if (Config.newMatch) this.signature matches that.signature else track("matches") { ctx.typeComparer.matchesType( - this, that, alwaysMatchSimple = !ctx.phase.erasedTypes) + this, that, relaxed = !ctx.phase.erasedTypes) } /** This is the same as `matches` except that it also matches => T with T and @@ -648,7 +653,7 @@ object Types { /** Remove all AnnotatedTypes wrapping this type. */ - def stripAnnots(implicit ctx: Context): Type = this + def stripAnnots: Type = this /** Widen from singleton type to its underlying non-singleton * base type by applying one or more `underlying` dereferences, @@ -661,6 +666,7 @@ object Types { */ final def widen(implicit ctx: Context): Type = widenSingleton match { case tp: ExprType => tp.resultType.widen + case tp: AnnotatedType => tp.derivedAnnotatedType(tp.annot, tp.tpe.widen) case tp => tp } @@ -669,6 +675,7 @@ object Types { */ final def widenSingleton(implicit ctx: Context): Type = stripTypeVar match { case tp: SingletonType if !tp.isOverloaded => tp.underlying.widenSingleton + case tp: AnnotatedType => tp.derivedAnnotatedType(tp.annot, tp.tpe.widenSingleton) case _ => this } @@ -677,6 +684,7 @@ object Types { */ final def widenExpr: Type = this match { case tp: ExprType => tp.resultType + case tp: AnnotatedType => tp.derivedAnnotatedType(tp.annot, tp.tpe.widenExpr) case _ => this } @@ -684,6 +692,7 @@ object Types { final def widenIfUnstable(implicit ctx: Context): Type = stripTypeVar match { case tp: ExprType => tp.resultType.widenIfUnstable case tp: TermRef if !tp.symbol.isStable => tp.underlying.widenIfUnstable + case tp: AnnotatedType => tp.derivedAnnotatedType(tp.annot, tp.tpe.widenIfUnstable) case _ => this } @@ -692,7 +701,7 @@ object Types { */ final def dealias(implicit ctx: Context): Type = this match { case tp: TypeRef => - tp.info match { + tp.info.stripAnnots match { case TypeAlias(tp) => tp.dealias case _ => tp } @@ -717,6 +726,7 @@ object Types { */ final def deconst(implicit ctx: Context): Type = stripTypeVar match { case tp: ConstantType => tp.value.tpe + case tp: AnnotatedType => tp.derivedAnnotatedType(tp.annot, tp.tpe.deconst) case _ => this } @@ -725,6 +735,7 @@ object Types { */ final def unrefine(implicit ctx: Context): Type = stripTypeVar match { case tp @ RefinedType(tycon, _) => tycon.unrefine + case tp: AnnotatedType => tp.derivedAnnotatedType(tp.annot, tp.tpe.unrefine) case _ => this } @@ -732,12 +743,11 @@ object Types { * a class, the class type ref, otherwise NoType. * @param refinementOK If `true` we also skip non-parameter refinements. */ - def underlyingClassRef(refinementOK: Boolean)(implicit ctx: Context): Type = dealias match { + def underlyingClassRef(refinementOK: Boolean)(implicit ctx: Context): Type = dealias.stripAnnots match { case tp: TypeRef => if (tp.symbol.isClass) tp else if (tp.symbol.isAliasType) tp.underlying.underlyingClassRef(refinementOK) else NoType - case tp: AnnotatedType => tp.underlying.underlyingClassRef(refinementOK) case tp: RefinedType => if (refinementOK) tp.underlying.underlyingClassRef(refinementOK) else { @@ -779,7 +789,7 @@ object Types { * yields `String` as the result of lookupRefined. */ def lookupRefined(name: Name)(implicit ctx: Context): Type = { - def loop(pre: Type): Type = pre.stripTypeVar match { + def loop(pre: Type): Type = pre.stripTypeVar.stripAnnots match { case pre: RefinedType => if (pre.refinedName ne name) loop(pre.parent) else pre.refinedInfo match { @@ -854,21 +864,21 @@ object Types { } /** The parameter types of a PolyType or MethodType, Empty list for others */ - final def paramTypess: List[List[Type]] = this match { + final def paramTypess: List[List[Type]] = stripAnnots match { case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess case pt: PolyType => pt.resultType.paramTypess case _ => Nil } /** The parameter types in the first parameter section of a PolyType or MethodType, Empty list for others */ - final def firstParamTypes: List[Type] = this match { + final def firstParamTypes: List[Type] = stripAnnots match { case mt: MethodType => mt.paramTypes case pt: PolyType => pt.resultType.firstParamTypes case _ => Nil } /** Is this either not a method at all, or a parameterless method? */ - final def isParameterless: Boolean = this match { + final def isParameterless: Boolean = stripAnnots match { case mt: MethodType => false case pt: PolyType => pt.resultType.isParameterless case _ => true @@ -880,14 +890,14 @@ object Types { /** The final result type of a PolyType, MethodType, or ExprType, after skipping * all parameter sections, the type itself for all others. */ - def finalResultType: Type = resultType match { + def finalResultType: Type = resultType.stripAnnots match { case mt: MethodType => mt.resultType.finalResultType case pt: PolyType => pt.resultType.finalResultType case _ => resultType } /** This type seen as a TypeBounds */ - final def bounds(implicit ctx: Context): TypeBounds = this match { + final def bounds(implicit ctx: Context): TypeBounds = stripAnnots match { case tp: TypeBounds => tp case ci: ClassInfo => TypeAlias(ci.typeRef) case wc: WildcardType => @@ -1913,7 +1923,7 @@ object Types { protected def computeSignature(implicit ctx: Context): Signature - protected def resultSignature(implicit ctx: Context) = try resultType match { + protected def resultSignature(implicit ctx: Context) = try resultType.stripAnnots match { case rtp: MethodicType => rtp.signature case tp => Signature(tp, isJava = false) } @@ -1955,7 +1965,7 @@ object Types { tp match { case MethodParam(`thisMethodType`, _) => true case tp @ TypeRef(MethodParam(`thisMethodType`, _), name) => - tp.info match { // follow type arguments to avoid dependency + tp.info.stripAnnots match { // follow type arguments to avoid dependency case TypeAlias(tp)=> apply(x, tp) case _ => true } @@ -2031,13 +2041,18 @@ object Types { def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType = apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType) def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = { - def paramInfo(param: Symbol): Type = param.info match { - case AnnotatedType(annot, tp) if annot matches defn.RepeatedAnnot => - val typeSym = param.info.typeSymbol.asClass - assert(typeSym == defn.SeqClass || typeSym == defn.ArrayClass) - tp.translateParameterized(typeSym, defn.RepeatedParamClass) - case tp => - tp + def paramInfo(param: Symbol): Type = { + def recur(info: Type): Type = info match { + case AnnotatedType(annot, tp) if annot matches defn.RepeatedAnnot => + val typeSym = param.info.typeSymbol.asClass + assert(typeSym == defn.SeqClass || typeSym == defn.ArrayClass) + tp.translateParameterized(typeSym, defn.RepeatedParamClass) + case tp: AnnotatedType => + tp.derivedAnnotatedType(tp.annot, recur(tp.tpe)) + case tp => + tp + } + recur(param.info) } def transformResult(mt: MethodType) = resultType.subst(params, (0 until params.length).toList map (MethodParam(mt, _))) @@ -2172,7 +2187,7 @@ object Types { * - fromBelow and param <:< bound * - !fromBelow and param >:> bound */ - def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match { + def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar.stripAnnots match { case bound: PolyParam => bound == this case bound: AndOrType => def occ1 = occursIn(bound.tp1, fromBelow) @@ -2264,7 +2279,7 @@ object Types { */ def instantiate(fromBelow: Boolean)(implicit ctx: Context): Type = { def upperBound = ctx.typerState.constraint.fullUpperBound(origin) - def isSingleton(tp: Type): Boolean = tp match { + def isSingleton(tp: Type): Boolean = tp.stripAnnots match { case tp: SingletonType => true case AndType(tp1, tp2) => isSingleton(tp1) | isSingleton(tp2) case OrType(tp1, tp2) => isSingleton(tp1) & isSingleton(tp2) @@ -2276,7 +2291,7 @@ object Types { case tp: AndOrType => isFullyDefined(tp.tp1) && isFullyDefined(tp.tp2) case _ => true } - def isOrType(tp: Type): Boolean = tp.stripTypeVar.dealias match { + def isOrType(tp: Type): Boolean = tp.stripTypeVar.dealias.stripAnnots match { case tp: OrType => true case AndType(tp1, tp2) => isOrType(tp1) | isOrType(tp2) case RefinedType(parent, _) => isOrType(parent) @@ -2463,7 +2478,7 @@ object Types { case _ => this } - def contains(tp: Type)(implicit ctx: Context) = tp match { + def contains(tp: Type)(implicit ctx: Context) = tp.stripAnnots match { case tp: TypeBounds => lo <:< tp.lo && tp.hi <:< hi case _ => lo <:< tp && tp <:< hi } @@ -2557,8 +2572,10 @@ object Types { if ((annot eq this.annot) && (tpe eq this.tpe)) this else AnnotatedType(annot, tpe) - override def stripTypeVar(implicit ctx: Context): Type = tpe.stripTypeVar - override def stripAnnots(implicit ctx: Context): Type = tpe.stripAnnots + override def stripTypeVar(implicit ctx: Context): Type = derivedAnnotatedType(annot, tpe.stripTypeVar) + override def stripAnnots: Type = tpe.stripAnnots + override def resultType: Type = tpe.resultType + override def signature(implicit ctx: Context): Signature = tpe.signature } object AnnotatedType { @@ -2622,7 +2639,7 @@ object Types { * denotation of the single abstract method as a member of the type. */ object SAMType { - def zeroParamClass(tp: Type)(implicit ctx: Context): Type = tp match { + def zeroParamClass(tp: Type)(implicit ctx: Context): Type = tp.stripAnnots match { case tp: ClassInfo => def zeroParams(tp: Type): Boolean = tp match { case pt: PolyType => zeroParams(pt.resultType) @@ -2656,7 +2673,7 @@ object Types { val absMems = tp.abstractTermMembers // println(s"absMems: ${absMems map (_.show) mkString ", "}") if (absMems.size == 1) - absMems.head.info match { + absMems.head.info.stripAnnots match { case mt: MethodType if !mt.isDependent => Some(absMems.head) case _ => None } diff --git a/src/dotty/tools/dotc/transform/ElimByName.scala b/src/dotty/tools/dotc/transform/ElimByName.scala index ca84fcaec9ad..3eea5feda3bb 100644 --- a/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/src/dotty/tools/dotc/transform/ElimByName.scala @@ -85,7 +85,7 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform arg } - val MethodType(_, formals) = tree.fun.tpe.widen + val MethodType(_, formals) = tree.fun.tpe.widen.stripAnnots val args1 = tree.args.zipWithConserve(formals)(transformArg) cpy.Apply(tree)(tree.fun, args1) } diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 933252ccd2d4..33c41fcff3a6 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -214,7 +214,7 @@ object Erasure extends TypeTestsCasts{ */ def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree = if (pt.isInstanceOf[FunProto]) tree - else tree.tpe.widen match { + else tree.tpe.widen.stripAnnots match { case MethodType(Nil, _) if tree.isTerm => adaptToType(tree.appliedToNone, pt) case tpw => @@ -236,9 +236,9 @@ object Erasure extends TypeTestsCasts{ class Typer extends typer.ReTyper with NoChecking { import Boxing._ - def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = tree.typeOpt match { + def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type = tree.typeOpt.stripAnnots match { case tp: TermRef if tree.isTerm => erasedRef(tp) - case tp => erasure(tp) + case _ => erasure(tree.typeOpt) } override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { @@ -306,18 +306,18 @@ object Erasure extends TypeTestsCasts{ } def recur(qual: Tree): Tree = { - val qualIsPrimitive = qual.tpe.widen.isPrimitiveValueType + val qualIsPrimitive = qual.tpe.widen.stripAnnots.isPrimitiveValueType val symIsPrimitive = sym.owner.isPrimitiveValueClass if ((sym.owner eq defn.AnyClass) || (sym.owner eq defn.AnyValClass)) { assert(sym.isConstructor, s"${sym.showLocated}") select(qual, defn.ObjectClass.info.decl(sym.name).symbol) } - else if (qualIsPrimitive && !symIsPrimitive || qual.tpe.isErasedValueType) + else if (qualIsPrimitive && !symIsPrimitive || qual.tpe.stripAnnots.isErasedValueType) recur(box(qual)) else if (!qualIsPrimitive && symIsPrimitive) recur(unbox(qual, sym.owner.typeRef)) else if (sym.owner eq defn.ArrayClass) - selectArrayMember(qual, erasure(tree.qualifier.typeOpt.widen.finalResultType)) + selectArrayMember(qual, erasure(tree.qualifier.typeOpt.widen.finalResultType.stripAnnots)) else { val qual1 = adaptIfSuper(qual) if (qual1.tpe.derivesFrom(sym.owner) || qual1.isInstanceOf[Super]) @@ -376,7 +376,7 @@ object Erasure extends TypeTestsCasts{ case fun1: Apply => // arguments passed in prototype were already passed fun1 case fun1 => - fun1.tpe.widen match { + fun1.tpe.widen.stripAnnots match { case mt: MethodType => val outers = outer.args(fun.asInstanceOf[tpd.Tree]) // can't use fun1 here because its type is already erased val args1 = (outers ::: args ++ protoArgs(pt)).zipWithConserve(mt.paramTypes)(typedExpr) @@ -500,7 +500,12 @@ object Erasure extends TypeTestsCasts{ }) } - override def adapt(tree: Tree, pt: Type, original: untpd.Tree)(implicit ctx: Context): Tree = + override def adapt(tree: Tree, pt: Type, original: untpd.Tree)(implicit ctx: Context): Tree = { + val tree1 = adapt1(tree, pt, original) + tree1.withType(tree1.tpe.stripAnnots) + } + + def adapt1(tree: Tree, pt: Type, original: untpd.Tree)(implicit ctx: Context): Tree = ctx.traceIndented(i"adapting ${tree.showSummary}: ${tree.tpe} to $pt", show = true) { assert(ctx.phase == ctx.erasurePhase.next, ctx.phase) if (tree.isEmpty) tree diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala index ba74de0a36ac..1d0c88e0977b 100644 --- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -50,6 +50,8 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf val newDecls = decls.cloneScope newOuterAccessors(cls).foreach(newDecls.enter) tp.derivedClassInfo(decls = newDecls) + case tp: AnnotatedType => + tp.derivedAnnotatedType(tp.annot, transformInfo(tp.tpe, sym)) case _ => tp } @@ -201,7 +203,7 @@ object ExplicitOuter { case thisTree @ This(_) => isOuter(thisTree.symbol) case id: Ident => - id.tpe match { + id.tpe.stripAnnots match { case ref @ TermRef(NoPrefix, _) => ref.symbol.is(Method) && isOuter(id.symbol.owner.enclosingClass) // methods will be placed in enclosing class scope by LambdaLift, so they will get diff --git a/src/dotty/tools/dotc/transform/Literalize.scala b/src/dotty/tools/dotc/transform/Literalize.scala index c5b6f1c21aa5..e451f67586a7 100644 --- a/src/dotty/tools/dotc/transform/Literalize.scala +++ b/src/dotty/tools/dotc/transform/Literalize.scala @@ -51,7 +51,7 @@ class Literalize extends MiniPhaseTransform { thisTransform => * Revisit this issue once we have implemented `inline`. Then we can demand * purity of the prefix unless the selection goes to an inline val. */ - def literalize(tree: Tree)(implicit ctx: Context): Tree = tree.tpe match { + def literalize(tree: Tree)(implicit ctx: Context): Tree = tree.tpe.stripAnnots match { case ConstantType(value) if isIdempotentExpr(tree) => Literal(value) case _ => tree } @@ -68,7 +68,7 @@ class Literalize extends MiniPhaseTransform { thisTransform => override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = literalize(tree) - override def transformLiteral(tree: Literal)(implicit ctx: Context, info: TransformerInfo): Tree = tree.tpe match { + override def transformLiteral(tree: Literal)(implicit ctx: Context, info: TransformerInfo): Tree = tree.tpe.stripAnnots match { case ConstantType(const) if tree.const.value != const.value || (tree.const.tag != const.tag) => Literal(const) case _ => tree } @@ -78,7 +78,7 @@ class Literalize extends MiniPhaseTransform { thisTransform => override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = { tree match { case Literal(c @ Constant(treeValue)) => - tree.tpe match { + tree.tpe.stripAnnots match { case ConstantType(c2 @ Constant(typeValue)) => assert(treeValue == typeValue && c2.tag == c.tag, i"Type of Literal $tree is inconsistent with underlying constant") diff --git a/src/dotty/tools/dotc/transform/OverridingPairs.scala b/src/dotty/tools/dotc/transform/OverridingPairs.scala index bc3c085a92a6..f7adec471541 100644 --- a/src/dotty/tools/dotc/transform/OverridingPairs.scala +++ b/src/dotty/tools/dotc/transform/OverridingPairs.scala @@ -39,12 +39,7 @@ object OverridingPairs { * relative to .this do */ protected def matches(sym1: Symbol, sym2: Symbol): Boolean = - sym1.isType || { - val info1 = self.memberInfo(sym1) - val info2 = self.memberInfo(sym2) - // info1.signature == info2.signature && // TODO enable for speed - info1 matches info2 - } + sym1.isType || self.memberInfo(sym1).matches(self.memberInfo(sym2)) /** The symbols that can take part in an overriding pair */ private val decls = { diff --git a/src/dotty/tools/dotc/transform/Splitter.scala b/src/dotty/tools/dotc/transform/Splitter.scala index 0a1e1b238aaf..2af3635abad9 100644 --- a/src/dotty/tools/dotc/transform/Splitter.scala +++ b/src/dotty/tools/dotc/transform/Splitter.scala @@ -18,7 +18,7 @@ class Splitter extends MiniPhaseTransform { thisTransform => override def phaseName: String = "splitter" /** Replace self referencing idents with ThisTypes. */ - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = tree.tpe match { + override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = tree.tpe.stripAnnots match { case tp: ThisType => ctx.debuglog(s"owner = ${ctx.owner}, context = ${ctx}") This(tp.cls) withPos tree.pos @@ -45,7 +45,7 @@ class Splitter extends MiniPhaseTransform { thisTransform => def memberDenot(tp: Type): SingleDenotation = { val mbr = tp.member(name) if (!mbr.isOverloaded) mbr.asSingleDenotation - else tree.tpe match { + else tree.tpe.stripAnnots match { case tref: TermRefWithSignature => mbr.atSignature(tref.sig) case _ => ctx.error(s"cannot disambiguate overloaded member $mbr"); NoDenotation } @@ -54,9 +54,9 @@ class Splitter extends MiniPhaseTransform { thisTransform => def candidates(tp: Type): List[Symbol] = { val mbr = memberDenot(tp) if (mbr.symbol.exists) mbr.symbol :: Nil - else tp.widen match { + else tp.widen.stripAnnots match { case tref: TypeRef => - tref.info match { + tref.info.stripAnnots match { case TypeBounds(_, hi) => candidates(hi) case _ => Nil } @@ -69,7 +69,7 @@ class Splitter extends MiniPhaseTransform { thisTransform => } } - def isStructuralSelect(tp: Type): Boolean = tp.stripTypeVar match { + def isStructuralSelect(tp: Type): Boolean = tp.stripTypeVar.stripAnnots match { case tp: RefinedType => tp.refinedName == name || isStructuralSelect(tp.parent) case tp: TypeProxy => isStructuralSelect(tp.underlying) case AndType(tp1, tp2) => isStructuralSelect(tp1) || isStructuralSelect(tp2) diff --git a/src/dotty/tools/dotc/transform/SuperAccessors.scala b/src/dotty/tools/dotc/transform/SuperAccessors.scala index f727201b2895..e58b167c5a9d 100644 --- a/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -76,8 +76,9 @@ class SuperAccessors extends MacroTransform with IdentityDenotTransformer { this buf += tree } - private def ensureMethodic(tpe: Type)(implicit ctx: Context) = tpe match { + private def ensureMethodic(tpe: Type)(implicit ctx: Context): Type = tpe match { case tpe: MethodicType => tpe + case tpe: AnnotatedType => tpe.derivedAnnotatedType(tpe.annot, ensureMethodic(tpe.tpe)) case _ => ExprType(tpe) } @@ -250,7 +251,7 @@ class SuperAccessors extends MacroTransform with IdentityDenotTransformer { this def forwardParamAccessors(stats: List[Tree]): List[Tree] = { val (superArgs, superParamNames) = impl.parents match { case superCall @ Apply(fn, args) :: _ => - fn.tpe.widen match { + fn.tpe.widen.stripAnnots match { case MethodType(paramNames, _) => (args, paramNames) case _ => (Nil, Nil) } @@ -391,7 +392,7 @@ class SuperAccessors extends MacroTransform with IdentityDenotTransformer { this transformAssign case Apply(fn, args) => - val MethodType(_, formals) = fn.tpe.widen + val MethodType(_, formals) = fn.tpe.widen.stripAnnots ctx.atPhase(thisTransformer.next) { implicit ctx => cpy.Apply(tree)(transform(fn), transformArgs(formals, args)) } @@ -434,7 +435,7 @@ class SuperAccessors extends MacroTransform with IdentityDenotTransformer { this // has to take an object of exactly this type, otherwise it's more general val receiverType = if (isThisType(sym.info.finalResultType)) clazz.thisType else clazz.classInfo.selfType val accType = { - def accTypeOf(tpe: Type): Type = tpe match { + def accTypeOf(tpe: Type): Type = tpe.stripAnnots match { case tpe: PolyType => tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType)) case _ => diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index c012e8837718..a276c2b59bc5 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -68,7 +68,7 @@ object Applications { if (seqArg.exists) return args map Function.const(seqArg) } else return getUnapplySelectors(getTp, args, pos) - else if (defn.isProductSubType(unapplyResult)) return productSelectorTypes(unapplyResult, pos) + else if (defn.isProductSubType(unapplyResult)) return productSelectorTypes(unapplyResult, pos).map(_.stripAnnots) } if (unapplyResult derivesFrom defn.SeqClass) seqSelector :: Nil else if (unapplyResult isRef defn.BooleanClass) Nil @@ -153,7 +153,7 @@ trait Applications extends Compatibility { self: Typer => /** The function's type after widening and instantiating polytypes * with polyparams in constraint set */ - val methType = funType.widen match { + val methType = funType.widen.stripAnnots match { case funType: MethodType => funType case funType: PolyType => constrained(funType).resultType case tp => tp //was: funType @@ -168,7 +168,7 @@ trait Applications extends Compatibility { self: Typer => else args - protected def init() = methType match { + protected def init() = methType.stripAnnots match { case methType: MethodType => // apply the result type constraint, unless method type is dependent if (!methType.isDependent) { @@ -254,7 +254,7 @@ trait Applications extends Compatibility { self: Typer => val meth = methRef.symbol.asTerm val receiver: Tree = methPart(normalizedFun) match { case Select(receiver, _) => receiver - case mr => mr.tpe.normalizedPrefix match { + case mr => mr.tpe.normalizedPrefix.stripAnnots match { case mr: TermRef => ref(mr) case _ => EmptyTree } @@ -523,7 +523,7 @@ trait Applications extends Compatibility { self: Typer => // a modified tree but this would be more convoluted and less efficient. if (proto.isTupled) proto = proto.tupled - methPart(fun1).tpe match { + methPart(fun1).tpe.stripAnnots match { case funRef: TermRef => tryEither { implicit ctx => val app = @@ -540,7 +540,7 @@ trait Applications extends Compatibility { self: Typer => cpy.Apply(tree)(untpd.TypedSplice(fun2), proto.typedArgs map untpd.TypedSplice), pt) } case _ => - fun1.tpe match { + fun1.tpe.stripAnnots match { case ErrorType => tree.withType(ErrorType) case tp => handleUnexpectedFunType(tree, fun1) } @@ -585,7 +585,7 @@ trait Applications extends Compatibility { self: Typer => def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context): Tree = track("typedTypeApply") { var typedArgs = tree.args mapconserve (typedType(_)) val typedFn = typedExpr(tree.fun, PolyProto(typedArgs.tpes, pt)) - typedFn.tpe.widen match { + typedFn.tpe.widen.stripAnnots match { case pt: PolyType => def adaptTypeArg(tree: tpd.Tree, bound: Type): tpd.Tree = if (bound.isLambda && !tree.tpe.isLambda && tree.tpe.typeParams.nonEmpty) @@ -622,8 +622,8 @@ trait Applications extends Compatibility { self: Typer => tree match { case tree: untpd.RefTree => val ttree = typedType(untpd.rename(tree, tree.name.toTypeName)) - ttree.tpe match { - case alias: TypeRef if alias.info.isAlias => + ttree.tpe.stripAnnots match { + case alias: TypeRef if alias.info.stripAnnots.isAlias => companionRef(alias) match { case companion: TermRef => return untpd.ref(companion) withPos tree.pos case _ => @@ -682,19 +682,19 @@ trait Applications extends Compatibility { self: Typer => */ def isSubTypeOfParent(subtp: Type, tp: Type)(implicit ctx: Context): Boolean = if (subtp <:< tp) true - else tp match { + else tp.stripAnnots match { case RefinedType(parent, _) => isSubTypeOfParent(subtp, parent) case _ => false } - unapplyFn.tpe.widen match { + unapplyFn.tpe.widen.stripAnnots match { case mt: MethodType if mt.paramTypes.length == 1 && !mt.isDependent => val m = mt val unapplyArgType = mt.paramTypes.head unapp.println(i"unapp arg tpe = $unapplyArgType, pt = $selType") def wpt = widenForMatchSelector(selType) // needed? val ownType = - if (selType <:< unapplyArgType) { + if (selType.stripAnnots <:< unapplyArgType) { //fullyDefinedType(unapplyArgType, "extractor argument", tree.pos) unapp.println(i"case 1 $unapplyArgType ${ctx.typerState.constraint}") selType @@ -853,7 +853,7 @@ trait Applications extends Compatibility { self: Typer => }} /** Drop any implicit parameter section */ - def stripImplicit(tp: Type): Type = tp match { + def stripImplicit(tp: Type): Type = tp.stripAnnots match { case mt: ImplicitMethodType if !mt.isDependent => mt.resultType // todo: make sure implicit method types are not dependent case pt: PolyType => diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index 1354b8926183..b8460da85e02 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -62,7 +62,7 @@ object Checking { /** Check info `tp` for cycles. Throw CyclicReference for illegal cycles, * break direct cycle with a LazyRef for legal, F-bounded cycles. */ - def checkInfo(tp: Type): Type = tp match { + def checkInfo(tp: Type): Type = tp.stripAnnots match { case tp @ TypeAlias(alias) => try tp.derivedTypeAlias(apply(alias)) finally { @@ -102,7 +102,7 @@ object Checking { // to symbol `sym` itself. We only check references with interesting // prefixes for cycles. This pruning is done in order not to force // global symbols when doing the cyclicity check. - def isInteresting(prefix: Type): Boolean = prefix.stripTypeVar match { + def isInteresting(prefix: Type): Boolean = prefix.stripTypeVar.stripAnnots match { case NoPrefix => true case prefix: ThisType => sym.owner.isClass && prefix.cls.isContainedIn(sym.owner) case prefix: NamedType => !prefix.symbol.isStaticOwner && isInteresting(prefix.prefix) @@ -246,7 +246,7 @@ trait Checking { * @return `tp` itself if it is a class or trait ref, ObjectClass.typeRef if not. */ def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type = - tp.underlyingClassRef(refinementOK = false) match { + tp.underlyingClassRef(refinementOK = false).stripAnnots match { case tref: TypeRef => if (ctx.phase <= ctx.refchecksPhase) checkStable(tref.prefix, pos) if (traitReq && !(tref.symbol is Trait)) ctx.error(d"$tref is not a trait", pos) @@ -270,7 +270,7 @@ trait Checking { * their lower bound conforms to their upper cound. If a type argument is * infeasible, issue and error and continue with upper bound. */ - def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp match { + def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp.stripAnnots match { case tp: RefinedType => tp.derivedRefinedType(tp.parent, tp.refinedName, checkFeasible(tp.refinedInfo, pos, where)) case tp @ TypeBounds(lo, hi) if !(lo <:< hi) => @@ -310,7 +310,7 @@ trait Checking { } cls.info.decls.foreach(checkDecl) - cls.info match { + cls.info.stripAnnots match { case ClassInfo(_, _, _, _, selfSym: Symbol) => checkDecl(selfSym) case _ => } diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala index 2ed720f83444..cddc5e7e60a4 100644 --- a/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -86,7 +86,7 @@ object ErrorReporting { else if (denot.symbol.exists) denot.symbol.showLocated else anonymousTypeMemberStr(denot.info) - def refStr(tp: Type): String = tp match { + def refStr(tp: Type): String = tp.stripAnnots match { case tp: NamedType => denotStr(tp.denot) case _ => anonymousTypeMemberStr(tp) } diff --git a/src/dotty/tools/dotc/typer/EtaExpansion.scala b/src/dotty/tools/dotc/typer/EtaExpansion.scala index 6ecd90c0865d..b59748247e4b 100644 --- a/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -34,8 +34,11 @@ object EtaExpansion { * lhs += expr */ def liftAssigned(defs: mutable.ListBuffer[Tree], tree: Tree)(implicit ctx: Context): Tree = tree match { - case Apply(fn @ Select(pre, name), args) => - cpy.Apply(tree)(cpy.Select(fn)(lift(defs, pre), name), liftArgs(defs, fn.tpe, args)) + case Apply(MaybePoly(fn @ Select(pre, name), targs), args) => + cpy.Apply(tree)( + cpy.Select(fn)( + lift(defs, pre), name).appliedToTypeTrees(targs), + liftArgs(defs, fn.tpe, args)) case Select(pre, name) => cpy.Select(tree)(lift(defs, pre), name) case _ => diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index 24d9ebf6d8b7..6042af253f7a 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -46,13 +46,13 @@ object Implicits { def refMatches(ref: TermRef)(implicit ctx: Context) = { - def discardForView(tpw: Type, argType: Type): Boolean = tpw match { + def discardForView(tpw: Type, argType: Type): Boolean = tpw.stripAnnots match { case mt: MethodType => mt.isImplicit || mt.paramTypes.length != 1 || !(argType <:< mt.paramTypes.head)(ctx.fresh.setExploreTyperState) case poly: PolyType => - poly.resultType match { + poly.resultType.stripAnnots match { case mt: MethodType => mt.isImplicit || mt.paramTypes.length != 1 || @@ -68,13 +68,13 @@ object Implicits { !tpw.derivesFrom(defn.FunctionClass(1)) || tpw.isRef(defn.PredefConformsClass) } - def discardForValueType(tpw: Type): Boolean = tpw match { + def discardForValueType(tpw: Type): Boolean = tpw.stripAnnots match { case mt: MethodType => !mt.isImplicit case mt: PolyType => discardForValueType(tpw.resultType) case _ => false } - def discard = pt match { + def discard = pt.stripAnnots match { case pt: ViewProto => discardForView(ref.widen, pt.argType) case _: ValueTypeOrProto => !defn.isFunctionType(pt) && discardForValueType(ref.widen) case _ => false @@ -302,7 +302,7 @@ trait ImplicitRunInfo { self: RunInfo => def collectCompanions(tp: Type): TermRefSet = track("computeImplicicScope") { ctx.traceIndented(i"collectCompanions($tp)", implicits) { val comps = new TermRefSet - tp match { + tp.stripAnnots match { case tp: NamedType => val pre = tp.prefix comps ++= iscopeRefs(pre) @@ -377,9 +377,9 @@ trait Implicits { self: Typer => !from.isError && !to.isError && (ctx.mode is Mode.ImplicitsEnabled) - && { from.widenExpr match { + && { from.widenExpr.stripAnnots match { case from: TypeRef if defn.ScalaValueClasses contains from.symbol => - to.widenExpr match { + to.widenExpr.stripAnnots match { case to: TypeRef if defn.ScalaValueClasses contains to.symbol => util.Stats.record("isValueSubClass") return defn.isValueSubClass(from.symbol, to.symbol) diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index e41b2d194274..16055314bcf4 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -107,7 +107,7 @@ trait Inferencing { this: Checking => * that companion module. Otherwise NoType */ def companionRef(tp: Type)(implicit ctx: Context): Type = - tp.underlyingClassRef(refinementOK = true) match { + tp.underlyingClassRef(refinementOK = true).stripAnnots match { case tp: TypeRef => val companion = tp.classSymbol.companionModule if (companion.exists) diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 323a1100ba1f..63961319a8fe 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -654,9 +654,14 @@ class Namer { typer: Typer => else restpe val monotpe = (paramSymss :\ restpe1) { (params, restpe) => + val isJava = ddef.mods is JavaDefined val make = if (params.nonEmpty && (params.head is Implicit)) ImplicitMethodType + else if(isJava) JavaMethodType else MethodType + if(isJava) params.foreach { symbol => + if(symbol.info.isDirectRef(defn.ObjectClass)) symbol.info = defn.AnyType + } make.fromSymbols(params, restpe) } if (typeParams.nonEmpty) PolyType.fromSymbols(typeParams, monotpe) diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala index 521f0deaae0e..a782d4496f36 100644 --- a/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -45,16 +45,16 @@ object ProtoTypes { /** Check that the result type of the current method * fits the given expected result type. */ - def constrainResult(mt: Type, pt: Type)(implicit ctx: Context): Boolean = pt match { + def constrainResult(mt: Type, pt: Type)(implicit ctx: Context): Boolean = pt.stripAnnots match { case _: FunProto => - mt match { + mt.stripAnnots match { case mt: MethodType => mt.isDependent || constrainResult(mt.resultType, pt.resultType) case _ => true } case _: ValueTypeOrProto if !(pt isRef defn.UnitClass) => - mt match { + mt.stripAnnots match { case mt: MethodType => mt.isDependent || isCompatible(normalize(mt, pt), pt) case _ => @@ -138,7 +138,7 @@ object ProtoTypes { */ def selectionProto(name: Name, tp: Type, typer: Typer)(implicit ctx: Context) = if (name.isConstructorName) WildcardType - else tp match { + else tp.stripAnnots match { case tp: UnapplyFunProto => new UnapplySelectionProto(name) case tp => SelectionProto(name, IgnoredProto(tp), typer) } @@ -276,7 +276,7 @@ object ProtoTypes { */ case class PolyProto(targs: List[Type], override val resultType: Type) extends UncachedGroundType with ProtoType { override def isMatchedBy(tp: Type)(implicit ctx: Context) = { - def isInstantiatable(tp: Type) = tp.widen match { + def isInstantiatable(tp: Type) = tp.widen.stripAnnots match { case PolyType(paramNames) => paramNames.length == targs.length case _ => false } @@ -361,6 +361,7 @@ object ProtoTypes { } } case et: ExprType => et.resultType + case tp: AnnotatedType => tp.derivedAnnotatedType(tp.annot, normalize(tp.tpe, pt)) case _ => tp } } diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 46aa2e953bd6..90ad5ed7ea4c 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -31,7 +31,7 @@ trait TypeAssigner { def avoid(tp: Type, syms: => List[Symbol])(implicit ctx: Context): Type = { val widenMap = new TypeMap { lazy val forbidden = syms.toSet - def toAvoid(tp: Type): Boolean = tp match { + def toAvoid(tp: Type): Boolean = tp.stripAnnots match { case tp: TermRef => val sym = tp.symbol sym.exists && ( @@ -112,9 +112,9 @@ trait TypeAssigner { * that the package object shows up as the prefix. */ def ensureAccessible(tpe: Type, superAccess: Boolean, pos: Position)(implicit ctx: Context): Type = { - def test(tpe: Type, firstTry: Boolean): Type = tpe match { + def test(tpe: Type, firstTry: Boolean): Type = tpe.stripAnnots match { case tpe: NamedType => - val pre = tpe.prefix + val pre = tpe.prefix.stripAnnots val name = tpe.name val d = tpe.denot.accessibleFrom(pre, superAccess) if (!d.exists) { @@ -183,7 +183,7 @@ trait TypeAssigner { tree.withType(tp) def assignType(tree: untpd.Select, qual: Tree)(implicit ctx: Context): Select = { - def qualType = qual.tpe.widen + def qualType = qual.tpe.widen.stripAnnots def arrayElemType = { val JavaArrayType(elemtp) = qualType elemtp @@ -222,7 +222,7 @@ trait TypeAssigner { def assignType(tree: untpd.Super, qual: Tree, inConstrCall: Boolean, mixinClass: Symbol = NoSymbol)(implicit ctx: Context) = { val mix = tree.mix - val qtype @ ThisType(_) = qual.tpe + val qtype @ ThisType(_) = qual.tpe.stripAnnots val cls = qtype.cls def findMixinSuper(site: Type): Type = site.parents filter (_.name == mix) match { @@ -245,25 +245,30 @@ trait TypeAssigner { } def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = { - val ownType = fn.tpe.widen match { + def recur(tp: Type): Type = tp.widen match { case fntpe @ MethodType(_, ptypes) => if (sameLength(ptypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes) else errorType(i"wrong number of parameters for ${fn.tpe}; expected: ${ptypes.length}", tree.pos) + case tp: AnnotatedType => + tp.derivedAnnotatedType(tp.annot, recur(tp.tpe)) case t => errorType(i"${err.exprStr(fn)} does not take parameters", tree.pos) } + val ownType = recur(fn.tpe) tree.withType(ownType) } def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(implicit ctx: Context) = { - val ownType = fn.tpe.widen match { + def recur(tp: Type): Type = tp match { case pt: PolyType => val argTypes = args.tpes if (sameLength(argTypes, pt.paramNames)|| ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes) else errorType(d"wrong number of type parameters for ${fn.tpe}; expected: ${pt.paramNames.length}", tree.pos) + case tp: AnnotatedType => tp.derivedAnnotatedType(tp.annot, recur(tp.tpe)) case _ => errorType(i"${err.exprStr(fn)} does not take type parameters", tree.pos) } + val ownType = recur(fn.tpe.widen) tree.withType(ownType) } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 9958b3b64ca2..69d78d397c51 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -271,7 +271,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit ErrorType } - val tree1 = ownType match { + val tree1 = ownType.stripAnnots match { case ownType: NamedType if !prefixIsElidable(ownType) => ref(ownType).withPos(tree.pos) case _ => @@ -400,24 +400,27 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit tree.lhs match { case lhs @ Apply(fn, args) => typed(cpy.Apply(lhs)(untpd.Select(fn, nme.update), args :+ tree.rhs), pt) - case untpd.TypedSplice(Apply(Select(fn, app), args)) if app == nme.apply => - typed(cpy.Apply(fn)( - untpd.Select(untpd.TypedSplice(fn), nme.update), - (args map untpd.TypedSplice) :+ tree.rhs), pt) + case untpd.TypedSplice(Apply(MaybePoly(Select(fn, app), targs), args)) if app == nme.apply => + val rawUpdate: untpd.Tree = untpd.Select(untpd.TypedSplice(fn), nme.update) + val wrappedUpdate = + if (targs.isEmpty) rawUpdate + else untpd.TypeApply(rawUpdate, targs map untpd.TypedSplice) + val appliedUpdate = cpy.Apply(fn)(wrappedUpdate, (args map untpd.TypedSplice) :+ tree.rhs) + typed(appliedUpdate, pt) case lhs => val lhsCore = typedUnadapted(lhs) def lhs1 = typed(untpd.TypedSplice(lhsCore)) def canAssign(sym: Symbol) = // allow assignments from the primary constructor to class fields sym.is(Mutable, butNot = Accessor) || ctx.owner.isPrimaryConstructor && !sym.is(Method) && sym.owner == ctx.owner.owner - lhsCore.tpe match { + lhsCore.tpe.stripAnnots match { case ref: TermRef if canAssign(ref.symbol) => assignType(cpy.Assign(tree)(lhs1, typed(tree.rhs, ref.info))) case _ => def reassignmentToVal = errorTree(cpy.Assign(tree)(lhsCore, typed(tree.rhs, lhs1.tpe.widen)), "reassignment to val") - lhsCore.tpe match { + lhsCore.tpe.stripAnnots match { case ref: TermRef => // todo: further conditions to impose on getter? val pre = ref.prefix val setterName = ref.name.setterName @@ -546,7 +549,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit */ def inferredParamType(param: untpd.ValDef, formal: Type): Type = { if (isFullyDefined(formal, ForceDegree.noBottom)) return formal - calleeType.widen match { + calleeType.widen.stripAnnots match { case mtpe: MethodType => val pos = params indexWhere (_.name == param.name) if (pos < mtpe.paramTypes.length) { @@ -1241,7 +1244,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } } - def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match { + def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp.stripAnnots match { case _: MethodType | _: PolyType => def isUnary = wtp.firstParamTypes match { case ptype :: Nil => !ptype.isRepeatedParam @@ -1260,7 +1263,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } } - def adaptNoArgs(wtp: Type): Tree = wtp match { + def adaptNoArgs(wtp: Type): Tree = wtp.stripAnnots match { case wtp: ExprType => adaptInterpolated(tree.withType(wtp.resultType), pt, original) case wtp: ImplicitMethodType if constrainResult(wtp, pt) => @@ -1323,7 +1326,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit tree match { case Closure(Nil, id @ Ident(nme.ANON_FUN), _) if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) => - pt match { + pt.stripAnnots match { case SAMType(meth) if wtp <:< meth.info.toFunctionType() => // was ... && isFullyDefined(pt, ForceDegree.noBottom) @@ -1347,7 +1350,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit tree match { case _: MemberDef | _: PackageDef | _: Import | _: WithoutTypeOrPos[_] => tree - case _ => tree.tpe.widen match { + case _ => tree.tpe.widen.stripAnnots match { case ErrorType => tree case ref: TermRef => diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 89ac2b6c4e45..524f3ce12dc9 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -57,6 +57,7 @@ class tests extends CompilerTest { @Test def pos_packageobject() = compileFile(posDir, "packageobject") @Test def pos_overloaded() = compileFile(posDir, "overloaded") @Test def pos_overrides() = compileFile(posDir, "overrides") + @Test def pos_javaOverride() = compileDir(posDir + "java-override") @Test def pos_templateParents() = compileFile(posDir, "templateParents") @Test def pos_structural() = compileFile(posDir, "structural") @Test def pos_overloadedAccess = compileFile(posDir, "overloadedAccess") @@ -82,8 +83,8 @@ class tests extends CompilerTest { @Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", "-language:noAutoTupling" :: Nil, xerrors = 4) @Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 4) @Test def neg_companions = compileFile(negDir, "companions", xerrors = 1) - @Test def neg_over = compileFile(negDir, "over", xerrors = 1) - @Test def neg_overrides = compileFile(negDir, "overrides", xerrors = 7) + @Test def neg_over = compileFile(negDir, "over", xerrors = 3) + @Test def neg_overrides = compileFile(negDir, "overrides", xerrors = 11) @Test def neg_projections = compileFile(negDir, "projections", xerrors = 1) @Test def neg_i39 = compileFile(negDir, "i39", xerrors = 1) @Test def neg_i50_volatile = compileFile(negDir, "i50-volatile", xerrors = 4) diff --git a/tests/pending/pos/t3498-old.scala b/tests/disabled/not-representable/pos/t3498-old.scala similarity index 100% rename from tests/pending/pos/t3498-old.scala rename to tests/disabled/not-representable/pos/t3498-old.scala diff --git a/tests/pending/pos/t3175-pos.scala b/tests/disabled/structural-type/pos/t3175-pos.scala similarity index 100% rename from tests/pending/pos/t3175-pos.scala rename to tests/disabled/structural-type/pos/t3175-pos.scala diff --git a/tests/pending/pos/t3363-new.scala b/tests/disabled/structural-type/pos/t3363-new.scala similarity index 86% rename from tests/pending/pos/t3363-new.scala rename to tests/disabled/structural-type/pos/t3363-new.scala index f935cfe1a363..835d9471b922 100644 --- a/tests/pending/pos/t3363-new.scala +++ b/tests/disabled/structural-type/pos/t3363-new.scala @@ -7,7 +7,7 @@ object TestCase { //if fs was reduced to List (generic type with one parameter) then the code compiles //if you inherit from MapOps[T] instead of MapOps[F] then code compiles fine - implicit def map2ops[T,F](fs: Map[T,F]): TestCase.MapOps[F]{lazy val m: reflect.runtime.universe.TypeTag[T]; def is(xs: List[T]): List[List[T]]} = new MapOps[F] { + implicit def map2ops[T,F](fs: Map[T,F]): TestCase.MapOps[F]{val m: reflect.runtime.universe.TypeTag[T]; def is(xs: List[T]): List[List[T]]} = new MapOps[F] { //if you remove this line, then code compiles lazy val m: TypeTag[T] = sys.error("just something to make it compile") def is(xs: List[T]) = List(xs) diff --git a/tests/pending/pos/t3363-old.scala b/tests/disabled/structural-type/pos/t3363-old.scala similarity index 88% rename from tests/pending/pos/t3363-old.scala rename to tests/disabled/structural-type/pos/t3363-old.scala index 8e54d4b4a8c3..0088eff3dc54 100644 --- a/tests/pending/pos/t3363-old.scala +++ b/tests/disabled/structural-type/pos/t3363-old.scala @@ -5,7 +5,7 @@ object TestCase { //if fs was reduced to List (generic type with one parameter) then the code compiles //if you inherit from MapOps[T] instead of MapOps[F] then code compiles fine - implicit def map2ops[T,F](fs: Map[T,F]): TestCase.MapOps[F]{lazy val m: Manifest[T]; def is(xs: List[T]): List[List[T]]} = new MapOps[F] { + implicit def map2ops[T,F](fs: Map[T,F]): TestCase.MapOps[F]{val m: Manifest[T]; def is(xs: List[T]): List[List[T]]} = new MapOps[F] { //if you remove this line, then code compiles lazy val m: Manifest[T] = sys.error("just something to make it compile") def is(xs: List[T]) = List(xs) diff --git a/tests/neg/over.scala b/tests/neg/over.scala index 488d71614c3c..80ce7d09f4c3 100644 --- a/tests/neg/over.scala +++ b/tests/neg/over.scala @@ -8,3 +8,11 @@ class C extends T { override val y = 2 } + +class D extends T { + + def x(): String = "" + +} + + diff --git a/tests/neg/overrides.scala b/tests/neg/overrides.scala index 943cc8bc4fda..9fe06d93020c 100644 --- a/tests/neg/overrides.scala +++ b/tests/neg/overrides.scala @@ -79,3 +79,45 @@ class Y2 extends X2 { class X3 { override type T = A1 } + +package p3 { + +// Dotty change of rules: Toverrider#f does not +// override TCommon#f, hence the accidental override rule +// applies. +trait TCommon { + def f: String +} + +class C1 extends TCommon { + def f = "in C1" +} + +trait TOverrider { this: TCommon => + override def f = "in TOverrider" // The overridden self-type member... +} + +class C2 extends C1 with TOverrider // ... fails to override, here. + +} + +package p4 { + + abstract class C[T] { def head: T } + case class D[T](head: Int) extends C[T] + +} + +package p5 { +class A { + def m: String = "foo" +} + +class B extends A { + override val m: Int = 42 +} + +class C extends A { + override def m: Int = 42 +} +} diff --git a/tests/pending/pos/self-type-override.scala b/tests/pending/pos/self-type-override.scala deleted file mode 100644 index 7c40ef37e69c..000000000000 --- a/tests/pending/pos/self-type-override.scala +++ /dev/null @@ -1,13 +0,0 @@ -trait TCommon { - def f: String -} - -class C1 extends TCommon { - def f = "in C1" -} - -trait TOverrider { this: TCommon => - override def f = "in TOverrider" // The overridden self-type member... -} - -class C2 extends C1 with TOverrider // ... fails to override, here. diff --git a/tests/pending/pos/t3278.scala b/tests/pending/pos/t3278.scala deleted file mode 100644 index 458070c5e7e7..000000000000 --- a/tests/pending/pos/t3278.scala +++ /dev/null @@ -1,15 +0,0 @@ -class Foo -class Test { - def update[B](x : B, b : Int): Unit = {} - def apply[B](x : B) = 1 -} - -object Test { - def main(a : Array[String]): Unit = { - val a = new Test - val f = new Foo - a(f) = 1 //works - a(f) = a(f) + 1 //works - a(f) += 1 //error: reassignment to val - } -} diff --git a/tests/pending/pos/t3480.scala b/tests/pending/pos/t3480.scala index d9a092e8a66a..f04ea2933370 100644 --- a/tests/pending/pos/t3480.scala +++ b/tests/pending/pos/t3480.scala @@ -1,4 +1,4 @@ object Test { - val List(_*) = List(1) + val List(_: _*) = List(1) val Array( who, what : _* ) = "Eclipse plugin cannot not handle this" split (" ") } diff --git a/tests/pos/java-override/A.java b/tests/pos/java-override/A.java new file mode 100644 index 000000000000..0d7f453e8554 --- /dev/null +++ b/tests/pos/java-override/A.java @@ -0,0 +1,3 @@ +public interface A { + void o(Object o); +} diff --git a/tests/pos/java-override/B.scala b/tests/pos/java-override/B.scala new file mode 100644 index 000000000000..cb4addbcce81 --- /dev/null +++ b/tests/pos/java-override/B.scala @@ -0,0 +1,7 @@ +//trait T { def t(o: Object): Unit } + +class B extends A /*with T*/ { + override def o(o: Any): Unit = () + + //override def t(o: AnyRef): Unit = () +} diff --git a/tests/pending/pos/sammy_poly.scala b/tests/pos/sammy_poly.scala similarity index 100% rename from tests/pending/pos/sammy_poly.scala rename to tests/pos/sammy_poly.scala diff --git a/tests/pending/pos/scoping1.scala b/tests/pos/scoping1.scala similarity index 84% rename from tests/pending/pos/scoping1.scala rename to tests/pos/scoping1.scala index 9fe1b5f3e5b7..83ad1357ae86 100644 --- a/tests/pending/pos/scoping1.scala +++ b/tests/pos/scoping1.scala @@ -2,7 +2,7 @@ object This extends App { trait A { def foo(): Unit } - class C { self: A => + abstract class C { self: A => def bar() = this.foo() } class D extends C with A { diff --git a/tests/pending/pos/sealed-final.scala b/tests/pos/sealed-final.scala similarity index 100% rename from tests/pending/pos/sealed-final.scala rename to tests/pos/sealed-final.scala diff --git a/tests/pending/pos/spec-sealed.scala b/tests/pos/spec-sealed.scala similarity index 100% rename from tests/pending/pos/spec-sealed.scala rename to tests/pos/spec-sealed.scala diff --git a/tests/pos/subtyping.scala b/tests/pos/subtyping.scala index 29d830dd2c8b..e65bdd16f027 100644 --- a/tests/pos/subtyping.scala +++ b/tests/pos/subtyping.scala @@ -1,32 +1,5 @@ -class A { - def test1(): Unit = { - implicitly[this.type <:< this.type] - implicitly[this.type <:< A] - } -} object test { - def tag1[T](x: T): String & T = ??? - def tag2[T](x: T): T & String = ??? - - val x1: Int & String = tag1(0) - val x2: Int & String = tag2(0) - val x3: String & Int = tag1(0) - val x4: String & Int = tag2(0) - -} - -object test2 { - - class A - class B - - val x: A | B = ??? - val y: B | A = x - - val a: A & B = ??? - val b: B & A = a + val x: Int = 1 } - - diff --git a/tests/pending/pos/t319.scala b/tests/pos/t319.scala similarity index 67% rename from tests/pending/pos/t319.scala rename to tests/pos/t319.scala index eed25eb84ce6..5c06f4db06ec 100644 --- a/tests/pending/pos/t319.scala +++ b/tests/pos/t319.scala @@ -14,7 +14,8 @@ object test { val a = new A { type T = String }; /** val b: B { type T = String } = functor(a) */ val b: B { type T = String } = { - val tmp = new functor() { val arg = a }; + val tmp = new functor() { val arg: A { type T = String } = a }; + // Dotty deviaton: arg needs an explicit type here, or else the inherited type `A` would be assumed. tmp.res } diff --git a/tests/pending/pos/t3252.scala b/tests/pos/t3252.scala similarity index 100% rename from tests/pending/pos/t3252.scala rename to tests/pos/t3252.scala diff --git a/tests/pos/t3278.scala b/tests/pos/t3278.scala new file mode 100644 index 000000000000..05bfbc1463a5 --- /dev/null +++ b/tests/pos/t3278.scala @@ -0,0 +1,30 @@ +class Foo +class Test { + def update[B](x : B, b : Int): Unit = {} + def apply[B](x : B) = 1 +} +class Test2 { + type B = Foo + def update(x : B, b : Int): Unit = {} + def apply(x : B) = 1 +} + +object Test { + def main(a : Array[String]): Unit = { + val a = new Test + val f = new Foo + a(f) = 1 //works + a(f) = a(f) + 1 //works + a(f) += 1 //error: reassignment to val + } +} +object Test2 { + def main(args : Array[String]): Unit = { + args(0) += "a" + val a = new Test2 + val f = new Foo + a(f) = 1 //works + a(f) = a(f) + 1 //works + a(f) += 1 //error: reassignment to val + } +} diff --git a/tests/pending/pos/t3343.scala b/tests/pos/t3343.scala similarity index 100% rename from tests/pending/pos/t3343.scala rename to tests/pos/t3343.scala diff --git a/tests/pending/pos/t3411.scala b/tests/pos/t3411.scala similarity index 100% rename from tests/pending/pos/t3411.scala rename to tests/pos/t3411.scala diff --git a/tests/pending/pos/t344.scala b/tests/pos/t344.scala similarity index 100% rename from tests/pending/pos/t344.scala rename to tests/pos/t344.scala