Skip to content

Commit 2b2fa90

Browse files
committed
Merge github.com:lampepfl/dotty
2 parents 6e55ceb + f0dd0eb commit 2b2fa90

File tree

52 files changed

+524
-116
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+524
-116
lines changed

.github/workflows/language-reference.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
- name: Generate reference documentation and test links
4646
run: |
4747
cd dotty
48-
./project/scripts/sbt scaladoc/generateReferenceDocumentation --no-regenerate-expected-links
48+
./project/scripts/sbt "scaladoc/generateReferenceDocumentation --no-regenerate-expected-links"
4949
./project/scripts/docsLinksStability ./scaladoc/output/reference ./project/scripts/expected-links/reference-expected-links.txt
5050
cd ..
5151

.github/workflows/scaladoc.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
run: ./project/scripts/sbt scaladoc/generateTestcasesDocumentation
5858

5959
- name: Generate reference documentation
60-
run: ./project/scripts/sbt scaladoc/generateReferenceDocumentation --no-regenerate-expected-links
60+
run: ./project/scripts/sbt scaladoc/generateReferenceDocumentation
6161

6262
- name: Generate Scala 3 documentation
6363
run: ./project/scripts/sbt scaladoc/generateScalaDocumentation

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,6 @@
219219
[submodule "community-build/community-projects/http4s"]
220220
path = community-build/community-projects/http4s
221221
url = https://github.com/dotty-staging/http4s.git
222+
[submodule "community-build/community-projects/parboiled2"]
223+
path = community-build/community-projects/parboiled2
224+
url = https://github.com/dotty-staging/parboiled2.git
Submodule parboiled2 added at 6281277

community-build/src/scala/dotty/communitybuild/projects.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,14 @@ object projects:
761761
dependencies = List(cats, catsEffect3, fs2, disciplineMunit, scalacheckEffect)
762762
)
763763

764+
lazy val parboiled2 = SbtCommunityProject(
765+
project = "parboiled2",
766+
sbtTestCommand = "parboiledCoreJVM/test; parboiledJVM/test",
767+
sbtPublishCommand = "publishLocal",
768+
scalacOptions = SbtCommunityProject.scalacOptions.filter(_ != "-Xcheck-macros"),
769+
dependencies = List(utest, scalacheck)
770+
)
771+
764772
end projects
765773

