Skip to content

Fix #9369: Use new extension syntax #9373

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 50 additions & 46 deletions compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,58 +116,62 @@ object DottyBackendInterface {
ctx.requiredModule(className)
}

extension symExtensions on (sym: Symbol) {

def isInterface(using Context): Boolean = (sym.is(PureInterface)) || sym.is(Trait)

def isStaticConstructor(using Context): Boolean = (sym.isStaticMember && sym.isClassConstructor) || (sym.name eq nme.STATIC_CONSTRUCTOR)

def isStaticMember(using Context): Boolean = (sym ne NoSymbol) &&
(sym.is(JavaStatic) || sym.isScalaStatic)
// guard against no sumbol cause this code is executed to select which call type(static\dynamic) to use to call array.clone

/**
* True for module classes of modules that are top-level or owned only by objects. Module classes
* for such objects will get a MODULE$ flag and a corresponding static initializer.
*/
def isStaticModuleClass(using Context): Boolean =
(sym.is(Module)) && {
// scalac uses atPickling here
// this would not work if modules are created after pickling
// for example by specialization
val original = toDenot(sym).initial
val validity = original.validFor
atPhase(validity.phaseId) {
toDenot(sym).isStatic
given symExtensions as AnyRef:
extension (sym: Symbol):

def isInterface(using Context): Boolean = (sym.is(PureInterface)) || sym.is(Trait)

def isStaticConstructor(using Context): Boolean = (sym.isStaticMember && sym.isClassConstructor) || (sym.name eq nme.STATIC_CONSTRUCTOR)

def isStaticMember(using Context): Boolean = (sym ne NoSymbol) &&
(sym.is(JavaStatic) || sym.isScalaStatic)
// guard against no sumbol cause this code is executed to select which call type(static\dynamic) to use to call array.clone

/**
* True for module classes of modules that are top-level or owned only by objects. Module classes
* for such objects will get a MODULE$ flag and a corresponding static initializer.
*/
def isStaticModuleClass(using Context): Boolean =
(sym.is(Module)) && {
// scalac uses atPickling here
// this would not work if modules are created after pickling
// for example by specialization
val original = toDenot(sym).initial
val validity = original.validFor
atPhase(validity.phaseId) {
toDenot(sym).isStatic
}
}
}



def originalLexicallyEnclosingClass(using Context): Symbol =
// used to populate the EnclosingMethod attribute.
// it is very tricky in presence of classes(and annonymous classes) defined inside supper calls.
if (sym.exists) {
val validity = toDenot(sym).initial.validFor
atPhase(validity.phaseId) {
toDenot(sym).lexicallyEnclosingClass
def originalLexicallyEnclosingClass(using Context): Symbol =
// used to populate the EnclosingMethod attribute.
// it is very tricky in presence of classes(and annonymous classes) defined inside supper calls.
if (sym.exists) {
val validity = toDenot(sym).initial.validFor
atPhase(validity.phaseId) {
toDenot(sym).lexicallyEnclosingClass
}
} else NoSymbol

/**
* True for module classes of package level objects. The backend will generate a mirror class for
* such objects.
*/
def isTopLevelModuleClass(using Context): Boolean =
sym.is(ModuleClass) &&
atPhase(flattenPhase) {
toDenot(sym).owner.is(PackageClass)
}
} else NoSymbol

/**
* True for module classes of package level objects. The backend will generate a mirror class for
* such objects.
*/
def isTopLevelModuleClass(using Context): Boolean =
sym.is(ModuleClass) &&
atPhase(flattenPhase) {
toDenot(sym).owner.is(PackageClass)
}

def javaSimpleName(using Context): String = toDenot(sym).name.mangledString
def javaClassName(using Context): String = toDenot(sym).fullName.mangledString
def javaBinaryName(using Context): String = javaClassName.replace('.', '/')
}
def javaSimpleName(using Context): String = toDenot(sym).name.mangledString
def javaClassName(using Context): String = toDenot(sym).fullName.mangledString
def javaBinaryName(using Context): String = javaClassName.replace('.', '/')

end extension

end symExtensions

private val primitiveCompilationUnits = Set(
"Unit.scala",
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Comments.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ object Comments {
val ContextDoc: Key[ContextDocstrings] = new Key[ContextDocstrings]

/** Decorator for getting docbase out of context */
extension CommentsContext on (c: Context):
def docCtx: Option[ContextDocstrings] = c.property(ContextDoc)
given CommentsContext as AnyRef:
extension (c: Context) def docCtx: Option[ContextDocstrings] = c.property(ContextDoc)

/** Context for Docstrings, contains basic functionality for getting
* docstrings via `Symbol` and expanding templates
Expand Down
16 changes: 9 additions & 7 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -603,15 +603,17 @@ object Contexts {
def setDebug: this.type = setSetting(base.settings.Ydebug, true)
}

extension ops on (c: Context):
def addNotNullInfo(info: NotNullInfo) =
c.withNotNullInfos(c.notNullInfos.extendWith(info))
given ops as AnyRef:
extension (c: Context):
def addNotNullInfo(info: NotNullInfo) =
c.withNotNullInfos(c.notNullInfos.extendWith(info))

def addNotNullRefs(refs: Set[TermRef]) =
c.addNotNullInfo(NotNullInfo(refs, Set()))
def addNotNullRefs(refs: Set[TermRef]) =
c.addNotNullInfo(NotNullInfo(refs, Set()))

def withNotNullInfos(infos: List[NotNullInfo]): Context =
if c.notNullInfos eq infos then c else c.fresh.setNotNullInfos(infos)
def withNotNullInfos(infos: List[NotNullInfo]): Context =
if c.notNullInfos eq infos then c else c.fresh.setNotNullInfos(infos)
end ops

// TODO: Fix issue when converting ModeChanges and FreshModeChanges to extension givens
implicit class ModeChanges(val c: Context) extends AnyVal {
Expand Down
16 changes: 9 additions & 7 deletions compiler/src/dotty/tools/dotc/core/Decorators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,15 @@ object Decorators {
def & (ys: List[T]): List[T] = xs filter (ys contains _)
}

extension ListOfListDecorator on [T, U](xss: List[List[T]]):
def nestedMap(f: T => U): List[List[U]] =
xss.map(_.map(f))
def nestedMapConserve(f: T => U): List[List[U]] =
xss.mapconserve(_.mapconserve(f))
def nestedZipWithConserve(yss: List[List[U]])(f: (T, U) => T): List[List[T]] =
xss.zipWithConserve(yss)((xs, ys) => xs.zipWithConserve(ys)(f))
given ListOfListDecorator as AnyRef:
extension [T, U](xss: List[List[T]]):
def nestedMap(f: T => U): List[List[U]] =
xss.map(_.map(f))
def nestedMapConserve(f: T => U): List[List[U]] =
xss.mapconserve(_.mapconserve(f))
def nestedZipWithConserve(yss: List[List[U]])(f: (T, U) => T): List[List[T]] =
xss.zipWithConserve(yss)((xs, ys) => xs.zipWithConserve(ys)(f))
end extension

implicit class TextToString(val text: Text) extends AnyVal {
def show(using Context): String = text.mkString(ctx.settings.pageWidth.value, ctx.settings.printLines.value)
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ object Cbufs {
object Cbuf:
def apply(): Cbuf = new StringBuilder(TargetCapacity)

extension StringBuilderOps on (buf: Cbuf):
extension (buf: Cbuf):
def clear(): Unit = {
if buf.capacity() > TargetCapacity then
buf.setLength(TargetCapacity)
Expand All @@ -48,6 +48,7 @@ object Cbufs {
def isEmpty: Boolean = buf.length() == 0
def length: Int = buf.length()
def last: Char = buf.charAt(buf.length() - 1)
end extension
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid the given line in other places, using the same solution here?

given ListOfListDecorator as AnyRef:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, the named ones needed to be in a given or they where not found in other classes.

}

import Cbufs._
Expand Down
Loading