Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class TypedFormatChecker(partsElems: List[Tree], parts: List[String], args: List
def at(g: SpecGroup): Int = descriptor.start(g.ordinal)
def end(g: SpecGroup): Int = descriptor.end(g.ordinal)
def offset(g: SpecGroup, i: Int = 0): Int = at(g) + i
def group(g: SpecGroup): Option[String] = Option(descriptor.group(g.ordinal)).asInstanceOf[Option[String]]
def group(g: SpecGroup): Option[String] = Option(descriptor.group(g.ordinal))
def stringOf(g: SpecGroup): String = group(g).getOrElse("")
def intOf(g: SpecGroup): Option[Int] = group(g).map(_.toInt)

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1922,7 +1922,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
NoType
}

pt match {
pt.stripNull() match {
case pt: TypeVar
if untpd.isFunctionWithUnknownParamType(tree) && !calleeType.exists =>
// try to instantiate `pt` if this is possible. If it does not
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/Option.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ object Option {
* @param x the value
* @return Some(value) if value != null, None if value == null
*/
def apply[A](x: A): Option[A] = if (x == null) None else Some(x)
def apply[A](x: A | Null): Option[A] = if (x == null) None else Some(x)

/** An Option factory which returns `None` in a manner consistent with
* the collections hierarchy.
Expand Down
4 changes: 0 additions & 4 deletions library/src/scala/Predef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,6 @@ object Predef extends LowPriorityImplicits {
inline infix def ne(inline y: AnyRef | Null): Boolean =
!(x eq y)

extension (opt: Option.type)
@experimental
inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf[Option[T]]
Copy link
Member Author

Choose a reason for hiding this comment

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

I removed it because it is useless now that we have Option.apply(A | Null)


/** A type supporting Self-based type classes.
*
* A is TC
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/concurrent/impl/Promise.scala
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ private[concurrent] object Promise {

override final def isCompleted: Boolean = value0 ne null

override final def value: Option[Try[T]] = Option(value0).asInstanceOf[Option[Try[T]]]
override final def value: Option[Try[T]] = Option(value0)

@tailrec // returns null if not completed
private final def value0: Try[T] | Null = {
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/quoted/FromExpr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ object FromExpr {
*/
given OptionFromExpr[T](using Type[T], FromExpr[T]): FromExpr[Option[T]] with {
def unapply(x: Expr[Option[T]])(using Quotes) = x match {
case '{ Option[T](${Expr(y)}) } => Some(Option(y))
case '{ Option[T](${Expr(y)}: T) } => Some(Option(y))
case '{ None } => Some(None)
case '{ ${Expr(opt)} : Some[T] } => Some(opt)
case _ => None
Expand Down
4 changes: 0 additions & 4 deletions library/src/scala/runtime/stdLibPatches/Predef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ object Predef:
inline infix def ne(inline y: AnyRef | Null): Boolean =
!(x eq y)

extension (opt: Option.type)
@experimental
inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf[Option[T]]

/** A type supporting Self-based type classes.
*
* A is TC
Expand Down
4 changes: 2 additions & 2 deletions scaladoc/src/dotty/tools/scaladoc/SourceLinks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ class SourceLinkParser(revision: Option[String]) extends ArgParser[SourceLink]:
else Right(TemplateSourceLink(supported.foldLeft(string)((template, pattern) =>
template.replace(pattern, SupportedScalaDocPatternReplacements(pattern)))))
case KnownProvider(name: String, organization: String, repo: String, rawRevision, rawSubPath) =>
val subPath = Option.fromNullable(rawSubPath).fold("")("/" + _.drop(1))
val pathRev = Option.fromNullable(rawRevision).map(_.drop(1)).orElse(revision)
val subPath = Option(rawSubPath).fold("")("/" + _.drop(1))
val pathRev = Option(rawRevision).map(_.drop(1)).orElse(revision)

def withRevision(template: String => SourceLink) =
pathRev.fold(Left(s"No revision provided"))(r => Right(template(r)))
Expand Down
4 changes: 2 additions & 2 deletions scaladoc/src/dotty/tools/scaladoc/site/StaticSiteLoader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ class StaticSiteLoader(val root: File, val args: Scaladoc.Args)(using StaticSite

def loadBlog(): Option[LoadedTemplate] = {
val blogConfig = BlogParser.readYml(root)
val rootPath = Option.fromNullable(blogConfig.input).map(input => ctx.resolveNewBlogPath(input)).getOrElse(ctx.blogPath)
val defaultDirectory = Option.fromNullable(blogConfig.output).getOrElse("blog")
val rootPath = Option(blogConfig.input).map(input => ctx.resolveNewBlogPath(input)).getOrElse(ctx.blogPath)
val defaultDirectory = Option(blogConfig.output).getOrElse("blog")

type Date = (String, String, String)
if (!Files.exists(rootPath) || blogConfig.hidden) None
Expand Down
2 changes: 1 addition & 1 deletion scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ class SymOpsWithLinkCache:
then externalLinkCache(csym.associatedFile)
else {
def calculatePath(file: AbstractFile): String = file.underlyingSource.filter(_ != file).fold("")(f => calculatePath(f) + "/") + file.path
val calculatedLink = Option.fromNullable(csym.associatedFile).map(f => calculatePath(f)).flatMap { path =>
val calculatedLink = Option(csym.associatedFile).map(f => calculatePath(f)).flatMap { path =>
dctx.externalDocumentationLinks.find(_.originRegexes.exists(r => r.matches(path)))
}
externalLinkCache += (csym.associatedFile -> calculatedLink)
Expand Down
6 changes: 0 additions & 6 deletions tests/explicit-nulls/neg/from-nullable.scala

This file was deleted.

4 changes: 2 additions & 2 deletions tests/explicit-nulls/run/from-nullable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ object Test:
val s1: String | Null = "hello"
val s2: String | Null = null

val opts1: Option[String] = Option.fromNullable(s1)
val opts2: Option[String] = Option.fromNullable(s2)
val opts1: Option[String] = Option(s1)
val opts2: Option[String] = Option(s2)

opts1 match
case Some(s) => println(s)
Expand Down
5 changes: 4 additions & 1 deletion tests/pos/i24206.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ class DispatchQuery:
trait Result
def getAll(nameFilter: Option[String => Boolean]): List[Result] = ???
def get(collectionName: String): List[Result] =
getAll(Option(_.startsWith(collectionName)))
getAll(Option(_.startsWith(collectionName)))

def f[T](x: T | Null): T = ???
val _: Any => Any = f(x => x)
3 changes: 0 additions & 3 deletions tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ val experimentalDefinitionInLibrary = Set(
"scala.quoted.Quotes.reflectModule.RenameSelectorModule.apply",
"scala.quoted.Quotes.reflectModule.SimpleSelectorModule.apply",

// New feature: fromNullable for explicit nulls
"scala.Predef$.fromNullable",

// New feature: modularity
"scala.Precise",
"scala.annotation.internal.WitnessNames",
Expand Down
Loading