Skip to content

Inline member selection breaks with Nothing arguments #8612

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
nicolasstucki opened this issue Mar 25, 2020 · 9 comments · Fixed by #11917
Closed

Inline member selection breaks with Nothing arguments #8612

nicolasstucki opened this issue Mar 25, 2020 · 9 comments · Fixed by #11917

Comments

@nicolasstucki
Copy link
Contributor

minimized code

object Foo:
  def assert1(x: Boolean) = if !x then ???
  inline def assert2(x: Boolean) = if !x then ???
  inline def assert3(inline x: Boolean) = if !x then ???

  assert1(???)
  assert2(???)
  assert3(???)

Compilation output

-- Error: Foo.scala:8:9 --------------------------------------------------------
8 |  assert2(???)
  |  ^^^^^^^^^^^^
  |unary_! cannot be accessed as a member of (x : Nothing) from module class Foo$.
  | This location contains code that was inlined from Foo.scala:4
-- Error: Foo.scala:9:9 --------------------------------------------------------
9 |  assert3(???)
  |  ^^^^^^^^^^^^
  |unary_! cannot be accessed as a member of (x : Nothing) from module class Foo$.
  | This location contains code that was inlined from Foo.scala:5```

## expectation
should compile
@odersky
Copy link
Contributor

odersky commented Mar 26, 2020

I don't think there's anything we can do here. Did you have some fix in mind?

@nicolasstucki
Copy link
Contributor Author

Maybe when inlining a Nothing, we can ascribe it. Something where assert2(???) would become if !(??? : Boolean) then ???.

@odersky
Copy link
Contributor

odersky commented Mar 26, 2020

I am reluctant to make things more complicated. Are there real usecases where we need this?

@nicolasstucki
Copy link
Contributor Author

I started writing some code with calling inline functions but placed the ??? as a placeholder while I wrote the other arguments and noticed the failure. It is mostly a potential usability issue with where things would fail with unhelpfully error messages.

@sjrd
Copy link
Member

sjrd commented Mar 27, 2020

From first principles---in this case, "If the invocation typechecks, then the expansion also typechecks"---, this should work.

Also: the same problem will arise with Null (when explicit-nulls are not enabled).

We had the same issue in the Scala.js IR at some point. Optimizations could reduce a term previously well-typed into null.method(), which would not typecheck. The fix in our case was to actually consider null.method() (and ???.method()) as type-correct (instead of inserting ascriptions).

@LPTK
Copy link
Contributor

LPTK commented Apr 3, 2020

Note that Nothing and Null are not the only things that may break when removing intermediate upcasts. Anywhere Scala's subtyping lacks transitivity will cause a problem. For instance:

type A
class B { def foo = 0 }
trait Ev { type T >: A <: B }

inline  // commenting this fixes the error
def test(ev: Ev)(x: ev.T): Int = x.foo

def trial(ev: Ev, a: A) = {
  test(ev)(a)  // foo cannot be accessed as a member of (a : A) from module class main$package$.
}

@bishabosha

This comment has been minimized.

@LPTK

This comment has been minimized.

@bishabosha

This comment has been minimized.

@nicolasstucki nicolasstucki changed the title Inline member selection brakes with Nothing arguments Inline member selection breaks with Nothing arguments Apr 15, 2020
odersky added a commit to dotty-staging/dotty that referenced this issue Mar 27, 2021
michelou pushed a commit to michelou/scala3 that referenced this issue Apr 6, 2021
@Kordyjan Kordyjan added this to the 3.0.0 milestone Aug 2, 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.

6 participants