Skip to content

Commit 8ee622a

Browse files
committed
Add tests
Add tests Add tests Add tests Update Desugar.scala Update InteractiveDriver.scala Update closureLeak.scala Update default-this.scala Update enum.scala Update leak-this-inner.scala Update leak-this.scala Update leak-warm.scala Update local-warm.scala updated test cases updated-default-this updated tests Add tests for cycle structure Add desugared version for enum.scala Update Desugar.scala Update InteractiveDriver.scala Update closureLeak.scala Update default-this.scala Update enum.scala Update leak-this-inner.scala Update leak-this.scala Update leak-warm.scala Update local-warm.scala Comment Typo Fix in Concat Correctly check experimental features - When inlining: emit "experimental" error only when the feature in question is actually annotated as experimental - Compiler-wide: treat non-bootstrapped compiler as experimental-friendly. The motivation is to compile the standard library with experimental features enabled at all times. This change isn't supposed to introduce any experimental features leaks into stable builds since we do not publish non-bootstrapped compiler. Fix #12128: Add test Don't force info to get signature in TreeChecker When we are reading a new definition from tasty and setting `info` of a symbol in `readNewDef`: sym.info = methodType(paramss, resType) The line above will reach `TreeChecker.transformSym`: assert(symd.signature == initial.signature At the time, the `symd` is not yet completed. Getting signature of the denotation will force the symbol and trigger completion of the info, which reaches the `PositionTree` in `readIndexedDef. Fix regression test for #12128 To properly reproduce #12128, the regression test has some atypical classpath requirements in addition to separate compilation. Snippet compiler PoC Reporter fix. Message levels Fix snippet wrapper. Integrate snippet checker with Wiki and Markdown renderers Further implementation of snippet compiler. Add package name and self type to pass context Add arguments to control snippet compiler. Start work on handling hide directives in code snippets Hide irrelevant code snippet fragments in scaladoc Apply review suggestions from PR #11822 Add returning real line of error in source file of snippet for snippet scaladoc compiler Add failing flag Add debug flag. Add addition operation for snippet compiler arg Refactor snippet compiler args Move snippet compiler logic to parsing phase. Refactor debug flag Display snippet compilation messages in scaladoc Apply review changes Run snippet compiler on static sites Further enhancements of snippet contexts Filter non-scala snippets. Report errors in parsing override flags Fix positions in static sites. Enchance snippet wrapping CRs Add and update tests for snippet compiler. Bugfixes found during testing Wrap compiler messages into Try block to avoid lazy exceptions Update branch Fix classpath problems. Add support for scala.js. Add bootclasspath to generateDocumentation task Temporarily turn off snippet checking for scala3 library Change requests from reviews Scala2Unpickler: Don't trust the owner field of tparams When a type parameter of a class external to the current pickle is referenced, Scala 2 will sometimes pickle it as if it was a type parameter of the current class. When we unpickle such a type parameter on our side, we enter it in the class, this leads the compiler to believe the class has more type parameters than it actually has. This doesn't happen in Scala 2 itself because it never enters unpickled type parameters in the class that owns them (it must be recreating them in some way, but I don't know how). It would be interesting to dig deeper to understand exactly how Scala 2 handles type parameter unpickling so we could emulate it given that this is not the first time we run into trouble here (cf #12120), but for now we fix the problem with the following heuristic: once we've loaded all the type parameters of a class (which we do eagerly via `ClassUnpickler#init()`), we simply stop from being entered any subsequent type parameter we see for this class. Time will tell if this is good enough. While I was touching that code, I also made ClassCompleter#completerTypeParams idempotent as one would expect it to be. Fixes #12641. Preserve hard unions in more situations There's multiple places where we take apart a union, apply some transformation to its parts, then either return the original union if nothing changed or recombine the transformed parts into a new union. The problem is that to check if nothing changed we use referential equality when `=:=` would be more correct, so we sometimes end up returning a union equivalent to the original one except the new one is a soft union. I've seen this lead to subtle type inference differences both when experimenting with changes to constraint solving and when trying to replace our Uniques hashmaps by weak hashmaps. We could fix this by replacing these `eq` calls by `=:=` but instead this commit takes the approach of preserving the softness of a union even when its components are modified, see the test case. Fix implicit ValueOf synthesis Foxes #12583 Fix hole in scan for outer references Type tests of singletons need to be considered as well. Fix typo in syntax.md The supertype symbol was ':>' and it was changed to '>:' . Always generate a partial function from a lambda `scalac` no longer complains, neither should `dotc`. I verified that the output of `i4241.scala` is the same for both `scalac` and `dotc`. Fixes #12661 drop unused code Fix test name Extract the function type and SAM in union type (#11760) Fixes #11694. forbid given patterns in val definitions. Suggest that they use an alias given instead. Fix #12544: Add test Add neg test Harden type comparer in presence of kind errors It should not crash when an override has the wrong kind. Fixes #12664 Fix #12546: Handle enum or object in provablyDisjoint A enum or object is provably disjoint with a class A if the module class does not derive from A. Better support type-heavy pattern matches Avoid type cast Fix unreachable code Fix CI Handle enums that have multiple parents Fix #12559: Try decomposable types in isSubspace Fix #12602: Only generate sum mirrors for sealed trait or sealed abstract class Fix #12681: Approximate `ThisType` in child instantiation Fix master: Remove test We will add the test again with a new PR fix #12634 - port sbt/zinc#979 Add sealedDescendants method to SymDenotation - recursive children of a symbol Add Matchable to the parents of Null in explicit nulls Add icons for all members. Add icons for search results. Re-enable the Scala.js test JSOptionalTest212FunParamInference. The issue #11694, which prevented this test from compiling, was fixed in #11760. Bump compiler version to the next one – 3.0.2-RC1 fix #12401: mangle ctor names in ExtractAPI Avoid assertion failure when forcing LazyRef while printing Fixes #12650 The fix that matters for #12650 is the one in Checking. The others generally increase robustness of printing diagnostics when triggering a LazyRef recursion. Drop flaky test Fixes #12693 Deskolemize PatternTypeConstrainer Before this commit, constrainSimplePatternType did a bunch of manipulations and then ran a subtype check. It wrapped one of the types in a SkolemType and replaces type arguments of the other one with wildcards. The point of those manipulations was to make TypeComparer take a specific path and compare appropriate subcomponents of constrainSimplePatternType's arguments. This turned out to be a problem overall. To improve the situation, we instead manually compare the appropriate subcomponents of constrainSimplePatternType - the changes can be seen as inlining pieces of code from TypeComparer. Also, this commit adds restoring the GADT constraint to TypeComparer - this turned out to be more important now that constrainSimplePatternType now does multiple isSubType checks. Fix failing test Add explanatory comments Adjust comments Insert conversions also on selections wrapped in type applications In i12708.scala, the problematic function was a selection `qual.m[tvs]` that was already applied to type variables. In that case we need to backtrack, forget the type variables and try to insert a conversion or extension method on `qual`. Fixes #12708 Fix tests Add 3.0.1-RC1 blog article Remove experimental macro feature mention Co-authored-by: Nicolas Stucki <[email protected]> macros.md: fix parentheses/braces in inlined Macros.assert() example The parantheses and braces where swapped. Also align the style with the follow up example to make it easier to spot the differences. Add regression test for #12723 Deleted unnecessary explanations As a result of replacing 'Dotty' with 'Scala 3' in the following commit, the explanation 'which is scheduled to become Scala 3' is no longer needed. ccb76da Improve display of references for ambiguous implicit errors If the first attempt yields equal strings, print the full path to the implicits instead. Fixes #12591 Reclassify test Add check file Improvements to search UX Pressing "S" while not focused on an input/textarea will now open the search. Pressing "F" while not focused on an input/textarea will focus the member filter input. Pressing Escape while focused on the search/filter will clear the input and close/unfocus it Search result links are now treated as block elements so you can click anywhere inside the rectangle rather than specifically on the result text. also allow '/' to trigger the search Add browsable versions extension for scaladoc Change local storage to session storage, fix bugs with undefined js variable Chagne try catching of undefined scalajs property to js.typeOf Add test for infix operator usage from Scala 2 libraries Fixes #7304 Preserve tvar instantiation in implicit error messages make default colors less harsh, add dark/light theme swapper make dottydoc anchors transparent instead of white when not hovered infer dark theme preference from user's system add some 'missing' semicolons to some JS set min-width on the theme switch so it doesn't get squished Make dark-mode footer actually dark. Improve contrast/accessibility. Used the "poor man's dark mode" approach to deal with the images in the footer in dark mode, i.e. invert and hue rotate (without the hue rotate, the red scala3doc logo becomes blue) Also fix an issue where if you click "back to top" and then refresh the page, the "container" element gains the "expand" class, which causes the main signature (i.e. `class List[A] ...`) to become 'inline' instead of a block, and it also triggers the 6.5em left-margin that's intended for method signatures when they get expanded. Also consolidated the `footer` styles, since they were spread all over. Check CLA for user who opened pull request, not workflow initiator Add regression test Closes #12754 Don't allow wildcard types in constraints Fixes #12677 Only drop wildcards for necesessary comparisons Wildcards in constraints essentially mean that the constrained variable is a sub/supertype of _every_ instance of the bound. For useNecesaryEither, this is wrong. Approximate the bound not to use wildcards instead. drop all kinds of WildcardType under useNecessaryEither better bounds for wildcards in resultTypeApprox Avoid wildcard types in constraints Ther semantics is fishy. Instead, use avoidance in necessarySubType and in TypeVarsMiss context mode, and use fresh type variables elsehwere. Cleanup addOneBound logic Verify that constraints do not contain wildcard types Cleanups Streamline approximateWildcards logic Test assertion Don't let wildcards enter constraints when adding type lambdas Fix typo Turn off "no wildcards in constraint" check Address review comments macros.md: Fix htmlized variant of first source code example Confusingly, the last part of the first source code example would appear as def showExpr(expr: Expr[Boolean])(using Quotes): Expr[String] = '{ " " } in the htmlized version of the markdown documentation source. Which reads as follows: def showExpr(expr: Expr[Boolean])(using Quotes): Expr[String] = '{ "<some source code>" } // Better implementation later in this document This seems to be cause by the usage of angle brackets. Also note that the code comment does not appear in the htmlized output. Fix typo in 3.0.1-RC1 release notes Fix #9588: Enable Scala.js test ObjectTest. The issue preventing that test from compiling in the past was fixed, although we don't know when or by what. Scala.js: Mangle test names when generating JUnit bootstrappers. This fixes the last remaining JUnit-related tests, which we therefore enable. Copy old site versions for Scala 3 instead of Dotty 0.X Support both 0.X and 3.X lines For extension label, avoid scala style Fix escaping illegal tokens in snippet renderer in scaladoc Use sbt makeScalaInstance Add definition Add doc for env Fix compilation Refactor trace Support Value.source for friendly error message Disallow non-hot arguments to non-constructors Handle access of parameters in constructors Handle exception No exceptions Fix Env.isHot Add missing checks for arguments Handle new expression with only cold args Fix soundness test Reorganize tests Add test Add test for secondary constructor Refactor promotion Add test More logging Fix bug with promotion of this The previous code does not work, because private fields are not included. Refactor code: introduce ArgInfo instead of Value.source Handle O.this outside of it's definition Fix owner of values with static flag With the flag <static>, the enclosing class will be skipped. See the documentation `SymDenotation.enclosingClass` Add documentation about caching Add test Add another neg test for promotion of ThisRef Handle outers of trait as the same in concrete semantics For traits, its outers will be proxy methods of the class that extends the trait. As the prefix is stable and is a valid value before any super constructor calls. Therefore, we may think the outers for traits are immediately set following the class parameters. Also, when trying promotion of warm values, we never try warm values whose fields are not fully filled -- which corresponds to promote ThisRef with non-initialized fields, and errors will be reported when the class is checked separately. Address review (thanks @michelou) Rename isFullyInitialized to isFullyFilled to avoid confusion Restrict function arguments to be hot This aligns with the design of restricting method arguments to be hot. We only allow non-hot to constructors. Add documentation Address review Simplify logic for checking local classes inside secondary constructors Address review: simplify logic Abstract parameters of non-local constructor parameters as cold This is a simple fix which should have no impact on expressiveness and usability, as local classes inside secondary constructors are extremely rare. Update docs Fix #11973: Add regression test community build: Update munit Add Libretto to community build. re-organize tests
1 parent ab197fb commit 8ee622a

File tree

234 files changed

+4825
-1546
lines changed

Some content is hidden

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

234 files changed

+4825
-1546
lines changed

.github/workflows/cla.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ jobs:
66
steps:
77
- uses: actions/checkout@v2
88
- run: ./project/scripts/check-cla.sh
9+
env:
10+
AUTHOR: ${{ github.event.pull_request.user.login }}

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,6 @@
201201
[submodule "community-build/community-projects/fs2"]
202202
path = community-build/community-projects/fs2
203203
url = https://github.com/dotty-staging/fs2.git
204+
[submodule "community-build/community-projects/libretto"]
205+
path = community-build/community-projects/libretto
206+
url = https://github.com/dotty-staging/libretto.git
Submodule libretto added at d229f3c
Submodule munit updated 38 files

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,13 @@ object projects:
691691
dependencies = List(cats, catsEffect3, munitCatsEffect, scalacheckEffect, scodecBits)
692692
)
693693

