Skip to content

Imports from unstable prefixes should not be allowed #10295

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
smarter opened this issue Nov 12, 2020 · 5 comments · Fixed by #10594
Closed

Imports from unstable prefixes should not be allowed #10295

smarter opened this issue Nov 12, 2020 · 5 comments · Fixed by #10594
Assignees
Milestone

Comments

@smarter
Copy link
Member

smarter commented Nov 12, 2020

I don't think this is intentionally allowed, it only works when the def returns a singleton type:

scala> def get: 1 = { println("hi"); 1 }
def get: 1

scala> import get._

scala> toLong
hi
val res0: Long = 1

scala> toLong
hi
val res1: Long = 1

(if one really wants to pretend a prefix is stable, there's an @uncheckedStable annotation, though it's implemented by Scala 2 but not Dotty)

@nicolasstucki
Copy link
Contributor

nicolasstucki commented Nov 12, 2020

We need this in some form to be able to support imports for contextual abstractions. This feature allows us to import the contents of the context parameter without naming it.

trait M:
  type X
  object X:
    def foo(): X

def m(using m: M): m.type = m

def doSomething(body: M ?=> Unit) = ...

doSomething {
  val x: m.X = m.X.foo()
  ...
}
// or with an import 
doSomething {
  import m._ // Consice and clear import of the same stable path `m`
  val x: X = X.foo()
  ...
}
// without this feature we would need an extra line in each call site
doSomething {
  // not ideal
  val myM = m // or summon[M] 
  import myM._
  val x: X = X.foo()
}
// or 
doSomething { (m: M) ?=> // defeats the purpose of context functions 
  import m._
  val x: X = X.foo()
}


def f(using M)(x: m.X) = m.X.foo()

@odersky
Copy link
Contributor

odersky commented Nov 13, 2020

@nicolasstucki Can m be an inline function?

@abgruszecki
Copy link
Contributor

abgruszecki commented Nov 13, 2020

Note that this is used in reflection API as follows:

   def qctx(using qctx: QuoteContext): qctx.type = qctx
   …
   def f(using QuoteContext)(tree: qctx.reflect.Tree): qctx.reflect.Position

It's also possible to use qctx as a singleton type:

  def f(using QuoteContext): qctx.type = qctx

To an extent, I'm fine with this being an idiom. It'd feel less like a hack if qctx was required to be an inline def - it's somewhat unexpected that qctx.type isn't actually the type of qctx. If we come to the conclusion that we want to support this, I think we should be explicit about that in the docs (of either given/using or inline) and we should have tests for both of the above.

@nicolasstucki
Copy link
Contributor

We also do the same with ctx in the compiler.

@nicolasstucki
Copy link
Contributor

Also for summon which is inline.

@odersky odersky self-assigned this Nov 23, 2020
odersky added a commit to dotty-staging/dotty that referenced this issue Dec 2, 2020
The use case for contextual abstractions is still supported if the function
returning an implicit parameter is declared `inline`.
@odersky odersky linked a pull request Dec 2, 2020 that will close this issue
odersky added a commit to dotty-staging/dotty that referenced this issue Dec 2, 2020
The use case for contextual abstractions is still supported if the function
returning an implicit parameter is declared `inline`.
odersky added a commit that referenced this issue Dec 6, 2020
Fix #10295: Require import qualifiers to be idempotent
@Kordyjan Kordyjan modified the milestones: 3.0.0-M3, 3.0.0 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.

5 participants