766774
def allProjects = List(
@@ -841,7 +849,8 @@ def allProjects = List(
841849
projects.specs2,
842850
projects.coop,
843851
projects.spire,
844-
projects.http4s
852+
projects.http4s,
853+
projects.parboiled2,
845854
)
846855

847856
lazy val projectMap = allProjects.groupBy(_.project)

community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class CommunityBuildTestC:
7474
@Test def onnxScala = projects.onnxScala.run()
7575
@Test def oslib = projects.oslib.run()
7676
// @Test def oslibWatch = projects.oslibWatch.run()
77+
@Test def parboiled2 = projects.parboiled2.run()
7778
@Test def playJson = projects.playJson.run()
7879
@Test def pprint = projects.pprint.run()
7980
@Test def protoquill = projects.protoquill.run()

compiler/src/dotty/tools/dotc/ast/MainProxies.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,10 @@ object MainProxies {
242242
val param = paramName.toString
243243
val paramType0 = if formal.isRepeatedParam then formal.argTypes.head.dealias else formal.dealias
244244
val paramType = paramType0.dealias
245-
246-
val paramTypeStr = formal.dealias.typeSymbol.owner.showFullName + "." + paramType.show
245+
val paramTypeOwner = paramType.typeSymbol.owner
246+
val paramTypeStr =
247+
if paramTypeOwner == defn.EmptyPackageClass then paramType.show
248+
else paramTypeOwner.showFullName + "." + paramType.show
247249
val hasDefault = defaultValueSymbols.contains(idx)
248250
val isRepeated = formal.isRepeatedParam
249251
val paramDoc = documentation.argDocs.getOrElse(param, "")

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -578,12 +578,12 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
578578
pre
579579
case _ =>
580580
tree1
581-
581+
582582
val countsAsPure =
583583
if dropOp(tree1).symbol.isInlineVal
584584
then isIdempotentExpr(tree1)
585585
else isPureExpr(tree1)
586-
586+
587587
if countsAsPure then Literal(value).withSpan(tree.span)
588588
else
589589
val pre = dropOp(tree1)
@@ -864,8 +864,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
864864
* that is not a member of an underlying class or trait?
865865
*/
866866
def isStructuralTermSelectOrApply(tree: Tree)(using Context): Boolean = {
867-
def isStructuralTermSelect(tree: Select) = {
868-
def hasRefinement(qualtpe: Type): Boolean = qualtpe.dealias match {
867+
def isStructuralTermSelect(tree: Select) =
868+
def hasRefinement(qualtpe: Type): Boolean = qualtpe.dealias match
869869
case RefinedType(parent, rname, rinfo) =>
870870
rname == tree.name || hasRefinement(parent)
871871
case tp: TypeProxy =>
@@ -876,17 +876,21 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
876876
hasRefinement(tp.tp1) || hasRefinement(tp.tp2)
877877
case _ =>
878878
false
879+
!tree.symbol.exists
880+
&& tree.isTerm
881+
&& {
882+
val qualType = tree.qualifier.tpe
883+
hasRefinement(qualType) && !qualType.derivesFrom(defn.PolyFunctionClass)
879884
}
880-
!tree.symbol.exists && tree.isTerm && hasRefinement(tree.qualifier.tpe)
881-
}
882-
def loop(tree: Tree): Boolean = tree match {
885+
def loop(tree: Tree): Boolean = tree match
886+
case TypeApply(fun, _) =>
887+
loop(fun)
883888
case Apply(fun, _) =>
884889
loop(fun)
885890
case tree: Select =>
886891
isStructuralTermSelect(tree)
887892
case _ =>
888893
false
889-
}
890894
loop(tree)
891895
}
892896

compiler/src/dotty/tools/dotc/core/TypeErasure.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,13 @@ object TypeErasure {
363363
* which leads to more predictable bytecode and (?) faster dynamic dispatch.
364364
*/
365365
def erasedLub(tp1: Type, tp2: Type)(using Context): Type = {
366-
// After erasure, C | {Null, Nothing} is just C, if C is a reference type.
367-
// We need to short-circuit this case here because the regular lub logic below
368-
// relies on the class hierarchy, which doesn't properly capture `Null`s subtyping
369-
// behaviour.
370-
if (tp1.isBottomTypeAfterErasure && tp2.derivesFrom(defn.ObjectClass)) return tp2
371-
if (tp2.isBottomTypeAfterErasure && tp1.derivesFrom(defn.ObjectClass)) return tp1
372-
tp1 match {
366+
// We need to short-circuit the following 2 case because the regular lub logic in the else relies on
367+
// the class hierarchy, which doesn't properly capture `Nothing`/`Null` subtyping behaviour.
368+
if tp1.isRef(defn.NothingClass) || (tp1.isRef(defn.NullClass) && tp2.derivesFrom(defn.ObjectClass)) then
369+
tp2 // After erasure, Nothing | T is just T and Null | C is just C, if C is a reference type.
370+
else if tp2.isRef(defn.NothingClass) || (tp2.isRef(defn.NullClass) && tp1.derivesFrom(defn.ObjectClass)) then
371+
tp1 // After erasure, T | Nothing is just T and C | Null is just C, if C is a reference type.
372+
else tp1 match {
373373
case JavaArrayType(elem1) =>
374374
import dotty.tools.dotc.transform.TypeUtils._
375375
tp2 match {

compiler/src/dotty/tools/dotc/interactive/Completion.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,10 @@ object Completion {
384384
if qual.tpe.isExactlyNothing || qual.tpe.isNullType then
385385
Map.empty
386386
else
387-
val membersFromConversion =
388-
implicitConversionTargets(qual)(using ctx.fresh.setExploreTyperState()).flatMap(accessibleMembers)
389-
membersFromConversion.toSeq.groupByName
387+
implicitConversionTargets(qual)(using ctx.fresh.setExploreTyperState())
388+
.flatMap(accessibleMembers)
389+
.toSeq
390+
.groupByName
390391

391392
/** Completions from extension methods */
392393
private def extensionCompletions(qual: Tree)(using Context): CompletionMap =
@@ -492,15 +493,17 @@ object Completion {
492493

493494
/**
494495
* Given `qual` of type T, finds all the types S such that there exists an implicit conversion
495-
* from T to S.
496+
* from T to S. It then applies conversion method for proper type parameter resolution.
496497
*
497498
* @param qual The argument to which the implicit conversion should be applied.
498-
* @return The set of types that `qual` can be converted to.
499+
* @return The set of types after `qual` implicit conversion.
499500
*/
500501
private def implicitConversionTargets(qual: Tree)(using Context): Set[Type] = {
501502
val typer = ctx.typer
502503
val conversions = new typer.ImplicitSearch(defn.AnyType, qual, pos.span).allImplicits
503-
val targets = conversions.map(_.widen.finalResultType)
504+
val convertedTrees = conversions.flatMap(typer.tryApplyingImplicitConversion(_, qual))
505+
val targets = convertedTrees.map(_.tpe.finalResultType)
506+
504507
interactiv.println(i"implicit conversion targets considered: ${targets.toList}%, %")
505508
targets
506509
}

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3888,7 +3888,7 @@ object Parsers {
38883888
stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens))
38893889
else
38903890
empty = true
3891-
statSepOrEnd(stats, empty, "toplevel definition")
3891+
statSepOrEnd(stats, noPrevStat = empty, "toplevel definition")
38923892
do ()
38933893
stats.toList
38943894
}
@@ -3938,7 +3938,7 @@ object Parsers {
39383938
stats += expr1()
39393939
else
39403940
empty = true
3941-
statSepOrEnd(stats, empty)
3941+
statSepOrEnd(stats, noPrevStat = empty)
39423942
do ()
39433943
(self, if stats.isEmpty then List(EmptyTree) else stats.toList)
39443944
}
@@ -3977,7 +3977,7 @@ object Parsers {
39773977
stats ++= checkLegal(defOrDcl(in.offset, Modifiers()))
39783978
var what = "declaration"
39793979
if inFunReturnType then what += " (possible cause: missing `=` in front of current method body)"
3980-
statSepOrEnd(stats, !dclFound, what)
3980+
statSepOrEnd(stats, noPrevStat = !dclFound, what)
39813981
do ()
39823982
stats.toList
39833983
}
@@ -4016,7 +4016,7 @@ object Parsers {
40164016
stats +++= localDef(in.offset)
40174017
else
40184018
empty = true
4019-
statSepOrEnd(stats, empty, altEnd = CASE)
4019+
statSepOrEnd(stats, noPrevStat = empty, altEnd = CASE)
40204020
do ()
40214021
stats.toList
40224022
}

compiler/src/dotty/tools/dotc/transform/SymUtils.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,9 @@ object SymUtils:
120120
def useCompanionAsSumMirror(using Context): Boolean =
121121
def companionExtendsSum(using Context): Boolean =
122122
self.linkedClass.isSubClass(defn.Mirror_SumClass)
123-
self.linkedClass.exists
124-
&& !self.is(Scala2x)
123+
!self.is(Scala2x)
124+
&& self.linkedClass.exists
125+
&& !self.linkedClass.is(Case)
125126
&& (
126127
// If the sum type is compiled from source, and `self` is a "generic sum"
127128
// then its companion object will become a sum mirror in `posttyper`. (This method

compiler/src/dotty/tools/dotc/transform/TypeUtils.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Contexts._
99
import Symbols._
1010
import Names.Name
1111

12+
import dotty.tools.dotc.core.Decorators.*
13+
1214
object TypeUtils {
1315
/** A decorator that provides methods on types
1416
* that are needed in the transformer pipeline.
@@ -84,11 +86,16 @@ object TypeUtils {
8486
/** The TermRef referring to the companion of the underlying class reference
8587
* of this type, while keeping the same prefix.
8688
*/
87-
def companionRef(using Context): TermRef = self match {
89+
def mirrorCompanionRef(using Context): TermRef = self match {
90+
case OrType(tp1, tp2) =>
91+
val r1 = tp1.mirrorCompanionRef
92+
val r2 = tp2.mirrorCompanionRef
93+
assert(r1.symbol == r2.symbol, em"mirrorCompanionRef mismatch for $self: $r1, $r2 did not have the same symbol")
94+
r1
8895
case self @ TypeRef(prefix, _) if self.symbol.isClass =>
8996
prefix.select(self.symbol.companionModule).asInstanceOf[TermRef]
9097
case self: TypeProxy =>
91-
self.underlying.companionRef
98+
self.underlying.mirrorCompanionRef
9299
}
93100

94101
/** Is this type a methodic type that takes implicit parameters (both old and new) at some point? */

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,27 @@ trait Applications extends Compatibility {
22892289
catch
22902290
case NonFatal(_) => None
22912291

2292+
/** Tries applying conversion method reference to a provided receiver
2293+
*
2294+
* returns converted tree in case of success.
2295+
* None is returned if conversion method application fails.
2296+
*/
2297+
def tryApplyingImplicitConversion(conversionMethodRef: TermRef, receiver: Tree)(using Context): Option[Tree] =
2298+
val conversionMethodTree = ref(conversionMethodRef, needLoad = false)
2299+
val newCtx = ctx.fresh.setNewScope.setReporter(new reporting.ThrowingReporter(ctx.reporter))
2300+
2301+
try
2302+
val appliedTree = inContext(newCtx) {
2303+
typed(untpd.Apply(conversionMethodTree, untpd.TypedSplice(receiver) :: Nil))
2304+
}
2305+
2306+
if appliedTree.tpe.exists && !appliedTree.tpe.isError then
2307+
Some(appliedTree)
2308+
else
2309+
None
2310+
catch
2311+
case NonFatal(x) => None
2312+
22922313
def isApplicableExtensionMethod(methodRef: TermRef, receiverType: Type)(using Context): Boolean =
22932314
methodRef.symbol.is(ExtensionMethod) && !receiverType.isBottomType &&
22942315
tryApplyingExtensionMethod(methodRef, nullLiteral.asInstance(receiverType)).nonEmpty

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
677677
* map them to their opaque proxies.
678678
*/
679679
def mapOpaquesInValueArg(arg: Tree)(using Context): Tree =
680-
val argType = arg.tpe.widen
680+
val argType = arg.tpe.widenDealias
681681
addOpaqueProxies(argType, arg.span, forThisProxy = false)
682682
if opaqueProxies.nonEmpty then
683683
val mappedType = mapOpaques.typeMap(argType)

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
249249

250250
/** A path referencing the companion of class type `clsType` */
251251
private def companionPath(clsType: Type, span: Span)(using Context) =
252-
val ref = pathFor(clsType.companionRef)
252+
val ref = pathFor(clsType.mirrorCompanionRef)
253253
assert(ref.symbol.is(Module) && (clsType.classSymbol.is(ModuleClass) || (ref.symbol.companionClass == clsType.classSymbol)))
254254
ref.withSpan(span)
255255

@@ -275,6 +275,36 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
275275
monoMap(mirroredType.resultType)
276276

277277
private def productMirror(mirroredType: Type, formal: Type, span: Span)(using Context): Tree =
278+
279+
/** do all parts match the class symbol? */
280+
def acceptable(tp: Type, cls: Symbol): Boolean = tp match
281+
case tp: HKTypeLambda if tp.resultType.isInstanceOf[HKTypeLambda] => false
282+
case tp: TypeProxy => acceptable(tp.underlying, cls)
283+
case OrType(tp1, tp2) => acceptable(tp1, cls) && acceptable(tp2, cls)
284+
case _ => tp.classSymbol eq cls
285+
286+
def makeProductMirror(cls: Symbol): Tree =
287+
val accessors = cls.caseAccessors.filterNot(_.isAllOf(PrivateLocal))
288+
val elemLabels = accessors.map(acc => ConstantType(Constant(acc.name.toString)))
289+
val nestedPairs = TypeOps.nestedPairs(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
290+
val (monoType, elemsType) = mirroredType match
291+
case mirroredType: HKTypeLambda =>
292+
(mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
293+
case _ =>
294+
(mirroredType, nestedPairs)
295+
val elemsLabels = TypeOps.nestedPairs(elemLabels)
296+
checkRefinement(formal, tpnme.MirroredElemTypes, elemsType, span)
297+
checkRefinement(formal, tpnme.MirroredElemLabels, elemsLabels, span)
298+
val mirrorType =
299+
mirrorCore(defn.Mirror_ProductClass, monoType, mirroredType, cls.name, formal)
300+
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(elemsType))
301+
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(elemsLabels))
302+
val mirrorRef =
303+
if (cls.is(Scala2x) || cls.linkedClass.is(Case)) anonymousMirror(monoType, ExtendsProductMirror, span)
304+
else companionPath(mirroredType, span)
305+
mirrorRef.cast(mirrorType)
306+
end makeProductMirror
307+
278308
mirroredType match
279309
case AndType(tp1, tp2) =>
280310
productMirror(tp1, formal, span).orElse(productMirror(tp2, formal, span))
@@ -289,28 +319,10 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
289319
else
290320
val mirrorType = mirrorCore(defn.Mirror_SingletonClass, mirroredType, mirroredType, module.name, formal)
291321
modulePath.cast(mirrorType)
292-
else if mirroredType.classSymbol.isGenericProduct then
322+
else
293323
val cls = mirroredType.classSymbol
294-
val accessors = cls.caseAccessors.filterNot(_.isAllOf(PrivateLocal))
295-
val elemLabels = accessors.map(acc => ConstantType(Constant(acc.name.toString)))
296-
val nestedPairs = TypeOps.nestedPairs(accessors.map(mirroredType.resultType.memberInfo(_).widenExpr))
297-
val (monoType, elemsType) = mirroredType match
298-
case mirroredType: HKTypeLambda =>
299-
(mkMirroredMonoType(mirroredType), mirroredType.derivedLambdaType(resType = nestedPairs))
300-
case _ =>
301-
(mirroredType, nestedPairs)
302-
val elemsLabels = TypeOps.nestedPairs(elemLabels)
303-
checkRefinement(formal, tpnme.MirroredElemTypes, elemsType, span)
304-
checkRefinement(formal, tpnme.MirroredElemLabels, elemsLabels, span)
305-
val mirrorType =
306-
mirrorCore(defn.Mirror_ProductClass, monoType, mirroredType, cls.name, formal)
307-
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(elemsType))
308-
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(elemsLabels))
309-
val mirrorRef =
310-
if (cls.is(Scala2x)) anonymousMirror(monoType, ExtendsProductMirror, span)
311-
else companionPath(mirroredType, span)
312-
mirrorRef.cast(mirrorType)
313-
else EmptyTree
324+
if acceptable(mirroredType, cls) && cls.isGenericProduct then makeProductMirror(cls)
325+
else EmptyTree
314326
end productMirror
315327

316328
private def sumMirror(mirroredType: Type, formal: Type, span: Span)(using Context): Tree =
@@ -319,6 +331,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
319331

320332
def acceptable(tp: Type): Boolean = tp match
321333
case tp: TermRef => false
334+
case tp: HKTypeLambda if tp.resultType.isInstanceOf[HKTypeLambda] => false
322335
case tp: TypeProxy => acceptable(tp.underlying)
323336
case OrType(tp1, tp2) => acceptable(tp1) && acceptable(tp2)
324337
case _ => tp.classSymbol eq cls

compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,12 @@ object SourceCode {
530530
case Closure(meth, _) =>
531531
printTree(meth)
532532

533-
case _:Unapply | _:Alternatives | _:Bind =>
533+
case _:TypedOrTest | _:Unapply | _:Alternatives | _:Bind =>
534534
printPattern(tree)
535535

536+
case tree: CaseDef =>
537+
printCaseDef(tree)
538+
536539
case _ =>
537540
throw new MatchError(tree.show(using Printer.TreeStructure))
538541

0 commit comments

Comments
 (0)