Skip to content

Fix definition of narrow in SIP-23 #1570

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
Closed

Conversation

valencik
Copy link
Contributor

@valencik valencik commented Nov 5, 2019

In SIP-23 there is a function defined:

def narrow[T <: Singleton](t: T): T = t

Using it to form a tuple appears to still return a wide type:

scala> val xt = (narrow(23), narrow(42))
xt: (Int, Int) = (23,42)

But if one changes the return type from T to T {} in, say, a narrower function:

def narrower[T <: Singleton](t: T): T {} = t

A tuple of literal types appears:

scala> val yt = (narrower(23), narrower(42))
yt: (23, 42) = (23,42)

Additionally the T {} return type is used in sip23-narrow.scala.

@SethTisue SethTisue requested a review from milessabin November 5, 2019 15:27
@julienrf
Copy link
Contributor

julienrf commented Dec 2, 2019

Indeed, the empty refinement seems to be needed by Scala 2.13: https://scastie.scala-lang.org/45N4U3xfTkmgEuReMoq2cA

But I believe this is a problem in the implementation. This behavior is not specified in the description:

The presence of an upper bound of Singleton on a formal type parameter indicates that
singleton types should be inferred for type parameters at call sites.

So, the presence of the Singleton upper bound should be enough.

I think we should open an issue in scala/bug.

By the way, Dotty does not implement what is in the proposal, and the empty type refinement does not work: https://scastie.scala-lang.org/qkmxdI6GQyG9IFk8cLTzpw (so, you can not have an inferred narrow type, you have to write it explicitly).

Any comment @smarter or @milessabin ?

@milessabin
Copy link
Contributor

The following should work in Scala 2 (and Dotty) without relying on the semantics of empty refinements,

type Id[T] = T
def narrow[T <: Singleton](t: T): Id[T] = t

Demo ...

miles@tarski:~% scala                                                                                                                      
Welcome to Scala 2.13.0-20190613-143643-unknown (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_231).
Type in expressions for evaluation. Or try :help.

scala> type Id[T] = T
defined type alias Id

scala> def narrow[T <: Singleton](t: T): Id[T] = t
narrow: [T <: Singleton](t: T)Id[T]

scala> val xt = (narrow(23), narrow(42))
xt: (Id[23], Id[42]) = (23,42)

@julienrf
Copy link
Contributor

julienrf commented Dec 2, 2019

According to the specification, the following should work as well:

def narrow[T <: Singleton](t: T): T = t
val x = narrow(42)
x: 42

Or am I missing something?

BTW, I find it confusing that the introduction of the Id type constructor changes the inferred type.

@milessabin
Copy link
Contributor

Or am I missing something?

Yes. In the example you give the compiler will widen the result type of the call of narrow,

scala> def narrow[T <: Singleton](t: T): T = t
narrow: [T <: Singleton](t: T)T

scala> val x = narrow(42)
x: Int = 42

BTW, I find it confusing that the introduction of the Id type constructor changes the inferred type.

It's consistent with the behaviour of other type constructors, eg.,

scala> def narrow[T <: Singleton](t: T): Option[T] = Some(t)
narrow: [T <: Singleton](t: T)Option[T]

scala> val x = narrow(42)
x: Option[42] = Some(42)

ie. widening doesn't reach under the type constructor.

@julienrf
Copy link
Contributor

julienrf commented Dec 2, 2019

Yes. In the example you give the compiler will widen the result type of the call of narrow,

In that case, I suggest that we fix the specification, then. Do you agree?

@milessabin
Copy link
Contributor

In that case, I suggest that we fix the specification, then. Do you agree?

Yes, we should. I suggest using the Id variant.

@SethTisue SethTisue closed this Dec 6, 2019
@SethTisue
Copy link
Member

would someone like to PR the suggested spec change?

@valencik
Copy link
Contributor Author

valencik commented Dec 6, 2019

I'd love to open a PR changing the spec. :)

@SethTisue
Copy link
Member

great! it's over in the scala/scala repo, https://github.com/scala/scala/tree/2.13.x/spec

@valencik valencik mentioned this pull request Dec 12, 2019
3 tasks
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.

4 participants