Skip to content

Do not flag match types as Deferred and amend #20077 #20147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1542,8 +1542,6 @@ class TreeUnpickler(reader: TastyReader,
// as the reduction of the match type definition!
//
// We also override the type, as that's what Typer does.
// The difference here is that a match type that reduces to a non-match type
// makes the TypeRef for that definition will have a TypeAlias info instead of a MatchAlias.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also update TreeUnpickler MATCHtpt doc to align with changes from #19871

I don't think this change is correct. #19871 is about making aliases to an applied type, even if that is backed by a match type, be a TypeAlias rather than a MatchAlias.

What we're dealing with here is a straight alias to a match type, except the match type immediately normalises to a non-match type. When compiling from source we simplify it and thus give the alias a TypeAlias. With this change, when we're unpickling we also simplify and thus give the alias a TypeAlias.

If you can find a clearer way to express that, we should keep this information.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I agree this shouldn't be impacted by the changes in #19871.
But I'm now not sure about which cases get reduced more from the Unpickler than when from the Typer ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing more. The point is the have the same definition, whether from source code or from tasty, have the same info, so that differences in MatchAlias and TypeAlias don't become a factor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So assuming the match type reduces to non match type, won't they all have a TypeAlias now ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, but only because I added overwriteType here. The deleted comment is part of (attempting to!) explain that and shouldn't have been removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so I agree we need tpt.overwriteType(tpt.tpe.normalized) and that it is because that's what Typer does.

Still, it was my understanding that the Typer and Unpickler now use AliasingBounds in a consistent way, so I don't understand how there is a difference here for the TypeRef for that definition.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By "The difference here" I meant "The reason that is important to do is because..."

tpt.overwriteType(tpt.tpe.normalized)
tpt
case TYPEBOUNDStpt =>
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ trait ImplicitRunInfo:
else if implicitScopeCache.contains(t) then parts += t
else
partSeen += t
t.dealias.normalized match
t.dealias match
case t: TypeRef =>
if isAnchor(t.symbol) then
parts += t
Expand Down Expand Up @@ -817,7 +817,7 @@ trait ImplicitRunInfo:
else AndType.make(apply(lo), apply(hi))
case u => apply(u)

def apply(t: Type) = t.dealias match
def apply(t: Type) = t.dealias.normalized match
case t: TypeRef =>
if t.symbol.isClass || isAnchor(t.symbol) then t else applyToUnderlying(t)
case t: TypeVar => apply(t.underlying)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,8 @@ class Namer { typer: Typer =>
else if flags.isAllOf(EnumValue) && ctx.owner.isStaticOwner then flags |= JavaStatic
case tree: TypeDef =>
def analyzeRHS(rhs: Tree): Unit = rhs match
case _: TypeBoundsTree | _: MatchTypeTree =>
flags |= Deferred // Typedefs with Match rhs classify as abstract
case _: TypeBoundsTree =>
flags |= Deferred
case LambdaTypeTree(_, body) =>
analyzeRHS(body)
case _ =>
Expand Down
File renamed without changes.
13 changes: 13 additions & 0 deletions tests/neg/i20071b/A_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

trait Scope
object Scope:
given i: Int = ???

type ReferencesScope[S] >: Int <: Int

type ScopeToInt[Why] = Why match
case Scope => Int

def foo[T](using d: ReferencesScope[T]): Any = ???

def bar[T](using d: ScopeToInt[T]): Any = ???
8 changes: 8 additions & 0 deletions tests/neg/i20071b/B_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

def test: Unit =
foo[Scope] // ok
bar[Scope] // error

import Scope.i
bar[Scope] // ok

14 changes: 14 additions & 0 deletions tests/pos/i20136a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

trait Expr:
type Value
object Expr:
type Of[V] = Expr { type Value = V }
type ExtractValue[E <: Expr] = E match
case Expr.Of[v] => v

trait TC[E <: Expr]:
type Elem = Expr.ExtractValue[E]
class BIExpr extends Expr:
type Value = BigInt
class Foo extends TC[BIExpr]:
val v: Elem = 0
8 changes: 8 additions & 0 deletions tests/pos/i20136b/A_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package a

trait Expr:
type Value
object Expr:
type Of[V] = Expr { type Value = V }
type ExtractValue[E <: Expr] = E match
case Expr.Of[v] => v
8 changes: 8 additions & 0 deletions tests/pos/i20136b/B_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package a

trait TC[E <: Expr]:
type Elem = Expr.ExtractValue[E]
class BIExpr extends Expr:
type Value = BigInt
class Foo extends TC[BIExpr]:
val v: Elem = 0
Loading