Skip to content

Drop transparent #9029

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
odersky opened this issue May 22, 2020 · 14 comments
Closed

Drop transparent #9029

odersky opened this issue May 22, 2020 · 14 comments

Comments

@odersky
Copy link
Contributor

odersky commented May 22, 2020

I'd like to go back from transparent to the earlier scheme where we used _ <: T to indicate an upper bound for a result type. So it would be

inline def f: _ <: T = ...
inline given g: _ <: T = ...

for whitebox macros. At the same time, I'd like to allow _ <: T as an upper bound of other result types as well. E.g.

inline val x: _ <: Byte = 1

would produce a Byte constant, which was not possible before. Similarly, if we assume #9028,

case object a extends B with C with D
def f: _ <: Product = a

f would get type B with C with D with Product, so there's not need anymore to list all supertypes.

The rules for this are straightforward

  • When inferring the type of a val or def with _ <: R result type, R is taken as the expected type of the right hand side.
  • The inferred type is then the type of the RHS, widened as usual, with upper bound R
@joroKr21
Copy link
Member

Is it possible to drop the wildcard as in def f <: Product or was that ruled out as too subtle?

@odersky
Copy link
Contributor Author

odersky commented May 24, 2020

The wildcard is needed for the given case so for consistency we should have it everywhere.

@nicolasstucki
Copy link
Contributor

Not sure about the second rule. We have to be careful with when widening types in vals

inline val x = 1 // should be: val x: 1 = 1 
inline val y: _ <: Int = 1 // should be: val y: 1 = 1 
inline val z: Int = 1 // error

With inline vals we have the additional restriction that the type must be a content type. Otherwise we would need to change the way we inline vals.

@nicolasstucki
Copy link
Contributor

This is related to #8850. There we tried to use this same typing scheme for vals but using transparent.

@nicolasstucki
Copy link
Contributor

Is it possible to drop the wildcard as in def f <: Product or was that ruled out as too subtle?

That was the previous syntax. It caused too much confusion in several situations.

@nicolasstucki
Copy link
Contributor

nicolasstucki commented May 25, 2020

Shouldn't we have the following to align with the normal given syntax?

inline given g as _ <: T = ...
inline given _ <: T = ...

@nicolasstucki
Copy link
Contributor

Maybe something like

type Precise[T] <: T // magical type
inline def f: Precise[T] = ...
inline given g as Precise[T] = ...

@liufengyun
Copy link
Contributor

liufengyun commented May 25, 2020

What about introduced Refined, tell the compiler it's white-box:

type Refined[T] = T

inline given g as Refined[T] = ...
inline val x: Refined[Byte] = 1

@odersky
Copy link
Contributor Author

odersky commented May 25, 2020

@liufengyun @nicolasstucki The problem with normal types is that you then have to explain why these cannot be used in other places.

One compromise would be to use <: and brackets:

inline given g as <:[T] = ...
inline val x: <:[Byte] = 1
inline def f(x: S): <:[T] = ...

The <: is syntax since <: is a keyword, but it looks like a type.

But that might be even more surprising , so I am not sure it's better than _ <: T.

@nicolasstucki
Copy link
Contributor

_ <: T looks more natural

@liufengyun
Copy link
Contributor

liufengyun commented May 25, 2020

What about regarding it as a generalization of type ascriptions? The typing rule for a type ascription expression is like the following:

    Γ ⊢ e : T
------------------
  Γ ⊢ (e : T) : T

If we introduce e: T @refine, we could give the following typing rule:

   Γ ⊢ e : S     S <: T
--------------------------
  Γ ⊢ (e : T @refine) : S

We could introduce a short-hand for @refined:

type Refined[T] = T @refined

Updated: seen from the perspective of type ascriptions, it seems to suggest the following:

e <: T   // syntax for refinable type ascription 

inline given g = e <: T
inline val x = 1 <: Byte
inline def f() = e <: T

@LPTK
Copy link
Contributor

LPTK commented May 25, 2020

Could this be used as a general syntax for expressing "do not widen here"?

This would solve the long-lasting issue of #3964 (and its predecessors #3920, #1262).

trait Context {
  type Tree
}

class Helper(val ctx: _ <: Context) {
  def f(x: Int): ctx.Tree = ???
}

val ctx  : Context   =  ???
val tree : ctx.Tree  =  new Helper(ctx).f(5)

@soronpo
Copy link
Contributor

soronpo commented May 25, 2020

I probably missed a discussion somewhere, but what was the problem with directly writing x <: Int instead of x : _ <: Int?

odersky added a commit to dotty-staging/dotty that referenced this issue May 26, 2020
After deliberating some more, I believe that `_ <: T` is the best alternative
for expressing whitebox macros.
@odersky
Copy link
Contributor Author

odersky commented May 26, 2020

@soronpo x <: Int does not work for givens.

In the end I have found it's not worth it. I tried to implement it in #9048, but that introuced more complexity than I have liked. Others at LAMP were not keen on the change either, so we'll leave it as it is.

@odersky odersky closed this as completed May 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants