Skip to content

Commit

Permalink
Merge branch 'scala:main' into fix-http4s
Browse files Browse the repository at this point in the history
  • Loading branch information
EnzeXing authored Dec 14, 2024
2 parents 966a174 + 7573951 commit b03ad81
Show file tree
Hide file tree
Showing 29 changed files with 494 additions and 135 deletions.
12 changes: 3 additions & 9 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -801,19 +801,13 @@ jobs:
distDir="$3"
# Build binaries
./project/scripts/sbt "${sbtProject}/Universal/stage"
./project/scripts/sbt "all ${sbtProject}/Universal/packageBin ${sbtProject}/Universal/packageZipTarball"
outputPath="${distDir}/target/universal/stage"
artifactName="scala3-${{ env.RELEASE_TAG }}${distroSuffix}"
zipArchive="${artifactName}.zip"
tarGzArchive="${artifactName}.tar.gz"
cwd=$(pwd)
(cd $outputPath && zip -r ${zipArchive} . && mv ${zipArchive} "${cwd}/")
tar -czf ${tarGzArchive} -C "$outputPath" .
# Caluclate SHA for each of archive files
for file in "${zipArchive}" "${tarGzArchive}"; do
for file in "${artifactName}.zip" "${artifactName}.tar.gz"; do
mv ${distDir}/target/universal/$file $file
sha256sum "${file}" > "${file}.sha256"
done
}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-chocolatey.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ jobs:
with:
name: scala.nupkg
- name: Publish the package to Chocolatey
run: choco push scala.nupkg --source https://push.chocolatey.org/ --api-key ${{ secrets.API-KEY }}
run: choco push scala.${{inputs.version}}.nupkg --source https://push.chocolatey.org/ --api-key ${{ secrets.API-KEY }}

3 changes: 1 addition & 2 deletions .vscode-template/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"**/*.class": true,
"**/*.tasty": true,
"**/target/": true,
"community-build/community-projects": true,
"tests/pos-with-compiler-cc/dotc/**/*.scala": true
"community-build/community-projects": true
}
}
19 changes: 12 additions & 7 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -694,15 +694,15 @@ object desugar {
val originalTparams = constr1.leadingTypeParams
val originalVparamss = asTermOnly(constr1.trailingParamss)
lazy val derivedEnumParams = enumClass.typeParams.map(derivedTypeParamWithVariance)
val impliedTparams =
if (isEnumCase) {
val enumTParams =
if isEnumCase then
val tparamReferenced = typeParamIsReferenced(
enumClass.typeParams, originalTparams, originalVparamss, parents)
if (originalTparams.isEmpty && (parents.isEmpty || tparamReferenced))
enumClass.typeParams, originalTparams, originalVparamss, parents)
if originalTparams.isEmpty && (parents.isEmpty || tparamReferenced) then
derivedEnumParams.map(tdef => tdef.withFlags(tdef.mods.flags | PrivateLocal))
else originalTparams
}
else originalTparams
else Nil
else Nil
val impliedTparams = enumTParams ++ originalTparams

