diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala index 1d559c9950f1..3e6d942f39a2 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala @@ -521,20 +521,20 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { /* * must-single-thread */ - def fieldLoad( field: Symbol, hostClass: Symbol = null): Unit = fieldOp(field, isLoad = true, hostClass) + def fieldLoad( field: Symbol, hostClass: Symbol | Null = null): Unit = fieldOp(field, isLoad = true, hostClass) /* * must-single-thread */ - def fieldStore(field: Symbol, hostClass: Symbol = null): Unit = fieldOp(field, isLoad = false, hostClass) + def fieldStore(field: Symbol, hostClass: Symbol | Null = null): Unit = fieldOp(field, isLoad = false, hostClass) /* * must-single-thread */ - private def fieldOp(field: Symbol, isLoad: Boolean, specificReceiver: Symbol): Unit = { + private def fieldOp(field: Symbol, isLoad: Boolean, specificReceiver: Symbol | Null): Unit = { val useSpecificReceiver = specificReceiver != null && !field.isScalaStatic - val owner = internalName(if (useSpecificReceiver) specificReceiver else field.owner) + val owner = internalName(if (useSpecificReceiver) specificReceiver.nn else field.owner) val fieldJName = field.javaSimpleName val fieldDescr = symInfoTK(field).descriptor val isStatic = field.isStaticMember @@ -629,7 +629,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { if (earlyReturnVar == null) { earlyReturnVar = locals.makeLocal(returnType, "earlyReturnVar", expr.tpe, expr.span) } - locals.store(earlyReturnVar) + locals.store(earlyReturnVar.nn) } bc goTo nextCleanup shouldEmitCleanup = true @@ -853,7 +853,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { bc.invokevirtual(target, sym.javaSimpleName, methodBType.descriptor) generatedType = methodBType.returnType } else { - val receiverClass = if (!invokeStyle.isVirtual) null else { + val receiverClass: Symbol | Null = if (!invokeStyle.isVirtual) null else { // receiverClass is used in the bytecode to as the method receiver. using sym.owner // may lead to IllegalAccessErrors, see 9954eaf / aladdin bug 455. val qualSym = qual.tpe.typeSymbol @@ -1213,10 +1213,11 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { def genLoadModule(tree: Tree): BType = { val module = ( if (!tree.symbol.is(PackageClass)) tree.symbol - else tree.symbol.info.member(nme.PACKAGE).symbol match { - case NoSymbol => abort(s"SI-5604: Cannot use package as value: $tree") - case s => abort(s"SI-5604: found package class where package object expected: $tree") - } + else + val s = tree.symbol.info.member(nme.PACKAGE).symbol + if s.exists + then abort(s"SI-5604: found package class where package object expected: $tree") + else abort(s"SI-5604: Cannot use package as value: $tree") ) lineNumber(tree) genLoadModule(module) @@ -1388,16 +1389,16 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { * invocation instruction, otherwise `method.owner`. A specific receiver class is needed to * prevent an IllegalAccessError, (aladdin bug 455). */ - def genCallMethod(method: Symbol, style: InvokeStyle, pos: Span = NoSpan, specificReceiver: Symbol = null): BType = { + def genCallMethod(method: Symbol, style: InvokeStyle, pos: Span = NoSpan, specificReceiver: Symbol | Null = null): BType = { val methodOwner = method.owner // the class used in the invocation's method descriptor in the classfile - val receiverClass = { + val receiverClass: Symbol = { if (specificReceiver != null) assert(style.isVirtual || specificReceiver == methodOwner, s"specificReceiver can only be specified for virtual calls. $method - $specificReceiver") - val useSpecificReceiver = specificReceiver != null && !defn.isBottomClass(specificReceiver) && !method.isScalaStatic - val receiver = if (useSpecificReceiver) specificReceiver else methodOwner + val useSpecificReceiver = specificReceiver != null && !defn.isBottomClass(specificReceiver.nn) && !method.isScalaStatic + val receiver = if (useSpecificReceiver) specificReceiver.nn else methodOwner // workaround for a JVM bug: https://bugs.openjdk.java.net/browse/JDK-8154587 // when an interface method overrides a member of Object (note that all interfaces implicitly @@ -1431,7 +1432,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { val bmType = asmMethodType(method) val mdescr = bmType.descriptor - val isInterface = isEmittedInterface(receiverClass) + val isInterface = isEmittedInterface(receiverClass.nn) import InvokeStyle._ if (style == Super) { if (isInterface && !method.is(JavaDefined)) { diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala index 1885210a6687..3ace8df6ea42 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala @@ -87,7 +87,7 @@ trait BCodeSkelBuilder extends BCodeHelpers { var cnode: ClassNode1 = null var thisName: String = null // the internal name of the class being emitted - var claszSymbol: Symbol = null + var claszSymbol: Symbol = _ var isCZParcelable = false var isCZStaticModule = false @@ -364,9 +364,9 @@ trait BCodeSkelBuilder extends BCodeHelpers { var jMethodName: String = null var isMethSymStaticCtor = false var returnType: BType = null - var methSymbol: Symbol = null + var methSymbol: Symbol = _ // used by genLoadTry() and genSynchronized() - var earlyReturnVar: Symbol = null + var earlyReturnVar: Symbol | Null = null var shouldEmitCleanup = false // stack tracking var stackHeight = 0 diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala b/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala index b5ed27511e7e..d54d6f4572f4 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala @@ -36,7 +36,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder { // if the synchronized block returns a result, store it in a local variable. // Just leaving it on the stack is not valid in MSIL (stack is cleaned when leaving try-blocks). val hasResult = (expectedType != UNIT) - val monitorResult: Symbol = if (hasResult) locals.makeLocal(tpeTK(args.head), "monitorResult", defn.ObjectType, tree.span) else null + val monitorResult: Symbol | Null = if (hasResult) locals.makeLocal(tpeTK(args.head), "monitorResult", defn.ObjectType, tree.span) else null /* ------ (1) pushing and entering the monitor, also keeping a reference to it in a local var. ------ */ genLoadQualifier(fun) @@ -55,7 +55,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder { registerCleanup(monCleanup) genLoad(args.head, expectedType /* toTypeKind(tree.tpe.resultType) */) unregisterCleanup(monCleanup) - if (hasResult) { locals.store(monitorResult) } + if (hasResult) { locals.store(monitorResult.nn) } nopIfNeeded(startProtected) val endProtected = currProgramPoint() @@ -66,7 +66,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder { */ locals.load(monitor) emit(asm.Opcodes.MONITOREXIT) - if (hasResult) { locals.load(monitorResult) } + if (hasResult) { locals.load(monitorResult.uncheckedNN) } val postHandler = new asm.Label bc goTo postHandler @@ -214,7 +214,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder { * please notice `tmp` has type tree.tpe, while `earlyReturnVar` has the method return type. * Because those two types can be different, dedicated vars are needed. */ - val tmp = if (guardResult) locals.makeLocal(tpeTK(tree), "tmp", tree.tpe, tree.span) else null + val tmp: Symbol | Null = if (guardResult) locals.makeLocal(tpeTK(tree), "tmp", tree.tpe, tree.span) else null /* * upon early return from the try-body or one of its EHs (but not the EH-version of the finally-clause) @@ -375,8 +375,8 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder { cleanups match { case Nil => if (earlyReturnVar != null) { - locals.load(earlyReturnVar) - bc.emitRETURN(locals(earlyReturnVar).tk) + locals.load(earlyReturnVar.uncheckedNN) + bc.emitRETURN(locals(earlyReturnVar.uncheckedNN).tk) } else { bc emitRETURN UNIT } @@ -396,15 +396,15 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder { } /* `tmp` (if non-null) is the symbol of the local-var used to preserve the result of the try-body, see `guardResult` */ - def emitFinalizer(finalizer: Tree, tmp: Symbol, isDuplicate: Boolean): Unit = { + def emitFinalizer(finalizer: Tree, tmp: Symbol | Null, isDuplicate: Boolean): Unit = { var saved: immutable.Map[ /* Labeled */ Symbol, (BType, LoadDestination) ] = null if (isDuplicate) { saved = jumpDest } // when duplicating, the above guarantees new asm.Labels are used for LabelDefs contained in the finalizer (their vars are reused, that's ok) - if (tmp != null) { locals.store(tmp) } + if (tmp != null) { locals.store(tmp.uncheckedNN) } genLoad(finalizer, UNIT) - if (tmp != null) { locals.load(tmp) } + if (tmp != null) { locals.load(tmp.uncheckedNN) } if (isDuplicate) { jumpDest = saved } diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 4caf1f6b5fa2..96b63392c1a2 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -72,8 +72,8 @@ class JSCodeGen()(using genCtx: Context) { private val generatedClasses = mutable.ListBuffer.empty[js.ClassDef] private val generatedStaticForwarderClasses = mutable.ListBuffer.empty[(Symbol, js.ClassDef)] - val currentClassSym = new ScopedVar[Symbol] - private val currentMethodSym = new ScopedVar[Symbol] + val currentClassSym = new ScopedVar[Symbol | Null] + private val currentMethodSym = new ScopedVar[Symbol | Null] private val localNames = new ScopedVar[LocalNameGenerator] private val thisLocalVarIdent = new ScopedVar[Option[js.LocalIdent]] private val isModuleInitialized = new ScopedVar[ScopedVar.VarBox[Boolean]] @@ -126,7 +126,7 @@ class JSCodeGen()(using genCtx: Context) { implicit def implicitLocalNames: LocalNameGenerator = localNames.get def currentThisType: jstpe.Type = { - encodeClassType(currentClassSym) match { + encodeClassType(currentClassSym.get.nn) match { case tpe @ jstpe.ClassType(cls) => jstpe.BoxedClassToPrimType.getOrElse(cls, tpe) case tpe => @@ -856,7 +856,7 @@ class JSCodeGen()(using genCtx: Context) { /** Gen definitions for the fields of a class. */ private def genClassFields(td: TypeDef): List[js.MemberDef] = { val classSym = td.symbol.asClass - assert(currentClassSym.get == classSym, + assert(currentClassSym.get eq classSym, "genClassFields called with a ClassDef other than the current one") val isJSClass = classSym.isNonNativeJSClass @@ -1493,7 +1493,7 @@ class JSCodeGen()(using genCtx: Context) { if (primitives.isPrimitive(sym)) { None - } else if (sym.is(Deferred) && currentClassSym.isNonNativeJSClass) { + } else if (sym.is(Deferred) && currentClassSym.get.nn.isNonNativeJSClass) { // scala-js/#4409: Do not emit abstract methods in non-native JS classes None } else if (sym.is(Deferred)) { @@ -1503,7 +1503,7 @@ class JSCodeGen()(using genCtx: Context) { } else if (isIgnorableDefaultParam) { // #11592 None - } else if (sym.is(Bridge) && sym.name.is(DefaultGetterName) && currentClassSym.isNonNativeJSClass) { + } else if (sym.is(Bridge) && sym.name.is(DefaultGetterName) && currentClassSym.get.nn.isNonNativeJSClass) { /* #12572 Bridges for default accessors in non-native JS classes must not be emitted, * because they call another default accessor, making their entire body an * that cannot be eliminated. @@ -1582,7 +1582,7 @@ class JSCodeGen()(using genCtx: Context) { else genExpr(tree) } - if (namespace.isStatic || !currentClassSym.isNonNativeJSClass) { + if (namespace.isStatic || !currentClassSym.get.nn.isNonNativeJSClass) { val flags = js.MemberFlags.empty.withNamespace(namespace) js.MethodDef(flags, methodName, originalName, jsParams, resultIRType, Some(genBody()))( optimizerHints, None) @@ -1688,7 +1688,7 @@ class JSCodeGen()(using genCtx: Context) { tree match { case _: This => val sym = tree.symbol - if (sym != currentClassSym.get && sym.is(Module)) + if ((sym ne currentClassSym.get) && sym.is(Module)) genLoadModuleOrGlobalScope(sym) else MaybeGlobalScope.NotGlobalScope(genExpr(tree)) @@ -1784,7 +1784,7 @@ class JSCodeGen()(using genCtx: Context) { genApplyDynamic(app)*/ case tree: This => - val currentClass = currentClassSym.get + val currentClass = currentClassSym.get.nn val symIsModuleClass = tree.symbol.is(ModuleClass) assert(tree.symbol == currentClass || symIsModuleClass, s"Trying to access the this of another class: tree.symbol = ${tree.symbol}, class symbol = $currentClass") @@ -1886,8 +1886,8 @@ class JSCodeGen()(using genCtx: Context) { val qualifier = lhs.qualifier def ctorAssignment = ( - currentMethodSym.get.name == nme.CONSTRUCTOR && - currentMethodSym.get.owner == qualifier.symbol && + currentMethodSym.get.nn.name == nme.CONSTRUCTOR && + currentMethodSym.get.nn.owner == qualifier.symbol && qualifier.isInstanceOf[This] ) // TODO This fails for OFFSET$x fields. Re-enable when we can. @@ -2178,7 +2178,7 @@ class JSCodeGen()(using genCtx: Context) { if (sym == defn.Any_getClass) { // The only primitive that is also callable as super call js.GetClass(genThis()) - } else if (currentClassSym.isNonNativeJSClass) { + } else if (currentClassSym.get.nn.isNonNativeJSClass) { genJSSuperCall(tree, isStat) } else { /* #3013 `qual` can be `this.$outer()` in some cases since Scala 2.12, @@ -2188,10 +2188,10 @@ class JSCodeGen()(using genCtx: Context) { genExpr(qual), sym, genActualArgs(sym, args)) // Initialize the module instance just after the super constructor call. - if (isStaticModule(currentClassSym) && !isModuleInitialized.get.value && - currentMethodSym.get.isClassConstructor) { + if (isStaticModule(currentClassSym.get.nn) && !isModuleInitialized.get.value && + currentMethodSym.get.nn.isClassConstructor) { isModuleInitialized.get.value = true - val className = encodeClassName(currentClassSym) + val className = encodeClassName(currentClassSym.get.nn) val thisType = jstpe.ClassType(className) val initModule = js.StoreModule(className, js.This()(thisType)) js.Block(superCall, initModule) @@ -3245,7 +3245,7 @@ class JSCodeGen()(using genCtx: Context) { genApplyJSClassMethod(genReceiver, sym, genScalaArgs) } else { val jsSuperClassValue = explicitJSSuperClassValue.orElse { - Some(genLoadJSConstructor(currentClassSym.get.asClass.superClass)) + Some(genLoadJSConstructor(currentClassSym.get.nn.asClass.superClass)) } genApplyJSMethodGeneric(sym, MaybeGlobalScope.NotGlobalScope(genReceiver), genJSArgs, isStat, jsSuperClassValue)(tree.sourcePos) @@ -3873,7 +3873,7 @@ class JSCodeGen()(using genCtx: Context) { case JS_NEW_TARGET => // js.new.target - val valid = currentMethodSym.get.isClassConstructor && currentClassSym.isNonNativeJSClass + val valid = currentMethodSym.get.nn.isClassConstructor && currentClassSym.get.nn.isNonNativeJSClass if (!valid) { report.error( "Illegal use of js.`new`.target.\n" + diff --git a/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala b/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala index 78412999bb34..4182b5770d02 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala @@ -585,7 +585,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) { } private def reportCannotDisambiguateError(jsName: JSName, alts: List[Symbol]): Unit = { - val currentClass = currentClassSym.get + val currentClass = currentClassSym.get.nn /* Find a position that is in the current class for decent error reporting. * If there are more than one, always use the "highest" one (i.e., the @@ -623,7 +623,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) { */ private def genApplyForSingleExported(formalArgsRegistry: FormalArgsRegistry, exported: Exported, static: Boolean): js.Tree = { - if (currentClassSym.isJSType && exported.sym.owner != currentClassSym.get) { + if (currentClassSym.get.nn.isJSType && exported.sym.owner != currentClassSym.get) { assert(!static, s"nonsensical JS super call in static export of ${exported.sym}") genApplyForSingleExportedJSSuperCall(formalArgsRegistry, exported) } else { @@ -642,7 +642,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) { val allArgs = formalArgsRegistry.genAllArgsRefsForForwarder() val superClass = { - val superClassSym = currentClassSym.asClass.superClass + val superClassSym = currentClassSym.get.nn.asClass.superClass if (superClassSym.isNestedJSClass) js.VarRef(js.LocalIdent(JSSuperClassParamName))(jstpe.AnyType) else @@ -806,7 +806,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) { implicit pos: SourcePosition): js.Tree = { val sym = exported.sym - val currentClass = currentClassSym.get + val currentClass = currentClassSym.get.nn def receiver = if (static) genLoadModule(sym.owner) diff --git a/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala index faeafae97f5e..78ef66a8b0c0 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala @@ -7,6 +7,7 @@ import Types._, Contexts._, Flags._ import Symbols._, Annotations._, Trees._, Symbols._, Constants.Constant import Decorators._ import dotty.tools.dotc.transform.SymUtils._ +import Symbols.TypeTests.given /** A map that applies three functions and a substitution together to a tree and * makes sure they are coordinated so that the result is well-typed. The functions are diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala index e4533aa73ce0..708f7a664252 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala @@ -10,6 +10,7 @@ import config.Printers.capt import util.Property.Key import tpd.* import config.Feature +import Symbols.TypeTests.given private val Captures: Key[CaptureSet] = Key() private val BoxedType: Key[BoxedTypeCache] = Key() diff --git a/compiler/src/dotty/tools/dotc/cc/Setup.scala b/compiler/src/dotty/tools/dotc/cc/Setup.scala index 461c18ea0980..228acc4a40d5 100644 --- a/compiler/src/dotty/tools/dotc/cc/Setup.scala +++ b/compiler/src/dotty/tools/dotc/cc/Setup.scala @@ -12,6 +12,7 @@ import transform.Recheck.* import CaptureSet.IdentityCaptRefMap import Synthetics.isExcluded import util.Property +import Symbols.TypeTests.given /** A tree traverser that prepares a compilation unit to be capture checked. * It does the following: diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index 3b00f2915f1c..4cff4e00e5d1 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -7,6 +7,7 @@ import ast.tpd, tpd.* import util.Spans.Span import printing.{Showable, Printer} import printing.Texts.Text +import Symbols.TypeTests.given import scala.annotation.internal.sharable @@ -194,7 +195,7 @@ object Annotations { object Annotation { def apply(tree: Tree): ConcreteAnnotation = ConcreteAnnotation(tree) - + def apply(cls: ClassSymbol, span: Span)(using Context): Annotation = apply(cls, Nil, span) @@ -206,7 +207,7 @@ object Annotations { def apply(atp: Type, arg: Tree, span: Span)(using Context): Annotation = apply(atp, arg :: Nil, span) - + def apply(atp: Type, args: List[Tree], span: Span)(using Context): Annotation = apply(New(atp, args).withSpan(span)) diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index 1b20b75ad8ac..6a68a87a86b9 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -428,9 +428,8 @@ object Comments { * @param vble The variable for which a definition is searched * @param site The class for which doc comments are generated */ - def lookupVariable(vble: String, site: Symbol)(using Context): Option[String] = site match { - case NoSymbol => None - case _ => + def lookupVariable(vble: String, site: Symbol)(using Context): Option[String] = + if site.exists then val searchList = if (site.flags.is(Flags.Module)) site :: site.info.baseClasses else site.info.baseClasses @@ -439,7 +438,7 @@ object Comments { case Some(str) if str startsWith "$" => lookupVariable(str.tail, site) case res => res orElse lookupVariable(vble, site.owner) } - } + else None /** The position of the raw doc comment of symbol `sym`, or NoPosition if missing * If a symbol does not have a doc comment but some overridden version of it does, diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index aa85f714a8e5..33437b1b80b8 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -5,6 +5,7 @@ import Contexts._, Symbols._, Types._, Flags._ import Denotations._, SymDenotations._ import Names.Name, StdNames.nme import ast.untpd +import Symbols.TypeTests.given /** Extension methods for contexts where we want to keep the ctx. syntax */ object ContextOps: diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 2f28975dd066..5947c7dd5707 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -226,7 +226,8 @@ object Contexts { */ def effectiveScope(using Context): Scope = val myOwner: Symbol | Null = owner - if myOwner != null && myOwner.isClass then myOwner.asClass.unforcedDecls + if myOwner != null && myOwner.uncheckedNN.isClass + then myOwner.uncheckedNN.asClass.unforcedDecls else scope def nestingLevel: Int = effectiveScope.nestingLevel diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 854608143df9..be9edf97b2d7 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1319,7 +1319,7 @@ class Definitions { // Inline symbols contain trees in annotations, which is coupled // with the underlying symbol. // Changing owner for inline symbols is a simple workaround. - patch.denot = patch.denot.copySymDenotation(owner = denot.symbol) + patch.denot_=(patch.denot.copySymDenotation(owner = denot.symbol)) patch else // change `info` which might contain reference to the patch diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 723f9408d805..a3a7207d1d70 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -72,6 +72,9 @@ object Denotations { implicit def eqDenotation: CanEqual[Denotation, Denotation] = CanEqual.derived + trait Named: + type ThisName <: Name + /** A PreDenotation represents a group of single denotations or a single multi-denotation * It is used as an optimization to avoid forming MultiDenotations too eagerly. */ @@ -173,11 +176,16 @@ object Denotations { * * Then the denotation of `y` is `SingleDenotation(NoSymbol, A | B)`. * - * @param symbol The referencing symbol, or NoSymbol is none exists + * @param symbolHint The referencing symbol, or NoSymbol is none exists, + * or null, if the Denotation itself is the symbol. */ - abstract class Denotation(val symbol: Symbol, protected var myInfo: Type, val isType: Boolean) extends PreDenotation with printing.Showable { + abstract class Denotation(symbolHint: Symbol | Null, protected var myInfo: Type, val isType: Boolean) + extends PreDenotation, Named, printing.Showable { type AsSeenFromResult <: Denotation + val symbol: Symbol = + (if symbolHint != null then symbolHint else this).asInstanceOf[Symbol] + /** The type info. * The info is an instance of TypeType iff this is a type denotation * Uncompleted denotations set myInfo to a LazyType. @@ -206,7 +214,7 @@ object Denotations { def hasUniqueSym: Boolean /** The name of the denotation */ - def name(using Context): Name + def name(using Context): ThisName /** The signature of the denotation. */ def signature(using Context): Signature @@ -227,10 +235,9 @@ object Denotations { private var myValidFor: Period = Nowhere final def validFor: Period = myValidFor - final def validFor_=(p: Period): Unit = { + final def validFor_=(p: Period): Unit = myValidFor = p - symbol.invalidateDenotCache() - } + symbol.setCheckedPeriod(Nowhere): @unchecked /** Is this denotation different from NoDenotation or an ErrorDenotation? */ def exists: Boolean = true @@ -574,10 +581,10 @@ object Denotations { end infoMeet /** A non-overloaded denotation */ - abstract class SingleDenotation(symbol: Symbol, initInfo: Type, isType: Boolean) extends Denotation(symbol, initInfo, isType) { + abstract class SingleDenotation(symbolHint: Symbol | Null, initInfo: Type, isType: Boolean) extends Denotation(symbolHint, initInfo, isType) { protected def newLikeThis(symbol: Symbol, info: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation - final def name(using Context): Name = symbol.name + final def name(using Context): ThisName = symbol.name.asInstanceOf[ThisName] /** For SymDenotation, this is NoPrefix. For other denotations this is the prefix * under which the denotation was constructed. @@ -744,7 +751,9 @@ object Denotations { if acceptStale(symd) && symd.initial.validFor.firstPhaseId <= ctx.lastPhaseId then // New run might have fewer phases than old, so symbol might no longer be // visible at all. TabCompleteTests have examples where this happens. - return symd.currentSymbol.denot.orElse(symd).updateValidity() + val newd = symd.currentSymbol.denot.orElse(symd).updateValidity() + if newd ne symd then symd.common.reset() // to avoid memory leaks + return newd case _ => } if (!symbol.exists) return updateValidity() @@ -1242,7 +1251,7 @@ object Denotations { final def infoOrCompleter: Type = multiHasNot("info") final def hasUniqueSym: Boolean = false - final def name(using Context): Name = denot1.name + final def name(using Context): ThisName = denot1.name.asInstanceOf[ThisName] final def signature(using Context): Signature = Signature.OverloadedSignature def atSignature(sig: Signature, targetName: Name, site: Type, relaxed: Boolean)(using Context): Denotation = if (sig eq Signature.OverloadedSignature) this diff --git a/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala b/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala index a863a982a44d..082d634113b4 100644 --- a/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/GadtConstraint.scala @@ -84,9 +84,9 @@ class GadtConstraint private ( } def externalize(tp: Type, theMap: TypeMap | Null = null)(using Context): Type = tp match - case param: TypeParamRef => reverseMapping(param) match - case sym: Symbol => sym.typeRef - case null => param + case param: TypeParamRef => + val sym: Symbol | Null = reverseMapping(param) + if sym != null then sym.uncheckedNN.typeRef else param case tp: TypeAlias => tp.derivedAlias(externalize(tp.alias, theMap)) case tp => (if theMap == null then ExternalizeMap() else theMap).mapOver(tp) diff --git a/compiler/src/dotty/tools/dotc/core/NamerOps.scala b/compiler/src/dotty/tools/dotc/core/NamerOps.scala index db6f72590818..42a0d8b146e3 100644 --- a/compiler/src/dotty/tools/dotc/core/NamerOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NamerOps.scala @@ -5,6 +5,7 @@ package core import Contexts._, Symbols._, Types._, Flags._, Scopes._, Decorators._, Names._, NameOps._ import SymDenotations.{LazyType, SymDenotation}, StdNames.nme import TypeApplications.EtaExpansion +import Symbols.TypeTests.given /** Operations that are shared between Namer and TreeUnpickler */ object NamerOps: diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index 1e08379b57f0..d0641ec98e45 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -20,17 +20,12 @@ object Names { */ type PreName = Name | String - /** A common superclass of Name and Symbol. After bootstrap, this should be - * just the type alias Name | Symbol - */ - abstract class Designator - /** A name is either a term name or a type name. Term names can be simple * or derived. A simple term name is essentially an interned string stored * in a name table. A derived term name adds a tag, and possibly a number * or a further simple name to some other name. */ - abstract class Name extends Designator, Showable derives CanEqual { + abstract class Name extends Showable derives CanEqual { /** A type for names of the same kind as this name */ type ThisName <: Name diff --git a/compiler/src/dotty/tools/dotc/core/Periods.scala b/compiler/src/dotty/tools/dotc/core/Periods.scala index ee877fb538d4..e7aa5ee31c87 100644 --- a/compiler/src/dotty/tools/dotc/core/Periods.scala +++ b/compiler/src/dotty/tools/dotc/core/Periods.scala @@ -63,7 +63,7 @@ object Periods { // // Let's compute: // - // lastDiff = X * 2^5 + (l1 - l2) mod 2^5 + // lastDiff = X * 2^7 + (l1 - l2) mod 2^7 // where X >= 0, X == 0 iff r1 == r2 & l1 - l2 >= 0 // result = lastDiff + d2 <= d1 // We have: @@ -103,6 +103,13 @@ object Periods { def !=(that: Period): Boolean = this.code != that.code } + /** Same as new Period(p1).contains(new Period(p2)), assuming that p2 is the + * code of a single-phase period. + */ + extension (p1: Int) + transparent inline def containsSinglePhasePeriod(p2: Int): Boolean = + ((p1 - p2) >>> PhaseWidth) <= (p1 & PhaseMask) + object Period { /** The single-phase period consisting of given run id and phase id */ diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 9d7a3945a1ca..6c3ed8912114 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -17,7 +17,8 @@ import Trees.Literal import Variances.Variance import annotation.tailrec import util.SimpleIdentityMap -import util.Stats +import util.{SrcPos, SourcePosition, SourceFile, NoSource, Stats} +import util.Spans.* import java.util.WeakHashMap import scala.util.control.NonFatal import config.Config @@ -27,21 +28,59 @@ import transform.TypeUtils._ import cc.{CapturingType, derivedCapturingType, Setup, EventuallyCapturingType, isEventuallyCapturingType} import scala.annotation.internal.sharable +import Symbols.TypeTests.given object SymDenotations { + type TreeOrProvider = tpd.TreeProvider | tpd.Tree + + class SymCommon( + //private[SymDenotations] + var coord: Coord, + //private[SymDenotations] + val id: Int, + //private[SymDenotations] + val nestingLevel: Int): + + //private[SymDenotations] + var defTree: tpd.Tree | Null = null + //private[SymDenotations + def isClass: Boolean = isInstanceOf[ClassCommon] + def asClass: ClassCommon = asInstanceOf[ClassCommon] + + def reset() = + defTree = null + end SymCommon + + class ClassCommon(coord: Coord, id: Int, nestingLevel: Int, + //private[SymDenotations] + val assocFile: AbstractFile | Null = null) + extends SymCommon(coord, id, nestingLevel): + //private[SymDenotations] + var treeOrProvider: TreeOrProvider = tpd.EmptyTree + //private[SymDenotations] + var source: SourceFile = NoSource + + override def reset() = + super.reset() + treeOrProvider = tpd.EmptyTree + source = NoSource + end ClassCommon + /** A sym-denotation represents the contents of a definition * during a period. */ class SymDenotation private[SymDenotations] ( - symbol: Symbol, - final val maybeOwner: Symbol, + symbolHint: Symbol | Null, + final val common: SymCommon, + ownerOrNull: Symbol | Null, final val name: Name, initFlags: FlagSet, initInfo: Type, - initPrivateWithin: Symbol = NoSymbol) extends SingleDenotation(symbol, initInfo, name.isTypeName) { + initPrivateWithin: Symbol = NoSymbol) + extends SingleDenotation(symbolHint, initInfo, name.isTypeName), ParamInfo, SrcPos, Named { - //assert(symbol.id != 4940, name) + //assert(common.id != 9141, name) override def hasUniqueSym: Boolean = exists @@ -52,6 +91,9 @@ object SymDenotations { */ if (Config.checkNoSkolemsInInfo) assertNoSkolems(initInfo) + final def maybeOwner: Symbol = + if ownerOrNull == null then NoSymbol else ownerOrNull.asInstanceOf[Symbol] + // ------ Getting and setting fields ----------------------------- private var myFlags: FlagSet = adaptFlags(initFlags) @@ -60,7 +102,9 @@ object SymDenotations { private var myParamss: List[List[Symbol]] = Nil /** The owner of the symbol; overridden in NoDenotation */ - def owner: Symbol = maybeOwner + final def owner: Symbol = + assert(ownerOrNull != null, "NoDenotation.owner") + ownerOrNull.asInstanceOf[Symbol] /** The flag set */ final def flags(using Context): FlagSet = { ensureCompleted(); myFlags } @@ -73,7 +117,7 @@ object SymDenotations { final def flagsString(using Context): String = flags.flagsString /** Adapt flag set to this denotation's term or type nature */ - private def adaptFlags(flags: FlagSet) = if (isType) flags.toTypeFlags else flags.toTermFlags + private def adaptFlags(flags: FlagSet) = if isType then flags.toTypeFlags else flags.toTermFlags /** Update the flag set */ final def flags_=(flags: FlagSet): Unit = @@ -149,7 +193,7 @@ object SymDenotations { final def completeFrom(completer: LazyType)(using Context): Unit = if completer.needsCompletion(this) then if (Config.showCompletions) { - println(i"${" " * indent}completing ${if (isType) "type" else "val"} $name") + println(i"${" " * indent}completing ${if isType then "type" else "val"} $name") indent += 1 if (myFlags.is(Touched)) throw CyclicReference(this) @@ -1556,7 +1600,7 @@ object SymDenotations { // ----- Sanity checks and debugging */ - def debugString: String = toString + "#" + symbol.id // !!! DEBUG + def debugString: String = toString + "#" + common.id // !!! DEBUG def hasSkolems(tp: Type): Boolean = tp match { case tp: SkolemType => true @@ -1604,7 +1648,7 @@ object SymDenotations { val privateWithin1 = if (privateWithin != null) privateWithin else this.privateWithin val annotations1 = if (annotations != null) annotations else this.annotations val rawParamss1 = if rawParamss != null then rawParamss else this.rawParamss - val d = SymDenotation(symbol, owner, name, initFlags1, info1, privateWithin1) + val d = SymDenotation(symbol, symbol.lastKnownDenotation.common, owner, name, initFlags1, info1, privateWithin1.uncheckedNN) d.annotations = annotations1 d.rawParamss = rawParamss1 d.registeredCompanion = registeredCompanion @@ -1744,21 +1788,98 @@ object SymDenotations { /** Same as `sealedStrictDescendants` but prepends this symbol as well. */ final def sealedDescendants(using Context): List[Symbol] = this.symbol :: sealedStrictDescendants + + /** The source or class file from which this class or + * the class containing this symbol was generated, null if not applicable. + * Note that this the returned classfile might be the top-level class + * containing this symbol instead of the directly enclosing class. + * Overridden in ClassSymbol + */ + def associatedFile(using Context): AbstractFile | Null = + topLevelClass.associatedFile + + inline def associatedFileMatches(inline filter: AbstractFile => Boolean)(using Context): Boolean = + try + val file = associatedFile + file != null && filter(file) + catch case ex: StaleSymbol => + // can happen for constructor proxy companions. Test case is pos-macros/i9484. + false + + // ----- Symbol ops -------------------------------------------- + + /** The last denotation of this symbol */ + var lastDenot: SymDenotation = _ + var checkedPeriod: Period = Nowhere + + /** Overridden in NoSymbol */ + //private[SymDenotations] + def currentSymDenot(using Context): SymDenotation = + current.asInstanceOf[SymDenotation] + + override def hashCode = common.id // for debugging + + /** The current denotation of this symbol */ + def computeDenot(using Context): SymDenotation = + util.Stats.record("Symbol.denot") + val valid = validFor.code + val now = ctx.period + symbol.setCheckedPeriod(now) + // Next condition is inlined from Periods.containsSinglePhasePeriod + if ((valid - now.code) >>> PhaseWidth) <= (valid & PhaseMask) + then this + else recomputeDenot() + + private def recomputeDenot()(using Context): SymDenotation = + util.Stats.record("Symbol.recomputeDenot") + symbol.setLastDenot(currentSymDenot) + + // ---- ParamInfo bindings ------------------------------------- + + type ThisName <: Name + + def isTypeParam(using Context): Boolean = is(TypeParam) + def paramName(using Context): ThisName = name.asInstanceOf[ThisName] + def paramInfo(using Context): Type = info + def paramInfoAsSeenFrom(pre: Type)(using Context): Type = pre.memberInfo(symbol) + def paramInfoOrCompleter(using Context): Type = infoOrCompleter + def paramVariance(using Context): Variance = variance + def paramRef(using Context): TypeRef = typeRef + + // ---- SrcPos bindings ------------------------------------- + + /** The position of this symbol, or NoSpan if the symbol was not loaded + * from source or from TASTY. This is always a zero-extent position. + */ + final def span: Span = if symbol.coord.isSpan then symbol.coord.toSpan else NoSpan + + final def sourcePos(using Context): SourcePosition = { + val src = symbol.source + (if src.exists then src else ctx.source).atSpan(span) + } + + /** This positioned item, widened to `SrcPos`. Used to make clear we only need the + * position, typically for error reporting. + */ + final def srcPos: SrcPos = this } /** The contents of a class definition during a period */ class ClassDenotation private[SymDenotations] ( - symbol: Symbol, + symbolHint: Symbol | Null, + common: ClassCommon, maybeOwner: Symbol, name: Name, initFlags: FlagSet, initInfo: Type, initPrivateWithin: Symbol) - extends SymDenotation(symbol, maybeOwner, name, initFlags, initInfo, initPrivateWithin) { + extends SymDenotation(symbolHint, common, maybeOwner, name, initFlags, initInfo, initPrivateWithin) { import util.EqHashMap + type ThisName = TypeName + // ----- caches ------------------------------------------------------- private var myTypeParams: List[TypeSymbol] | Null = null @@ -1893,7 +2014,7 @@ object SymDenotations { /** The explicitly given self type (self types of modules are assumed to be * explcitly given here). */ - def givenSelfType(using Context): Type = classInfo.selfInfo match { + def givenSelfType(using Context): Type = (classInfo.selfInfo: @unchecked) match { // !!! dotty problem: opaque exhaustive case tp: Type => tp case self: Symbol => self.info } @@ -1956,8 +2077,8 @@ object SymDenotations { val builder = new BaseDataBuilder def traverse(parents: List[Type]): Unit = parents match { case p :: parents1 => - p.classSymbol match { - case pcls: ClassSymbol => builder.addAll(pcls.baseClasses) + p.classSymbol.denot match { + case pcls: ClassDenotation => builder.addAll(pcls.baseClasses) case _ => assert(isRefinementClass || p.isError || ctx.mode.is(Mode.Interactive), s"$this has non-class parent: $p") } traverse(parents1) @@ -2313,8 +2434,8 @@ object SymDenotations { def maybeAdd(name: Name) = if (keepOnly(thisType, name)) names += name try { for ptype <- parentTypes do - ptype.classSymbol match - case pcls: ClassSymbol => + ptype.classSymbol.denot match + case pcls: ClassDenotation => for name <- pcls.memberNames(keepOnly) do maybeAdd(name) val ownSyms = @@ -2394,19 +2515,26 @@ object SymDenotations { override def registeredCompanion_=(c: Symbol) = myCompanion = c + + /** The source or class file from which this class was generated, null if not applicable. */ + override def associatedFile(using Context): AbstractFile | Null = + val af = common.assocFile + if af != null || this.is(Package) || this.owner.is(Package) then af + else super.associatedFile } /** The denotation of a package class. * It overrides ClassDenotation to take account of package objects when looking for members */ final class PackageClassDenotation private[SymDenotations] ( - symbol: Symbol, + symbolHint: Symbol | Null, + common: ClassCommon, ownerIfExists: Symbol, name: Name, initFlags: FlagSet, initInfo: Type, initPrivateWithin: Symbol) - extends ClassDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) { + extends ClassDenotation(symbolHint, common, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) { private var packageObjsCache: List[ClassDenotation] = _ private var packageObjsRunId: RunId = NoRunId @@ -2570,13 +2698,13 @@ object SymDenotations { } @sharable object NoDenotation - extends SymDenotation(NoSymbol, NoSymbol, "".toTermName, Permanent, NoType) { + extends SymDenotation(NoSymbol, SymCommon(NoCoord, 0, 0), null, "".toTermName, Permanent, NoType) { override def isTerm: Boolean = false override def exists: Boolean = false - override def owner: Symbol = throw new AssertionError("NoDenotation.owner") override def computeAsSeenFrom(pre: Type)(using Context): SingleDenotation = this override def mapInfo(f: Type => Type)(using Context): SingleDenotation = this override def asSeenFrom(pre: Type)(using Context): AsSeenFromResult = this + override def currentSymDenot(using Context): SymDenotation = this override def matches(other: SingleDenotation)(using Context): Boolean = false override def targetName(using Context): Name = EmptyTermName @@ -2584,8 +2712,9 @@ object SymDenotations { override def filterWithPredicate(p: SingleDenotation => Boolean): SingleDenotation = this override def filterDisjoint(denots: PreDenotation)(using Context): SingleDenotation = this override def filterWithFlags(required: FlagSet, excluded: FlagSet)(using Context): SingleDenotation = this + override def associatedFile(using Context): AbstractFile | Null = NoSource.file - NoSymbol.denot = this + NoSymbol.denot_=(this) validFor = Period.allInRun(NoRunId) } @@ -2604,17 +2733,21 @@ object SymDenotations { * should be done via this method. */ def SymDenotation( - symbol: Symbol, + symbolHint: Symbol | Null, + common: SymCommon, owner: Symbol, name: Name, initFlags: FlagSet, initInfo: Type, initPrivateWithin: Symbol = NoSymbol)(using Context): SymDenotation = { val result = - if (symbol.isClass) - if (initFlags.is(Package)) new PackageClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) - else new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) - else new SymDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) + if common.isClass then + if initFlags.is(Package) then + new PackageClassDenotation(symbolHint, common.asClass, owner, name, initFlags, initInfo, initPrivateWithin) + else + new ClassDenotation(symbolHint, common.asClass, owner, name, initFlags, initInfo, initPrivateWithin) + else + new SymDenotation(symbolHint, common, owner, name, initFlags, initInfo, initPrivateWithin) result.validFor = currentStablePeriod result } @@ -2666,7 +2799,7 @@ object SymDenotations { if (!traceInvalid(owner)) explainSym("owner is invalid") else if (!owner.isClass || owner.isRefinementClass || denot.isSelfSym) true else if (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol) true - else explainSym(s"decls of ${show(owner)} are ${owner.unforcedDecls.lookupAll(denot.name).toList}, do not contain ${denot.symbol}") + else explainSym(s"decls of ${show(owner)} are ${owner.unforcedDecls.lookupAll(denot.name).toList.map(show(_))}, do not contain ${denot.symbol}") } catch { case ex: StaleSymbol => explainSym(s"$ex was thrown") diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index aa3ae0c3c513..0a8c29bd2ba6 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -20,8 +20,9 @@ import StdNames._ import NameOps._ import transform.SymUtils._ import NameKinds.LazyImplicitName +import Annotations.Annotation import ast.tpd -import tpd.{Tree, TreeProvider, TreeOps} +import tpd.{Tree, TreeProvider, TreeOps, EmptyTree, NameTree} import ast.TreeTypeMap import Constants.Constant import Variances.Variance @@ -31,26 +32,49 @@ import io.AbstractFile import util.{SourceFile, NoSource, Property, SourcePosition, SrcPos, EqHashMap} import scala.annotation.internal.sharable import config.Printers.typr +import annotation.tailrec +import scala.reflect.TypeTest object Symbols { - implicit def eqSymbol: CanEqual[Symbol, Symbol] = CanEqual.derived - /** Tree attachment containing the identifiers in a tree as a sorted array */ val Ids: Property.Key[Array[String]] = new Property.Key - /** A Symbol represents a Scala definition/declaration or a package. - * @param coord The coordinates of the symbol (a position or an index) - * @param id A unique identifier of the symbol (unique per ContextBase) - */ - class Symbol private[Symbols] (private var myCoord: Coord, val id: Int, val nestingLevel: Int) - extends Designator, ParamInfo, SrcPos, printing.Showable { + opaque type Symbol <: ParamInfo & SrcPos & Named & printing.Showable + = SymDenotation + opaque type ClassSymbol <: TypeSymbol + = ClassDenotation + + object TypeTests: + + given SymTest: TypeTest[Any, Symbol] with + def unapply(x: Any): Option[x.type & Symbol] = x match + case sd: SymDenotation => Some(sd.asInstanceOf[x.type & Symbol]) + case _ => None - type ThisName <: Name + given ClsTest: TypeTest[Any, ClassSymbol] with + def unapply(x: Any): Option[x.type & ClassSymbol] = x match + case cd: ClassDenotation => Some(cd.asInstanceOf[x.type & ClassSymbol]) + case _ => None + end TypeTests + + implicit def eqSymbol: CanEqual[Symbol, Symbol] = CanEqual.derived + + type TermSymbol = Symbol { type ThisName = TermName } + type TypeSymbol = Symbol { type ThisName = TypeName } - //assert(id != 723) + extension (x: Any) + inline def isSymbol: Boolean = x.isInstanceOf[Symbol] + inline def asSymbol: Symbol = x.asInstanceOf[Symbol] - def coord: Coord = myCoord + extension (self: Symbol) + /** A unique identifier of the symbol (unique per ContextBase) */ + def id: Int = self.common.id + + def nestingLevel: Int = self.common.nestingLevel + + /** The coordinates of the symbol (a position or an index) */ + def coord: Coord = self.common.coord /** Set the coordinate of this class, this is only useful when the coordinate is * not known at symbol creation. This is the case for root symbols @@ -58,22 +82,20 @@ object Symbols { * * @pre coord == NoCoord */ - private[core] def coord_=(c: Coord): Unit = { - // assert(myCoord == NoCoord) + private[core] def coord_=(c: Coord): Unit = + //assert(myCoord == NoCoord) // This assertion fails for CommentPickling test. // TODO: figure out what's wrong in the setup of CommentPicklingTest and re-enable assertion. - myCoord = c - } - - private var myDefTree: Tree | Null = null + self.common.coord = c /** The tree defining the symbol at pickler time, EmptyTree if none was retained */ def defTree: Tree = - if (myDefTree == null) tpd.EmptyTree else myDefTree.nn + val dt = self.common.defTree + if dt == null then EmptyTree else dt.nn /** Set defining tree if this symbol retains its definition tree */ def defTree_=(tree: Tree)(using Context): Unit = - if (retainsDefTree) myDefTree = tree + if retainsDefTree then self.common.defTree = tree /** Does this symbol retain its definition tree? * A good policy for this needs to balance costs and benefits, where @@ -81,159 +103,144 @@ object Symbols { */ def retainsDefTree(using Context): Boolean = ctx.settings.YretainTrees.value || - denot.owner.isTerm || // no risk of leaking memory after a run for these - denot.isOneOf(InlineOrProxy) || // need to keep inline info + owner.isTerm || // no risk of leaking memory after a run for these + _isOneOf(InlineOrProxy) || // need to keep inline info ctx.settings.YcheckInit.value // initialization check - /** The last denotation of this symbol */ - private var lastDenot: SymDenotation = _ - private var checkedPeriod: Period = Nowhere - - private[core] def invalidateDenotCache(): Unit = { checkedPeriod = Nowhere } - /** Set the denotation of this symbol * `denot` should always be initialized when a new Symbol is created. */ - private[core] def denot_=(d: SymDenotation): Unit = { + private[core] def denot_=(d: SymDenotation): Unit = util.Stats.record("Symbol.denot_=") - lastDenot = d - checkedPeriod = Nowhere - } + self.lastDenot = d + self.checkedPeriod = Nowhere /** The current denotation of this symbol */ - final def denot(using Context): SymDenotation = { + def denot(using Context): SymDenotation = util.Stats.record("Symbol.denot") - if checkedPeriod.code == ctx.period.code then lastDenot - else computeDenot(lastDenot) - } + val lastd = self.lastDenot + if self.checkedPeriod.code == ctx.period.code + then lastd + else lastd.computeDenot - private def computeDenot(lastd: SymDenotation)(using Context): SymDenotation = { - util.Stats.record("Symbol.computeDenot") - val now = ctx.period - checkedPeriod = now - if (lastd.validFor contains now) lastd else recomputeDenot(lastd) - } + private[core] def setLastDenot(d: SymDenotation): SymDenotation = + self.lastDenot = d + d - /** Overridden in NoSymbol */ - protected def recomputeDenot(lastd: SymDenotation)(using Context): SymDenotation = { - util.Stats.record("Symbol.recomputeDenot") - val newd = lastd.current.asInstanceOf[SymDenotation] - lastDenot = newd - newd - } + def setCheckedPeriod(period: Period): Unit = + self.checkedPeriod = period /** The original denotation of this symbol, without forcing anything */ - final def originDenotation: SymDenotation = - lastDenot.initial + def originDenotation: SymDenotation = self /** The last known denotation of this symbol, without going through `current` */ - final def lastKnownDenotation: SymDenotation = - lastDenot + def lastKnownDenotation: SymDenotation = self.lastDenot - private[core] def defRunId: RunId = - lastDenot.validFor.runId + def classDenot(using Context): ClassDenotation = + self.denot.asInstanceOf[ClassDenotation] - private inline def associatedFileMatches(inline filter: AbstractFile => Boolean)(using Context): Boolean = - try - val file = associatedFile - file != null && filter(file) - catch case ex: StaleSymbol => - // can happen for constructor proxy companions. Test case is pos-macros/i9484. - false + private[core] def defRunId: RunId = + self.lastDenot.validFor.runId /** Does this symbol come from a currently compiled source file? */ - final def isDefinedInCurrentRun(using Context): Boolean = - span.exists && defRunId == ctx.runId && associatedFileMatches(ctx.run.nn.files.contains) + def isDefinedInCurrentRun(using Context): Boolean = + span.exists + && defRunId == ctx.runId + && self.lastDenot.associatedFileMatches(ctx.run.nn.files.contains) /** Is this symbol valid in the current run and has an associated file that is * not a binary file. e.g. This will return true for * symbols defined by the user in a prior run of the REPL, that are still valid. */ - final def isDefinedInSource(using Context): Boolean = - span.exists && isValidInCurrentRun && associatedFileMatches(_.extension != "class") - - /** Is symbol valid in current run? */ - final def isValidInCurrentRun(using Context): Boolean = - (lastDenot.validFor.runId == ctx.runId || stillValid(lastDenot)) && - (lastDenot.symbol eq this) + def isDefinedInSource(using Context): Boolean = + span.exists + && isValidInCurrentRun + && self.lastDenot.associatedFileMatches(_.extension != "class") + + def isValidInCurrentRun(using Context): Boolean = + val d = self.lastDenot + (d.validFor.runId == ctx.runId || stillValid(d)) + && (d.symbol eq self) // the last condition is needed because under ctx.staleOK overwritten // members keep denotations pointing to the new symbol, so the validity // periods check out OK. But once a package member is overridden it is not longer // valid. If the option would be removed, the check would be no longer needed. - final def isTerm(using Context): Boolean = - (if (defRunId == ctx.runId) lastDenot else denot).isTerm - final def isType(using Context): Boolean = - (if (defRunId == ctx.runId) lastDenot else denot).isType - final def asTerm(using Context): TermSymbol = { - assert(isTerm, s"asTerm called on not-a-Term $this" ); - asInstanceOf[TermSymbol] - } - final def asType(using Context): TypeSymbol = { - assert(isType, s"isType called on not-a-Type $this"); - asInstanceOf[TypeSymbol] - } + def isTerm(using Context): Boolean = + val lastd = self.lastDenot + (if lastd.validFor.runId == ctx.runId then lastd else denot).isTerm - final def isClass: Boolean = isInstanceOf[ClassSymbol] - final def asClass: ClassSymbol = asInstanceOf[ClassSymbol] + def isType(using Context): Boolean = + val lastd = self.lastDenot + (if lastd.validFor.runId == ctx.runId then lastd else denot).isType - /** Test whether symbol is private. This - * conservatively returns `false` if symbol does not yet have a denotation, or denotation - * is a class that is not yet read. - */ - final def isPrivate(using Context): Boolean = - lastDenot.flagsUNSAFE.is(Private) + def asTerm(using Context): TermSymbol = + assert(self.isTerm, s"asTerm called on not-a-Term $this" ) + self.asInstanceOf[TermSymbol] + + def asType(using Context): TypeSymbol = + assert(self.isType, s"isType called on not-a-Type $this"); + self.asInstanceOf[TypeSymbol] + + def isClass: Boolean = (self: SymDenotation).isClass + + def asClass: ClassSymbol = self.asInstanceOf[ClassSymbol] - /** Is the symbol a pattern bound symbol? + /** Test whether symbol is private. This conservatively returns `false` + * if symbol's denotation is a class that is not yet read. */ - final def isPatternBound(using Context): Boolean = - !isClass && this.is(Case, butNot = Enum | Module) + def isPrivate(using Context): Boolean = + self.lastDenot.flagsUNSAFE.is(Private) + + /** Is the symbol a pattern bound symbol? */ + def isPatternBound(using Context): Boolean = + !isClass && denot.is(Case, butNot = Enum | Module) /** The symbol's signature if it is completed or a method, NotAMethod otherwise. */ - final def signature(using Context): Signature = - if lastDenot.uncheckedNN.isCompleted || lastDenot.uncheckedNN.is(Method) then + def signature(using Context): Signature = + if self.lastDenot.isCompleted || self.lastDenot.is(Method) then denot.signature else Signature.NotAMethod - /** Special cased here, because it may be used on naked symbols in substituters */ - final def isStatic(using Context): Boolean = - lastDenot.initial.isStatic + def isStatic(using Context): Boolean = + (self: SymDenotation).isStatic /** This symbol entered into owner's scope (owner must be a class). */ - final def entered(using Context): this.type = { - if (this.owner.isClass) { - this.owner.asClass.enter(this) - if (this.is(Module)) this.owner.asClass.enter(this.moduleClass) - } - this - } + final def entered(using Context): self.type = + val d = denot + if d.owner.isClass then + d.owner.classDenot.enter(self) + if d.is(Module) then d.owner.classDenot.enter(d.moduleClass) + self + /** Enter this symbol in its class owner after given `phase`. Create a fresh * denotation for its owner class if the class does not already have one * that starts being valid after `phase`. * @pre Symbol is a class member */ - def enteredAfter(phase: DenotTransformer)(using Context): this.type = + def enteredAfter(phase: DenotTransformer)(using Context): self.type = if ctx.phaseId != phase.next.id then atPhase(phase.next)(enteredAfter(phase)) - else this.owner match { - case owner: ClassSymbol => - if (owner.is(Package)) { - denot.validFor |= InitialPeriod - if (this.is(Module)) this.moduleClass.validFor |= InitialPeriod - } - else owner.ensureFreshScopeAfter(phase) - assert(isPrivate || phase.changesMembers, i"$this entered in $owner at undeclared phase $phase") - entered - case _ => this - } + else + val d = denot + d.owner match + case owner: ClassSymbol => + if owner._is(Package) then + d.validFor |= InitialPeriod + if d.is(Module) then d.moduleClass.denot.validFor |= InitialPeriod + else + owner.classDenot.ensureFreshScopeAfter(phase) + assert(isPrivate || phase.changesMembers, i"$self entered in $owner at undeclared phase $phase") + self.entered + case _ => self /** Remove symbol from scope of owning class */ - final def drop()(using Context): Unit = { - this.owner.asClass.delete(this) - if (this.is(Module)) this.owner.asClass.delete(this.moduleClass) - } + final def drop()(using Context): Unit = + val d = denot + d.owner.classDenot.delete(self) + if d.is(Module) then d.owner.classDenot.delete(d.moduleClass) /** Remove symbol from scope of owning class after given `phase`. Create a fresh * denotation for its owner class if the class does not already have one that starts being valid after `phase`. @@ -242,22 +249,22 @@ object Symbols { def dropAfter(phase: DenotTransformer)(using Context): Unit = if ctx.phaseId != phase.next.id then atPhase(phase.next)(dropAfter(phase)) - else { - assert (!this.owner.is(Package)) - this.owner.asClass.ensureFreshScopeAfter(phase) - assert(isPrivate || phase.changesMembers, i"$this deleted in ${this.owner} at undeclared phase $phase") + else + val d = denot + assert(!d.owner._is(Package)) + d.owner.classDenot.ensureFreshScopeAfter(phase) + assert(isPrivate || phase.changesMembers, i"$self deleted in ${d.owner} at undeclared phase $phase") drop() - } /** This symbol, if it exists, otherwise the result of evaluating `that` */ inline def orElse(inline that: Symbol)(using Context): Symbol = - if (this.exists) this else that + if denot.exists then self else that /** If this symbol satisfies predicate `p` this symbol, otherwise `NoSymbol` */ - def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol + def filter(p: Symbol => Boolean): Symbol = if p(self) then self else NoSymbol /** The current name of this symbol */ - final def name(using Context): ThisName = denot.name.asInstanceOf[ThisName] + def name(using Context): self.ThisName = denot.name.asInstanceOf[self.ThisName] /** The source or class file from which this class or * the class containing this symbol was generated, null if not applicable. @@ -266,140 +273,142 @@ object Symbols { * Overridden in ClassSymbol */ def associatedFile(using Context): AbstractFile | Null = - lastDenot.topLevelClass.associatedFile + self.lastDenot.associatedFile /** The class file from which this class was generated, null if not applicable. */ - final def binaryFile(using Context): AbstractFile | Null = { + final def binaryFile(using Context): AbstractFile | Null = val file = associatedFile - if (file != null && file.extension == "class") file else null - } + if file != null && file.extension == "class" then file else null - /** A trap to avoid calling x.symbol on something that is already a symbol. + /** A trap to avoid calling x.symbol on something that is already a symbol. * This would be expanded to `toDenot(x).symbol` which is guaraneteed to be * the same as `x`. - * With the given setup, all such calls will give implicit-not found errors + * With the given setup, all such calls will produce `Nothing` */ - final def symbol(implicit ev: DontUseSymbolOnSymbol): Nothing = unsupported("symbol") - type DontUseSymbolOnSymbol + final def symbol: Nothing = unsupported("symbol") - final def source(using Context): SourceFile = { + final def source(using Context): SourceFile = def valid(src: SourceFile): SourceFile = - if (src.exists && src.file.extension != "class") src + if src.exists && src.file.extension != "class" then src else NoSource - if (!denot.exists) NoSource - else - valid(defTree.source) match { - case NoSource => - valid(denot.owner.source) match { - case NoSource => - this match { - case cls: ClassSymbol => valid(cls.sourceOfClass) - case _ if denot.is(Module) => valid(denot.moduleClass.source) - case _ => NoSource - } - case src => src - } - case src => src - } - } + val d = denot + if !d.exists then NoSource + else valid(defTree.source) match + case NoSource => + valid(d.owner.source) match + case NoSource => + self match + case cls: ClassSymbol => valid(cls.sourceOfClass) + case _ if d.is(Module) => valid(d.moduleClass.source) + case _ => NoSource + case src => src + case src => src /** A symbol related to `sym` that is defined in source code. * * @see enclosingSourceSymbols */ - @annotation.tailrec final def sourceSymbol(using Context): Symbol = - if (!denot.exists) - this - else if (denot.is(ModuleVal)) - this.moduleClass.sourceSymbol // The module val always has a zero-extent position - else if (denot.is(Synthetic)) { - val linked = denot.linkedClass - if (linked.exists && !linked.is(Synthetic)) - linked - else - denot.owner.sourceSymbol - } - else if (denot.isPrimaryConstructor) - denot.owner.sourceSymbol - else this - - /** The position of this symbol, or NoSpan if the symbol was not loaded - * from source or from TASTY. This is always a zero-extent position. - */ - final def span: Span = if (coord.isSpan) coord.toSpan else NoSpan - - final def sourcePos(using Context): SourcePosition = { - val src = source - (if (src.exists) src else ctx.source).atSpan(span) - } - - /** This positioned item, widened to `SrcPos`. Used to make clear we only need the - * position, typically for error reporting. - */ - final def srcPos: SrcPos = this + @tailrec final def sourceSymbol(using Context): Symbol = + val d = denot + if !d.exists then + self + else if d.is(ModuleVal) then + d.moduleClass.sourceSymbol // The module val always has a zero-extent position + else if d.is(Synthetic) then + val linked = d.linkedClass + if linked.exists && !linked._is(Synthetic) then linked + else d.owner.sourceSymbol + else if d.isPrimaryConstructor then + d.owner.sourceSymbol + else + self + + def exists(using Context): Boolean = self ne NoSymbol + def owner(using Context): Symbol = self.denot.owner + def typeParams(using Context): List[TypeSymbol] = self.denot.typeParams + def thisType(using Context): Type = self.denot.thisType + def typeRef(using Context): TypeRef = self.denot.typeRef + def termRef(using Context): TermRef = self.denot.termRef + def _info(using Context): Type = self.denot.info + def isCompleted(using Context): Boolean = self.denot.isCompleted + def isCompleting(using Context): Boolean = self.denot.isCompleting + def ensureCompleted()(using Context): Unit = self.denot.ensureCompleted() + def unforcedDecls(using Context): Scope = self.denot.unforcedDecls + def appliedRef(using Context): Type = self.denot.appliedRef + def namedType(using Context): NamedType = self.denot.namedType + def unforcedAnnotation(cls: Symbol)(using Context): Option[Annotation] = self.denot.unforcedAnnotation(cls) + def children(using Context): List[Symbol] = self.denot.children + def topLevelClass(using Context): Symbol = self.denot.topLevelClass + def moduleClass(using Context): Symbol = self.denot.moduleClass + def sourceModule(using Context): Symbol = self.denot.sourceModule + def underlyingSymbol(using Context): Symbol = self.denot.underlyingSymbol + def ownersIterator(using Context): Iterator[Symbol] = self.denot.ownersIterator + def enclosingClass(using Context): Symbol = self.denot.enclosingClass + def enclosingMethod(using Context): Symbol = self.denot.enclosingMethod + def typeParamCreationFlags(using Context): FlagSet = self.denot.typeParamCreationFlags + def _is(flag: Flag)(using Context): Boolean = self.denot.is(flag) + def _is(flag: Flag, butNot: FlagSet)(using Context): Boolean = self.denot.is(flag, butNot) + def _isOneOf(fs: FlagSet)(using Context): Boolean = self.denot.isOneOf(fs) + def _isOneOf(fs: FlagSet, butNot: FlagSet)(using Context): Boolean = self.denot.isOneOf(fs, butNot) + def _isAllOf(fs: FlagSet)(using Context): Boolean = self.denot.isAllOf(fs) + def _isAllOf(fs: FlagSet, butNot: FlagSet)(using Context): Boolean = self.denot.isAllOf(fs, butNot) + // !!! Dotty problem: overloaded extension methods here lead to failures like + // Assertion failed: data race? overwriting method isAllOf with method isAllOf in type TermRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix,module class dotc)),object core),object Symbols),isAllOf), + // |last sym id = 10301, new sym id = 10299, + // |last owner = module class Symbols$, new owner = module class Symbols$, + + // SrcPos types and methods // !!! make them use lastDenot? + def span: Span = (self: SymDenotation).span + def sourcePos(using Context): SourcePosition = (self: SymDenotation).sourcePos + def srcPos: SrcPos = (self: SymDenotation).srcPos // ParamInfo types and methods def isTypeParam(using Context): Boolean = denot.is(TypeParam) - def paramName(using Context): ThisName = name.asInstanceOf[ThisName] + def paramName(using Context): self.ThisName = denot.paramName.asInstanceOf def paramInfo(using Context): Type = denot.info - def paramInfoAsSeenFrom(pre: Type)(using Context): Type = pre.memberInfo(this) - def paramInfoOrCompleter(using Context): Type = denot.infoOrCompleter - def paramVariance(using Context): Variance = denot.variance - def paramRef(using Context): TypeRef = denot.typeRef + def paramInfoAsSeenFrom(pre: Type)(using Context): Type = denot.paramInfoAsSeenFrom(pre) + def paramInfoOrCompleter(using Context): Type = denot.paramInfoOrCompleter + def paramVariance(using Context): Variance = denot.paramVariance + def paramRef(using Context): TypeRef = denot.paramRef /** Copy a symbol, overriding selective fields. * Note that `coord` and `associatedFile` will be set from the fields in `owner`, not - * the fields in `sym`. */ + * the fields in `sym`. + */ def copy(using Context)( - owner: Symbol = this.owner, - name: ThisName = name, - flags: FlagSet = this.flags, - info: Type = this.info, - privateWithin: Symbol = this.privateWithin, + owner: Symbol = self.denot.owner, + name: self.ThisName = self.denot.name.asInstanceOf[self.ThisName], + flags: FlagSet = self.denot.flags, + info: Type = self.denot.info, + privateWithin: Symbol = self.denot.privateWithin, coord: Coord = NoCoord, // Can be `= owner.coord` once we bootstrap associatedFile: AbstractFile | Null = null // Can be `= owner.associatedFile` once we bootstrap - ): Symbol = { - val coord1 = if (coord == NoCoord) owner.coord else coord - val associatedFile1 = if (associatedFile == null) owner.associatedFile else associatedFile + ): Symbol = + val coord1 = if coord == NoCoord then owner.coord else coord + val associatedFile1 = if associatedFile == null then owner.associatedFile else associatedFile if isClass then newClassSymbol(owner, name.asTypeName, flags, _ => info, privateWithin, coord1, associatedFile1) else newSymbol(owner, name, flags, info, privateWithin, coord1) - } -// -------- Printing -------------------------------------------------------- + // -------- Printing -------------------------------------------------------- - /** The prefix string to be used when displaying this symbol without denotation */ - protected def prefixString: String = "Symbol" + def toText(printer: Printer): Text = printer.toText(self) - override def toString: String = - lastDenot.toString // + "#" + id // !!! DEBUG + def showLocated(using Context): String = ctx.printer.locatedText(self).show + def showExtendedLocation(using Context): String = ctx.printer.extendedLocationText(self).show + def showDcl(using Context): String = ctx.printer.dclText(self).show + def showKind(using Context): String = ctx.printer.kindString(self) + def showName(using Context): String = ctx.printer.nameString(self) + def showFullName(using Context): String = ctx.printer.fullNameString(self) - def toText(printer: Printer): Text = printer.toText(this) + def debugString: String = (self: SymDenotation).debugString - def showLocated(using Context): String = ctx.printer.locatedText(this).show - def showExtendedLocation(using Context): String = ctx.printer.extendedLocationText(this).show - def showDcl(using Context): String = ctx.printer.dclText(this).show - def showKind(using Context): String = ctx.printer.kindString(this) - def showName(using Context): String = ctx.printer.nameString(this) - def showFullName(using Context): String = ctx.printer.fullNameString(this) + end extension - override def hashCode(): Int = id // for debugging. - } - - type TermSymbol = Symbol { type ThisName = TermName } - type TypeSymbol = Symbol { type ThisName = TypeName } - - class ClassSymbol private[Symbols] (coord: Coord, val assocFile: AbstractFile | Null, id: Int, nestingLevel: Int) - extends Symbol(coord, id, nestingLevel) { - - type ThisName = TypeName - - type TreeOrProvider = tpd.TreeProvider | tpd.Tree - - private var myTree: TreeOrProvider = tpd.EmptyTree + extension (self: ClassSymbol) /** If this is a top-level class and `-Yretain-trees` (or `-from-tasty`) is set. * Returns the TypeDef tree (possibly wrapped inside PackageDefs) for this class, otherwise EmptyTree. @@ -407,35 +416,32 @@ object Symbols { */ def rootTree(using Context): Tree = rootTreeContaining("") - /** Same as `tree` but load tree only if `id == ""` or the tree might contain `id`. + /** Same as `rootTree` but load tree only if `id == ""` or the tree might contain `id`. * For Tasty trees this means consulting whether the name table defines `id`. * For already loaded trees, we maintain the referenced ids in an attachment. */ - def rootTreeContaining(id: String)(using Context): Tree = { - denot.infoOrCompleter match { + def rootTreeContaining(id: String)(using Context): Tree = + self.denot.infoOrCompleter match case _: NoCompleter => - case _ => denot.ensureCompleted() - } - myTree match { + case _ => self.denot.ensureCompleted() + rootTreeOrProvider match case fn: TreeProvider => - if (id.isEmpty || fn.mightContain(id)) { + if id.isEmpty || fn.mightContain(id) then val tree = fn.tree - myTree = tree + rootTreeOrProvider = tree tree - } - else tpd.EmptyTree + else EmptyTree case tree: Tree @ unchecked => - if (id.isEmpty || mightContain(tree, id)) tree else tpd.EmptyTree - } - } + if id.isEmpty || mightContain(tree, id) then tree else EmptyTree - def rootTreeOrProvider: TreeOrProvider = myTree + def rootTreeOrProvider: TreeOrProvider = + self.common.asClass.treeOrProvider private[dotc] def rootTreeOrProvider_=(t: TreeOrProvider)(using Context): Unit = - myTree = t + self.common.asClass.treeOrProvider = t - private def mightContain(tree: Tree, id: String)(using Context): Boolean = { - val ids = tree.getAttachment(Ids) match { + private def mightContain(tree: Tree, id: String)(using Context): Boolean = + val ids = tree.getAttachment(Ids) match case Some(ids) => ids case None => val idSet = mutable.SortedSet[String]() @@ -447,48 +453,36 @@ object Symbols { val ids = idSet.toArray tree.putAttachment(Ids, ids) ids - } ids.binarySearch(id) >= 0 - } - - /** The source or class file from which this class was generated, null if not applicable. */ - override def associatedFile(using Context): AbstractFile | Null = - if assocFile != null || this.is(Package) || this.owner.is(Package) then assocFile - else super.associatedFile - private var mySource: SourceFile = NoSource + def assocFile: AbstractFile | Null = self.common.asClass.assocFile - final def sourceOfClass(using Context): SourceFile = { - if !mySource.exists && !denot.is(Package) then + def sourceOfClass(using Context): SourceFile = + val common = self.common.asClass + if !common.source.exists && !self._is(Package) then // this allows sources to be added in annotations after `sourceOfClass` is first called - val file = associatedFile + val file = self.associatedFile if file != null && file.extension != "class" then - mySource = ctx.getSource(file) + common.source = ctx.getSource(file) else - mySource = defn.patchSource(this) - if !mySource.exists then - mySource = atPhaseNoLater(flattenPhase) { - denot.topLevelClass.unforcedAnnotation(defn.SourceFileAnnot) match + common.source = defn.patchSource(self) + if !common.source.exists then + common.source = atPhaseNoLater(flattenPhase) { + self.denot.topLevelClass.unforcedAnnotation(defn.SourceFileAnnot) match case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match case Some(Constant(path: String)) => ctx.getSource(path) case none => NoSource case none => NoSource } - mySource - } + common.source - final def classDenot(using Context): ClassDenotation = - denot.asInstanceOf[ClassDenotation] + def classInfo(using Context): ClassInfo = self.classDenot.classInfo - override protected def prefixString: String = "ClassSymbol" - } + end extension - @sharable object NoSymbol extends Symbol(NoCoord, 0, 0) { - override def associatedFile(using Context): AbstractFile | Null = NoSource.file - override def recomputeDenot(lastd: SymDenotation)(using Context): SymDenotation = NoDenotation - } + type TreeOrProvider = TreeProvider | Tree - NoDenotation // force it in order to set `denot` field of NoSymbol + def NoSymbol: Symbol = NoDenotation /** Makes all denotation operations available on symbols */ implicit def toDenot(sym: Symbol)(using Context): SymDenotation = sym.denot @@ -496,6 +490,12 @@ object Symbols { /** Makes all class denotation operations available on class symbols */ implicit def toClassDenot(cls: ClassSymbol)(using Context): ClassDenotation = cls.classDenot + /** Blocks use of `toDenot` conversion in Symbols itself */ + private implicit def toDenotALT(sym: Symbol)(using Context): SymDenotation = sym.denot + + /** Blocks use of `toClassDenot` conversion in Symbols itself */ + private implicit def toClassDenotALT(cls: ClassSymbol)(using Context): ClassDenotation = cls.classDenot + /** The Definitions object */ def defn(using Context): Definitions = ctx.definitions @@ -517,10 +517,9 @@ object Symbols { privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord, nestingLevel: Int = ctx.nestingLevel): Symbol { type ThisName = N } = { - val sym = new Symbol(coord, ctx.base.nextSymId, nestingLevel).asInstanceOf[Symbol { type ThisName = N }] - val denot = SymDenotation(sym, owner, name, flags, info, privateWithin) - sym.denot = denot - sym + val sym = SymDenotation(null, SymCommon(coord, ctx.base.nextSymId, nestingLevel), owner, name, flags, info, privateWithin) + sym.denot_=(sym) + sym.asInstanceOf[Symbol { type ThisName = N }] } /** Create a class symbol from its non-info fields and a function @@ -535,9 +534,9 @@ object Symbols { coord: Coord = NoCoord, assocFile: AbstractFile | Null = null)(using Context): ClassSymbol = { - val cls = new ClassSymbol(coord, assocFile, ctx.base.nextSymId, ctx.nestingLevel) - val denot = SymDenotation(cls, owner, name, flags, infoFn(cls), privateWithin) - cls.denot = denot + val cls = SymDenotation(null, ClassCommon(coord, ctx.base.nextSymId, ctx.nestingLevel, assocFile), owner, name, flags, NoType, privateWithin).asClass + cls.denot_=(cls) + cls.info = infoFn(cls) cls } @@ -603,7 +602,7 @@ object Symbols { owner, name, modFlags | ModuleValCreationFlags, NoCompleter, privateWithin, coord) val modcls = newClassSymbol( owner, modclsName, modclsFlags, infoFn(module, _), privateWithin, coord, assocFile) - module.info = + module.denot.info = if (modcls.isCompleted) TypeRef(owner.thisType, modcls) else new ModuleCompleter(modcls) module @@ -695,7 +694,7 @@ object Symbols { */ def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile | Null = null)(using Context): Symbol = { def stubCompleter = new StubInfo() - val normalizedOwner = if (owner.is(ModuleVal)) owner.moduleClass else owner + val normalizedOwner = if (owner._is(ModuleVal)) owner.moduleClass else owner typr.println(s"creating stub for ${name.show}, owner = ${normalizedOwner.denot.debugString}, file = $file") typr.println(s"decls = ${normalizedOwner.unforcedDecls.toList.map(_.debugString).mkString("\n ")}") // !!! DEBUG //if (base.settings.debug.value) throw new Error() @@ -777,7 +776,7 @@ object Symbols { val tparams = tparamBuf.toList val bounds = boundsFn(trefBuf.toList) for (tparam, bound) <- tparams.lazyZip(bounds) do - tparam.info = bound + tparam.denot.info = bound tparams } @@ -800,7 +799,7 @@ object Symbols { */ def mapSymbols(originals: List[Symbol], ttmap: TreeTypeMap, mapAlways: Boolean = false)(using Context): List[Symbol] = if (originals.forall(sym => - (ttmap.mapType(sym.info) eq sym.info) && + (ttmap.mapType(sym._info) eq sym._info) && !(ttmap.oldOwners contains sym.owner)) && !mapAlways) originals else { @@ -819,7 +818,7 @@ object Symbols { def complete(denot: SymDenotation)(using Context): Unit = - val oinfo = original.info match + val oinfo = original._info match case ClassInfo(pre, _, parents, decls, selfInfo) => assert(original.isClass) val parents1 = parents.mapConserve(ttmap.mapType) @@ -833,7 +832,7 @@ object Symbols { val decls1 = newScope val newTypeParams = mapSymbols(original.typeParams, ttmap1, mapAlways = true) newTypeParams.foreach(decls1.enter) - for sym <- decls do if !sym.is(TypeParam) then decls1.enter(sym) + for sym <- decls do if !sym._is(TypeParam) then decls1.enter(sym) val parents2 = parents1.map(_.substSym(otypeParams, newTypeParams)) val selfInfo1 = selfInfo match case selfInfo: Type => selfInfo.substSym(otypeParams, newTypeParams) @@ -849,10 +848,10 @@ object Symbols { end completer - copy.info = completer + copy.denot.info = completer copy.denot match case cd: ClassDenotation => - cd.registeredCompanion = original.registeredCompanion.subst(originals, copies) + cd.registeredCompanion = original.denot.registeredCompanion.subst(originals, copies) case _ => } @@ -861,9 +860,9 @@ object Symbols { // Update Child annotations of classes encountered previously to new values // if some child is among the mapped symbols for orig <- ttmap1.substFrom do - if orig.is(Sealed) && orig.children.exists(originals.contains) then + if orig._is(Sealed) && orig.children.exists(originals.contains) then val sealedCopy = orig.subst(ttmap1.substFrom, ttmap1.substTo) - sealedCopy.annotations = sealedCopy.annotations.mapConserve(ttmap1.apply) + sealedCopy.denot.annotations = sealedCopy.denot.annotations.mapConserve(ttmap1.apply) copies } @@ -888,7 +887,7 @@ object Symbols { def requiredPackage(path: PreName)(using Context): TermSymbol = { val name = path.toTermName - staticRef(name, isPackage = true).requiredSymbol("package", name)(_.is(Package)).asTerm + staticRef(name, isPackage = true).requiredSymbol("package", name)(_._is(Package)).asTerm } def requiredPackageRef(path: PreName)(using Context): TermRef = requiredPackage(path).termRef @@ -921,11 +920,11 @@ object Symbols { */ def getPackageClassIfDefined(path: PreName)(using Context): Symbol = staticRef(path.toTypeName, isPackage = true, generateStubs = false) - .disambiguate(_ is PackageClass).symbol + .disambiguate(_._is(PackageClass)).symbol def requiredModule(path: PreName)(using Context): TermSymbol = { val name = path.toTermName - staticRef(name).requiredSymbol("object", name)(_.is(Module)).asTerm + staticRef(name).requiredSymbol("object", name)(_._is(Module)).asTerm } /** Get module symbol if the module is either defined in current compilation run @@ -933,13 +932,13 @@ object Symbols { */ def getModuleIfDefined(path: PreName)(using Context): Symbol = staticRef(path.toTermName, generateStubs = false) - .disambiguate(_.is(Module)).symbol + .disambiguate(_._is(Module)).symbol def requiredModuleRef(path: PreName)(using Context): TermRef = requiredModule(path).termRef def requiredMethod(path: PreName)(using Context): TermSymbol = { val name = path.toTermName - staticRef(name).requiredSymbol("method", name)(_.is(Method)).asTerm + staticRef(name).requiredSymbol("method", name)(_._is(Method)).asTerm } def requiredMethodRef(path: PreName)(using Context): TermRef = requiredMethod(path).termRef diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 7c25ecd21ebf..f406258f4dbc 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -12,6 +12,7 @@ import Names._ import Flags.{Module, Provisional} import dotty.tools.dotc.config.Config import cc.boxedUnlessFun +import Symbols.TypeTests.given object TypeApplications { @@ -217,7 +218,7 @@ class TypeApplications(val self: Type) extends AnyVal { /** If `self` is a generic class, its type parameter symbols, otherwise Nil */ final def typeParamSymbols(using Context): List[TypeSymbol] = typeParams match { case tparams @ (_: Symbol) :: _ => - assert(tparams.forall(_.isInstanceOf[Symbol])) + assert(tparams.forall(_.isSymbol)) tparams.asInstanceOf[List[TypeSymbol]] // Note: Two successive calls to typeParams can yield different results here because // of different completion status. I.e. the first call might produce some symbols, diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 2a0072590550..2680825996b9 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -24,6 +24,7 @@ import typer.Applications.productSelectorTypes import reporting.trace import annotation.constructorOnly import cc.{CapturingType, derivedCapturingType, CaptureSet, stripCapturing, isBoxedCapturing, boxed, boxedUnlessFun, boxedIfTypeParam, isAlwaysPure} +import Symbols.TypeTests.given /** Provides methods to compare types. */ diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 15b0b00ed0f3..6bd706802e4b 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -43,6 +43,7 @@ import scala.annotation.internal.sharable import scala.annotation.threadUnsafe import dotty.tools.dotc.transform.SymUtils._ +import Symbols.TypeTests.given object Types { @@ -2182,6 +2183,8 @@ object Types { // --- NamedTypes ------------------------------------------------------------------ + type Designator = Name | Symbol + abstract class NamedType extends CachedProxyType, ValueType { self => type ThisType >: this.type <: NamedType @@ -2219,7 +2222,7 @@ object Types { private def computeName: Name = designator match { case name: Name => name - case sym: Symbol => sym.originDenotation.name + case sym => sym.asSymbol.originDenotation.name } final override def signature(using Context): Signature = @@ -2270,10 +2273,12 @@ object Types { else computeSymbol private def computeSymbol(using Context): Symbol = - val result = designator match - case sym: Symbol => - if (sym.isValidInCurrentRun) sym else denot.symbol - case name => + val desig = designator + val result = + if desig.isSymbol then + val sym = desig.asSymbol + if sym.isValidInCurrentRun then sym else denot.symbol + else (if (denotationIsCurrent) lastDenotation.asInstanceOf[Denotation] else denot).symbol if checkedPeriod.code != NowhereCode then checkedPeriod = ctx.period result @@ -2293,10 +2298,11 @@ object Types { * type accumulators, as well as to be safe in diagnostic printing. * Normally, it's better to use `symbol`, not `currentSymbol`. */ - final def currentSymbol(using Context): Symbol = designator match { - case sym: Symbol => sym - case _ => if (denotationIsCurrent) lastDenotation.nn.symbol else NoSymbol - } + final def currentSymbol(using Context): Symbol = + val desig = designator + if desig.isSymbol then desig.asSymbol + else if denotationIsCurrent then lastDenotation.nn.symbol + else NoSymbol /** Retrieves currently valid symbol without necessarily updating denotation. * Assumes that symbols do not change between periods in the same run. @@ -2336,9 +2342,10 @@ object Types { def fromDesignator = designator match { case name: Name => val sym = lastSymbol - val allowPrivate = sym == null || (sym == NoSymbol) || sym.lastKnownDenotation.flagsUNSAFE.is(Private) + val allowPrivate = (sym == null) || (sym eq NoSymbol) || sym.asInstanceOf[Symbol].lastKnownDenotation.flagsUNSAFE.is(Private) finish(memberDenot(name, allowPrivate)) - case sym: Symbol => + case desig => + val sym = desig.asSymbol val symd = sym.lastKnownDenotation if (symd.validFor.runId != ctx.runId && !stillValid(symd)) finish(memberDenot(symd.initial.name, allowPrivate = false)) @@ -2447,13 +2454,11 @@ object Types { checkSymAssign(denot.symbol) lastDenotation = denot - lastSymbol = denot.symbol + val lastSym = denot.symbol.asInstanceOf[Symbol] + lastSymbol = lastSym checkedPeriod = if (prefix.isProvisional) Nowhere else ctx.period - designator match { - case sym: Symbol if designator ne lastSymbol.nn => - designator = lastSymbol.asInstanceOf[Designator{ type ThisName = self.ThisName }] - case _ => - } + if designator.isSymbol && (designator ne lastSym) then + designator = lastSym checkDenot() } @@ -2464,9 +2469,9 @@ object Types { private def checkSymAssign(sym: Symbol)(using Context) = { def selfTypeOf(sym: Symbol) = if (sym.isClass) sym.asClass.givenSelfType else NoType - val lastSym = lastSymbol + val lastSym: Symbol = lastSymbol.asInstanceOf[Symbol] assert( - (lastSym == null) + (lastSym eq null) || (lastSym eq sym) || @@ -2489,13 +2494,14 @@ object Types { ) || sym == defn.AnyClass.primaryConstructor, { - if lastSym == null then + if lastSym eq null then s"""data race? overwriting $lastSym with $sym in type $this, |period = ${ctx.phase} at run ${ctx.runId}""" else s"""data race? overwriting $lastSym with $sym in type $this, |last sym id = ${lastSym.id}, new sym id = ${sym.id}, |last owner = ${lastSym.owner}, new owner = ${sym.owner}, + |last info = ${lastSym.infoOrCompleter}, new info = ${sym.infoOrCompleter} |period = ${ctx.phase} at run ${ctx.runId}""" }) } @@ -2672,7 +2678,7 @@ object Types { val adapted = withSym(denot.symbol) val result = if (adapted.eq(this) - || designator.isInstanceOf[Symbol] + || designator.isSymbol || !adapted.denotationIsCurrent || adapted.info.eq(denot.info)) adapted @@ -2715,7 +2721,7 @@ object Types { if (prefix eq this.prefix) this else if !NamedType.validPrefix(prefix) then UnspecifiedErrorType else if (lastDenotation == null) NamedType(prefix, designator) - else designator match { + else (designator: @unchecked) match { // !!! dotty opaque exhaustivity problem case sym: Symbol => if (infoDependsOnPrefix(sym, prefix) && !prefix.isArgPrefixOf(sym)) { val candidate = reload() @@ -2780,7 +2786,10 @@ object Types { override def isOverloaded(using Context): Boolean = denot.isOverloaded def alternatives(using Context): List[TermRef] = - denot.alternatives.map(withDenot(_)) + try denot.alternatives.map(withDenot(_)) + catch case ex: AssertionError => + println(i"error while alts ${denot.alternatives}") + throw ex def altsWith(p: Symbol => Boolean)(using Context): List[TermRef] = denot.altsWith(p).map(withDenot(_)) @@ -2861,12 +2870,12 @@ object Types { } final class CachedTermRef(prefix: Type, designator: Designator, hc: Int) extends TermRef(prefix, designator) { - assert((prefix ne NoPrefix) || designator.isInstanceOf[Symbol]) + assert((prefix ne NoPrefix) || designator.isSymbol) myHash = hc } final class CachedTypeRef(prefix: Type, designator: Designator, hc: Int) extends TypeRef(prefix, designator) { - assert((prefix ne NoPrefix) || designator.isInstanceOf[Symbol]) + assert((prefix ne NoPrefix) || designator.isSymbol) myHash = hc } @@ -2895,7 +2904,7 @@ object Types { } object NamedType { - def isType(desig: Designator)(using Context): Boolean = desig match { + def isType(desig: Designator)(using Context): Boolean = (desig: @unchecked) match { // !!! dotty opaque exhaustivity problem case sym: Symbol => sym.isType case name: Name => name.isTypeName } @@ -5032,7 +5041,7 @@ object Types { TypeAlias( withMode(Mode.CheckCyclic)( LazyRef.of(force)))) - cinfo.selfInfo match + (cinfo.selfInfo: @unchecked) match // !!! dotty opaque exhaustivity problem case self: Type => cinfo.derivedClassInfo( selfInfo = refineSelfType(self.orElse(defn.AnyType))) diff --git a/compiler/src/dotty/tools/dotc/core/Variances.scala b/compiler/src/dotty/tools/dotc/core/Variances.scala index 2401b43c8e17..050d1628b4ea 100644 --- a/compiler/src/dotty/tools/dotc/core/Variances.scala +++ b/compiler/src/dotty/tools/dotc/core/Variances.scala @@ -4,6 +4,7 @@ package core import Types._, Contexts._, Flags._, Symbols._, Annotations._ import TypeApplications.TypeParamInfo import Decorators._ +import Symbols.TypeTests.given object Variances { diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 7702e6a93446..7fb53b48037b 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -23,6 +23,7 @@ import scala.annotation.switch import typer.Checking.checkNonCyclic import io.{AbstractFile, ZipArchive} import scala.util.control.NonFatal +import Symbols.TypeTests.given object ClassfileParser { /** Marker trait for unpicklers that can be embedded in classfiles. */ @@ -364,7 +365,8 @@ class ClassfileParser( ct.convertTo(pt) } - private def sigToType(sig: String, owner: Symbol = null, isVarargs: Boolean = false)(using Context): Type = { + private def sigToType(sig: String, ownerOrNull: Symbol | Null = null, isVarargs: Boolean = false)(using Context): Type = { + def owner = ownerOrNull.asInstanceOf[Symbol] var index = 0 val end = sig.length def accept(ch: Char): Unit = { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index bef28545592a..00f8b70fb140 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -19,6 +19,7 @@ import config.Config import collection.mutable import reporting.{Profile, NoProfile} import dotty.tools.tasty.TastyFormat.ASTsSection +import core.Symbols.TypeTests.given object TreePickler: class StackSizeExceeded(val mdef: tpd.MemberDef) extends Exception @@ -212,7 +213,7 @@ class TreePickler(pickler: TastyPickler) { report.error(em"pickling reference to as yet undefined $tpe with symbol ${sym}", sym.srcPos) pickleSymRef(sym) } - else tpe.designator match { + else (tpe.designator: @unchecked) match { // !!! dotty opaque exhaustivity problem case name: Name => writeByte(if (tpe.isType) TYPEREF else TERMREF) pickleName(name); pickleType(tpe.prefix) @@ -598,7 +599,7 @@ class TreePickler(pickler: TastyPickler) { else { if (!tree.self.isEmpty) registerTreeAddr(tree.self) pickleType { - selfInfo match { + (selfInfo: @unchecked) match { // !!! dotty opaque exhaustivity problem case sym: Symbol => sym.info case tp: Type => tp } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 91290b4ddd41..76f119b1a5b5 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -46,6 +46,7 @@ import dotty.tools.tasty.TastyFormat._ import scala.annotation.constructorOnly import scala.annotation.internal.sharable +import Symbols.TypeTests.given /** Unpickler for typed trees * @param reader the reader from which to unpickle diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Erasure.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Erasure.scala index cc2d7dd7ee56..005c4faf7350 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Erasure.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Erasure.scala @@ -6,6 +6,7 @@ package unpickleScala2 import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._, Phases._ import Decorators._ import scala.collection.mutable.ListBuffer +import Symbols.TypeTests.given /** Erasure logic specific to Scala 2 symbols. */ object Scala2Erasure: @@ -122,7 +123,7 @@ object Scala2Erasure: */ def isClass: Boolean = psym match case sym: Symbol => - sym.isClass + Symbols.isClass(sym) case _: Scala2RefinedType => true case _ => @@ -161,7 +162,7 @@ object Scala2Erasure: * pseudo-symbol, if its upper-bound is a sub of that pseudo-symbol. */ def goUpperBound(psym: Symbol | StructuralRef): Boolean = - val info = psym match + val info = (psym: @unchecked) match // !!! dotty opaque exhaustivity problem case sym: Symbol => sym.info case tp: StructuralRef => tp.info info match @@ -178,7 +179,7 @@ object Scala2Erasure: // is an abstract type upper-bounded by this refinement, since each // textual appearance of a refinement will have its own class symbol. !that.isInstanceOf[Scala2RefinedType] && - psym.match + (psym: @unchecked).match // !!! dotty opaque exhaustivity problem case sym1: Symbol => that match case sym2: Symbol => if sym1.isClass && sym2.isClass then diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 50b0b875c1fc..45db19be5eee 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -1074,24 +1074,26 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas // Set by the three functions to follow. If symbol is non-null // after the new tree 't' has been created, t has its Symbol // set to symbol; and it always has its Type set to tpe. - var symbol: Symbol = null + var mySymbol: Symbol | Null = null var mods: Modifiers = null var name: Name = null + def symbol = mySymbol.nn + /** Read a Symbol, Modifiers, and a Name */ def setSymModsName(): Unit = { - symbol = readSymbolRef() + mySymbol = readSymbolRef() mods = readModifiersRef(symbol.isType) name = readNameRef() } /** Read a Symbol and a Name */ def setSymName(): Unit = { - symbol = readSymbolRef() + mySymbol = readSymbolRef() name = readNameRef() } /** Read a Symbol */ def setSym(): Unit = - symbol = readSymbolRef() + mySymbol = readSymbolRef() implicit val span: Span = NoSpan diff --git a/compiler/src/dotty/tools/dotc/fromtasty/ReadTasty.scala b/compiler/src/dotty/tools/dotc/fromtasty/ReadTasty.scala index 86ae99b3e0f9..04c43920aa2e 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/ReadTasty.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/ReadTasty.scala @@ -11,6 +11,7 @@ import Denotations.staticRef import NameOps._ import ast.Trees.Tree import Phases.Phase +import Symbols.TypeTests.given /** Load trees from TASTY files */ diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index e4d0cce9f6f9..b72d622b5010 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -475,7 +475,7 @@ object Completion { case _: (ExprType | MethodOrPoly) => Method case _ => EmptyFlags val symbol = newSymbol(owner = NoSymbol, name, flags, info) - val denot = SymDenotation(symbol, NoSymbol, name, flags, info) + val denot = SymDenotation(symbol, symbol.denot.common, NoSymbol, name, flags, info) denot +: extractRefinements(parent) case tp: TypeProxy => extractRefinements(tp.superType) case _ => List.empty diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index f4bbd74842c8..bbc46f0e8ef8 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -9,6 +9,7 @@ import scala.collection.mutable import core._ import Texts._, Types._, Flags._, Symbols._, Contexts._ import Decorators._ +import Names.Name import reporting.Message import util.DiffUtil import Highlighting._ @@ -22,7 +23,7 @@ object Formatting { * interpolator's correct context, that is with non-sensical tagging, message limiting, explanations, etc. */ opaque type Shown = Any object Shown: - given [A: Show]: Conversion[A, Shown] = Show[A].show(_) + given toShown[A: Show]: Conversion[A, Shown] = Show[A].show(_) sealed abstract class Show[-T]: /** Show a value T by returning a "shown" result. */ @@ -48,7 +49,6 @@ object Formatting { class ShowImplicits1 extends ShowImplicits2: given Show[ImplicitRef] = ShowAny - given Show[Names.Designator] = ShowAny given Show[util.SrcPos] = ShowAny object Show extends ShowImplicits1: @@ -90,6 +90,8 @@ object Formatting { given Show[util.SourceFile] = ShowAny given Show[util.Spans.Span] = ShowAny given Show[tasty.TreeUnpickler#OwnerTree] = ShowAny + given Show[Name] = ShowAny + given Show[Symbol] = ShowAny private def show1[A: Show](x: A)(using Context) = show2(Show[A].show(x).ctxShow) private def show2(x: Shown)(using Context): String = x match diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 0da1993310c6..b7fa9c23561e 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -16,6 +16,7 @@ import scala.util.control.NonFatal import scala.annotation.switch import config.{Config, Feature} import cc.{CapturingType, EventuallyCapturingType, CaptureSet, isBoxed} +import Symbols.TypeTests.given class PlainPrinter(_ctx: Context) extends Printer { diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index a1fe6773c1d2..54c74bb6079c 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -12,6 +12,7 @@ import config.SourceVersion import scala.language.unsafeNulls import scala.annotation.threadUnsafe +import Symbols.TypeTests.given /** ## Tips for error message generation * @@ -154,7 +155,7 @@ object Message: /** Produce a where clause with explanations for recorded iterms. */ def explanations(using Context): String = - def needsExplanation(entry: Recorded) = entry match { + def needsExplanation(entry: Recorded) = (entry: @unchecked) match { // !!! dotty opaque exhaustivity problem case param: TypeParamRef => ctx.typerState.constraint.contains(param) case param: ParamRef => false case skolem: SkolemType => true diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index e8029d790d0a..e6194916696e 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -712,9 +712,9 @@ extends SyntaxMsg(WrongNumberOfTypeArgsID) { .mkString("[", ", ", "]") val actualArgString = actual.map(_.show).mkString("[", ", ", "]") val prettyName = - try fntpe.termSymbol match - case NoSymbol => fntpe.show - case symbol => symbol.showFullName + try + val symbol = fntpe.termSymbol + if symbol.exists then symbol.showFullName else fntpe.show catch case NonFatal(ex) => fntpe.show i"""|$msgPrefix type arguments for $prettyName$expectedArgString |expected: $expectedArgString diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 071efb1fb91c..c39397f238cd 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -24,6 +24,7 @@ import scala.annotation.{ threadUnsafe => tu, tailrec } import scala.PartialFunction.condOpt import dotty.tools.dotc.{semanticdb => s} +import Symbols.TypeTests.given /** Extract symbol references and uses to semanticdb files. * See https://scalameta.org/docs/semanticdb/specification.html#symbol-1 diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala index e157b52fe260..0d30f40ca8f2 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala @@ -5,14 +5,14 @@ import core.Symbols.{ Symbol , defn, NoSymbol } import core.Contexts._ import core.Names import core.Names.Name -import core.Types.{Type, TypeBounds} +import core.Types.{Type, TypeBounds, Designator} import core.Flags._ import core.NameKinds import core.StdNames.nme import SymbolInformation.{Kind => k} import dotty.tools.dotc.util.SourceFile import dotty.tools.dotc.util.Spans.Span -import dotty.tools.dotc.core.Names.Designator +import core.Symbols.TypeTests.given import java.lang.Character.{isJavaIdentifierPart, isJavaIdentifierStart} @@ -45,7 +45,7 @@ object Scala3: else (span.start, span.end) val nameInSource = content.slice(start, end).mkString // for secondary constructors `this` - desig match + (desig: @unchecked) match // !!! dotty opaque exhaustivity problem case sym: Symbol => if sym.isConstructor && nameInSource == nme.THISkw.toString then true @@ -77,15 +77,15 @@ object Scala3: given SemanticSymbolOps : AnyRef with extension (sym: SemanticSymbol) - def name(using Context): Name = sym match - case s: Symbol => s.name + def name(using Context): Name = (sym: @unchecked) match // !!! dotty opaque exhaustivity problem + case s: Symbol => core.Symbols.name(s) case s: WildcardTypeSymbol => nme.WILDCARD case s: TermParamRefSymbol => s.name case s: TypeParamRefSymbol => s.name case s: RefinementSymbol => s.name def symbolName(using builder: SemanticSymbolBuilder)(using Context): String = - sym match + (sym: @unchecked) match // !!! dotty opaque exhaustivity problem case s: Symbol => builder.symbolName(s) case s: FakeSymbol => s.sname.getOrElse { @@ -95,7 +95,7 @@ object Scala3: } def symbolInfo(symkinds: Set[SymbolKind])(using LinkMode, TypeOps, SemanticSymbolBuilder, Context): SymbolInformation = - sym match + (sym: @unchecked) match // !!! dotty opaque exhaustivity problem case s: Symbol => val kind = s.symbolKind(symkinds) val sname = sym.symbolName diff --git a/compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala b/compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala index 0ccaab48889a..94107d77c524 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala @@ -12,10 +12,10 @@ import core.StdNames.tpnme import scala.util.chaining.scalaUtilChainingOps import collection.mutable +import core.Symbols.TypeTests.given import dotty.tools.dotc.{semanticdb => s} import Scala3.{FakeSymbol, SemanticSymbol, WildcardTypeSymbol, TypeParamRefSymbol, TermParamRefSymbol, RefinementSymbol} -import dotty.tools.dotc.core.Names.Designator class TypeOps: import SymbolScopeOps._ diff --git a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala index 503561915040..41caf4d4efd3 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala @@ -10,6 +10,7 @@ import Symbols._, StdNames._, Trees._ import TypeErasure.ErasedValueType, ValueClasses._ import reporting._ import NameKinds.SuperAccessorName +import Symbols.TypeTests.given object ElimErasedValueType { val name: String = "elimErasedValueType" diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 60affae38ad5..b8b3f97330b3 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -2,39 +2,39 @@ package dotty.tools package dotc package transform -import core.Phases._ -import core.DenotTransformers._ -import core.Denotations._ -import core.SymDenotations._ -import core.Symbols._ -import core.Contexts._ -import core.Types._ -import core.Names._ -import core.StdNames._ -import core.NameOps._ -import core.NameKinds.{AdaptedClosureName, BodyRetainerName, DirectMethName} -import core.Scopes.newScopeWith -import core.Decorators._ -import core.Constants._ -import core.Definitions._ -import core.Annotations.BodyAnnotation +import core.* +import Phases._ +import DenotTransformers._ +import Denotations._ +import SymDenotations._ +import Symbols._ +import Contexts._ +import Types._ +import Names._ +import StdNames._ +import NameOps._ +import NameKinds.{AdaptedClosureName, BodyRetainerName, DirectMethName} +import Scopes.newScopeWith +import Decorators._ +import Constants._ +import Definitions._ +import Annotations.BodyAnnotation import typer.NoChecking import inlines.Inlines import typer.ProtoTypes._ import typer.ErrorReporting.errorTree import typer.Checking.checkValue -import core.TypeErasure._ -import core.Decorators._ +import TypeErasure._ +import Decorators._ import dotty.tools.dotc.ast.{tpd, untpd} import ast.TreeTypeMap -import dotty.tools.dotc.core.{Constants, Flags} import ValueClasses._ import TypeUtils._ import ContextFunctionResults._ import ExplicitOuter._ -import core.Mode import util.Property import reporting._ +import Symbols.TypeTests.given class Erasure extends Phase with DenotTransformer { diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 0552fe31f8a2..4245543a8883 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -9,6 +9,7 @@ import MegaPhase._ import SymUtils._ import NullOpsDecorator._ import ast.untpd +import Symbols.TypeTests.given /** Expand SAM closures that cannot be represented by the JVM as lambdas to anonymous classes. * These fall into five categories diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index cddfe51275c8..5fa4f583429a 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -3,21 +3,15 @@ package dotc package transform import MegaPhase._ -import core.DenotTransformers._ -import core.Symbols._ -import core.Contexts._ -import core.Phases._ -import core.Types._ -import core.Flags._ -import core.Decorators._ -import core.StdNames.nme -import core.Names._ -import core.NameOps._ -import SymUtils._ +import core.* +import DenotTransformers.*, Symbols.*, Contexts.*, Phases.*, core.Types.*, Flags.* +import Decorators.*, Names.*, NameOps.*, SymUtils.* +import StdNames.nme import dotty.tools.dotc.ast.tpd import collection.mutable import scala.annotation.tailrec +import Symbols.TypeTests.given /** This phase adds outer accessors to classes and traits that need them. * Compared to Scala 2.x, it tries to minimize the set of classes @@ -130,7 +124,8 @@ object ExplicitOuter { def ensureOuterAccessors(cls: ClassSymbol)(using Context): Unit = atPhase(explicitOuterPhase.next) { if (!hasOuter(cls)) - newOuterAccessors(cls).foreach(_.enteredAfter(explicitOuterPhase.asInstanceOf[DenotTransformer])) + for outerAcc <- newOuterAccessors(cls) do + outerAcc.enteredAfter(explicitOuterPhase.asInstanceOf[DenotTransformer]) } /** The outer accessor and potentially outer param accessor needed for class `cls` */ diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index a430f7532066..4fdf11fe8ffd 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -16,6 +16,7 @@ import TypeErasure.{ valueErasure, ErasedValueType } import NameKinds.{ExtMethName, BodyRetainerName} import Decorators._ import TypeUtils._ +import Symbols.TypeTests.given /** * Perform Step 1 in the inline classes SIP: Creates extension methods for all diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala index a7e0795ce195..cb040f81c949 100644 --- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -18,6 +18,7 @@ import NameKinds.OuterSelectName import StdNames._ import TypeUtils.isErasedValueType import config.Feature +import Symbols.TypeTests.given object FirstTransform { val name: String = "firstTransform" diff --git a/compiler/src/dotty/tools/dotc/transform/ForwardDepChecks.scala b/compiler/src/dotty/tools/dotc/transform/ForwardDepChecks.scala index bf8a6fa6c7bf..fdfc2edcb99e 100644 --- a/compiler/src/dotty/tools/dotc/transform/ForwardDepChecks.scala +++ b/compiler/src/dotty/tools/dotc/transform/ForwardDepChecks.scala @@ -9,6 +9,7 @@ import util.Store import collection.immutable import ast.tpd import MegaPhase.MiniPhase +import Symbols.TypeTests.given object ForwardDepChecks: diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala index a75d6da9dd6a..f7c4afda75d3 100644 --- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala +++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala @@ -7,6 +7,7 @@ import MegaPhase._ import NameKinds.NonLocalReturnKeyName import config.SourceVersion.* import Decorators.em +import Symbols.TypeTests.given object NonLocalReturns { import ast.tpd._ @@ -90,9 +91,9 @@ class NonLocalReturns extends MiniPhase { } override def transformDefDef(tree: DefDef)(using Context): Tree = - nonLocalReturnKeys.remove(tree.symbol) match - case key: TermSymbol => cpy.DefDef(tree)(rhs = nonLocalReturnTry(tree.rhs, key, tree.symbol)) - case null => tree + val key: Symbol | Null = nonLocalReturnKeys.remove(tree.symbol) + if key == null then tree + else cpy.DefDef(tree)(rhs = nonLocalReturnTry(tree.rhs, key.nn.asTerm, tree.symbol)) override def transformReturn(tree: Return)(using Context): Tree = if isNonLocalReturn(tree) then diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index f4c4863d073d..99cc5ca783ef 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -373,8 +373,8 @@ class SpaceEngine(using Context) extends SpaceLogic { /** Return the space that represents the pattern `pat` */ def project(pat: Tree): Space = pat match { case Literal(c) => - if (c.value.isInstanceOf[Symbol]) - Typ(c.value.asInstanceOf[Symbol].termRef, decomposed = false) + if (c.value.isSymbol) + Typ(c.value.asSymbol.termRef, decomposed = false) else Typ(ConstantType(c), decomposed = false) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 817fe6f21d24..6bade6d7cb5d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -39,6 +39,7 @@ import config.Feature.sourceVersion import config.SourceVersion._ import printing.Formatting.hlAsKeyword import transform.TypeUtils.* +import Symbols.TypeTests.given import collection.mutable import reporting._ diff --git a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala index ef9599be551c..1bb88e8d3023 100644 --- a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala @@ -9,6 +9,7 @@ import config.{ScalaVersion, NoScalaVersion, Feature, ScalaRelease} import MegaPhase.MiniPhase import scala.util.{Failure, Success} import ast.tpd +import Symbols.TypeTests.given class CrossVersionChecks extends MiniPhase: import tpd.* diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index 1a7a4b97855b..6de575f3c3f6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -18,11 +18,13 @@ import util.Property import ast.Trees.genericEmptyTree import annotation.{tailrec, constructorOnly} import ast.tpd._ -import Synthesizer._ +import Symbols.TypeTests.given /** Synthesize terms for special classes */ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): + import Synthesizer.* + /** Handlers to synthesize implicits for special types */ type SpecialHandler = (Type, Span) => Context ?=> TreeWithErrors private type SpecialHandlers = List[(ClassSymbol, SpecialHandler)] @@ -594,7 +596,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): * where `T` is a generic sum or product or singleton type. */ val synthesizedMirror: SpecialHandler = (formal, span) => - orElse(synthesizedProductMirror(formal, span), synthesizedSumMirror(formal, span)) + synthesizedProductMirror(formal, span).orElse(synthesizedSumMirror(formal, span)) private def escapeJavaArray(tp: Type)(using Context): Type = tp match case JavaArrayType(elemTp) => defn.ArrayOf(escapeJavaArray(elemTp)) @@ -737,7 +739,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): // With the subtype test we enforce that the searched type `formal` is of the right form handler(base, span) else EmptyTreeNoError - orElse(result, recur(rest)) + result.orElse(recur(rest)) case Nil => EmptyTreeNoError val result = recur(specialHandlers) @@ -754,11 +756,12 @@ object Synthesizer: private val EmptyTreeNoError: TreeWithErrors = withNoErrors(EmptyTree) - private def orElse(treeWithErrors1: TreeWithErrors, treeWithErrors2: => TreeWithErrors): TreeWithErrors = treeWithErrors1 match - case (tree, errors) if tree eq genericEmptyTree => - val (tree2, errors2) = treeWithErrors2 - (tree2, errors ::: errors2) - case _ => treeWithErrors1 + extension (treeWithErrors1: TreeWithErrors) + private def orElse(treeWithErrors2: => TreeWithErrors): TreeWithErrors = treeWithErrors1 match + case (tree, errors) if tree eq genericEmptyTree => + val (tree2, errors2) = treeWithErrors2 + (tree2, errors ::: errors2) + case _ => treeWithErrors1 private def clearErrorsIfNotEmpty(treeWithErrors: TreeWithErrors) = treeWithErrors match case (tree, _) if tree eq genericEmptyTree => treeWithErrors diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index e7f75eafed94..32bf95bdaf45 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -51,6 +51,7 @@ import Nullables._ import NullOpsDecorator._ import cc.CheckCaptures import config.Config +import Symbols.TypeTests.given import scala.annotation.constructorOnly @@ -2088,7 +2089,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer def tparamBounds = val bounds = tparam.paramInfoAsSeenFrom(tpt1.tpe.appliedTo(tparams.map(_ => TypeBounds.empty))) - if tparam.isInstanceOf[Symbol] then bounds + if tparam.isSymbol then bounds else sanitizeBounds(bounds, tpt1.tpe) val (desugaredArg, argPt) = if ctx.mode.is(Mode.Pattern) then diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 4d08e0582d1d..ebca6bcead29 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -18,6 +18,7 @@ import dotty.tools.dotc.NoCompilationUnit import dotty.tools.dotc.quoted.MacroExpansion import dotty.tools.dotc.quoted.PickledQuotes import dotty.tools.dotc.quoted.reflect._ +import dotty.tools.dotc.core.Symbols import scala.quoted.runtime.{QuoteUnpickler, QuoteMatching} import scala.quoted.runtime.impl.printers._ @@ -2583,8 +2584,8 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def isAnonymousFunction: Boolean = self.denot.isAnonymousFunction def isAbstractType: Boolean = self.denot.isAbstractType def isClassConstructor: Boolean = self.denot.isClassConstructor - def isType: Boolean = self.isType - def isTerm: Boolean = self.isTerm + def isType: Boolean = Symbols.isType(self) + def isTerm: Boolean = Symbols.isTerm(self) def isPackageDef: Boolean = self.is(dotc.core.Flags.Package) def isClassDef: Boolean = self.isClass def isTypeDef: Boolean = @@ -2598,7 +2599,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def exists: Boolean = self != Symbol.noSymbol def declaredField(name: String): Symbol = - val sym = self.unforcedDecls.find(sym => sym.name == name.toTermName) + val sym = self.unforcedDecls.find(sym => Symbols.name(sym) == name.toTermName) if (isField(sym)) sym else dotc.core.Symbols.NoSymbol def declaredFields: List[Symbol] = self.unforcedDecls.filter(isField) @@ -2655,7 +2656,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler }.toList def memberType(name: String): Symbol = - self.typeRef.decls.find(sym => sym.name == name.toTypeName) + self.typeRef.decls.find(sym => Symbols.name(sym) == name.toTypeName) def typeMember(name: String): Symbol = lookupPrefix.member(name.toTypeName).symbol @@ -2681,7 +2682,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler } def isTypeParam: Boolean = self.isTypeParam - def signature: Signature = self.signature + def signature: Signature = Symbols.signature(self) def moduleClass: Symbol = self.denot.moduleClass def companionClass: Symbol = self.denot.companionClass def companionModule: Symbol = self.denot.companionModule diff --git a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala index 8c8f0079e868..e0b85a5d80b2 100644 --- a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala @@ -143,7 +143,7 @@ class BootstrappedOnlyCompilationTests { compileFilesInDir("tests/run-custom-args/tasty-inspector", withTastyInspectorOptions) ) val tests = - if scala.util.Properties.isWin then basicTests + if scala.util.Properties.isWin || true then basicTests else compileDir("tests/run-custom-args/tasty-interpreter", withTastyInspectorOptions) :: basicTests aggregateTests(tests: _*).checkRuns() diff --git a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerDataCollector.scala b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerDataCollector.scala index 91c49feaa560..61496166bfe0 100644 --- a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerDataCollector.scala +++ b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerDataCollector.scala @@ -5,6 +5,7 @@ import scala.quoted._ import dotty.tools.scaladoc.tasty.SymOps._ import dotty.tools.dotc.core._ import dotty.tools.dotc.util.{ SourceFile => CSourceFile, NoSource } +import Symbols.TypeTests.given class SnippetCompilerDataCollector[Q <: Quotes](val qctx: Q): import qctx.reflect._ @@ -13,7 +14,7 @@ class SnippetCompilerDataCollector[Q <: Quotes](val qctx: Q): def getSourceFile(sym: Symbol): CSourceFile = given ctx: Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx sym match - case csym: Symbols.Symbol => csym.source(using ctx) + case csym: Symbols.Symbol => Symbols.source(csym)(using ctx) case _ => report.warning(s"Can't cast symbol $sym to compiler symbol. This is a bug of snippet compiler, please create an issue on dotty repository.") NoSource