Skip to content

Union and intersection types are not causing checking the kind of type parameters #16696

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

Closed
bertlebee opened this issue Jan 14, 2023 · 4 comments · Fixed by #16712
Closed

Union and intersection types are not causing checking the kind of type parameters #16696

bertlebee opened this issue Jan 14, 2023 · 4 comments · Fixed by #16712

Comments

@bertlebee
Copy link

bertlebee commented Jan 14, 2023

Compiler version

3.2.1

Minimized code

https://scastie.scala-lang.org/VEozYp5OQlmLyTb0hn3KQw

Output (click arrow to expand)

java.lang.AssertionError: assertion failed: R & Playground.Foo / TypeParamRef(R) & HKTypeLambda(List(A), List(TypeBounds(TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Nothing),TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Any))), AppliedType(TypeRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),module class Playground$)),trait Foo),List(TypeParamRef(A))))
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.core.Types$AndType$.apply(Types.scala:3203)
	at dotty.tools.dotc.core.Types$AndType$.make(Types.scala:3238)
	at dotty.tools.dotc.core.Types$AndType.derivedAndType(Types.scala:3184)
	at dotty.tools.dotc.core.Types$ApproximatingTypeMap.derivedAndType(Types.scala:5961)
	at dotty.tools.dotc.core.Types$TypeMap.mapOver(Types.scala:5689)
	at dotty.tools.dotc.core.TypeOps$AsSeenFromMap.apply(TypeOps.scala:109)
	at dotty.tools.dotc.core.Types$TypeMap.op$proxy16$1(Types.scala:5590)
	at dotty.tools.dotc.core.Types$TypeMap.mapArgs(Types.scala:5590)
	at dotty.tools.dotc.core.Types$TypeMap.mapOver(Types.scala:5627)
	at dotty.tools.dotc.core.TypeOps$AsSeenFromMap.apply(TypeOps.scala:109)
	at dotty.tools.dotc.core.Types$TypeMap.mapOverLambda(Types.scala:5603)
	at dotty.tools.dotc.core.TypeOps$AsSeenFromMap.apply(TypeOps.scala:103)
	at dotty.tools.dotc.core.Types$TypeMap.mapOverLambda(Types.scala:5603)
	at dotty.tools.dotc.core.TypeOps$AsSeenFromMap.apply(TypeOps.scala:103)
	at dotty.tools.dotc.core.Types$TypeMap.mapOverLambda(Types.scala:5603)
	at dotty.tools.dotc.core.TypeOps$AsSeenFromMap.apply(TypeOps.scala:103)
	at dotty.tools.dotc.core.TypeOps$.asSeenFrom(TypeOps.scala:51)
	at dotty.tools.dotc.core.Types$Type.asSeenFrom(Types.scala:1036)
	at dotty.tools.dotc.core.Denotations$SingleDenotation.derived$1(Denotations.scala:1099)
	at dotty.tools.dotc.core.Denotations$SingleDenotation.computeAsSeenFrom(Denotations.scala:1125)
	at dotty.tools.dotc.core.Denotations$SingleDenotation.computeAsSeenFrom(Denotations.scala:1079)
	at dotty.tools.dotc.core.Denotations$PreDenotation.asSeenFrom(Denotations.scala:134)
	at dotty.tools.dotc.core.SymDenotations$ClassDenotation.findMember(SymDenotations.scala:2069)
	at dotty.tools.dotc.core.Types$Type.go$1(Types.scala:686)
	at dotty.tools.dotc.core.Types$Type.findMember(Types.scala:879)
	at dotty.tools.dotc.core.Types$Type.memberBasedOnFlags(Types.scala:669)
	at dotty.tools.dotc.core.Types$Type.member(Types.scala:653)
	at dotty.tools.dotc.typer.ProtoTypes$SelectionProto.liftedTree1$1(ProtoTypes.scala:195)
	at dotty.tools.dotc.typer.ProtoTypes$SelectionProto.isMatchedBy(ProtoTypes.scala:217)
	at dotty.tools.dotc.core.TypeComparer.isMatchedByProto(TypeComparer.scala:1917)
	at dotty.tools.dotc.core.TypeComparer.firstTry$1(TypeComparer.scala:314)
	at dotty.tools.dotc.core.TypeComparer.recur(TypeComparer.scala:1336)
	at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:194)
	at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:204)
	at dotty.tools.dotc.core.TypeComparer.topLevelSubType(TypeComparer.scala:128)
	at dotty.tools.dotc.core.TypeComparer.testSubType(TypeComparer.scala:144)
	at dotty.tools.dotc.core.TypeComparer$.testSubType(TypeComparer.scala:2767)
	at dotty.tools.dotc.typer.Typer.adaptNoArgsOther$1(Typer.scala:3725)
	at dotty.tools.dotc.typer.Typer.adaptNoArgs$1(Typer.scala:3822)
	at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:4038)
	at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:3368)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2987)
