diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index bf11a442e515..27be8c9d6b22 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1077,6 +1077,13 @@ object Trees { /** Hook to indicate that a transform of some subtree should be skipped */ protected def skipTransform(tree: Tree)(implicit ctx: Context): Boolean = false + /** For untyped trees, this is just the identity. + * For typed trees, a context derived form `ctx` that records `call` as the + * innermost enclosing call for which the inlined version is currently + * processed. + */ + protected def inlineContext(call: Tree)(implicit ctx: Context): Context = ctx + abstract class TreeMap(val cpy: TreeCopier = inst.cpy) { def transform(tree: Tree)(implicit ctx: Context): Tree = @@ -1121,7 +1128,7 @@ object Trees { case SeqLiteral(elems, elemtpt) => cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt)) case Inlined(call, bindings, expansion) => - cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)) + cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(inlineContext(call))) case TypeTree() => tree case SingletonTypeTree(ref) => @@ -1225,7 +1232,7 @@ object Trees { case SeqLiteral(elems, elemtpt) => this(this(x, elems), elemtpt) case Inlined(call, bindings, expansion) => - this(this(x, bindings), expansion) + this(this(x, bindings), expansion)(inlineContext(call)) case TypeTree() => x case SingletonTypeTree(ref) => diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index ed268fda7326..d1d886c5550f 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -933,10 +933,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** A key to be used in a context property that tracks enclosing inlined calls */ private val InlinedCalls = new Property.Key[List[Tree]] - /** A context derived form `ctx` that records `call` as innermost enclosing - * call for which the inlined version is currently processed. - */ - def inlineContext(call: Tree)(implicit ctx: Context): Context = + override def inlineContext(call: Tree)(implicit ctx: Context): Context = ctx.fresh.setProperty(InlinedCalls, call :: enclosingInlineds) /** All enclosing calls that are currently inlined, from innermost to outermost */ diff --git a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala index 19ede3cece9b..c2301a3aa252 100644 --- a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala @@ -93,21 +93,20 @@ object CompilerCommand extends DotClass { def shouldStopWithInfo = { import settings._ - Set(help, Xhelp, Yhelp, showPlugins, showPhases) exists (_.value) + Set(help, Xhelp, Yhelp) exists (_.value) } def infoMessage: String = { import settings._ - if (help.value) usageMessage - else if (Xhelp.value) xusageMessage - else if (Yhelp.value) yusageMessage -// else if (showPlugins.value) global.pluginDescriptions -// else if (showPhases.value) global.phaseDescriptions + ( -// if (debug.value) "\n" + global.phaseFlagDescriptions else "" -// ) - else "" + if (help.value) usageMessage + else if (Xhelp.value) xusageMessage + else if (Yhelp.value) yusageMessage + else "" } + // Print all warnings encountered during arguments parsing + summary.warnings.foreach(ctx.warning(_)) + if (summary.errors.nonEmpty) { summary.errors foreach (ctx.error(_)) ctx.echo(" dotc -help gives more information") diff --git a/compiler/src/dotty/tools/dotc/config/PathResolver.scala b/compiler/src/dotty/tools/dotc/config/PathResolver.scala index 184b3718a486..159989e6f97c 100644 --- a/compiler/src/dotty/tools/dotc/config/PathResolver.scala +++ b/compiler/src/dotty/tools/dotc/config/PathResolver.scala @@ -144,7 +144,7 @@ object PathResolver { } else { implicit val ctx = (new ContextBase).initialCtx - val ArgsSummary(sstate, rest, errors) = + val ArgsSummary(sstate, rest, errors, warnings) = ctx.settings.processArguments(args.toList, true) errors.foreach(println) val pr = new PathResolver()(ctx.fresh.setSettings(sstate)) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index e4c90789cf0e..fd79fcaa696c 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -8,152 +8,74 @@ class ScalaSettings extends Settings.SettingGroup { protected def defaultClasspath = sys.env.getOrElse("CLASSPATH", ".") - /** Path related settings. - */ + /** Path related settings */ val bootclasspath = PathSetting("-bootclasspath", "Override location of bootstrap class files.", Defaults.scalaBootClassPath) val extdirs = PathSetting("-extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs) val javabootclasspath = PathSetting("-javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath) val javaextdirs = PathSetting("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs) val sourcepath = PathSetting("-sourcepath", "Specify location(s) of source files.", "") // Defaults.scalaSourcePath - val argfiles = BooleanSetting("@", "A text file containing compiler arguments (options and source files)") val classpath = PathSetting("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp" val d = StringSetting("-d", "directory|jar", "destination for generated classfiles.", ".") val priorityclasspath = PathSetting("-priorityclasspath", "class path that takes precedence over all other paths (or testing only)", "") - /** Other settings. - */ - val dependencyfile = StringSetting("-dependencyfile", "file", "Set dependency tracking file.", ".scala_dependencies") + /** Other settings */ val deprecation = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.") val migration = BooleanSetting("-migration", "Emit warning and location for migration issues from Scala 2.") val encoding = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding) val explaintypes = BooleanSetting("-explaintypes", "Explain type errors in more detail.") val explain = BooleanSetting("-explain", "Explain errors in more detail.") val feature = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.") - val g = ChoiceSetting("-g", "level", "Set level of generated debugging info.", List("none", "source", "line", "vars", "notailcalls"), "vars") val help = BooleanSetting("-help", "Print a synopsis of standard options") - val nowarn = BooleanSetting("-nowarn", "Generate no warnings.") val color = ChoiceSetting("-color", "mode", "Colored output", List("always", "never"/*, "auto"*/), "always"/* "auto"*/) val target = ChoiceSetting("-target", "target", "Target platform for object files. All JVM 1.5 targets are deprecated.", - List("jvm-1.5", "jvm-1.5-fjbg", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "jvm-1.8", "msil"), - "jvm-1.8") - val scalajs = BooleanSetting("-scalajs", "Compile in Scala.js mode (requires scalajs-library.jar on the classpath).") + List("jvm-1.5", "jvm-1.5-fjbg", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "jvm-1.8", "msil"), "jvm-1.8") val unchecked = BooleanSetting("-unchecked", "Enable additional warnings where generated code depends on assumptions.") val uniqid = BooleanSetting("-uniqid", "Uniquely tag all identifiers in debugging output.") val usejavacp = BooleanSetting("-usejavacp", "Utilize the java.class.path in classpath resolution.") val verbose = BooleanSetting("-verbose", "Output messages about what the compiler is doing.") val version = BooleanSetting("-version", "Print product version and exit.") val pageWidth = IntSetting("-pagewidth", "Set page width", 80) - - val jvmargs = PrefixSetting("-J", "-J", "Pass directly to the runtime system.") - val defines = PrefixSetting("-Dproperty=value", "-D", "Pass -Dproperty=value directly to the runtime system.") - val toolcp = PathSetting("-toolcp", "Add to the runner classpath.", "") - val nobootcp = BooleanSetting("-nobootcp", "Do not use the boot classpath for the scala jars.") val strict = BooleanSetting("-strict", "Use strict type rules, which means some formerly legal code does not typecheck anymore.") - - val nospecialization = BooleanSetting("-no-specialization", "Ignore @specialize annotations.") val language = MultiStringSetting("-language", "feature", "Enable one or more language features.") val rewrite = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with -language:Scala2 rewrites sources to migrate to new syntax") /** -X "Advanced" settings */ val Xhelp = BooleanSetting("-X", "Print a synopsis of advanced options.") - val assemname = StringSetting("-Xassem-name", "file", "(Requires -target:msil) Name of the output assembly.", "").dependsOn(target, "msil") - val assemrefs = StringSetting("-Xassem-path", "path", "(Requires -target:msil) List of assemblies referenced by the program.", ".").dependsOn(target, "msil") - val assemextdirs = StringSetting("-Xassem-extdirs", "dirs", "(Requires -target:msil) List of directories containing assemblies. default:lib", Defaults.scalaLibDir.path).dependsOn(target, "msil") - val sourcedir = StringSetting("-Xsourcedir", "directory", "(Requires -target:msil) Mirror source folder structure in output directory.", ".").dependsOn(target, "msil") - val checkInit = BooleanSetting("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.") - val noassertions = BooleanSetting("-Xdisable-assertions", "Generate no assertions or assumptions.") -// val elidebelow = IntSetting("-Xelide-below", "Calls to @elidable methods are omitted if method priority is lower than argument", -// elidable.MINIMUM, None, elidable.byName get _) val noForwarders = BooleanSetting("-Xno-forwarders", "Do not generate static forwarders in mirror classes.") - val genPhaseGraph = StringSetting("-Xgenerate-phase-graph", "file", "Generate the phase graphs (outputs .dot files) to fileX.dot.", "") - val XlogImplicits = BooleanSetting("-Xlog-implicits", "Show more detail on why some implicits are not applicable.") val XminImplicitSearchDepth = IntSetting("-Xmin-implicit-search-depth", "Set number of levels of implicit searches undertaken before checking for divergence.", 5) val xmaxInlines = IntSetting("-Xmax-inlines", "Maximal number of successive inlines", 32) - val logImplicitConv = BooleanSetting("-Xlog-implicit-conversions", "Print a message whenever an implicit conversion is inserted.") - val logReflectiveCalls = BooleanSetting("-Xlog-reflective-calls", "Print a message when a reflective method call is generated") - val logFreeTerms = BooleanSetting("-Xlog-free-terms", "Print a message when reification creates a free term.") - val logFreeTypes = BooleanSetting("-Xlog-free-types", "Print a message when reification resorts to generating a free type.") val maxClassfileName = IntSetting("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, 72 to 255) val Xmigration = VersionSetting("-Xmigration", "Warn about constructs whose behavior may have changed since version.") - val Xsource = VersionSetting("-Xsource", "Treat compiler input as Scala source for the specified version.") - val Xverify = BooleanSetting("-Xverify", "Verify generic signatures in generated bytecode (asm backend only.)") - val plugin = MultiStringSetting("-Xplugin", "file", "Load one or more plugins from files.") - val disable = MultiStringSetting("-Xplugin-disable", "plugin", "Disable the given plugin(s).") - val showPlugins = BooleanSetting("-Xplugin-list", "Print a synopsis of loaded plugins.") - val require = MultiStringSetting("-Xplugin-require", "plugin", "Abort unless the given plugin(s) are available.") - val pluginsDir = StringSetting("-Xpluginsdir", "path", "Path to search compiler plugins.", Defaults.scalaPluginPath) val Xprint = PhasesSetting("-Xprint", "Print out program after") - val writeICode = PhasesSetting("-Xprint-icode", "Log internal icode to *.icode files after", "icode") - val Xprintpos = BooleanSetting("-Xprint-pos", "Print tree positions, as offsets.") val printtypes = BooleanSetting("-Xprint-types", "Print tree types (debugging option).") val XprintDiff = BooleanSetting("-Xprint-diff", "Print changed parts of the tree since last print.") val XprintDiffDel = BooleanSetting("-Xprint-diff-del", "Print chaged parts of the tree since last print including deleted parts.") val prompt = BooleanSetting("-Xprompt", "Display a prompt after each error (debugging option).") - val script = StringSetting("-Xscript", "object", "Treat the source file as a script and wrap it in a main method.", "") val mainClass = StringSetting("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d )", "") - val Xshowcls = StringSetting("-Xshow-class", "class", "Show internal representation of class.", "") - val Xshowobj = StringSetting("-Xshow-object", "object", "Show internal representation of object.", "") - val showPhases = BooleanSetting("-Xshow-phases", "Print a synopsis of compiler phases.") - val sourceReader = StringSetting("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "") val XnoValueClasses = BooleanSetting("-Xno-value-classes", "Do not use value classes. Helps debugging.") val XreplLineWidth = IntSetting("-Xrepl-line-width", "Maximial number of columns per line for REPL output", 390) - val XoldPatmat = BooleanSetting("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.") - val XnoPatmatAnalysis = BooleanSetting("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.") - val XfullLubs = BooleanSetting("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.") - val wikiSyntax = BooleanSetting("-Xwiki-syntax", "Retains the Scala2 behavior of using Wiki Syntax in Scaladoc") - /** -Y "Private" settings - */ - val overrideObjects = BooleanSetting("-Yoverride-objects", "Allow member objects to be overridden.") + /** -Y "Private" settings */ val overrideVars = BooleanSetting("-Yoverride-vars", "Allow vars to be overridden.") val Yhelp = BooleanSetting("-Y", "Print a synopsis of private options.") - val browse = PhasesSetting("-Ybrowse", "Browse the abstract syntax tree after") val Ycheck = PhasesSetting("-Ycheck", "Check the tree at the end of") val YcheckMods = BooleanSetting("-Ycheck-mods", "Check that symbols and their defining trees have modifiers in sync") - val YcheckTypedTrees = BooleanSetting("-YcheckTypedTrees", "Check all constructured typed trees for type correctness") - val Yshow = PhasesSetting("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after") - val Ycloselim = BooleanSetting("-Yclosure-elim", "Perform closure elimination.") - val Ycompacttrees = BooleanSetting("-Ycompact-trees", "Use compact tree printer when displaying trees.") - val noCompletion = BooleanSetting("-Yno-completion", "Disable tab-completion in the REPL.") - val Ydce = BooleanSetting("-Ydead-code", "Perform dead code elimination.") val debug = BooleanSetting("-Ydebug", "Increase the quantity of debugging output.") val debugNames = BooleanSetting("-YdebugNames", "Show name-space indicators when printing names") val debugTrace = BooleanSetting("-Ydebug-trace", "Trace core operations") val debugFlags = BooleanSetting("-Ydebug-flags", "Print all flags of definitions") val debugOwners = BooleanSetting("-Ydebug-owners", "Print all owners of definitions (requires -Yprint-syms)") - //val doc = BooleanSetting ("-Ydoc", "Generate documentation") val termConflict = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") - val inlineHandlers = BooleanSetting("-Yinline-handlers", "Perform exception handler inlining when possible.") - val YinlinerWarnings = BooleanSetting("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)") - val Ylinearizer = ChoiceSetting("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo") val log = PhasesSetting("-Ylog", "Log operations during") val Ylogcp = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.") - val Ynogenericsig = BooleanSetting("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.") val YnoImports = BooleanSetting("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.") val YnoPredef = BooleanSetting("-Yno-predef", "Compile without importing Predef.") - val noAdaptedArgs = BooleanSetting("-Yno-adapted-args", "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.") - val selfInAnnots = BooleanSetting("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.") - val Yshowtrees = BooleanSetting("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs in formatted form.") - val YshowtreesCompact = BooleanSetting("-Yshow-trees-compact", "(Requires -Xprint:) Print detailed ASTs in compact form.") - val YshowtreesStringified = BooleanSetting("-Yshow-trees-stringified", "(Requires -Xprint:) Print stringifications along with detailed ASTs.") - val Yshowsyms = BooleanSetting("-Yshow-syms", "Print the AST symbol hierarchy after each phase.") - val Yshowsymkinds = BooleanSetting("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.") val Yskip = PhasesSetting("-Yskip", "Skip") - val Ygenjavap = StringSetting("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "") val Ydumpclasses = StringSetting("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") - val Ynosqueeze = BooleanSetting("-Yno-squeeze", "Disable creation of compact code in matching.") val YstopAfter = PhasesSetting("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat val YstopBefore = PhasesSetting("-Ystop-before", "Stop before") // stop before erasure as long as we have not debugged it fully - val refinementMethodDispatch = ChoiceSetting("-Ystruct-dispatch", "policy", "structural method dispatch policy", List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache") - val Yrangepos = BooleanSetting("-Yrangepos", "Use range positions for syntax trees.") - val Ybuilderdebug = ChoiceSetting("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none") - val Yreifycopypaste = BooleanSetting("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.") - val Yreplsync = BooleanSetting("-Yrepl-sync", "Do not use asynchronous code for repl startup") val YmethodInfer = BooleanSetting("-Yinfer-argument-types", "Infer types for arguments of overriden methods.") - val etaExpandKeepsStar = BooleanSetting("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.") - val Yinvalidate = StringSetting("-Yinvalidate", "classpath-entry", "Invalidate classpath entry before run", "") - val noSelfCheck = BooleanSetting("-Yno-self-type-checks", "Suppress check for self-type conformance among inherited members.") val YtraceContextCreation = BooleanSetting("-Ytrace-context-creation", "Store stack trace of context creations.") val YshowSuppressedErrors = BooleanSetting("-Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally supressed.") val Yheartbeat = BooleanSetting("-Yheartbeat", "show heartbeat stack trace of compiler operations.") @@ -167,52 +89,17 @@ class ScalaSettings extends Settings.SettingGroup { val YforceSbtPhases = BooleanSetting("-Yforce-sbt-phases", "Run the phases used by sbt for incremental compilation (ExtractDependencies and ExtractAPI) even if the compiler is ran outside of sbt, for debugging.") val YdumpSbtInc = BooleanSetting("-Ydump-sbt-inc", "For every compiled foo.scala, output the API representation and dependencies used for sbt incremental compilation in foo.inc, implies -Yforce-sbt-phases.") val YcheckAllPatmat = BooleanSetting("-Ycheck-all-patmat", "Check exhaustivity and redundancy of all pattern matching (used for testing the algorithm)") - def stop = YstopAfter - /** Area-specific debug output. - */ - val Ybuildmanagerdebug = BooleanSetting("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.") - val Ycompletion = BooleanSetting("-Ycompletion-debug", "Trace all tab completion activity.") - val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.") - val Yidedebug = BooleanSetting("-Yide-debug", "Generate, validate and output trees using the interactive compiler.") - val Yinferdebug = BooleanSetting("-Yinfer-debug", "Trace type inference and implicit search.") - val Yissuedebug = BooleanSetting("-Yissue-debug", "Print stack traces when a context issues an error.") - val YmacrodebugLite = BooleanSetting("-Ymacro-debug-lite", "Trace essential macro-related activities.") - val YmacrodebugVerbose = BooleanSetting("-Ymacro-debug-verbose", "Trace all macro-related activities: compilation, generation of synthetics, classloading, expansion, exceptions.") - val Ypmatdebug = BooleanSetting("-Ypmat-debug", "Trace all pattern matcher activity.") - val Yposdebug = BooleanSetting("-Ypos-debug", "Trace position validation.") - val Yreifydebug = BooleanSetting("-Yreify-debug", "Trace reification.") - val Yrepldebug = BooleanSetting("-Yrepl-debug", "Trace all repl activity.") - val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.") - val Ypatmatdebug = BooleanSetting("-Ypatmat-debug", "Trace pattern matching translation.") + /** Area-specific debug output */ val Yexplainlowlevel = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.") val YnoDoubleBindings = BooleanSetting("-Yno-double-bindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).") val YshowVarBounds = BooleanSetting("-Yshow-var-bounds", "Print type variables with their bounds") val YnoInline = BooleanSetting("-Yno-inline", "Suppress inlining.") + /** Linker specific flags */ val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize" - /** IDE-specific settings - */ - val YpresentationVerbose = BooleanSetting("-Ypresentation-verbose", "Print information about presentation compiler tasks.") - val YpresentationDebug = BooleanSetting("-Ypresentation-debug", "Enable debugging output for the presentation compiler.") - val YpresentationStrict = BooleanSetting("-Ypresentation-strict", "Do not report type errors in sources with syntax errors.") - - val YpresentationLog = StringSetting("-Ypresentation-log", "file", "Log presentation compiler events into file", "") - val YpresentationReplay = StringSetting("-Ypresentation-replay", "file", "Replay presentation compiler events from file", "") - val YpresentationDelay = IntSetting("-Ypresentation-delay", "Wait number of ms after typing before starting typechecking", 0, 0 to 999) - - /** Doc specific settings */ - val template = OptionSetting[String]( - "-template", - "A mustache template for rendering each top-level entity in the API" - ) - - val resources = OptionSetting[String]( - "-resources", - "A directory containing static resources needed for the API documentation" - ) - + /** Dottydoc specific settings */ val siteRoot = StringSetting( "-siteroot", "site root", @@ -227,49 +114,5 @@ class ScalaSettings extends Settings.SettingGroup { sys.props("user.dir").split(sys.props("file.separator")).last ) - val DocVersion = StringSetting ( - "-Ydoc-version", - "version", - "An optional version number, to be appended to the title", - "" - ) - - val DocOutput = StringSetting ( - "-Ydoc-output", - "outdir", - "The output directory in which to place the documentation", - "." - ) - - val DocFooter = StringSetting ( - "-Ydoc-footer", - "footer", - "A footer on every Scaladoc page, by default the EPFL/Lightbend copyright notice. Can be overridden with a custom footer.", - "" - ) - - val DocUncompilable = StringSetting ( - "-Ydoc-no-compile", - "path", - "A directory containing sources which should be parsed, no more (e.g. AnyRef.scala)", - "" - ) - - //def DocUncompilableFiles(implicit ctx: Context) = DocUncompilable.value match { - // case "" => Nil - // case path => io.Directory(path).deepFiles.filter(_ hasExtension "scala").toList - //} - - val DocExternalDoc = MultiStringSetting ( - "-Ydoc-external-doc", - "external-doc", - "comma-separated list of classpath_entry_path#doc_URL pairs describing external dependencies." - ) - - val DocAuthor = BooleanSetting("-Ydoc-author", "Include authors.", true) - - val DocGroups = BooleanSetting ( - "-Ydoc:groups", - "Group similar functions together (based on the @group annotation)" - ) + val wikiSyntax = BooleanSetting("-Xwiki-syntax", "Retains the Scala2 behavior of using Wiki Syntax in Scaladoc") } diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index cffa047fee16..58fa6d366db8 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -44,10 +44,14 @@ object Settings { case class ArgsSummary( sstate: SettingsState, arguments: List[String], - errors: List[String]) { + errors: List[String], + warnings: List[String]) { def fail(msg: String) = - ArgsSummary(sstate, arguments, errors :+ msg) + ArgsSummary(sstate, arguments.tail, errors :+ msg, warnings) + + def warn(msg: String) = + ArgsSummary(sstate, arguments.tail, errors, warnings :+ msg) } case class Setting[T: ClassTag] private[Settings] ( @@ -106,11 +110,11 @@ object Settings { } def tryToSet(state: ArgsSummary): ArgsSummary = { - val ArgsSummary(sstate, arg :: args, errors) = state + val ArgsSummary(sstate, arg :: args, errors, warnings) = state def update(value: Any, args: List[String]) = - ArgsSummary(updateIn(sstate, value), args, errors) + ArgsSummary(updateIn(sstate, value), args, errors, warnings) def fail(msg: String, args: List[String]) = - ArgsSummary(sstate, args, errors :+ msg) + ArgsSummary(sstate, args, errors :+ msg, warnings) def missingArg = fail(s"missing argument for option $name", args) def doSet(argRest: String) = ((implicitly[ClassTag[T]], args): @unchecked) match { @@ -206,7 +210,7 @@ object Settings { * to get their arguments. */ protected def processArguments(state: ArgsSummary, processAll: Boolean, skipped: List[String]): ArgsSummary = { - def stateWithArgs(args: List[String]) = ArgsSummary(state.sstate, args, state.errors) + def stateWithArgs(args: List[String]) = ArgsSummary(state.sstate, args, state.errors, state.warnings) state.arguments match { case Nil => checkDependencies(stateWithArgs(skipped)) @@ -219,7 +223,7 @@ object Settings { if (state1 ne state) processArguments(state1, processAll, skipped) else loop(settings1) case Nil => - state.fail(s"bad option: '$x'") + processArguments(state.warn(s"bad option '$x' was ignored"), processAll, skipped) } loop(allSettings.toList) case arg :: args => @@ -229,7 +233,7 @@ object Settings { } def processArguments(arguments: List[String], processAll: Boolean)(implicit ctx: Context): ArgsSummary = - processArguments(ArgsSummary(ctx.sstate, arguments, Nil), processAll, Nil) + processArguments(ArgsSummary(ctx.sstate, arguments, Nil, Nil), processAll, Nil) def publish[T](settingf: Int => Setting[T]): Setting[T] = { val setting = settingf(_allSettings.length) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 01a164a812d9..9e9e39a8439d 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -637,13 +637,9 @@ class Definitions { FunctionType(args.length, isImplicit).appliedTo(args ::: resultType :: Nil) def unapply(ft: Type)(implicit ctx: Context) = { val tsym = ft.typeSymbol - val isImplicitFun = isImplicitFunctionClass(tsym) - if (isImplicitFun || isFunctionClass(tsym)) { - val targs = ft.argInfos - val numArgs = targs.length - 1 - if (numArgs >= 0 && FunctionType(numArgs, isImplicitFun).symbol == tsym) - Some(targs.init, targs.last, isImplicitFun) - else None + if (isFunctionClass(tsym)) { + val targs = ft.dealias.argInfos + Some(targs.init, targs.last, tsym.name.isImplicitFunction) } else None } @@ -696,20 +692,17 @@ class Definitions { lazy val TupleType = mkArityArray("scala.Tuple", MaxTupleArity, 2) lazy val ProductNType = mkArityArray("scala.Product", MaxTupleArity, 0) - def FunctionClass(n: Int)(implicit ctx: Context) = - if (n < MaxImplementedFunctionArity) FunctionClassPerRun()(ctx)(n) + def FunctionClass(n: Int, isImplicit: Boolean = false)(implicit ctx: Context) = + if (isImplicit) ctx.requiredClass("scala.ImplicitFunction" + n.toString) + else if (n <= MaxImplementedFunctionArity) FunctionClassPerRun()(ctx)(n) else ctx.requiredClass("scala.Function" + n.toString) lazy val Function0_applyR = ImplementedFunctionType(0).symbol.requiredMethodRef(nme.apply) def Function0_apply(implicit ctx: Context) = Function0_applyR.symbol - def ImplicitFunctionClass(n: Int)(implicit ctx: Context) = - ctx.requiredClass("scala.ImplicitFunction" + n.toString) - def FunctionType(n: Int, isImplicit: Boolean = false)(implicit ctx: Context): TypeRef = - if (isImplicit && !ctx.erasedTypes) ImplicitFunctionClass(n).typeRef - else if (n < MaxImplementedFunctionArity) ImplementedFunctionType(n) - else FunctionClass(n).typeRef + if (n <= MaxImplementedFunctionArity && (!isImplicit || ctx.erasedTypes)) ImplementedFunctionType(n) + else FunctionClass(n, isImplicit).typeRef private lazy val TupleTypes: Set[TypeRef] = TupleType.toSet private lazy val ProductTypes: Set[TypeRef] = ProductNType.toSet @@ -733,14 +726,61 @@ class Definitions { def isBottomType(tp: Type) = tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass) - def isFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.Function) - def isImplicitFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.ImplicitFunction) - /** Is a class that will be erased to FunctionXXL */ - def isXXLFunctionClass(cls: Symbol) = cls.name.functionArity > MaxImplementedFunctionArity + /** Is a function class. + * - FunctionN for N >= 0 + * - ImplicitFunctionN for N >= 0 + */ + def isFunctionClass(cls: Symbol) = scalaClassName(cls).isFunction + + /** Is an implicit function class. + * - ImplicitFunctionN for N >= 0 + */ + def isImplicitFunctionClass(cls: Symbol) = scalaClassName(cls).isImplicitFunction + + /** Is a class that will be erased to FunctionXXL + * - FunctionN for N >= 22 + * - ImplicitFunctionN for N >= 22 + */ + def isXXLFunctionClass(cls: Symbol) = scalaClassName(cls).functionArity > MaxImplementedFunctionArity + + /** Is a synthetic function class + * - FunctionN for N > 22 + * - ImplicitFunctionN for N >= 0 + */ + def isSyntheticFunctionClass(cls: Symbol) = scalaClassName(cls).isSyntheticFunction + def isAbstractFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.AbstractFunction) def isTupleClass(cls: Symbol) = isVarArityClass(cls, tpnme.Tuple) def isProductClass(cls: Symbol) = isVarArityClass(cls, tpnme.Product) + /** Returns the erased class of the function class `cls` + * - FunctionN for N > 22 becomes FunctionXXL + * - FunctionN for 22 > N >= 0 remains as FunctionN + * - ImplicitFunctionN for N > 22 becomes FunctionXXL + * - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN + * - anything else becomes a NoSymbol + */ + def erasedFunctionClass(cls: Symbol): Symbol = { + val arity = scalaClassName(cls).functionArity + if (arity > 22) defn.FunctionXXLClass + else if (arity >= 0) defn.FunctionClass(arity) + else NoSymbol + } + + /** Returns the erased type of the function class `cls` + * - FunctionN for N > 22 becomes FunctionXXL + * - FunctionN for 22 > N >= 0 remains as FunctionN + * - ImplicitFunctionN for N > 22 becomes FunctionXXL + * - ImplicitFunctionN for 22 > N >= 0 becomes FunctionN + * - anything else becomes a NoType + */ + def erasedFunctionType(cls: Symbol): Type = { + val arity = scalaClassName(cls).functionArity + if (arity > 22) defn.FunctionXXLType + else if (arity >= 0) defn.FunctionType(arity) + else NoType + } + val predefClassNames: Set[Name] = Set("Predef$", "DeprecatedPredef", "LowPriorityImplicits").map(_.toTypeName) @@ -811,16 +851,13 @@ class Definitions { def isFunctionType(tp: Type)(implicit ctx: Context) = { val arity = functionArity(tp) val sym = tp.dealias.typeSymbol - arity >= 0 && ( - isFunctionClass(sym) && tp.isRef(FunctionType(arity, isImplicit = false).typeSymbol) || - isImplicitFunctionClass(sym) && tp.isRef(FunctionType(arity, isImplicit = true).typeSymbol) - ) + arity >= 0 && isFunctionClass(sym) && tp.isRef(FunctionType(arity, sym.name.isImplicitFunction).typeSymbol) } def functionArity(tp: Type)(implicit ctx: Context) = tp.dealias.argInfos.length - 1 def isImplicitFunctionType(tp: Type)(implicit ctx: Context) = - isFunctionType(tp) && tp.dealias.typeSymbol.name.startsWith(tpnme.ImplicitFunction) + isFunctionType(tp) && tp.dealias.typeSymbol.name.isImplicitFunction // ----- primitive value class machinery ------------------------------------------ @@ -894,9 +931,6 @@ class Definitions { // ----- Initialization --------------------------------------------------- - private def maxImplemented(name: Name) = - if (name `startsWith` tpnme.Function) MaxImplementedFunctionArity else 0 - /** Give the scala package a scope where a FunctionN trait is automatically * added when someone looks for it. */ @@ -906,7 +940,7 @@ class Definitions { val newDecls = new MutableScope(oldDecls) { override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = { val res = super.lookupEntry(name) - if (res == null && name.isTypeName && name.functionArity > maxImplemented(name)) + if (res == null && name.isTypeName && name.isSyntheticFunction) newScopeEntry(newFunctionNTrait(name.asTypeName)) else res } diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index c037d1ce7d12..cd3ae2a25632 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -8,6 +8,7 @@ import Names._, StdNames._, Contexts._, Symbols._, Flags._ import Decorators.StringDecorator import util.{Chars, NameTransformer} import Chars.isOperatorPart +import Definitions._ object NameOps { @@ -231,13 +232,43 @@ object NameOps { } } - def functionArity: Int = { - def test(prefix: Name): Int = - if (name.startsWith(prefix)) - try name.drop(prefix.length).toString.toInt - catch { case ex: NumberFormatException => -1 } - else -1 - test(tpnme.Function) max test(tpnme.ImplicitFunction) + /** Is a synthetic function name + * - N for FunctionN + * - N for ImplicitFunctionN + * - (-1) otherwise + */ + def functionArity: Int = + functionArityFor(tpnme.Function) max functionArityFor(tpnme.ImplicitFunction) + + /** Is a function name + * - FunctionN for N >= 0 + * - ImplicitFunctionN for N >= 0 + * - false otherwise + */ + def isFunction: Boolean = functionArity >= 0 + + /** Is a implicit function name + * - ImplicitFunctionN for N >= 0 + * - false otherwise + */ + def isImplicitFunction: Boolean = functionArityFor(tpnme.ImplicitFunction) >= 0 + + /** Is a synthetic function name + * - FunctionN for N > 22 + * - ImplicitFunctionN for N >= 0 + * - false otherwise + */ + def isSyntheticFunction: Boolean = { + functionArityFor(tpnme.Function) > MaxImplementedFunctionArity || + functionArityFor(tpnme.ImplicitFunction) >= 0 + } + + /** Parsed function arity for function with some specific prefix */ + private def functionArityFor(prefix: Name): Int = { + if (name.startsWith(prefix)) + try name.toString.substring(prefix.length).toInt + catch { case _: NumberFormatException => -1 } + else -1 } /** The name of the generic runtime operation corresponding to an array operation */ diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 2a341390b5d2..ff99008bbf61 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -44,7 +44,7 @@ object TypeErasure { val sym = tp.symbol sym.isClass && sym != defn.AnyClass && sym != defn.ArrayClass && - !defn.isXXLFunctionClass(sym) && !defn.isImplicitFunctionClass(sym) + !defn.isSyntheticFunctionClass(sym) case _: TermRef => true case JavaArrayType(elem) => @@ -358,8 +358,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean if (!sym.isClass) this(tp.info) else if (semiEraseVCs && isDerivedValueClass(sym)) eraseDerivedValueClassRef(tp) else if (sym == defn.ArrayClass) apply(tp.appliedTo(TypeBounds.empty)) // i966 shows that we can hit a raw Array type. - else if (defn.isXXLFunctionClass(sym)) defn.FunctionXXLType - else if (defn.isImplicitFunctionClass(sym)) apply(defn.FunctionType(sym.name.functionArity)) + else if (defn.isSyntheticFunctionClass(sym)) defn.erasedFunctionType(sym) else eraseNormalClassRef(tp) case tp: RefinedType => val parent = tp.parent @@ -370,7 +369,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean case SuperType(thistpe, supertpe) => SuperType(this(thistpe), this(supertpe)) case ExprType(rt) => - defn.FunctionClass(0).typeRef + defn.FunctionType(0) case AndType(tp1, tp2) => erasedGlb(this(tp1), this(tp2), isJava) case OrType(tp1, tp2) => @@ -496,8 +495,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean val erasedVCRef = eraseDerivedValueClassRef(tp) if (erasedVCRef.exists) return sigName(erasedVCRef) } - if (defn.isImplicitFunctionClass(sym)) - sigName(defn.FunctionType(sym.name.functionArity)) + if (defn.isSyntheticFunctionClass(sym)) + sigName(defn.erasedFunctionType(sym)) else normalizeClass(sym.asClass).fullName.asTypeName case defn.ArrayOf(elem) => diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 45ae842b6021..b46bc401da68 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -404,14 +404,13 @@ object Parsers { var opStack: List[OpInfo] = Nil - def checkAssoc(offset: Int, op: Name, leftAssoc: Boolean) = - if (isLeftAssoc(op) != leftAssoc) - syntaxError( - "left- and right-associative operators with same precedence may not be mixed", offset) + def checkAssoc(offset: Token, op1: Name, op2: Name, op2LeftAssoc: Boolean): Unit = + if (isLeftAssoc(op1) != op2LeftAssoc) + syntaxError(MixedLeftAndRightAssociativeOps(op1, op2, op2LeftAssoc), offset) - def reduceStack(base: List[OpInfo], top: Tree, prec: Int, leftAssoc: Boolean): Tree = { + def reduceStack(base: List[OpInfo], top: Tree, prec: Int, leftAssoc: Boolean, op2: Name): Tree = { if (opStack != base && precedence(opStack.head.operator.name) == prec) - checkAssoc(opStack.head.offset, opStack.head.operator.name, leftAssoc) + checkAssoc(opStack.head.offset, opStack.head.operator.name, op2, leftAssoc) def recur(top: Tree): Tree = { if (opStack == base) top else { @@ -445,20 +444,20 @@ object Parsers { var top = first while (isIdent && in.name != notAnOperator) { val op = if (isType) typeIdent() else termIdent() - top = reduceStack(base, top, precedence(op.name), isLeftAssoc(op.name)) + top = reduceStack(base, top, precedence(op.name), isLeftAssoc(op.name), op.name) opStack = OpInfo(top, op, in.offset) :: opStack newLineOptWhenFollowing(canStartOperand) if (maybePostfix && !canStartOperand(in.token)) { val topInfo = opStack.head opStack = opStack.tail - val od = reduceStack(base, topInfo.operand, 0, true) + val od = reduceStack(base, topInfo.operand, 0, true, in.name) return atPos(startOffset(od), topInfo.offset) { PostfixOp(od, topInfo.operator) } } top = operand() } - reduceStack(base, top, 0, true) + reduceStack(base, top, 0, true, in.name) } /* -------- IDENTIFIERS AND LITERALS ------------------------------------------- */ diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 5b75df6b26f7..3d952f425e9c 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -126,8 +126,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case AppliedType(tycon, args) => val cls = tycon.typeSymbol if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*" - if (defn.isFunctionClass(cls)) return toTextFunction(args, isImplicit = false) - if (defn.isImplicitFunctionClass(cls)) return toTextFunction(args, isImplicit = true) + if (defn.isFunctionClass(cls)) return toTextFunction(args, cls.name.isImplicitFunction) if (defn.isTupleClass(cls)) return toTextTuple(args) return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close case tp: TypeRef => diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala index 24d583b19fe7..190445d60171 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -5,7 +5,7 @@ package reporting import core.Contexts.Context import core.Decorators._ import printing.Highlighting.{Blue, Red} -import diagnostic.{Message, MessageContainer, NoExplanation} +import diagnostic.{ErrorMessageID, Message, MessageContainer, NoExplanation} import diagnostic.messages._ import util.SourcePosition @@ -95,9 +95,10 @@ trait MessageRendering { if (pos.exists) Blue({ val file = pos.source.file.toString val errId = - if (message.errorId != NoExplanation.ID) - s"[E${"0" * (3 - message.errorId.toString.length) + message.errorId}] " - else "" + if (message.errorId ne ErrorMessageID.NoExplanationID) { + val errorNumber = message.errorId.errorNumber() + s"[E${"0" * (3 - errorNumber.toString.length) + errorNumber}] " + } else "" val kind = if (message.kind == "") diagnosticLevel else s"${message.kind} $diagnosticLevel" diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java new file mode 100644 index 000000000000..c74130b445cf --- /dev/null +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -0,0 +1,58 @@ +package dotty.tools.dotc.reporting.diagnostic; + +/** Unique IDs identifying the messages */ +public enum ErrorMessageID { + + // IMPORTANT: Add new IDs only at the end and never remove IDs + + LazyErrorId, // // errorNumber: -2 + NoExplanationID, // errorNumber: -1 + + EmptyCatchOrFinallyBlockID, // errorNumber: 0 + EmptyCatchBlockID, // errorNumber: 1 + EmptyCatchAndFinallyBlockID, // errorNumber: 2 + DeprecatedWithOperatorID, + CaseClassMissingParamListID, + DuplicateBindID, + MissingIdentID, + TypeMismatchID, + NotAMemberID, + EarlyDefinitionsNotSupportedID, + TopLevelImplicitClassID, + ImplicitCaseClassID, + ObjectMayNotHaveSelfTypeID, + TupleTooLongID, + RepeatedModifierID, + InterpolatedStringErrorID, + UnboundPlaceholderParameterID, + IllegalStartSimpleExprID, + MissingReturnTypeID, + YieldOrDoExpectedInForComprehensionID, + ProperDefinitionNotFoundID, + ByNameParameterNotSupportedID, + WrongNumberOfTypeArgsID, + IllegalVariableInPatternAlternativeID, + TypeParamsTypeExpectedID, + IdentifierExpectedID, + AuxConstructorNeedsNonImplicitParameterID, + IncorrectRepeatedParameterSyntaxID, + IllegalLiteralID, + PatternMatchExhaustivityID, + MatchCaseUnreachableID, + SeqWildcardPatternPosID, + IllegalStartOfSimplePatternID, + PkgDuplicateSymbolID, + ExistentialTypesNoLongerSupportedID, + UnboundWildcardTypeID, + DanglingThisInPathID, + OverridesNothingID, + OverridesNothingButNameExistsID, + ForwardReferenceExtendsOverDefinitionID, + ExpectedTokenButFoundID, + MixedLeftAndRightAssociativeOpsID; + + public int errorNumber() { + return ordinal() - 2; + } + +} diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala index ab1222dab6b7..09d7ae9751be 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala @@ -30,11 +30,10 @@ object Message { * Instead use the `persist` method to create an instance that does not keep a * reference to these contexts. * - * @param errorId a unique number identifying the message, this will later be + * @param errorId a unique id identifying the message, this will later be * used to reference documentation online */ -abstract class Message(val errorId: Int) { self => - import messages._ +abstract class Message(val errorId: ErrorMessageID) { self => /** The `msg` contains the diagnostic message e.g: * @@ -116,7 +115,7 @@ class ExtendMessage(_msg: () => Message)(f: String => String) { self => } /** The fallback `Message` containing no explanation and having no `kind` */ -class NoExplanation(val msg: String) extends Message(NoExplanation.ID) { +class NoExplanation(val msg: String) extends Message(ErrorMessageID.NoExplanationID) { val explanation = "" val kind = "" @@ -127,8 +126,6 @@ class NoExplanation(val msg: String) extends Message(NoExplanation.ID) { * lacks an explanation */ object NoExplanation { - final val ID = -1 - def unapply(m: Message): Option[Message] = if (m.explanation == "") Some(m) else None diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 94611e10d014..7fccebef9427 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -17,6 +17,7 @@ import dotc.parsing.Scanners.Token import dotc.parsing.Tokens import printing.Highlighting._ import printing.Formatting +import ErrorMessageID._ object messages { @@ -94,8 +95,8 @@ object messages { // Syntax Errors ---------------------------------------------------------- // - abstract class EmptyCatchOrFinallyBlock(tryBody: untpd.Tree, errNo: Int)(implicit ctx: Context) - extends Message(errNo) { + abstract class EmptyCatchOrFinallyBlock(tryBody: untpd.Tree, errNo: ErrorMessageID)(implicit ctx: Context) + extends Message(EmptyCatchOrFinallyBlockID) { val explanation = { val tryString = tryBody match { case Block(Nil, untpd.EmptyTree) => "{}" @@ -131,7 +132,7 @@ object messages { } case class EmptyCatchBlock(tryBody: untpd.Tree)(implicit ctx: Context) - extends EmptyCatchOrFinallyBlock(tryBody, 1) { + extends EmptyCatchOrFinallyBlock(tryBody, EmptyCatchBlockID) { val kind = "Syntax" val msg = hl"""|The ${"catch"} block does not contain a valid expression, try @@ -139,7 +140,7 @@ object messages { } case class EmptyCatchAndFinallyBlock(tryBody: untpd.Tree)(implicit ctx: Context) - extends EmptyCatchOrFinallyBlock(tryBody, 2) { + extends EmptyCatchOrFinallyBlock(tryBody, EmptyCatchAndFinallyBlockID) { val kind = "Syntax" val msg = hl"""|A ${"try"} without ${"catch"} or ${"finally"} is equivalent to putting @@ -147,7 +148,7 @@ object messages { } case class DeprecatedWithOperator()(implicit ctx: Context) - extends Message(3) { + extends Message(DeprecatedWithOperatorID) { val kind = "Syntax" val msg = hl"""${"with"} as a type operator has been deprecated; use `&' instead""" @@ -158,7 +159,7 @@ object messages { } case class CaseClassMissingParamList(cdef: untpd.TypeDef)(implicit ctx: Context) - extends Message(4) { + extends Message(CaseClassMissingParamListID) { val kind = "Syntax" val msg = hl"""|A ${"case class"} must have at least one parameter list""" @@ -172,7 +173,7 @@ object messages { // Type Errors ------------------------------------------------------------ // case class DuplicateBind(bind: untpd.Bind, tree: untpd.CaseDef)(implicit ctx: Context) - extends Message(5) { + extends Message(DuplicateBindID) { val kind = "Naming" val msg = em"duplicate pattern variable: `${bind.name}`" @@ -199,7 +200,7 @@ object messages { } case class MissingIdent(tree: untpd.Ident, treeKind: String, name: String)(implicit ctx: Context) - extends Message(6) { + extends Message(MissingIdentID) { val kind = "Unbound Identifier" val msg = em"not found: $treeKind$name" @@ -212,7 +213,7 @@ object messages { } case class TypeMismatch(found: Type, expected: Type, whyNoMatch: String = "", implicitFailure: String = "")(implicit ctx: Context) - extends Message(7) { + extends Message(TypeMismatchID) { val kind = "Type Mismatch" val msg = { val (where, printCtx) = Formatting.disambiguateTypes(found, expected) @@ -227,7 +228,7 @@ object messages { } case class NotAMember(site: Type, name: Name, selected: String)(implicit ctx: Context) - extends Message(8) { + extends Message(NotAMemberID) { val kind = "Member Not Found" //println(i"site = $site, decls = ${site.decls}, source = ${site.widen.typeSymbol.sourceFile}") //DEBUG @@ -293,7 +294,7 @@ object messages { } case class EarlyDefinitionsNotSupported()(implicit ctx: Context) - extends Message(9) { + extends Message(EarlyDefinitionsNotSupportedID) { val kind = "Syntax" val msg = "early definitions are not supported; use trait parameters instead" @@ -339,7 +340,7 @@ object messages { } case class TopLevelImplicitClass(cdef: untpd.TypeDef)(implicit ctx: Context) - extends Message(10) { + extends Message(TopLevelImplicitClassID) { val kind = "Syntax" val msg = hl"""An ${"implicit class"} may not be top-level""" @@ -369,7 +370,7 @@ object messages { } case class ImplicitCaseClass(cdef: untpd.TypeDef)(implicit ctx: Context) - extends Message(11) { + extends Message(ImplicitCaseClassID) { val kind = "Syntax" val msg = hl"""A ${"case class"} may not be defined as ${"implicit"}""" @@ -382,7 +383,7 @@ object messages { } case class ObjectMayNotHaveSelfType(mdef: untpd.ModuleDef)(implicit ctx: Context) - extends Message(12) { + extends Message(ObjectMayNotHaveSelfTypeID) { val kind = "Syntax" val msg = hl"""${"object"}s must not have a self ${"type"}""" @@ -400,7 +401,7 @@ object messages { } case class TupleTooLong(ts: List[untpd.Tree])(implicit ctx: Context) - extends Message(13) { + extends Message(TupleTooLongID) { import Definitions.MaxTupleArity val kind = "Syntax" val msg = hl"""A ${"tuple"} cannot have more than ${MaxTupleArity} members""" @@ -416,7 +417,7 @@ object messages { } case class RepeatedModifier(modifier: String)(implicit ctx:Context) - extends Message(14) { + extends Message(RepeatedModifierID) { val kind = "Syntax" val msg = hl"""repeated modifier $modifier""" @@ -438,7 +439,7 @@ object messages { } case class InterpolatedStringError()(implicit ctx:Context) - extends Message(15) { + extends Message(InterpolatedStringErrorID) { val kind = "Syntax" val msg = "error in interpolated string: identifier or block expected" val explanation = { @@ -456,7 +457,7 @@ object messages { } case class UnboundPlaceholderParameter()(implicit ctx:Context) - extends Message(16) { + extends Message(UnboundPlaceholderParameterID) { val kind = "Syntax" val msg = "unbound placeholder parameter; incorrect use of `_`" val explanation = @@ -489,7 +490,7 @@ object messages { } case class IllegalStartSimpleExpr(illegalToken: String)(implicit ctx: Context) - extends Message(17) { + extends Message(IllegalStartSimpleExprID) { val kind = "Syntax" val msg = "illegal start of simple expression" val explanation = { @@ -507,7 +508,8 @@ object messages { } } - case class MissingReturnType()(implicit ctx:Context) extends Message(18) { + case class MissingReturnType()(implicit ctx:Context) + extends Message(MissingReturnTypeID) { val kind = "Syntax" val msg = "missing return type" val explanation = @@ -519,7 +521,7 @@ object messages { } case class YieldOrDoExpectedInForComprehension()(implicit ctx: Context) - extends Message(19) { + extends Message(YieldOrDoExpectedInForComprehensionID) { val kind = "Syntax" val msg = hl"${"yield"} or ${"do"} expected" @@ -552,7 +554,7 @@ object messages { } case class ProperDefinitionNotFound()(implicit ctx: Context) - extends Message(20) { + extends Message(ProperDefinitionNotFoundID) { val kind = "Definition Not Found" val msg = hl"""Proper definition was not found in ${"@usecase"}""" @@ -591,7 +593,7 @@ object messages { } case class ByNameParameterNotSupported()(implicit ctx: Context) - extends Message(21) { + extends Message(ByNameParameterNotSupportedID) { val kind = "Syntax" val msg = "By-name parameter type not allowed here." @@ -615,7 +617,7 @@ object messages { } case class WrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree])(implicit ctx: Context) - extends Message(22) { + extends Message(WrongNumberOfTypeArgsID) { val kind = "Syntax" private val expectedCount = expectedArgs.length @@ -661,7 +663,7 @@ object messages { } case class IllegalVariableInPatternAlternative()(implicit ctx: Context) - extends Message(23) { + extends Message(IllegalVariableInPatternAlternativeID) { val kind = "Syntax" val msg = "Variables are not allowed in alternative patterns" val explanation = { @@ -690,7 +692,7 @@ object messages { } case class TypeParamsTypeExpected(mods: untpd.Modifiers, identifier: TermName)(implicit ctx: Context) - extends Message(24) { + extends Message(TypeParamsTypeExpectedID) { val kind = "Syntax" val msg = hl"""Expected ${"type"} keyword for type parameter $identifier""" val explanation = @@ -703,7 +705,7 @@ object messages { } case class IdentifierExpected(identifier: String)(implicit ctx: Context) - extends Message(25) { + extends Message(IdentifierExpectedID) { val kind = "Syntax" val msg = "identifier expected" val explanation = { @@ -724,7 +726,7 @@ object messages { } case class AuxConstructorNeedsNonImplicitParameter()(implicit ctx:Context) - extends Message(26) { + extends Message(AuxConstructorNeedsNonImplicitParameterID) { val kind = "Syntax" val msg = "auxiliary constructor needs non-implicit parameter list" val explanation = @@ -739,7 +741,8 @@ object messages { |""" } - case class IncorrectRepeatedParameterSyntax()(implicit ctx: Context) extends Message(27) { + case class IncorrectRepeatedParameterSyntax()(implicit ctx: Context) + extends Message(IncorrectRepeatedParameterSyntaxID) { val kind = "Syntax" val msg = "'*' expected" val explanation = @@ -765,7 +768,8 @@ object messages { |""".stripMargin } - case class IllegalLiteral()(implicit ctx: Context) extends Message(28) { + case class IllegalLiteral()(implicit ctx: Context) + extends Message(IllegalLiteralID) { val kind = "Syntax" val msg = "illegal literal" val explanation = @@ -780,7 +784,7 @@ object messages { } case class PatternMatchExhaustivity(uncovered: String)(implicit ctx: Context) - extends Message(29) { + extends Message(PatternMatchExhaustivityID) { val kind = "Pattern Match Exhaustivity" val msg = hl"""|match may not be exhaustive. @@ -792,14 +796,14 @@ object messages { } case class MatchCaseUnreachable()(implicit ctx: Context) - extends Message(30) { + extends Message(MatchCaseUnreachableID) { val kind = s"""Match ${hl"case"} Unreachable""" val msg = "unreachable code" val explanation = "" } case class SeqWildcardPatternPos()(implicit ctx: Context) - extends Message(31) { + extends Message(SeqWildcardPatternPosID) { val kind = "Syntax" val msg = "`_*' can be used only for last argument" val explanation = { @@ -822,7 +826,8 @@ object messages { } } - case class IllegalStartOfSimplePattern()(implicit ctx: Context) extends Message(32) { + case class IllegalStartOfSimplePattern()(implicit ctx: Context) + extends Message(IllegalStartOfSimplePatternID) { val kind = "Syntax" val msg = "illegal start of simple pattern" val explanation = { @@ -902,13 +907,14 @@ object messages { } case class PkgDuplicateSymbol(existing: Symbol)(implicit ctx: Context) - extends Message(33) { + extends Message(PkgDuplicateSymbolID) { val kind = "Duplicate Symbol" val msg = hl"trying to define package with same name as `$existing`" val explanation = "" } - case class ExistentialTypesNoLongerSupported()(implicit ctx: Context) extends Message(34) { + case class ExistentialTypesNoLongerSupported()(implicit ctx: Context) + extends Message(ExistentialTypesNoLongerSupportedID) { val kind = "Syntax" val msg = hl"""|Existential types are no longer supported - @@ -930,7 +936,8 @@ object messages { |""" } - case class UnboundWildcardType()(implicit ctx: Context) extends Message(35) { + case class UnboundWildcardType()(implicit ctx: Context) + extends Message(UnboundWildcardTypeID) { val kind = "Syntax" val msg = "Unbound wildcard type" val explanation = @@ -974,7 +981,7 @@ object messages { |""" } - case class DanglingThisInPath()(implicit ctx: Context) extends Message(36) { + case class DanglingThisInPath()(implicit ctx: Context) extends Message(DanglingThisInPathID) { val kind = "Syntax" val msg = hl"""Expected an additional member selection after the keyword ${"this"}""" @@ -1011,7 +1018,7 @@ object messages { } case class OverridesNothing(member: Symbol)(implicit ctx: Context) - extends Message(37) { + extends Message(OverridesNothingID) { val kind = "Reference" val msg = hl"""${member} overrides nothing""" @@ -1023,7 +1030,7 @@ object messages { } case class OverridesNothingButNameExists(member: Symbol, existing: List[Denotations.SingleDenotation])(implicit ctx: Context) - extends Message(38) { + extends Message(OverridesNothingButNameExistsID) { val kind = "Reference" val msg = hl"""${member} has a different signature than the overridden declaration""" @@ -1042,7 +1049,7 @@ object messages { } case class ForwardReferenceExtendsOverDefinition(value: Symbol, definition: Symbol)(implicit ctx: Context) - extends Message(39) { + extends Message(ForwardReferenceExtendsOverDefinitionID) { val kind = "Reference" val msg = hl"`${definition.name}` is a forward reference extending over the definition of `${value.name}`" @@ -1061,7 +1068,7 @@ object messages { } case class ExpectedTokenButFound(expected: Token, found: Token, foundName: TermName)(implicit ctx: Context) - extends Message(40) { + extends Message(ExpectedTokenButFoundID) { val kind = "Syntax" private val expectedText = @@ -1086,4 +1093,38 @@ object messages { |""".stripMargin } + case class MixedLeftAndRightAssociativeOps(op1: Name, op2: Name, op2LeftAssoc: Boolean)(implicit ctx: Context) + extends Message(MixedLeftAndRightAssociativeOpsID) { + val kind = "Syntax" + val op1Asso = if (op2LeftAssoc) "which is right-associative" else "which is left-associative" + val op2Asso = if (op2LeftAssoc) "which is left-associative" else "which is right-associative" + val msg = s"`${op1}` (${op1Asso}) and `${op2}` ($op2Asso) have same precedence and may not be mixed" + val explanation = + s"""|The operators ${op1} and ${op2} are used as infix operators in the same expression, + |but they bind to different sides: + |${op1} is applied to the operand to its ${if (op2LeftAssoc) "right" else "left"} + |${op2} is applied to the operand to its ${if (op2LeftAssoc) "left" else "right"} + |As both have the same precedence the compiler can't decide which to apply first. + | + |You may use parenthesis to make the application order explicit, + |or use method application syntax `operand1.${op1}(operand2)`. + | + |Operators ending in a colon `:` are right-associative. All other operators are left-associative. + | + |Infix operator precedence is determined by the operator's first character. Characters are listed + |below in increasing order of precedence, with characters on the same line having the same precedence. + | (all letters) + | | + | ^ + | & + | = ! + | < > + | : + | + - + | * / % + | (all other special characters) + |Operators starting with a letter have lowest precedence, followed by operators starting with `|`, etc. + |""".stripMargin + } + } diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index bba97c4c206d..34ea2bc6fa8f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -349,10 +349,8 @@ object Erasure extends TypeTestsCasts{ if ((owner eq defn.AnyClass) || (owner eq defn.AnyValClass)) { assert(sym.isConstructor, s"${sym.showLocated}") defn.ObjectClass - } else if (defn.isXXLFunctionClass(owner)) - defn.FunctionXXLClass - else if (defn.isImplicitFunctionClass(owner)) - recur(defn.FunctionClass(owner.name.functionArity)) + } else if (defn.isSyntheticFunctionClass(owner)) + defn.erasedFunctionClass(owner) else owner recur(sym.owner) diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index eee429a87e3c..b2b99160b35c 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -81,7 +81,7 @@ class TreeChecker extends Phase with SymTransformer { val sym = symd.symbol if (sym.isClass && !sym.isAbsent) { - val validSuperclass = sym.isPrimitiveValueClass || defn.syntheticCoreClasses.contains(sym) || + val validSuperclass = sym.isPrimitiveValueClass || defn.syntheticCoreClasses.contains(sym) || (sym eq defn.ObjectClass) || (sym is NoSuperClass) || (sym.asClass.superClass.exists) if (!validSuperclass) printError(s"$sym has no superclass set") diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 42c24ffb7723..0ed6ed6b49b6 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -916,7 +916,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits, unapplyPatterns), ownType) unapp.println(s"unapply patterns = $unapplyPatterns") if ((ownType eq selType) || ownType.isError) result - else Typed(result, TypeTree(ownType)) + else tryWithClassTag(Typed(result, TypeTree(ownType)), selType) case tp => val unapplyErr = if (tp.isError) unapplyFn else notAnExtractor(unapplyFn) val typedArgsErr = args mapconserve (typed(_, defn.AnyType)) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 27b0f28ca914..fb0497c2b9b1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -356,8 +356,7 @@ object Checking { */ def checkNoPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type = { class NotPrivate extends TypeMap { - type Errors = List[(String, Position)] - var errors: Errors = Nil + var errors: List[String] = Nil def accessBoundary(sym: Symbol): Symbol = if (sym.is(Private) || !sym.owner.isClass) sym.owner @@ -383,8 +382,8 @@ object Checking { val prevErrors = errors var tp1 = if (isLeaked(tp.symbol)) { - errors = (em"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}", - sym.pos) :: errors + errors = + em"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}" :: errors tp } else mapOver(tp) @@ -408,7 +407,7 @@ object Checking { } val notPrivate = new NotPrivate val info = notPrivate(sym.info) - notPrivate.errors.foreach { case (msg, pos) => ctx.errorOrMigrationWarning(msg, pos) } + notPrivate.errors.foreach(ctx.errorOrMigrationWarning(_, pos)) info } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 52f0a7ec7595..498fd001bdf8 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -523,18 +523,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def handlePattern: Tree = { val tpt1 = typedTpt // special case for an abstract type that comes with a class tag - tpt1.tpe.dealias match { - case tref: TypeRef if !tref.symbol.isClass && !ctx.isAfterTyper => - inferImplicit(defn.ClassTagType.appliedTo(tref), - EmptyTree, tpt1.pos)(ctx.retractMode(Mode.Pattern)) match { - case SearchSuccess(arg, _, _, _) => - return typed(untpd.Apply(untpd.TypedSplice(arg), tree.expr), pt) - case _ => - } - case _ => - if (!ctx.isAfterTyper) tpt1.tpe.<:<(pt)(ctx.addMode(Mode.GADTflexible)) - } - ascription(tpt1, isWildcard = true) + if (!ctx.isAfterTyper) tpt1.tpe.<:<(pt)(ctx.addMode(Mode.GADTflexible)) + tryWithClassTag(ascription(tpt1, isWildcard = true), pt) } cases( ifPat = handlePattern, @@ -543,6 +533,23 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } } + /** For a typed tree `e: T`, if `T` is an abstract type for which an implicit class tag `ctag` + * exists, rewrite to `ctag(e)`. + * @pre We are in pattern-matching mode (Mode.Pattern) + */ + def tryWithClassTag(tree: Typed, pt: Type)(implicit ctx: Context) = tree.tpt.tpe.dealias match { + case tref: TypeRef if !tref.symbol.isClass && !ctx.isAfterTyper => + require(ctx.mode.is(Mode.Pattern)) + inferImplicit(defn.ClassTagType.appliedTo(tref), + EmptyTree, tree.tpt.pos)(ctx.retractMode(Mode.Pattern)) match { + case SearchSuccess(clsTag, _, _, _) => + typed(untpd.Apply(untpd.TypedSplice(clsTag), untpd.TypedSplice(tree.expr)), pt) + case _ => + tree + } + case _ => tree + } + def typedNamedArg(tree: untpd.NamedArg, pt: Type)(implicit ctx: Context) = track("typedNamedArg") { val arg1 = typed(tree.arg, pt) assignType(cpy.NamedArg(tree)(tree.name, arg1), arg1) @@ -669,9 +676,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedFunction(tree: untpd.Function, pt: Type)(implicit ctx: Context) = track("typedFunction") { val untpd.Function(args, body) = tree if (ctx.mode is Mode.Type) { - val funCls = - if (tree.isInstanceOf[untpd.ImplicitFunction]) defn.ImplicitFunctionClass(args.length) - else defn.FunctionClass(args.length) + val funCls = defn.FunctionClass(args.length, tree.isInstanceOf[untpd.ImplicitFunction]) typed(cpy.AppliedTypeTree(tree)( untpd.TypeTree(funCls.typeRef), args :+ body), pt) } @@ -1123,15 +1128,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Tree = track("typedBind") { val pt1 = fullyDefinedType(pt, "pattern variable", tree.pos) val body1 = typed(tree.body, pt1) - typr.println(i"typed bind $tree pt = $pt1 bodytpe = ${body1.tpe}") body1 match { - case UnApply(fn, Nil, arg :: Nil) if tree.body.isInstanceOf[untpd.Typed] => - // A typed pattern `x @ (_: T)` with an implicit `ctag: ClassTag[T]` - // was rewritten to `x @ ctag(_)`. - // Rewrite further to `ctag(x @ _)` - assert(fn.symbol.owner == defn.ClassTagClass) + case UnApply(fn, Nil, arg :: Nil) if fn.symbol.owner == defn.ClassTagClass && !body1.tpe.isError => + // A typed pattern `x @ (e: T)` with an implicit `ctag: ClassTag[T]` + // was rewritten to `x @ ctag(e)` by `tryWithClassTag`. + // Rewrite further to `ctag(x @ e)` tpd.cpy.UnApply(body1)(fn, Nil, - typed(untpd.Bind(tree.name, arg).withPos(tree.pos), arg.tpe) :: Nil) + typed(untpd.Bind(tree.name, untpd.TypedSplice(arg)).withPos(tree.pos), arg.tpe) :: Nil) case _ => val sym = newPatternBoundSym(tree.name, body1.tpe, tree.pos) assignType(cpy.Bind(tree)(tree.name, body1), sym) @@ -1942,7 +1945,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit !untpd.isImplicitClosure(tree) && !isApplyProto(pt) && !ctx.isAfterTyper) { - typr.println("insert apply on implicit $tree") + typr.println(i"insert apply on implicit $tree") typed(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt) } else if (ctx.mode is Mode.Pattern) { diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala index 6ef6bb7413d0..7af9033640b0 100644 --- a/compiler/test/dotc/tests.scala +++ b/compiler/test/dotc/tests.scala @@ -160,7 +160,6 @@ class tests extends CompilerTest { @Test def rewrites = compileFile(posScala2Dir, "rewrites", "-rewrite" :: scala2mode) - @Test def pos_859 = compileFile(posSpecialDir, "i859", scala2mode)(allowDeepSubtypes) @Test def pos_t8146a = compileFile(posSpecialDir, "t8146a")(allowDeepSubtypes) @Test def pos_t5545 = { @@ -180,8 +179,6 @@ class tests extends CompilerTest { val negCustomArgs = negDir + "customArgs/" - @Test def neg_cli_error = compileFile(negCustomArgs, "cliError", List("-thisOptionDoesNotExist")) - @Test def neg_typers() = compileFile(negCustomArgs, "typers")(allowDoubleBindings) @Test def neg_overrideClass = compileFile(negCustomArgs, "overrideClass", scala2mode) @Test def neg_autoTupling = compileFile(negCustomArgs, "autoTuplingTest", args = "-language:noAutoTupling" :: Nil) diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 697a00510e06..37d1404bb278 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -136,4 +136,27 @@ class ErrorMessagesTests extends ErrorMessagesTest { """.stripMargin } .expectNoErrors + + @Test def leftAndRightAssociative = + checkMessagesAfter("frontend") { + """ + |object Ops { + | case class I(j: Int) { + | def +-(i: Int) = i + | def +:(i: Int) = i + | } + | val v = I(1) +- I(4) +: I(4) + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + val defn = ictx.definitions + + assertMessageCount(1, messages) + val MixedLeftAndRightAssociativeOps(op1, op2, op2LeftAssoc) :: Nil = messages + assertEquals("+-", op1.show) + assertEquals("+:", op2.show) + assertFalse(op2LeftAssoc) + } } diff --git a/compiler/test/dotty/tools/dotc/reporting/TestMessageLaziness.scala b/compiler/test/dotty/tools/dotc/reporting/TestMessageLaziness.scala index bf727d51a701..858660075bb2 100644 --- a/compiler/test/dotty/tools/dotc/reporting/TestMessageLaziness.scala +++ b/compiler/test/dotty/tools/dotc/reporting/TestMessageLaziness.scala @@ -4,10 +4,8 @@ package reporting import org.junit.Assert._ import org.junit.Test - import core.Contexts._ - -import diagnostic.{ Message, MessageContainer, ExtendMessage } +import diagnostic.{ErrorMessageID, ExtendMessage, Message, MessageContainer} class TestMessageLaziness extends DottyTest { ctx = ctx.fresh.setReporter(new NonchalantReporter) @@ -19,7 +17,7 @@ class TestMessageLaziness extends DottyTest { override def report(m: MessageContainer)(implicit ctx: Context) = () } - case class LazyError() extends Message(1000) { + case class LazyError() extends Message(ErrorMessageID.LazyErrorId) { throw new Error("Didn't stay lazy.") val kind = "Test" diff --git a/project/Build.scala b/project/Build.scala index 730632b747d6..f03111f7617e 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -105,7 +105,12 @@ object DottyBuild extends Build { (dottyOrganization % "dotty-sbt-bridge" % scalaVersion.value % "component").sources(), // sbt gets very unhappy if two projects use the same target - target := baseDirectory.value / ".." / "out" / name.value + target := baseDirectory.value / ".." / "out" / name.value, + + // The non-bootstrapped dotty-library is not necessary when bootstrapping dotty + autoScalaLibrary := false, + // ...but scala-library is + libraryDependencies += "org.scala-lang" % "scala-library" % scalacVersion ) /** Projects -------------------------------------------------------------- */ @@ -126,6 +131,8 @@ object DottyBuild extends Build { dependsOn(`dotty-compiler`). dependsOn(`dotty-library`). settings( + triggeredMessage in ThisBuild := Watched.clearWhenTriggered, + addCommandAlias("run", "dotty-compiler/run") ++ addCommandAlias( "partest", diff --git a/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala b/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala index db037effeb70..40972902312c 100644 --- a/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala +++ b/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala @@ -22,6 +22,7 @@ import ScalaCompilerForUnitTesting.ExtractedSourceDependencies * source code using Scala compiler. */ class ScalaCompilerForUnitTesting(nameHashing: Boolean = false) { + import scala.language.reflectiveCalls /** * Compiles given source code using Scala compiler and returns API representation diff --git a/tests/neg/selfreq.scala b/tests/disabled/scalac-dependent/neg/selfreq.scala similarity index 100% rename from tests/neg/selfreq.scala rename to tests/disabled/scalac-dependent/neg/selfreq.scala diff --git a/tests/pos-special/i859.scala b/tests/disabled/scalac-dependent/pos-special/i859.scala similarity index 100% rename from tests/pos-special/i859.scala rename to tests/disabled/scalac-dependent/pos-special/i859.scala diff --git a/tests/pos/t5604/ReplConfig.scala b/tests/disabled/scalac-dependent/pos/t5604/ReplConfig.scala similarity index 100% rename from tests/pos/t5604/ReplConfig.scala rename to tests/disabled/scalac-dependent/pos/t5604/ReplConfig.scala diff --git a/tests/pos/t5604/ReplReporter.scala b/tests/disabled/scalac-dependent/pos/t5604/ReplReporter.scala similarity index 100% rename from tests/pos/t5604/ReplReporter.scala rename to tests/disabled/scalac-dependent/pos/t5604/ReplReporter.scala diff --git a/tests/pos/t5899.scala b/tests/disabled/scalac-dependent/pos/t5899.scala similarity index 100% rename from tests/pos/t5899.scala rename to tests/disabled/scalac-dependent/pos/t5899.scala diff --git a/tests/pos/t7591.scala b/tests/disabled/scalac-dependent/pos/t7591.scala similarity index 100% rename from tests/pos/t7591.scala rename to tests/disabled/scalac-dependent/pos/t7591.scala diff --git a/tests/pos/trait-force-info.scala b/tests/disabled/scalac-dependent/pos/trait-force-info.scala similarity index 100% rename from tests/pos/trait-force-info.scala rename to tests/disabled/scalac-dependent/pos/trait-force-info.scala diff --git a/tests/run/t1618.scala b/tests/disabled/scalac-dependent/run/t1618.scala similarity index 100% rename from tests/run/t1618.scala rename to tests/disabled/scalac-dependent/run/t1618.scala diff --git a/tests/run/t7775.scala b/tests/disabled/scalac-dependent/run/t7775.scala similarity index 100% rename from tests/run/t7775.scala rename to tests/disabled/scalac-dependent/run/t7775.scala diff --git a/tests/neg/customArgs/cliError.scala b/tests/neg/customArgs/cliError.scala deleted file mode 100644 index b2f0f6cdc4af..000000000000 --- a/tests/neg/customArgs/cliError.scala +++ /dev/null @@ -1,2 +0,0 @@ -// nopos-error -object Test diff --git a/tests/run/i1991.scala b/tests/run/i1991.scala new file mode 100644 index 000000000000..cec1dec89f75 --- /dev/null +++ b/tests/run/i1991.scala @@ -0,0 +1,29 @@ +import scala.reflect.ClassTag + +class A[Foo](implicit tag: ClassTag[Foo]) { + object ExtractFoo { + def unapply(foo: Foo): Boolean = true + } + + def isFoo(x: Any) = x match { + case ExtractFoo() => true + //case foo: Foo => true + case _ => false + } + + def testBind(x: Any) = x match { + case foo0: Foo => + (foo0: Foo) + case foo1 @ (_: Foo) => + (foo1: Foo) + case foo2 @ ExtractFoo() => + (foo2: Foo) + } +} + +object Test { + def main(args: Array[String]): Unit = { + assert((new A[String]).isFoo("foo")) // OK + assert(!(new A[String]).isFoo(42)) // OK in scalac, fails in Dotty + } +}