aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Decorators.scala32
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala11
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala5
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala10
-rw-r--r--src/dotty/tools/dotc/core/Types.scala37
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 {