Skip to content

Fix incorrect wrong staging level error for Singleton type #16237

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
wants to merge 1 commit into from

Conversation

jchyb
Copy link
Contributor

@jchyb jchyb commented Oct 24, 2022

FIxes #15709.
Initially, when I started working on this I thought that it was interesting that 's was transformed into Apply(TypeApply(Ident(quote),List(TypeTree[TypeVar(TypeParamRef(T) -> TermRef(NoPrefix,val s))])),List(Ident(s)))during the Typer phase, with the interesting part being the typetree TypeTree[TypeVar(TypeParamRef(T) -> TermRef(NoPrefix,val s))]. Directly inside a TypeVar a TermRef can be found, which was the direct cause of errors thrown via PCPCheckAndHeal. Initially I wanted to see if it was possible to somehow painlessly wrap the TermRef into a TypeRef, however after spending too much time fruitlessly exploring Typer I decided to adjust checks in PCPCheckAndHeal instead.

There I changed it so that type arguments were healed via healType instead of healTypeOfTerm, as that seems more applicable there just by name alone. Next, after encountering an error with an annotation I changed things so that annotation contents are not recursively visited by PCPCheckAndHeal, like it was previously done in healTypeOfTerm. This lead to no failed tests, and I was not able to find any examples that would break the above changes.

@jchyb
Copy link
Contributor Author

jchyb commented Oct 24, 2022

Hi @smarter, what do you think about this fix? It was difficult for me to judge from what direction to approach this problem, and I know you are well versed in all things Typer. I imagine that Typer may be more easy to break with small changes than PCPCheckAndHeal, but maybe the TypeTree with top level TermRef does not look right after all (again, it's difficult for me to judge these things still). If you see something off in the solution or it seems too hacky overall, please let me know

@jchyb jchyb requested a review from smarter October 24, 2022 13:25
@jchyb jchyb marked this pull request as ready for review October 24, 2022 13:25
@smarter
Copy link
Member

smarter commented Oct 24, 2022

maybe the TypeTree with top level TermRef does not look right after all

It's not wrong technically, but I don't know if it's what should happen in this case. If I write s.type in source code, this will be represented by the typechecker as TermRef(..., s). The expression:

's

is desugared into

scala.quoted.runtime.Expr.quote(s)

when we typecheck this method, we get:

scala.quoted.runtime.Expr.quote[s.type](s)

Which is where the TermRef comes from. This only happens because fooImpl takes an Expr[Singleton], if we change it to take an Expr[Any] instead, then the type argument of quote is widened to a non-singleton. This is because type inference has a special-case where it doesn't widen type argument when the expected type is Singleton to give more precise types.

I would be a little bit hesitant to change the logic in PCPCheckAndHeal without having @nicolasstucki or @odersky double-check it first. Maybe instead we could change the behavior of type inference just for Expr.quote but I'm not sure how this could be done exactly.

@dwijnand dwijnand assigned smarter and odersky and unassigned smarter Oct 24, 2022
Copy link
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

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

I don't know enough about PCPCheckAndHeal to be able to say whether this is a fix or not. We have to wait for @nicolasstucki to come back.

@@ -209,8 +209,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
case tp: ThisType if level != -1 && level != levelOf(tp.cls) =>
levelError(tp.cls, tp, pos)
case tp: AnnotatedType =>
val newAnnotTree = transform(tp.annot.tree)
derivedAnnotatedType(tp, apply(tp.parent), tp.annot.derivedAnnotation(newAnnotTree))
derivedAnnotatedType(tp, apply(tp.parent), tp.annot)
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the reasoning to allow us to ignore annotations here?

@odersky odersky assigned nicolasstucki and unassigned odersky Oct 24, 2022
@jchyb jchyb marked this pull request as draft October 27, 2022 13:33
@jchyb
Copy link
Contributor Author

jchyb commented Oct 27, 2022

I think it's wrong after all. Thank you for all the explanations and help. Back into the drafts it goes

@nicolasstucki
Copy link
Contributor

It seems I fixed this issue with one of my recent PRs. I will add a regression test in #17143.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Wrong staging level for quoted singleton
4 participants