Skip to content
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

fix override return type check #10141

Conversation

jxnu-liguobin
Copy link
Member

@jxnu-liguobin jxnu-liguobin commented Sep 16, 2022

@scala-jenkins scala-jenkins added this to the 2.13.10 milestone Sep 16, 2022
@jxnu-liguobin jxnu-liguobin changed the title closed scala/bug#12621. fix override return type Sep 16, 2022
@jxnu-liguobin jxnu-liguobin changed the title fix override return type fix override return type check Sep 16, 2022
@som-snytt
Copy link
Contributor

I think it must be fixed in Namers where the overridden type is computed to use as expected type for RHS. RefChecks is not wrong.

@jxnu-liguobin
Copy link
Member Author

Namers

Thank you, I'll take a look.

@jxnu-liguobin jxnu-liguobin force-pushed the p12621-fix-override-return-type branch 3 times, most recently from 6f0fbe4 to d6b109f Compare September 16, 2022 14:25
@jxnu-liguobin jxnu-liguobin marked this pull request as ready for review September 17, 2022 07:29
@lrytz lrytz modified the milestones: 2.13.10, 2.13.11 Sep 26, 2022
@SethTisue
Copy link
Member

@jxnu-liguobin we've been slow with PR reviews lately, because of the 2.13.10 release and other factors... but I'm trying to get things moving again. mind rebasing this one to resolve the merge conflict? then we can try to find a reviewer.

@som-snytt
Copy link
Contributor

The override inference behavior has needed a couple of passes for correctness. The conflict is probably due to those edits. I'm not sure how this issue will interact. In particular, there is also #10198 (which may not stand scrutiny).

@SethTisue SethTisue force-pushed the p12621-fix-override-return-type branch from 9a12064 to 52db6ec Compare January 31, 2023 03:42
@SethTisue
Copy link
Member

I pushed a rebase — the merge conflict seemed easy to resolve. Let's see what CI thinks.

@SethTisue
Copy link
Member

CI likes it. @som-snytt can I interest you in serving as reviewer here?

@som-snytt
Copy link
Contributor

som-snytt commented Mar 2, 2023

I'm taking a look. I'd like to understand why the pt is already widened by ExistentialExtrapolation:

Widened lone occurrence of sb.type inside existential to upper bound: StringBuilder

The proposed fix is downstream from there.

Edit: something to do with whether the param type is stable. Probably that only matters if the result is a member type sb.T. Currently, this works in the example:

  val x: StringBuilder = new StringBuilder
  def f(sb: x.type): sb.type = sb

@som-snytt
Copy link
Contributor

I submitted an alternative that attempts to infer or construct the correct pt more directly. That happens before the RHS is typechecked.

The approach in this PR is to keep the type of the RHS, but pt has already been used (so the expected type was StringBuilder instead of sb.type).

I'll leave this PR open until I understand the alternatives better.

@@ -1109,14 +1109,26 @@ trait Namers extends MethodSynthesis {
case _ => sym.isStable && !refersToSymbolLessAccessibleThan(tpe, sym)
}

def keepWhenMissResultTypeForSingleton: Option[Type] = {
sym.overrideChain.drop(1).map(_.tpe).headOption.flatMap {
case MethodType(_, rt) if !rt.typeSymbol.isAliasType && rt.isInstanceOf[SingletonType] && tpe <:< rt.dealiasWiden => Some(rt)
Copy link
Contributor

Choose a reason for hiding this comment

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

overrideChain may be too much; compare computeOverridden. What is isAliasType guarding? A test would show it.

@som-snytt
Copy link
Contributor

I tried the neg test (from the other PR), and this compiles! To review, the overridden type becomes an existential with StringBuilder as upper bound, which is why StringBuilder is the expected type, so the RHS typechecks. After the horses have escaped through the barn door, we fix the result type of the overloading f so it seems correct after that.

class C { def f(sb: StringBuilder): sb.type = sb }

// It's ok, if not specify a return type.
class D extends C { override def f(sb: StringBuilder) = new StringBuilder }

Now I see that keepWhenMissResultTypeForSingleton is keeping sb.type, I had misread that big expr to mean it was keeping the singleton type of the RHS if it conformed to the overridden type.

@som-snytt som-snytt closed this Mar 5, 2023
@SethTisue
Copy link
Member

(the other PR being #10334)

@SethTisue SethTisue removed this from the 2.13.11 milestone Mar 5, 2023
@SethTisue
Copy link
Member

@jxnu-liguobin thank you for pursuing this as far as you did — looks like the baton is passed to Som

@som-snytt
Copy link
Contributor

Also thanks for patience and actually taking the first two swings. It's a lot to chew on, and I might have had actionable feedback earlier if I knew what I was doing, or what the compiler is doing. I definitely would not have waded into these waters first. Also the other PR isn't over the finish line. It's not even on the last lap.

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