694+
lazy val libretto = SbtCommunityProject(
695+
project = "libretto",
696+
sbtTestCommand = "core/test; examples/compile",
697+
sbtPublishCommand = "core/publishLocal; examples/publishLocal",
698+
dependencies = List(scalatest)
699+
)
700+
694701
end projects
695702

696703
def allProjects = List(
@@ -765,6 +772,7 @@ def allProjects = List(
765772
projects.munitCatsEffect,
766773
projects.scalacheckEffect,
767774
projects.fs2,
775+
projects.libretto,
768776
)
769777

770778
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
@@ -144,6 +144,7 @@ class CommunityBuildTestC extends CommunityBuildTest:
144144
@Test def fastparse = projects.fastparse.run()
145145
@Test def geny = projects.geny.run()
146146
@Test def intent = projects.intent.run()
147+
@Test def libretto = projects.libretto.run()
147148
@Test def minitest = projects.minitest.run()
148149
@Test def onnxScala = projects.onnxScala.run()
149150
@Test def oslib = projects.oslib.run()

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

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,16 @@ object desugar {
10931093
case IdPattern(named, tpt) =>
10941094
derivedValDef(original, named, tpt, rhs, mods)
10951095
case _ =>
1096+
1097+
def filterWildcardGivenBinding(givenPat: Bind): Boolean =
1098+
givenPat.name != nme.WILDCARD
1099+
1100+
def errorOnGivenBinding(bind: Bind)(using Context): Boolean =
1101+
report.error(
1102+
em"""${hl("given")} patterns are not allowed in a ${hl("val")} definition,
1103+
|please bind to an identifier and use an alias given.""".stripMargin, bind)
1104+
false
1105+
10961106
def isTuplePattern(arity: Int): Boolean = pat match {
10971107
case Tuple(pats) if pats.size == arity =>
10981108
pats.forall(isVarPattern)
@@ -1108,13 +1118,23 @@ object desugar {
11081118
// - `pat` is a tuple of N variables or wildcard patterns like `(x1, x2, ..., xN)`
11091119
val tupleOptimizable = forallResults(rhs, isMatchingTuple)
11101120

1121+
val inAliasGenerator = original match
1122+
case _: GenAlias => true
1123+
case _ => false
1124+
11111125
val vars =
11121126
if (tupleOptimizable) // include `_`
1113-
pat match {
1114-
case Tuple(pats) =>
1115-
pats.map { case id: Ident => id -> TypeTree() }
1116-
}
1117-
else getVariables(pat) // no `_`
1127+
pat match
1128+
case Tuple(pats) => pats.map { case id: Ident => id -> TypeTree() }
1129+
else
1130+
getVariables(
1131+
tree = pat,
1132+
shouldAddGiven =
1133+
if inAliasGenerator then
1134+
filterWildcardGivenBinding
1135+
else
1136+
errorOnGivenBinding
1137+
) // no `_`
11181138

11191139
val ids = for ((named, _) <- vars) yield Ident(named.name)
11201140
val caseDef = CaseDef(pat, EmptyTree, makeTuple(ids))
@@ -1800,16 +1820,21 @@ object desugar {
18001820
/** Returns list of all pattern variables, possibly with their types,
18011821
* without duplicates
18021822
*/
1803-
private def getVariables(tree: Tree)(using Context): List[VarInfo] = {
1823+
private def getVariables(tree: Tree, shouldAddGiven: Context ?=> Bind => Boolean)(using Context): List[VarInfo] = {
18041824
val buf = ListBuffer[VarInfo]()
18051825
def seenName(name: Name) = buf exists (_._1.name == name)
18061826
def add(named: NameTree, t: Tree): Unit =
18071827
if (!seenName(named.name) && named.name.isTermName) buf += ((named, t))
18081828
def collect(tree: Tree): Unit = tree match {
1809-
case Bind(nme.WILDCARD, tree1) =>
1829+
case tree @ Bind(nme.WILDCARD, tree1) =>
1830+
if tree.mods.is(Given) then
1831+
val Typed(_, tpt) = tree1: @unchecked
1832+
if shouldAddGiven(tree) then
1833+
add(tree, tpt)
18101834
collect(tree1)
18111835
case tree @ Bind(_, Typed(tree1, tpt)) =>
1812-
add(tree, tpt)
1836+
if !(tree.mods.is(Given) && !shouldAddGiven(tree)) then
1837+
add(tree, tpt)
18131838
collect(tree1)
18141839
case tree @ Bind(_, tree1) =>
18151840
add(tree, TypeTree())
@@ -1827,7 +1852,7 @@ object desugar {
18271852
case SeqLiteral(elems, _) =>
18281853
elems foreach collect
18291854
case Alternative(trees) =>
1830-
for (tree <- trees; (vble, _) <- getVariables(tree))
1855+
for (tree <- trees; (vble, _) <- getVariables(tree, shouldAddGiven))
18311856
report.error(IllegalVariableInPatternAlternative(), vble.srcPos)
18321857
case Annotated(arg, _) =>
18331858
collect(arg)

compiler/src/dotty/tools/dotc/config/Config.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ object Config {
3434
*/
3535
inline val checkConstraintsPropagated = false
3636

37+
/** Check that constraint bounds do not contain wildcard types */
38+
inline val checkNoWildcardsInConstraint = false
39+
3740
/** If a constraint is over a type lambda `tl` and `tvar` is one of
3841
* the type variables associated with `tl` in the constraint, check
3942
* that the origin of `tvar` is a parameter of `tl`.

compiler/src/dotty/tools/dotc/config/Properties.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ trait PropertiesTrait {
8484

8585
/** Whether the current version of compiler is experimental
8686
*
87-
* 1. Snapshot and nightly releases are experimental.
87+
* 1. Snapshot, nightly releases and non-bootstrapped compiler are experimental.
8888
* 2. Features supported by experimental versions of the compiler:
8989
* - research plugins
9090
*/
91-
val experimental: Boolean = versionString.contains("SNAPSHOT") || versionString.contains("NIGHTLY")
91+
val experimental: Boolean = versionString.contains("SNAPSHOT") || versionString.contains("NIGHTLY") || versionString.contains("nonbootstrapped")
9292

9393
val copyrightString: String = scalaPropOrElse("copyright.string", "(c) 2002-2017 LAMP/EPFL")
9494

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

Lines changed: 18 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Flags._
1010
import config.Config
1111
import config.Printers.typr
1212
import reporting.trace
13+
import typer.ProtoTypes.newTypeVar
1314
import StdNames.tpnme
1415

1516
/** Methods for adding constraints and solving them.
@@ -78,22 +79,29 @@ trait ConstraintHandling {
7879
def fullBounds(param: TypeParamRef)(using Context): TypeBounds =
7980
nonParamBounds(param).derivedTypeBounds(fullLowerBound(param), fullUpperBound(param))
8081

81-
protected def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean)(using Context): Boolean =
82+
/** If true, eliminate wildcards in bounds by avoidance, otherwise replace
83+
* them by fresh variables.
84+
*/
85+
protected def approximateWildcards: Boolean = true
86+
87+
protected def addOneBound(param: TypeParamRef, rawBound: Type, isUpper: Boolean)(using Context): Boolean =
8288
if !constraint.contains(param) then true
83-
else if !isUpper && param.occursIn(bound) then
89+
else if !isUpper && param.occursIn(rawBound) then
8490
// We don't allow recursive lower bounds when defining a type,
8591
// so we shouldn't allow them as constraints either.
8692
false
8793
else
94+
val dropWildcards = new AvoidWildcardsMap:
95+
if !isUpper then variance = -1
96+
override def mapWild(t: WildcardType) =
97+
if approximateWildcards then super.mapWild(t)
98+
else newTypeVar(apply(t.effectiveBounds).toBounds)
99+
val bound = dropWildcards(rawBound)
88100
val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param)
89101
val equalBounds = (if isUpper then lo else hi) eq bound
90-
if equalBounds
91-
&& !bound.existsPart(bp => bp.isInstanceOf[WildcardType] || (bp eq param))
92-
then
93-
// The narrowed bounds are equal and do not contain wildcards,
102+
if equalBounds && !bound.existsPart(_ eq param, stopAtStatic = true) then
103+
// The narrowed bounds are equal and not recursive,
94104
// so we can remove `param` from the constraint.
95-
// (Handling wildcards requires choosing a bound, but we don't know which
96-
// bound to choose here, this is handled in `ConstraintHandling#approximation`)
97105
constraint = constraint.replace(param, bound)
98106
true
99107
else
@@ -245,81 +253,11 @@ trait ConstraintHandling {
245253
* @pre `param` is in the constraint's domain.
246254
*/
247255
final def approximation(param: TypeParamRef, fromBelow: Boolean)(using Context): Type =
248-
249-
/** Substitute wildcards with fresh TypeParamRefs, to be compared with
250-
* other bound, so that they can be instantiated.
251-
*/
252-
object substWildcards extends TypeMap:
253-
override def stopAtStatic = true
254-
255-
var trackedPolis: List[PolyType] = Nil
256-
def apply(tp: Type) = tp match
257-
case tp: WildcardType =>
258-
val poly = PolyType(tpnme.EMPTY :: Nil)(pt => tp.bounds :: Nil, pt => defn.AnyType)
259-
trackedPolis = poly :: trackedPolis
260-
poly.paramRefs.head
261-
case _ =>
262-
mapOver(tp)
263-
end substWildcards
264-
265-
/** Replace TypeParamRefs substituted for wildcards by `substWildCards`
266-
* and any remaining wildcards by a safe approximation
267-
*/
268-
val replaceWildcards = new TypeMap:
269-
override def stopAtStatic = true
270-
271-
/** Try to instantiate a wildcard or TypeParamRef representing a wildcard
272-
* to a type that is known to conform to it.
273-
* This means:
274-
* If fromBelow is true, we minimize the type overall
275-
* Hence, if variance < 0, pick the maximal safe type: bounds.lo
276-
* (i.e. the whole bounds range is over the type).
277-
* If variance > 0, pick the minimal safe type: bounds.hi
278-
* (i.e. the whole bounds range is under the type).
279-
* If variance == 0, pick bounds.lo anyway (this is arbitrary but in line with
280-
* the principle that we pick the smaller type when in doubt).
281-
* If fromBelow is false, we maximize the type overall and reverse the bounds
282-
* If variance != 0. For variance == 0, we still minimize.
283-
* In summary we pick the bound given by this table:
284-
*
285-
* variance | -1 0 1
286-
* ------------------------
287-
* from below | lo lo hi
288-
* from above | hi lo lo
289-
*/
290-
def pickOneBound(bounds: TypeBounds) =
291-
if variance == 0 || fromBelow == (variance < 0) then bounds.lo
292-
else bounds.hi
293-
294-
def apply(tp: Type) = mapOver {
295-
tp match
296-
case tp: WildcardType =>
297-
pickOneBound(tp.bounds)
298-
case tp: TypeParamRef if substWildcards.trackedPolis.contains(tp.binder) =>
299-
pickOneBound(fullBounds(tp))
300-
case _ => tp
301-
}
302-
end replaceWildcards
303-
304256
constraint.entry(param) match
305257
case entry: TypeBounds =>
306258
val useLowerBound = fromBelow || param.occursIn(entry.hi)
307-
val rawBound = if useLowerBound then fullLowerBound(param) else fullUpperBound(param)
308-
val bound = substWildcards(rawBound)
309-
val inst =
310-
if bound eq rawBound then bound
311-
else
312-
// Get rid of wildcards by mapping them to fresh TypeParamRefs
313-
// with constraints derived from comparing both bounds, and then
314-
// instantiating. See pos/i10161.scala for a test where this matters.
315-
val saved = constraint
316-
try
317-
for poly <- substWildcards.trackedPolis do addToConstraint(poly, Nil)
318-
if useLowerBound then bound <:< fullUpperBound(param)
319-
else fullLowerBound(param) <:< bound
320-
replaceWildcards(bound)
321-
finally constraint = saved
322-
typr.println(s"approx ${param.show}, from below = $fromBelow, bound = ${bound.show}, inst = ${inst.show}")
259+
val inst = if useLowerBound then fullLowerBound(param) else fullUpperBound(param)
260+
typr.println(s"approx ${param.show}, from below = $fromBelow, inst = ${inst.show}")
323261
inst
324262
case inst =>
325263
assert(inst.exists, i"param = $param\nconstraint = $constraint")

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,9 @@ class Definitions {
455455
ScalaPackageClass, tpnme.Nothing, AbstractFinal, List(AnyType))
456456
def NothingType: TypeRef = NothingClass.typeRef
457457
@tu lazy val NullClass: ClassSymbol = {
458-
val parent = if ctx.explicitNulls then AnyType else ObjectType
459-
enterCompleteClassSymbol(ScalaPackageClass, tpnme.Null, AbstractFinal, parent :: Nil)
458+
// When explicit-nulls is enabled, Null becomes a direct subtype of Any and Matchable
459+
val parents = if ctx.explicitNulls then AnyType :: MatchableType :: Nil else ObjectType :: Nil
460+
enterCompleteClassSymbol(ScalaPackageClass, tpnme.Null, AbstractFinal, parents)
460461
}
461462
def NullType: TypeRef = NullClass.typeRef
462463

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import ast.untpd
1111
/** Operations that are shared between Namer and TreeUnpickler */
1212
object NamerOps:
1313

14-
/** The given type, unless `sym` is a constructor, in which case the
15-
* type of the constructed instance is returned
14+
/** The type of the constructed instance is returned
15+
*
16+
* @param ctor the constructor
1617
*/
17-
def effectiveResultType(sym: Symbol, paramss: List[List[Symbol]], givenTp: Type)(using Context): Type =
18-
if sym.name == nme.CONSTRUCTOR then
19-
paramss match
20-
case TypeSymbols(tparams) :: _ => sym.owner.typeRef.appliedTo(tparams.map(_.typeRef))
21-
case _ => sym.owner.typeRef
22-
else givenTp
18+
def effectiveResultType(ctor: Symbol, paramss: List[List[Symbol]])(using Context): Type =
19+
paramss match
20+
case TypeSymbols(tparams) :: _ => ctor.owner.typeRef.appliedTo(tparams.map(_.typeRef))
21+
case _ => ctor.owner.typeRef
2322

2423
/** if isConstructor, make sure it has one leading non-implicit parameter list */
2524
def normalizeIfConstructor(paramss: List[List[Symbol]], isConstructor: Boolean)(using Context): List[List[Symbol]] =

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,11 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
280280
var current = this
281281
val todos = new mutable.ListBuffer[(OrderingConstraint, TypeParamRef) => OrderingConstraint]
282282
var i = 0
283+
val dropWildcards = AvoidWildcardsMap()
283284
while (i < poly.paramNames.length) {
284285
val param = poly.paramRefs(i)
285-
val stripped = stripParams(nonParamBounds(param), todos, isUpper = true)
286+
val bounds = dropWildcards(nonParamBounds(param))
287+
val stripped = stripParams(bounds, todos, isUpper = true)
286288
current = updateEntry(current, param, stripped)
287289
while todos.nonEmpty do
288290
current = todos.head(current, param)
@@ -309,8 +311,11 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
309311
val r1 = recur(tp.tp1, fromBelow)
310312
val r2 = recur(tp.tp2, fromBelow)
311313
if (r1 eq tp.tp1) && (r2 eq tp.tp2) then tp
312-
else if tp.isAnd then r1 & r2
313-
else r1 | r2
314+
else tp.match
315+
case tp: OrType =>
316+
TypeComparer.lub(r1, r2, isSoft = tp.isSoft)
317+
case _ =>
318+
r1 & r2
314319
case tp: TypeParamRef =>
315320
if tp eq param then
316321
if fromBelow then defn.NothingType else defn.AnyType
@@ -373,6 +378,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
373378
Nil
374379

375380
private def updateEntry(current: This, param: TypeParamRef, tp: Type)(using Context): This = {
381+
if Config.checkNoWildcardsInConstraint then assert(!tp.containsWildcardTypes)
376382
var current1 = boundsLens.update(this, current, param, tp)
377383
tp match {
378384
case TypeBounds(lo, hi) =>

0 commit comments

Comments
 (0)