Skip to content

Commit

Permalink
Merge branch 'main' into parametricity-for-safe-init-enums
Browse files Browse the repository at this point in the history
  • Loading branch information
Xavientois committed Apr 5, 2022
2 parents da09d3a + 8c404b1 commit 6ff1edd
Show file tree
Hide file tree
Showing 41 changed files with 2,460 additions and 87 deletions.
49 changes: 43 additions & 6 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,6 @@ jobs:
./project/scripts/cmdTests
./project/scripts/bootstrappedOnlyCmdTests
- name: MiMa
run: |
./project/scripts/sbt ";scala3-interfaces/mimaReportBinaryIssues ;scala3-library-bootstrapped/mimaReportBinaryIssues ;scala3-library-bootstrappedJS/mimaReportBinaryIssues; tasty-core-bootstrapped/mimaReportBinaryIssues"
test_windows_fast:
runs-on: [self-hosted, Windows]
if: "(
Expand Down Expand Up @@ -189,6 +185,47 @@ jobs:
run: sbt ";sjsJUnitTests/test ;sjsCompilerTests/test"
shell: cmd

mima:
name: MiMa
runs-on: [self-hosted, Linux]
container:
image: lampepfl/dotty:2021-03-22
options: --cpu-shares 4096
volumes:
- ${{ github.workspace }}/../../cache/sbt:/root/.sbt
- ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache
- ${{ github.workspace }}/../../cache/general:/root/.cache
if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty'
|| github.event_name == 'push'
|| (
github.event_name == 'pull_request'
&& !contains(github.event.pull_request.body, '[skip ci]')
&& !contains(github.event.pull_request.body, '[skip mima]')
)
|| (
github.event_name == 'workflow_dispatch'
&& github.repository == 'lampepfl/dotty'
)"
steps:
- name: Reset existing repo
run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true

- name: Checkout cleanup script
uses: actions/checkout@v2

- name: Cleanup
run: .github/workflows/cleanup.sh

- name: Git Checkout
uses: actions/checkout@v2

- name: Add SBT proxy repositories
run: cp -vf .github/workflows/repositories /root/.sbt/ ; true

- name: MiMa
run: |
./project/scripts/sbt ";scala3-interfaces/mimaReportBinaryIssues ;scala3-library-bootstrapped/mimaReportBinaryIssues ;scala3-library-bootstrappedJS/mimaReportBinaryIssues; tasty-core-bootstrapped/mimaReportBinaryIssues"
community_build_a:
runs-on: [self-hosted, Linux]
container:
Expand Down Expand Up @@ -472,7 +509,7 @@ jobs:
- ${{ github.workspace }}/../../cache/sbt:/root/.sbt
- ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache
- ${{ github.workspace }}/../../cache/general:/root/.cache
needs: [test_non_bootstrapped, test, community_build_a, community_build_b, community_build_c, community_build_forward_compat, test_sbt, test_java8]
needs: [test_non_bootstrapped, test, mima, community_build_a, community_build_b, community_build_c, community_build_forward_compat, test_sbt, test_java8]
if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'lampepfl/dotty'"
env:
NIGHTLYBUILD: yes
Expand Down Expand Up @@ -573,7 +610,7 @@ jobs:
- ${{ github.workspace }}/../../cache/sbt:/root/.sbt
- ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache
- ${{ github.workspace }}/../../cache/general:/root/.cache
needs: [test_non_bootstrapped, test, community_build_a, community_build_b, community_build_c, test_sbt, test_java8]
needs: [test_non_bootstrapped, test, mima, community_build_a, community_build_b, community_build_c, test_sbt, test_java8]
if: "github.event_name == 'push'
&& startsWith(github.event.ref, 'refs/tags/')"

Expand Down
12 changes: 8 additions & 4 deletions .github/workflows/scaladoc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,15 @@ jobs:
- name: Generate testcases documentation
run: ./project/scripts/sbt scaladoc/generateTestcasesDocumentation