if mods.is(Trait) then
for vparams <- originalVparamss; vparam <- vparams do
Expand Down Expand Up @@ -735,6 +735,11 @@ object desugar {
derived.withAnnotations(Nil)

val constr = cpy.DefDef(constr1)(paramss = joinParams(constrTparams, constrVparamss))
if enumTParams.nonEmpty then
defaultGetters = defaultGetters.map:
case ddef: DefDef =>
val tParams = enumTParams.map(tparam => toMethParam(tparam, KeepAnnotations.All))
cpy.DefDef(ddef)(paramss = joinParams(tParams, ddef.trailingParamss))

val (normalizedBody, enumCases, enumCompanionRef) = {
// Add constructor type parameters and evidence implicit parameters
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -777,13 +777,13 @@ object Contexts {

extension (c: Context)
def addNotNullInfo(info: NotNullInfo) =
c.withNotNullInfos(c.notNullInfos.extendWith(info))
if c.explicitNulls then c.withNotNullInfos(c.notNullInfos.extendWith(info)) else c

def addNotNullRefs(refs: Set[TermRef]) =
c.addNotNullInfo(NotNullInfo(refs, Set()))
if c.explicitNulls then c.addNotNullInfo(NotNullInfo(refs, Set())) else c

def withNotNullInfos(infos: List[NotNullInfo]): Context =
if c.notNullInfos eq infos then c else c.fresh.setNotNullInfos(infos)
if !c.explicitNulls || (c.notNullInfos eq infos) then c else c.fresh.setNotNullInfos(infos)

def relaxedOverrideContext: Context =
c.withModeBits(c.mode &~ Mode.SafeNulls | Mode.RelaxedOverriding)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
case QuotedTypeMissingID // errorNumber: 202
case DeprecatedAssignmentSyntaxID // errorNumber: 203
case DeprecatedInfixNamedArgumentSyntaxID // errorNumber: 204
case GivenSearchPriorityID // errorNumber: 205

def errorNumber = ordinal - 1

Expand Down
38 changes: 38 additions & 0 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3361,3 +3361,41 @@ class DeprecatedInfixNamedArgumentSyntax()(using Context) extends SyntaxMsg(Depr
+ Message.rewriteNotice("This", version = SourceVersion.`3.6-migration`)

def explain(using Context) = ""

class GivenSearchPriorityWarning(
pt: Type,
cmp: Int,
prev: Int,
winner: TermRef,
loser: TermRef,
isLastOldVersion: Boolean
)(using Context) extends Message(GivenSearchPriorityID):
def kind = MessageKind.PotentialIssue
def choice(nth: String, c: Int) =
if c == 0 then "none - it's ambiguous"
else s"the $nth alternative"
val (change, whichChoice) =
if isLastOldVersion
then ("will change in the future release", "Current choice ")
else ("has changed", "Previous choice")
def warningMessage: String =
i"""Given search preference for $pt between alternatives
| ${loser}
|and
| ${winner}
|$change.
|$whichChoice : ${choice("first", prev)}
|Choice from Scala 3.7 : ${choice("second", cmp)}"""
def migrationHints: String =
i"""Suppress this warning by choosing -source 3.5, -source 3.7, or
|by using @annotation.nowarn("id=205")"""
def ambiguousNote: String =
i"""
|
|Note: $warningMessage"""
def msg(using Context) =
i"""$warningMessage
|
|$migrationHints"""

def explain(using Context) = ""
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,8 @@ trait Applications extends Compatibility {
case (arg: NamedArg, _) => arg
case (arg, name) => NamedArg(name, arg)
}
else if isAnnotConstr(methRef.symbol) then
typedArgs
else if !sameSeq(args, orderedArgs) && !typedArgs.forall(isSafeArg) then
// need to lift arguments to maintain evaluation order in the
// presence of argument reorderings.
Expand Down Expand Up @@ -1134,7 +1136,7 @@ trait Applications extends Compatibility {
case _ => ()
else ()

fun1.tpe match {
val result = fun1.tpe match {
case err: ErrorType => cpy.Apply(tree)(fun1, proto.typedArgs()).withType(err)
case TryDynamicCallType =>
val isInsertedApply = fun1 match {
Expand Down Expand Up @@ -1208,6 +1210,11 @@ trait Applications extends Compatibility {
else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail))
}
}

if result.tpe.isNothingType then
val nnInfo = result.notNullInfo
result.withNotNullInfo(nnInfo.terminatedInfo)
else result
}

/** Convert expression like
Expand Down
22 changes: 4 additions & 18 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -549,10 +549,10 @@ object Implicits:
/** An ambiguous implicits failure */
class AmbiguousImplicits(val alt1: SearchSuccess, val alt2: SearchSuccess, val expectedType: Type, val argument: Tree, val nested: Boolean = false) extends SearchFailureType:

private[Implicits] var priorityChangeWarnings: List[Message] = Nil
private[Implicits] var priorityChangeWarnings: List[GivenSearchPriorityWarning] = Nil

def priorityChangeWarningNote(using Context): String =
priorityChangeWarnings.map(msg => s"\n\nNote: $msg").mkString
priorityChangeWarnings.map(_.ambiguousNote).mkString

def msg(using Context): Message =
var str1 = err.refStr(alt1.ref)
Expand Down Expand Up @@ -1312,7 +1312,7 @@ trait Implicits:
// A map that associates a priority change warning (between -source 3.6 and 3.7)
// with the candidate refs mentioned in the warning. We report the associated
// message if one of the critical candidates is part of the result of the implicit search.
val priorityChangeWarnings = mutable.ListBuffer[(/*critical:*/ List[TermRef], Message)]()
val priorityChangeWarnings = mutable.ListBuffer[(/*critical:*/ List[TermRef], GivenSearchPriorityWarning)]()

val sv = Feature.sourceVersion
val isLastOldVersion = sv.stable == SourceVersion.`3.6`
Expand Down Expand Up @@ -1353,21 +1353,7 @@ trait Implicits:
cmp match
case 1 => (alt2, alt1)
case -1 => (alt1, alt2)
def choice(nth: String, c: Int) =
if c == 0 then "none - it's ambiguous"
else s"the $nth alternative"
val (change, whichChoice) =
if isLastOldVersion
then ("will change", "Current choice ")
else ("has changed", "Previous choice")
val msg =
em"""Given search preference for $pt between alternatives
| ${loser.ref}
|and
| ${winner.ref}
|$change.
|$whichChoice : ${choice("first", prev)}
|New choice from Scala 3.7: ${choice("second", cmp)}"""
val msg = GivenSearchPriorityWarning(pt, cmp, prev, winner.ref, loser.ref, isLastOldVersion)
val critical = alt1.ref :: alt2.ref :: Nil
priorityChangeWarnings += ((critical, msg))
if isLastOldVersion then prev else cmp
Expand Down
116 changes: 76 additions & 40 deletions compiler/src/dotty/tools/dotc/typer/Nullables.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,34 +52,46 @@ object Nullables:
val hiTree = if(hiTpe eq hi.typeOpt) hi else TypeTree(hiTpe)
TypeBoundsTree(lo, hiTree, alias)

/** A set of val or var references that are known to be not null, plus a set of
* variable references that are not known (anymore) to be not null
/** A set of val or var references that are known to be not null
* after the tree finishes executing normally (non-exceptionally),
* plus a set of variable references that are ever assigned to null,
* and may therefore be null if execution of the tree is interrupted
* by an exception.
*/
case class NotNullInfo(asserted: Set[TermRef], retracted: Set[TermRef]):
assert((asserted & retracted).isEmpty)

case class NotNullInfo(asserted: Set[TermRef] | Null, retracted: Set[TermRef]):
def isEmpty = this eq NotNullInfo.empty

def retractedInfo = NotNullInfo(Set(), retracted)

def terminatedInfo = NotNullInfo(null, retracted)

/** The sequential combination with another not-null info */
def seq(that: NotNullInfo): NotNullInfo =
if this.isEmpty then that
else if that.isEmpty then this
else NotNullInfo(
this.asserted.union(that.asserted).diff(that.retracted),
this.retracted.union(that.retracted).diff(that.asserted))
else
val newAsserted =
if this.asserted == null || that.asserted == null then null
else this.asserted.diff(that.retracted).union(that.asserted)
val newRetracted = this.retracted.union(that.retracted)
NotNullInfo(newAsserted, newRetracted)

/** The alternative path combination with another not-null info. Used to merge
* the nullability info of the two branches of an if.
* the nullability info of the branches of an if or match.
*/
def alt(that: NotNullInfo): NotNullInfo =
NotNullInfo(this.asserted.intersect(that.asserted), this.retracted.union(that.retracted))
val newAsserted =
if this.asserted == null then that.asserted
else if that.asserted == null then this.asserted
else this.asserted.intersect(that.asserted)
val newRetracted = this.retracted.union(that.retracted)
NotNullInfo(newAsserted, newRetracted)
end NotNullInfo

object NotNullInfo:
val empty = new NotNullInfo(Set(), Set())
def apply(asserted: Set[TermRef], retracted: Set[TermRef]): NotNullInfo =
if asserted.isEmpty && retracted.isEmpty then empty
def apply(asserted: Set[TermRef] | Null, retracted: Set[TermRef]): NotNullInfo =
if asserted != null && asserted.isEmpty && retracted.isEmpty then empty
else new NotNullInfo(asserted, retracted)
end NotNullInfo

Expand Down Expand Up @@ -223,7 +235,7 @@ object Nullables:
*/
@tailrec def impliesNotNull(ref: TermRef): Boolean = infos match
case info :: infos1 =>
if info.asserted.contains(ref) then true
if info.asserted == null || info.asserted.contains(ref) then true
else if info.retracted.contains(ref) then false
else infos1.impliesNotNull(ref)
case _ =>
Expand All @@ -233,16 +245,15 @@ object Nullables:
* or retractions in `info` supersede infos in existing entries of `infos`.
*/
def extendWith(info: NotNullInfo) =
if info.isEmpty
|| info.asserted.forall(infos.impliesNotNull(_))
&& !info.retracted.exists(infos.impliesNotNull(_))
then infos
if info.isEmpty then infos
else info :: infos

/** Retract all references to mutable variables */
def retractMutables(using Context) =
val mutables = infos.foldLeft(Set[TermRef]())((ms, info) =>
ms.union(info.asserted.filter(_.symbol.is(Mutable))))
val mutables = infos.foldLeft(Set[TermRef]()):
(ms, info) => ms.union(
if info.asserted == null then Set.empty
else info.asserted.filter(_.symbol.is(Mutable)))
infos.extendWith(NotNullInfo(Set(), mutables))

end extension
Expand Down Expand Up @@ -304,15 +315,35 @@ object Nullables:
extension (tree: Tree)

/* The `tree` with added nullability attachment */
def withNotNullInfo(info: NotNullInfo): tree.type =
if !info.isEmpty then tree.putAttachment(NNInfo, info)
def withNotNullInfo(info: NotNullInfo)(using Context): tree.type =
if ctx.explicitNulls && !info.isEmpty then tree.putAttachment(NNInfo, info)
tree

/* Collect the nullability info from parts of `tree` */
def collectNotNullInfo(using Context): NotNullInfo = tree match
case Typed(expr, _) =>
expr.notNullInfo
case Apply(fn, args) =>
val argsInfo = args.map(_.notNullInfo)
val fnInfo = fn.notNullInfo
argsInfo.foldLeft(fnInfo)(_ seq _)
case TypeApply(fn, _) =>
fn.notNullInfo
case _ =>
// Other cases are handled specially in typer.
NotNullInfo.empty

/* The nullability info of `tree` */
def notNullInfo(using Context): NotNullInfo =
stripInlined(tree).getAttachment(NNInfo) match
case Some(info) if !ctx.erasedTypes => info
case _ => NotNullInfo.empty
if !ctx.explicitNulls then NotNullInfo.empty
else
val tree1 = stripInlined(tree)
tree1.getAttachment(NNInfo) match
case Some(info) if !ctx.erasedTypes => info
case _ =>
val nnInfo = tree1.collectNotNullInfo
tree1.withNotNullInfo(nnInfo)
nnInfo

/* The nullability info of `tree`, assuming it is a condition that evaluates to `c` */
def notNullInfoIf(c: Boolean)(using Context): NotNullInfo =
Expand Down Expand Up @@ -393,21 +424,23 @@ object Nullables:
end extension

extension (tree: Assign)
def computeAssignNullable()(using Context): tree.type = tree.lhs match
case TrackedRef(ref) =>
val rhstp = tree.rhs.typeOpt
if ctx.explicitNulls && ref.isNullableUnion then
if rhstp.isNullType || rhstp.isNullableUnion then
// If the type of rhs is nullable (`T|Null` or `Null`), then the nullability of the
// lhs variable is no longer trackable. We don't need to check whether the type `T`
// is correct here, as typer will check it.
tree.withNotNullInfo(NotNullInfo(Set(), Set(ref)))
else
// If the initial type is nullable and the assigned value is non-null,
// we add it to the NotNull.
tree.withNotNullInfo(NotNullInfo(Set(ref), Set()))
else tree
case _ => tree
def computeAssignNullable()(using Context): tree.type =
var nnInfo = tree.rhs.notNullInfo
tree.lhs match
case TrackedRef(ref) if ctx.explicitNulls && ref.isNullableUnion =>
nnInfo = nnInfo.seq:
val rhstp = tree.rhs.typeOpt
if rhstp.isNullType || rhstp.isNullableUnion then
// If the type of rhs is nullable (`T|Null` or `Null`), then the nullability of the
// lhs variable is no longer trackable. We don't need to check whether the type `T`
// is correct here, as typer will check it.
NotNullInfo(Set(), Set(ref))
else
// If the initial type is nullable and the assigned value is non-null,
// we add it to the NotNull.
NotNullInfo(Set(ref), Set())
case _ =>
tree.withNotNullInfo(nnInfo)
end extension

private val analyzedOps = Set(nme.EQ, nme.NE, nme.eq, nme.ne, nme.ZAND, nme.ZOR, nme.UNARY_!)
Expand Down Expand Up @@ -515,7 +548,10 @@ object Nullables:
&& assignmentSpans.getOrElse(sym.span.start, Nil).exists(whileSpan.contains(_))
&& ctx.notNullInfos.impliesNotNull(ref)

val retractedVars = ctx.notNullInfos.flatMap(_.asserted.filter(isRetracted)).toSet
val retractedVars = ctx.notNullInfos.flatMap(info =>
if info.asserted == null then Set.empty
else info.asserted.filter(isRetracted)
).toSet
ctx.addNotNullInfo(NotNullInfo(Set(), retractedVars))
end whileContext

Expand Down
Loading

0 comments on commit b03ad81

Please sign in to comment.