Skip to content

Commit 2068de5

Browse files
authored
Merge pull request #658 from tgodzik/revert-24192
Revert 24192
2 parents c1f6d0e + b3e6697 commit 2068de5

File tree

7 files changed

+60
-103
lines changed

7 files changed

+60
-103
lines changed

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ object TyperState {
2727

2828
opaque type Snapshot = (Constraint, TypeVars, LevelMap)
2929

30-
class BadTyperStateAssertion(msg: String) extends AssertionError(msg)
31-
3230
extension (ts: TyperState)
3331
def snapshot()(using Context): Snapshot =
3432
(ts.constraint, ts.ownedVars, ts.upLevels)
@@ -44,7 +42,7 @@ object TyperState {
4442
}
4543

4644
class TyperState() {
47-
import TyperState.{LevelMap, BadTyperStateAssertion}
45+
import TyperState.LevelMap
4846

4947
private var myId: Int = _
5048
def id: Int = myId
@@ -270,10 +268,8 @@ class TyperState() {
270268
*/
271269
private def includeVar(tvar: TypeVar)(using Context): Unit =
272270
val oldState = tvar.owningState.nn.get
273-
274-
if oldState != null && oldState.isCommittable then
275-
throw BadTyperStateAssertion(
276-
i"$this attempted to take ownership of $tvar which is already owned by committable $oldState")
271+
assert(oldState == null || !oldState.isCommittable,
272+
i"$this attempted to take ownership of $tvar which is already owned by committable $oldState")
277273
tvar.owningState = new WeakReference(this)
278274
ownedVars += tvar
279275

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,7 @@ object Inferencing {
377377
}
378378

379379
/** The instantiation decision for given poly param computed from the constraint. */
380-
enum Decision:
381-
case Min, Max, ToMax, Skip, Fail
382-
380+
enum Decision { case Min; case Max; case ToMax; case Skip; case Fail }
383381
private def instDecision(tvar: TypeVar, v: Int, minimizeSelected: Boolean, ifBottom: IfBottom)(using Context): Decision =
384382
import Decision.*
385383
val direction = instDirection(tvar.origin)

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

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,43 +28,17 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
2828
private type SpecialHandlers = List[(ClassSymbol, SpecialHandler)]
2929

3030
val synthesizedClassTag: SpecialHandler = (formal, span) =>
31-
def instArg(tp: Type): Type = tp.dealias match
31+
def instArg(tp: Type): Type = tp.stripTypeVar match
32+
// Special case to avoid instantiating `Int & S` to `Int & Nothing` in
33+
// i16328.scala. The intersection comes from an earlier instantiation
34+
// to an upper bound.
35+
// The dual situation with unions is harder to trigger because lower
36+
// bounds are usually widened during instantiation.
3237
case tp: AndOrType if tp.tp1 =:= tp.tp2 =>
33-
// Special case to avoid instantiating `Int & S` to `Int & Nothing` in
34-
// i16328.scala. The intersection comes from an earlier instantiation
35-
// to an upper bound.
36-
// The dual situation with unions is harder to trigger because lower
37-
// bounds are usually widened during instantiation.
3838
instArg(tp.tp1)
39-
case tvar: TypeVar if ctx.typerState.constraint.contains(tvar) =>
40-
// If tvar has a lower or upper bound:
41-
// 1. If the bound is not another type variable, use this as approximation.
42-
// 2. Otherwise, if the type can be forced to be fully defined, use that type
43-
// as approximation.
44-
// 3. Otherwise leave argument uninstantiated.
45-
// The reason for (2) is that we observed complicated constraints in i23611.scala
46-
// that get better types if a fully defined type is computed than if several type
47-
// variables are approximated incrementally. This is a minimization of some ZIO code.
48-
// So in order to keep backwards compatibility (where before we _only_ did 2) we
49-
// add that special case.
50-
def isGroundConstr(tp: Type): Boolean = tp.dealias match
51-
case tvar: TypeVar if ctx.typerState.constraint.contains(tvar) => false
52-
case pref: TypeParamRef if ctx.typerState.constraint.contains(pref) => false
53-
case tp: AndOrType => isGroundConstr(tp.tp1) && isGroundConstr(tp.tp2)
54-
case _ => true
55-
instArg(
56-
if tvar.hasLowerBound then
57-
if isGroundConstr(fullLowerBound(tvar.origin)) then tvar.instantiate(fromBelow = true)
58-
else if isFullyDefined(tp, ForceDegree.all) then tp
59-
else NoType
60-
else if tvar.hasUpperBound then
61-
if isGroundConstr(fullUpperBound(tvar.origin)) then tvar.instantiate(fromBelow = false)
62-
else if isFullyDefined(tp, ForceDegree.all) then tp
63-
else NoType
64-
else
65-
NoType)
6639
case _ =>
67-
tp
40+
if isFullyDefined(tp, ForceDegree.all) then tp
41+
else NoType // this happens in tests/neg/i15372.scala
6842

6943
val tag = formal.argInfos match
7044
case arg :: Nil =>

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

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3869,12 +3869,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38693869

38703870
def addImplicitArgs(using Context) =
38713871
def hasDefaultParams = methPart(tree).symbol.hasDefaultParams
3872-
def findDefaultArgument(argIndex: Int): Tree =
3873-
def appPart(t: Tree): Tree = t match
3874-
case Block(_, expr) => appPart(expr)
3875-
case Inlined(_, _, expr) => appPart(expr)
3876-
case t => t
3877-
defaultArgument(appPart(tree), n = argIndex, testOnly = false)
38783872
def implicitArgs(formals: List[Type], argIndex: Int, pt: Type): List[Tree] = formals match
38793873
case Nil => Nil
38803874
case formal :: formals1 =>
@@ -3889,40 +3883,27 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38893883
implicitArgs(formals2, argIndex + 1, pt)
38903884

38913885
val arg = inferImplicitArg(formal, tree.span.endPos)
3892-
3893-
lazy val defaultArg = findDefaultArgument(argIndex)
3894-
.showing(i"default argument: for $formal, $tree, $argIndex = $result", typr)
3895-
def argHasDefault = hasDefaultParams && !defaultArg.isEmpty
3896-
3897-
def canProfitFromMoreConstraints =
3898-
arg.tpe.isInstanceOf[AmbiguousImplicits]
3899-
// Ambiguity could be decided by more constraints
3900-
|| !isFullyDefined(formal, ForceDegree.none) && !argHasDefault
3901-
// More context might constrain type variables which could make implicit scope larger.
3902-
// But in this case we should search with additional arguments typed only if there
3903-
// is no default argument.
3904-
3905-
// Try to constrain the result using `pt1`, but back out if a BadTyperStateAssertion
3906-
// is thrown. TODO Find out why the bad typer state arises and prevent it. The try-catch
3907-
// is a temporary hack to keep projects compiling that would fail otherwise due to
3908-
// searching more arguments to instantiate implicits (PR #23532). A failing project
3909-
// is described in issue #23609.
3910-
def tryConstrainResult(pt: Type): Boolean =
3911-
try constrainResult(tree.symbol, wtp, pt)
3912-
catch case ex: TyperState.BadTyperStateAssertion => false
3913-
3914-
arg.tpe match
3915-
case failed: SearchFailureType if canProfitFromMoreConstraints =>
3916-
val pt1 = pt.deepenProtoTrans
3917-
if (pt1 `ne` pt) && (pt1 ne sharpenedPt) && tryConstrainResult(pt1) then
3918-
return implicitArgs(formals, argIndex, pt1)
3919-
case _ =>
3920-
39213886
arg.tpe match
39223887
case failed: AmbiguousImplicits =>
3923-
arg :: implicitArgs(formals1, argIndex + 1, pt)
3888+
val pt1 = pt.deepenProtoTrans
3889+
if (pt1 `ne` pt) && (pt1 ne sharpenedPt) && constrainResult(tree.symbol, wtp, pt1)
3890+
then implicitArgs(formals, argIndex, pt1)
3891+
else arg :: implicitArgs(formals1, argIndex + 1, pt1)
39243892
case failed: SearchFailureType =>
3925-
if argHasDefault then
3893+
lazy val defaultArg =
3894+
def appPart(t: Tree): Tree = t match
3895+
case Block(stats, expr) => appPart(expr)
3896+
case Inlined(_, _, expr) => appPart(expr)
3897+
case _ => t
3898+
defaultArgument(appPart(tree), argIndex, testOnly = false)
3899+
.showing(i"default argument: for $formal, $tree, $argIndex = $result", typr)
3900+
if !hasDefaultParams || defaultArg.isEmpty then
3901+
// no need to search further, the adapt fails in any case
3902+
// the reason why we continue inferring arguments in case of an AmbiguousImplicits
3903+
// is that we need to know whether there are further errors.
3904+
// If there are none, we have to propagate the ambiguity to the caller.
3905+
arg :: formals1.map(dummyArg)
3906+
else
39263907
// This is tricky. On the one hand, we need the defaultArg to
39273908
// correctly type subsequent formal parameters in the same using
39283909
// clause in case there are parameter dependencies. On the other hand,
@@ -3933,12 +3914,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
39333914
// `if propFail.exists` where we re-type the whole using clause with named
39343915
// arguments for all implicits that were found.
39353916
arg :: inferArgsAfter(defaultArg)
3936-
else
3937-
// no need to search further, the adapt fails in any case
3938-
// the reason why we continue inferring arguments in case of an AmbiguousImplicits
3939-
// is that we need to know whether there are further errors.
3940-
// If there are none, we have to propagate the ambiguity to the caller.
3941-
arg :: formals1.map(dummyArg)
39423917
case _ =>
39433918
arg :: inferArgsAfter(arg)
39443919
end implicitArgs

tests/neg/i9568.check

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
| No given instance of type => Monad[F] was found for parameter ev of method blaMonad in object Test.
55
| I found:
66
|
7-
| Test.blaMonad[F², S]
7+
| Test.blaMonad[F², S](Test.blaMonad[F³, S²])
88
|
9-
| But method blaMonad in object Test does not match type => Monad[F]
9+
| But method blaMonad in object Test does not match type => Monad[F²]
1010
|
1111
| where: F is a type variable with constraint <: [_] =>> Any
1212
| F² is a type variable with constraint <: [_] =>> Any
13+
| F³ is a type variable with constraint <: [_] =>> Any
14+
| S is a type variable
15+
| S² is a type variable
1316
| .

tests/pos/i23526.scala

Lines changed: 0 additions & 14 deletions
This file was deleted.

tests/pos/i24192.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// https://github.com/scala/scala-collection-contrib/blob/main/src/main/scala/scala/collection/decorators/package.scala
2+
object decorators {
3+
trait IsMap[A]
4+
implicit def mapDecorator[C](coll: C)(implicit map: IsMap[C]): Map[C, map.type] = ???
5+
}
6+
import decorators.mapDecorator // unused, required to reprouce
7+
8+
trait Eq[T]
9+
trait Applicative[F[_]]
10+
given Applicative[Option] = ???
11+
12+
trait Traverse[F[_]]:
13+
// context bound required to reproduce
14+
def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]] = ???
15+
16+
object Traverse:
17+
def apply[F[_]]: Traverse[F] = ???
18+
19+
trait Segment[Element: Eq]
20+
21+
case class MergeResult[Element: Eq] private (segments: Seq[Segment[Element]]):
22+
def thisFailsToCompile(): Option[MergeResult[Element]] =
23+
Traverse[Seq]
24+
.sequence(Seq.empty[Option[Segment[Element]]])
25+
.map(MergeResult.apply) // error

0 commit comments

Comments
 (0)