- name: Generate reference documentation
run: ./project/scripts/sbt scaladoc/generateReferenceDocumentation
- name: Generate reference documentation and check links stability
run: |
./project/scripts/sbt scaladoc/generateReferenceDocumentation
./project/scripts/docsLinksStability ./scaladoc/output/reference ./project/scripts/expected-links/reference-expected-links.txt
- name: Generate Scala 3 documentation
run: ./project/scripts/sbt scaladoc/generateScalaDocumentation
- name: Generate Scala 3 documentation and check links stability
run: |
./project/scripts/sbt scaladoc/generateScalaDocumentation
./project/scripts/docsLinksStability ./scaladoc/output/scala3 ./project/scripts/expected-links/scala3-expected-links.txt
- name: Generate documentation for example project using dotty-sbt
run: ./project/scripts/sbt "sbt-test/scripted sbt-dotty/scaladoc"
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/reporting/Reporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ abstract class Reporter extends interfaces.ReporterResult {
case w: Warning if ctx.settings.XfatalWarnings.value => w.toError
case _ => dia
if !isHidden(d) then // avoid isHidden test for summarized warnings so that message is not forced
markReported(d)
withMode(Mode.Printing)(doReport(d))
d match {
case _: Warning => _warningCount += 1
Expand Down Expand Up @@ -236,6 +237,8 @@ abstract class Reporter extends interfaces.ReporterResult {
def isHidden(dia: Diagnostic)(using Context): Boolean =
ctx.mode.is(Mode.Printing)

def markReported(dia: Diagnostic)(using Context): Unit = ()

/** Does this reporter contain errors that have yet to be reported by its outer reporter ?
* Note: this is always false when there is no outer reporter.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,27 @@ trait UniqueMessagePositions extends Reporter {

private val positions = new mutable.HashMap[(SourceFile, Integer), Diagnostic]

extension (dia1: Diagnostic)
private def hides(dia2: Diagnostic)(using Context): Boolean =
if dia2.msg.showAlways then dia1.msg.getClass == dia2.msg.getClass
else dia1.level >= dia2.level

/** Logs a position and returns true if it was already logged.
* @note Two positions are considered identical for logging if they have the same point.
*/
override def isHidden(dia: Diagnostic)(using Context): Boolean =
extension (dia1: Diagnostic) def hides(dia2: Diagnostic): Boolean =
if dia2.msg.showAlways then dia1.msg.getClass == dia2.msg.getClass
else dia1.level >= dia2.level
super.isHidden(dia) || {
super.isHidden(dia)
||
dia.pos.exists
&& !ctx.settings.YshowSuppressedErrors.value
&& {
var shouldHide = false
for (pos <- dia.pos.start to dia.pos.end)
positions get (ctx.source, pos) match {
case Some(dia1) if dia1.hides(dia) => shouldHide = true
case _ => positions((ctx.source, pos)) = dia
}
shouldHide
}
}
&& (dia.pos.start to dia.pos.end).exists(pos =>
positions.get((ctx.source, pos)).exists(_.hides(dia)))

override def markReported(dia: Diagnostic)(using Context): Unit =
if dia.pos.exists then
for (pos <- dia.pos.start to dia.pos.end)
positions.get(ctx.source, pos) match
case Some(dia1) if dia1.hides(dia) =>
case _ => positions((ctx.source, pos)) = dia
super.markReported(dia)
}
25 changes: 21 additions & 4 deletions compiler/src/dotty/tools/dotc/transform/init/Errors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package init

import ast.tpd._
import core._
import util.SourcePosition
import Decorators._, printing.SyntaxHighlighting
import Types._, Symbols._, Contexts._

Expand All @@ -26,28 +27,44 @@ object Errors {
def toErrors: Errors = this :: Nil

def stacktrace(using Context): String = if (trace.isEmpty) "" else " Calling trace:\n" + {
var indentCount = 0
var last: String = ""
val sb = new StringBuilder
trace.foreach { tree =>
indentCount += 1
val pos = tree.sourcePos
val prefix = s"${ " " * indentCount }-> "
val prefix = "-> "
val line =
if pos.source.exists then
val loc = "[ " + pos.source.file.name + ":" + (pos.line + 1) + " ]"
val code = SyntaxHighlighting.highlight(pos.lineContent.trim.nn)
i"$code\t$loc"
else
tree.show
val positionMarkerLine =
if pos.exists && pos.source.exists then
positionMarker(pos)
else ""

if (last != line) sb.append(prefix + line + "\n")
if (last != line) sb.append(prefix + line + "\n" + positionMarkerLine )

last = line
}
sb.toString
}

/** Used to underline source positions in the stack trace
* pos.source must exist
*/
private def positionMarker(pos: SourcePosition): String = {
val trimmed = pos.lineContent.takeWhile(c => c.isWhitespace).length
val padding = pos.startColumnPadding.substring(trimmed).nn + " "
val carets =
if (pos.startLine == pos.endLine)
"^" * math.max(1, pos.endColumn - pos.startColumn)
else "^"

s"$padding$carets\n"
}

/** Flatten UnsafePromotion errors
*/
def flatten: Errors = this match {
Expand Down
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ object Inliner {

private type DefBuffer = mutable.ListBuffer[ValOrDefDef]

/** An exception signalling that an inline info cannot be computed due to a
* cyclic reference. i14772.scala shows a case where this happens.
*/
private[typer] class MissingInlineInfo extends Exception

/** `sym` is an inline method with a known body to inline.
*/
def hasBodyToInline(sym: SymDenotation)(using Context): Boolean =
Expand Down Expand Up @@ -154,7 +159,10 @@ object Inliner {
if bindings.nonEmpty then
cpy.Block(tree)(bindings.toList, inlineCall(tree1))
else if enclosingInlineds.length < ctx.settings.XmaxInlines.value && !reachedInlinedTreesLimit then
val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
val body =
try bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
catch case _: MissingInlineInfo =>
throw CyclicReference(ctx.owner)
new Inliner(tree, body).inlined(tree.srcPos)
else
ctx.base.stopInlining = true
Expand Down
8 changes: 8 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ class Namer { typer: Typer =>
}
}

def hasDefinedSymbol(tree: Tree)(using Context): Boolean =
val xtree = expanded(tree)
xtree.hasAttachment(TypedAhead) || xtree.hasAttachment(SymOfTree)

/** The enclosing class with given name; error if none exists */
def enclosingClassNamed(name: TypeName, span: Span)(using Context): Symbol =
if (name.isEmpty) NoSymbol
Expand Down Expand Up @@ -837,6 +841,10 @@ class Namer { typer: Typer =>
private def addInlineInfo(sym: Symbol) = original match {
case original: untpd.DefDef if sym.isInlineMethod =>
def rhsToInline(using Context): tpd.Tree =
if !original.symbol.exists && !hasDefinedSymbol(original) then
throw
if sym.isCompleted then Inliner.MissingInlineInfo()
else CyclicReference(sym)
val mdef = typedAheadExpr(original).asInstanceOf[tpd.DefDef]
PrepareInlineable.wrapRHS(original, mdef.tpt, mdef.rhs)
PrepareInlineable.registerInlineInfo(sym, rhsToInline)(using localContext(sym))
Expand Down
12 changes: 4 additions & 8 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3539,14 +3539,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
val namedArgs = wtp.paramNames.lazyZip(args).flatMap { (pname, arg) =>
if (arg.tpe.isError) Nil else untpd.NamedArg(pname, untpd.TypedSplice(arg)) :: Nil
}
tryEither {
val app = cpy.Apply(tree)(untpd.TypedSplice(tree), namedArgs)
if (wtp.isContextualMethod) app.setApplyKind(ApplyKind.Using)
typr.println(i"try with default implicit args $app")
typed(app, pt, locked)
} { (_, _) =>
issueErrors()
}
val app = cpy.Apply(tree)(untpd.TypedSplice(tree), namedArgs)
if (wtp.isContextualMethod) app.setApplyKind(ApplyKind.Using)
typr.println(i"try with default implicit args $app")
typed(app, pt, locked)
else issueErrors()
}
else tree match {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/util/SourceFile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class SourceFile(val file: AbstractFile, computeContent: => Array[Char]) extends
var idx = startOfLine(offset)
val pad = new StringBuilder
while (idx != offset) {
pad.append(if (idx < length && content()(idx) == '\t') '\t' else ' ')
pad.append(if (idx < content().length && content()(idx) == '\t') '\t' else ' ')
idx += 1
}
pad.result()
Expand Down
23 changes: 23 additions & 0 deletions project/scripts/docsLinksStability
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -u

echo "Testing links stability in documentation"

DOCS_DIR=$1 # The location of documentation is passed as a first parameter

EXPECTED_LINKS_FILE=$2 # The location of expected-links.txt is passed as a second parameter

pushd $DOCS_DIR > /dev/null # Go to docs dir but remember previous location
# We need to go to docs dir to make find return correct relative paths
find . -type f -name "*.html" | sort | (popd > /dev/null; diff $EXPECTED_LINKS_FILE -;)
# We list every html file in documentation, then sort it and finally compare to the expected links list.
# Before running diff we need to popd to return to the previous location because we don't have relative path to the expected links file.

if [ ! $? -eq 0 ]
then
echo "Links changed. If it's intentional, regenerate expected links list by running ./project/scripts/regenerateExpectedLinks $1 $2"
exit -1
else
echo "Links OK!"
exit 0
fi
Loading

0 comments on commit 6ff1edd

Please sign in to comment.