diff options
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Decorators.scala | 32 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Flags.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 37 |
5 files changed, 82 insertions, 13 deletions
diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index 094aa7b4a..476b97ec2 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -4,6 +4,8 @@ package core import annotation.tailrec import Symbols._ import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer +import util.Positions.Position, util.SourcePosition +import collection.mutable.ListBuffer /** This object provides useful implicit decorators for types defined elsewhere */ object Decorators { @@ -35,6 +37,33 @@ object Decorators { */ implicit class ListDecorator[T](val xs: List[T]) extends AnyVal { + @inline final def mapconserve[U](f: T => U): List[U] = { + @tailrec + def loop(mapped: ListBuffer[U], unchanged: List[U], pending: List[T]): List[U] = + if (pending.isEmpty) { + if (mapped eq null) unchanged + else mapped.prependToList(unchanged) + } else { + val head0 = pending.head + val head1 = f(head0) + + if (head1.asInstanceOf[AnyRef] eq head0.asInstanceOf[AnyRef]) + loop(mapped, unchanged, pending.tail) + else { + val b = if (mapped eq null) new ListBuffer[U] else mapped + var xc = unchanged + while (xc ne pending) { + b += xc.head + xc = xc.tail + } + b += head1 + val tail0 = pending.tail + loop(b, tail0.asInstanceOf[List[U]], tail0) + } + } + loop(null, xs.asInstanceOf[List[U]], xs) + } + /** Like `xs filter p` but returns list `xs` itself - instead of a copy - * if `p` is true for all elements and `xs` is not longer * than `MaxFilterRecursions`. @@ -86,5 +115,8 @@ object Decorators { def containsPhase(phase: Phase) = names exists (phase.name.startsWith) } + + implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition = + ctx.source.atPos(pos) } diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 97b25be00..9c89a28cf 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -197,6 +197,17 @@ object Denotations { def requiredMethod(name: PreName)(implicit ctx: Context): TermSymbol = info.member(name.toTermName).requiredSymbol(_ is Method).asTerm + /** The denotation that has a type matching `targetType` when seen + * as a member of type `site`, `NoDenotation` if none exists. + */ + def matchingDenotation(site: Type, targetType: Type)(implicit ctx: Context): SingleDenotation = + if (isOverloaded) + atSignature(targetType.signature).matchingDenotation(site, targetType) + else if (exists && !(site.memberInfo(symbol) matches targetType)) + NoDenotation + else + this.asInstanceOf[SingleDenotation] + /** Form a denotation by conjoining with denotation `that` */ def & (that: Denotation)(implicit ctx: Context): Denotation = if (this eq that) this diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index f22c2a0f2..1b918cfcd 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -63,6 +63,8 @@ object Flags { */ def is(flags: FlagConjunction, butNot: FlagSet): Boolean = is(flags) && !is(butNot) + def isEmpty = (bits & ~KINDFLAGS) == 0 + /** Is this flag set a subset of that one? */ def <= (that: FlagSet) = (bits & that.bits) == bits @@ -434,6 +436,9 @@ object Flags { /** Labeled private[this] */ final val PrivateLocal = allOf(Private, Local) + /** A private parameter accessor */ + final val PrivateLocalParamAccessor = allOf(Private, Local, ParamAccessor) + /** A local parameter */ final val ParamAndLocal = allOf(Param, Local) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 56b168102..e1550d529 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -533,17 +533,11 @@ object SymDenotations { * inClass <-- find denot.symbol class C { <-- symbol is here * * site: Subtype of both inClass and C - * */ final def matchingSymbol(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = { var denot = inClass.info.nonPrivateDecl(name) - if (denot.isTerm) { // types of the same name always match - val targetType = site.memberInfo(symbol) - if (denot.isOverloaded) - denot = denot.atSignature(targetType.signature) // seems we need two kinds of signatures here - if (!(site.memberInfo(denot.symbol) matches targetType)) - denot = NoDenotation - } + if (denot.isTerm) // types of the same name always match + denot = denot.matchingDenotation(site, site.memberInfo(symbol)) denot.symbol } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index c0e338ef1..c78b876b4 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -411,6 +411,22 @@ object Types { ctx.typeComparer.matchesType( this, that, alwaysMatchSimple = !ctx.phase.erasedTypes) + /** The non-private symbol with given name in the given class that matches this type. + * @param inClass The class containing the symbol's definition + * @param name The name of the symbol we are looking for + * @param site The base type from which member types are computed + */ + def matchingTermSymbol(inClass: Symbol, name: Name, site: Type)(implicit ctx: Context): Symbol = { + var denot = inClass.info.nonPrivateDecl(name) + if (denot.isTerm) { // types of the same name always match + if (denot.isOverloaded) + denot = denot.atSignature(this.signature) // seems we need two kinds of signatures here + if (!(site.memberInfo(denot.symbol) matches this)) + denot = NoDenotation + } + denot.symbol + } + /** The basetype of this type with given class symbol */ final def baseType(base: Symbol)(implicit ctx: Context): Type = base.denot match { case classd: ClassDenotation => classd.baseTypeOf(this) @@ -505,6 +521,15 @@ object Types { /** The resultType of a PolyType, MethodType, or ExprType, the type itself for others */ def resultType: Type = this + /** 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 { + 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 { case tp: TypeBounds => tp @@ -1369,13 +1394,15 @@ object Types { } object PolyType { - def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context) = { - def transform(pt: PolyType, tp: Type) = - tp.subst(tparams, (0 until tparams.length).toList map (PolyParam(pt, _))) - apply(tparams map (_.name.asTypeName))( + def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context) = + if (tparams.isEmpty) resultType + else { + def transform(pt: PolyType, tp: Type) = + tp.subst(tparams, (0 until tparams.length).toList map (PolyParam(pt, _))) + apply(tparams map (_.name.asTypeName))( pt => tparams map (tparam => transform(pt, tparam.info).bounds), pt => transform(pt, resultType)) - } + } } abstract class BoundType extends UncachedProxyType with ValueType { |