diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index bd43578e3d53..c39db64b77cf 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -2720,7 +2720,7 @@ object SymDenotations { || owner.isRefinementClass || owner.is(Scala2x) || owner.unforcedDecls.contains(denot.name, denot.symbol) - || (denot.is(Synthetic) && denot.is(ModuleClass) && stillValidInOwner(denot.companionClass)) + || (denot.is(Synthetic) && denot.is(ModuleClass) && denot.companionClass.exists && stillValidInOwner(denot.companionClass)) || denot.isSelfSym || denot.isLocalDummy) catch case ex: StaleSymbol => false diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index de9fcb8f6cb4..dc683aabe1e6 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -324,15 +324,15 @@ object Completion: * 8. symbol is not a constructor proxy module when in type completion mode * 9. have same term/type kind as name prefix given so far */ - def isValidCompletionSymbol(sym: Symbol, completionMode: Mode, isNew: Boolean)(using Context): Boolean = - + def isValidCompletionSymbol(sym: Symbol, completionMode: Mode, isNew: Boolean)(using Context): Boolean = try lazy val isEnum = sym.is(Enum) || (sym.companionClass.exists && sym.companionClass.is(Enum)) sym.exists && !sym.isAbsent(canForce = false) && !sym.isPrimaryConstructor && - sym.sourceSymbol.exists && + // running sourceSymbol on ExportedTerm will force a lot of computation from collectSubTrees + (sym.is(ExportedTerm) || sym.sourceSymbol.exists) && (!sym.is(Package) || sym.is(ModuleClass)) && !sym.isAllOf(Mutable | Accessor) && !sym.isPackageObject && @@ -343,6 +343,9 @@ object Completion: (completionMode.is(Mode.Term) && (sym.isTerm || sym.is(ModuleClass)) || (completionMode.is(Mode.Type) && (sym.isType || sym.isStableMember))) ) + catch + case NonFatal(ex) => + false end isValidCompletionSymbol given ScopeOrdering(using Context): Ordering[Seq[SingleDenotation]] with diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index b452f558f969..f23c762ed6f3 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -924,7 +924,7 @@ object CheckUnused: def isCanEqual: Boolean = sym.isOneOf(GivenOrImplicit) && sym.info.finalResultType.baseClasses.exists(_.derivesFrom(defn.CanEqualClass)) def isMarkerTrait: Boolean = - sym.info.hiBound.allMembers.forall: d => + sym.info.hiBound.resultType.allMembers.forall: d => val m = d.symbol !m.isTerm || m.isSelfSym || m.is(Method) && (m.owner == defn.AnyClass || m.owner == defn.ObjectClass) def isEffectivelyPrivate: Boolean = diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala index 472ed78bfb6b..08c2c6a015c0 100644 --- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala +++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala @@ -346,7 +346,10 @@ class TailRec extends MiniPhase { case prefix: This if prefix.symbol == enclosingClass => // Avoid assigning `this = this` assignParamPairs - case prefix if prefix.symbol.is(Module) && prefix.symbol.moduleClass == enclosingClass => + case prefix + if prefix.symbol.is(Module) + && prefix.symbol.moduleClass == enclosingClass + && isPurePath(prefix) => // Avoid assigning `this = MyObject` assignParamPairs case _ => diff --git a/tests/neg/i19351.check b/tests/neg/i19351.check deleted file mode 100644 index a9ee10510b32..000000000000 --- a/tests/neg/i19351.check +++ /dev/null @@ -1,4 +0,0 @@ --- Error: tests/neg/i19351/A.scala:3:35 -------------------------------------------------------------------------------- -3 | inline def myMacro(): x.type = ${myMacroExpr} // error - | ^ - |Cyclic macro dependency; macro refers to a toplevel symbol in tests/neg/i19351/A.scala from which the macro is called diff --git a/tests/neg/i19351/A.scala b/tests/neg/i19351/A.scala deleted file mode 100644 index f2258631a15a..000000000000 --- a/tests/neg/i19351/A.scala +++ /dev/null @@ -1,5 +0,0 @@ -//object A: - val x: Int = 1 - inline def myMacro(): x.type = ${myMacroExpr} // error - def test = myMacro() - diff --git a/tests/neg/i19351a.check b/tests/neg/i19351a.check deleted file mode 100644 index 10789c2db5aa..000000000000 --- a/tests/neg/i19351a.check +++ /dev/null @@ -1,4 +0,0 @@ --- Error: tests/neg/i19351a/Test.scala:8:34 ---------------------------------------------------------------------------- -8 |inline def not(b: Bool): Bool = ${notMacro('b)} // error - | ^ - |Cyclic macro dependency; macro refers to a toplevel symbol in tests/neg/i19351a/Test.scala from which the macro is called diff --git a/tests/pos-macros/i13821-a/Macro.scala b/tests/pos-macros/i13821-a/Macro.scala new file mode 100644 index 000000000000..3583a44ffddc --- /dev/null +++ b/tests/pos-macros/i13821-a/Macro.scala @@ -0,0 +1,6 @@ +trait Conversions: + given conv(using DFBits.Candidate): Conversion[Int, DFVal] = ??? + +import scala.quoted.* +transparent inline def f: Short = ${ getWidthMacro } +private def getWidthMacro(using Quotes): Expr[Short] = '{ ??? } diff --git a/tests/pos-macros/i13821-a/Test.scala b/tests/pos-macros/i13821-a/Test.scala new file mode 100644 index 000000000000..86f5a6289a80 --- /dev/null +++ b/tests/pos-macros/i13821-a/Test.scala @@ -0,0 +1,12 @@ +type DFBits = Long +object DFBits: + def a: Unit = f // forces suspension of this compilation unit in typer + def b: DFVal = 2 // uses implicit conversion `DFVal.conv` + + trait Candidate + object Candidate: + given candidate: Candidate = ??? // completed in run 3 but created in run 2 +end DFBits + +trait DFVal +object DFVal extends Conversions diff --git a/tests/pos-macros/i13821-b/Macro.scala b/tests/pos-macros/i13821-b/Macro.scala new file mode 100644 index 000000000000..c1c9c5e17851 --- /dev/null +++ b/tests/pos-macros/i13821-b/Macro.scala @@ -0,0 +1,7 @@ +import outer._ +trait Conversions: + given conv(using DFBits.Candidate): Conversion[Int, DFVal] = ??? + +import scala.quoted.* +transparent inline def f: Short = ${ getWidthMacro } +private def getWidthMacro(using Quotes): Expr[Short] = '{ ??? } diff --git a/tests/pos-macros/i13821-b/Test.scala b/tests/pos-macros/i13821-b/Test.scala new file mode 100644 index 000000000000..5c9b8755a33c --- /dev/null +++ b/tests/pos-macros/i13821-b/Test.scala @@ -0,0 +1,14 @@ +type outer = Int +object outer: + type DFBits = Long + object DFBits: + def a: Unit = f // forces suspension of this compilation unit in typer + def b: DFVal = 2 // uses implicit conversion `DFVal.conv` + + trait Candidate + object Candidate: + given candidate: Candidate = ??? // completed in run 3 but created in run 2 + end DFBits + + trait DFVal + object DFVal extends Conversions diff --git a/tests/pos-macros/i19351/A.scala b/tests/pos-macros/i19351/A.scala new file mode 100644 index 000000000000..0b2c7acc3797 --- /dev/null +++ b/tests/pos-macros/i19351/A.scala @@ -0,0 +1,6 @@ +// object A: + val x: Int = 1 + inline def myMacro(): x.type = ${myMacroExpr} + def test = myMacro() + +@main def main() = () \ No newline at end of file diff --git a/tests/neg/i19351/B.scala b/tests/pos-macros/i19351/B.scala similarity index 84% rename from tests/neg/i19351/B.scala rename to tests/pos-macros/i19351/B.scala index 8c8c071f3607..a22b4d5c51b6 100644 --- a/tests/neg/i19351/B.scala +++ b/tests/pos-macros/i19351/B.scala @@ -1,3 +1,3 @@ import scala.quoted.* -//import A.* +// import A.* def myMacroExpr(using Quotes): Expr[x.type] = '{???} \ No newline at end of file diff --git a/tests/neg/i19351a/Macro.scala b/tests/pos-macros/i19351a/Macro.scala similarity index 100% rename from tests/neg/i19351a/Macro.scala rename to tests/pos-macros/i19351a/Macro.scala diff --git a/tests/neg/i19351a/Test.scala b/tests/pos-macros/i19351a/Test.scala similarity index 87% rename from tests/neg/i19351a/Test.scala rename to tests/pos-macros/i19351a/Test.scala index 84fb6ca4ae78..7f9e6dbc9786 100644 --- a/tests/neg/i19351a/Test.scala +++ b/tests/pos-macros/i19351a/Test.scala @@ -5,7 +5,7 @@ type Bool = [R] => (R, R) => R val True: Bool = [R] => (t: R, _: R) => t val False: Bool = [R] => (_: R, f: R) => f -inline def not(b: Bool): Bool = ${notMacro('b)} // error +inline def not(b: Bool): Bool = ${notMacro('b)} inline def show(b: Bool): String = ${showMacro('b)} //inline def not(b: Bool): Bool = ${foldMacro('b, 'False, 'True)} //inline def show(b: Bool): String = ${foldMacro('b, '{"TRUE"}, '{"FALSE"})} diff --git a/tests/run/i23444.scala b/tests/run/i23444.scala new file mode 100644 index 000000000000..ada7545e077f --- /dev/null +++ b/tests/run/i23444.scala @@ -0,0 +1,22 @@ + +import annotation.* + +class Path(action: () => Unit, parent: Option[Path]): + object O: + @tailrec + def apply(): Unit = + action() + + parent match + case Some(p) => + p.O.apply() + case None => + +@main def Test: Unit = + var counter = 0 + val fun = () => { + counter += 1 + if counter > 2 then throw AssertionError("bad loop") + } + val path = Path(fun, Some(Path(fun, None))) + path.O() diff --git a/tests/warn/i15503f.scala b/tests/warn/i15503f.scala index c2eef8a529c5..70d0b9182eb2 100644 --- a/tests/warn/i15503f.scala +++ b/tests/warn/i15503f.scala @@ -1,4 +1,4 @@ -//> using options -Wunused:implicits +//> using options -Wunused:implicits /* This goes around the "trivial method" detection */ val default_int = 1 @@ -67,6 +67,8 @@ package givens: trait Y: def doY: String + trait Z + given X: def doX = 7 @@ -84,6 +86,9 @@ package givens: given namely: (x: X) => Y: // warn protected param to given class def doY = "8" + + def f(using => X) = println() // warn + def g(using => Z) = println() // nowarn marker trait end givens object i22895: diff --git a/tests/warn/i23494.scala b/tests/warn/i23494.scala new file mode 100644 index 000000000000..c3c0c5a2e0bc --- /dev/null +++ b/tests/warn/i23494.scala @@ -0,0 +1,15 @@ +//> using options -Wunused:implicits + +import scala.deriving.Mirror + +abstract class EnumerationValues[A]: + type Out + +object EnumerationValues: + type Aux[A, B] = EnumerationValues[A] { type Out = B } + + def apply[A, B](): EnumerationValues.Aux[A, B] = new EnumerationValues[A]: + override type Out = B + + given sum[A, B <: Tuple](using mirror: Mirror.SumOf[A] { type MirroredElemTypes = B }): EnumerationValues.Aux[A, A] = + EnumerationValues[A, A]()