@bertlebee bertlebee added itype:bug itype:crash stat:needs triage Every issue needs to have an "area" and "itype" label labels Jan 14, 2023
@Kordyjan Kordyjan added area:typer stat:needs minimization Needs a self contained minimization and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Jan 16, 2023
@Kordyjan
Copy link
Contributor

Self-contained example:

class Box[R]

class BoxMaker[T] {
  def make[R <: T](f: T => Box[R]): Box[R & T] = ???
}

trait Foo[A]{
  def foo: Box[Foo[Unit]]
}
val boom = BoxMaker[Foo/*[Unit]*/].make(_.foo)

Uncommenting [Unit] in the last line will make it compile.

@Kordyjan Kordyjan removed the stat:needs minimization Needs a self contained minimization label Jan 16, 2023
@Kordyjan
Copy link
Contributor

It still crashes on the current nightly and has been crashing since 3.0.0.

@Kordyjan
Copy link
Contributor

Kordyjan commented Jan 16, 2023

I've played a bit with it and was able to minimise it to just:

class BoxMaker[T] {
  def make: T & Int = ???
}

val boom = BoxMaker[Some].make

If we use union type instead of intersection, it also crashes similarly.

class BoxMaker[T] {
  def make: T | Int = ???
}

val boom = BoxMaker[Some].make

It seems that intersections and unions are not enforcing kinds of type parameters.

@Kordyjan Kordyjan changed the title Forgotten type param causes crash Union and intersection types are not causing checking the kind of type parameters Jan 16, 2023
@Kordyjan Kordyjan added this to the Future versions milestone Jan 16, 2023
@odersky odersky self-assigned this Jan 16, 2023
odersky added a commit to dotty-staging/dotty that referenced this issue Jan 17, 2023
Throw a type error instead of crashing when using higher-kinded types in unions or intersections.

We check kindedness only in PostTyper (to avoid cycles), which means we might get into situations
where we coming a higher-kinded type in a union or intersection, which is illegal. In this case
we now diagnose the problem with a TypeError instead of failing an assert. However, after Typer
we do fail since by then such situations should have been checked by then.

Fixeds scala#16696
odersky added a commit that referenced this issue Jan 18, 2023
…6712)

Throw a type error instead of crashing when using higher-kinded types in
unions or intersections.

We check kindedness only in PostTyper (to avoid cycles), which means we
might get into situations where we combine a higher-kinded type in a
union or intersection, which is illegal. In this case we now diagnose
the problem with a TypeError instead of failing an assert. However,
after Typer we do fail since by then such situations should have been
checked by then.

Fixes #16696
@bertlebee
Copy link
Author

Wow, thanks for getting all of these sorted for me!

little-inferno pushed a commit to little-inferno/dotty that referenced this issue Jan 25, 2023
Throw a type error instead of crashing when using higher-kinded types in unions or intersections.

We check kindedness only in PostTyper (to avoid cycles), which means we might get into situations
where we coming a higher-kinded type in a union or intersection, which is illegal. In this case
we now diagnose the problem with a TypeError instead of failing an assert. However, after Typer
we do fail since by then such situations should have been checked by then.

Fixeds scala#16696
@Kordyjan Kordyjan modified the milestones: Future versions, 3.3.0 Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants