diff options
15 files changed, 117 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala index df8dcc690a..7aadd2c466 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala @@ -114,7 +114,7 @@ object BytecodeUtils { } def sameTargetExecutableInstruction(a: JumpInsnNode, b: JumpInsnNode): Boolean = { - // Compare next executable instead of the the labels. Identifies a, b as the same target: + // Compare next executable instead of the labels. Identifies a, b as the same target: // LabelNode(a) // LabelNode(b) // Instr diff --git a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala index fb1799e092..a7ce7dfa04 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala @@ -248,7 +248,7 @@ abstract class ConstantOptimization extends SubComponent { new State(newVariables, stack.tail) } /** - * Load the specified local onto the top of the stack. An error the the local is uninitialized. + * Load the specified local onto the top of the stack. An error if the local is uninitialized. */ def load(variable: Local): State = { val contents: Contents = locals.getOrElse(variable, sys.error(s"$variable is not initialized")) diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 6a46c65267..b2aac587eb 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -328,7 +328,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { val delayedHook: DefDef = delayedEndpointDef(remainingConstrStats) defBuf += delayedHook val hookCallerClass = { - // transform to make the closure-class' default constructor assign the the outer instance to its param-accessor field. + // transform to make the closure-class' default constructor assign the outer instance to its param-accessor field. val drillDown = new ConstructorTransformer(unit) drillDown transform delayedInitClosure(delayedHook.symbol.asInstanceOf[MethodSymbol]) } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index ee7c839de9..870c35338c 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -638,7 +638,7 @@ abstract class UnCurry extends InfoTransform * This transformation erases the dependent method types by: * - Widening the formal parameter type to existentially abstract * over the prior parameters (using `packSymbols`). This transformation - * is performed in the the `InfoTransform`er [[scala.reflect.internal.transform.UnCurry]]. + * is performed in the `InfoTransform`er [[scala.reflect.internal.transform.UnCurry]]. * - Inserting casts in the method body to cast to the original, * precise type. * diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index 62d9c497ba..91777b34d5 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -542,7 +542,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { * * (0) A or B must be in the domain to draw any conclusions. * - * For example, knowing the the scrutinee is *not* true does not + * For example, knowing the scrutinee is *not* true does not * statically exclude it from being `X`, because that is an opaque * Boolean. * diff --git a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala index 0574869714..9898cfd785 100644 --- a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala +++ b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala @@ -65,7 +65,7 @@ trait AnalyzerPlugins { self: Analyzer => * The hooks into `typeSig` allow analyzer plugins to add annotations to (or change the types * of) definition symbols. This cannot not be achieved by using `pluginsTyped`: this method * is only called during type checking, so changing the type of a symbol at this point is too - * late: references to the symbol might already be typed and therefore obtain the the original + * late: references to the symbol might already be typed and therefore obtain the original * type assigned during naming. * * @param defTree is the definition for which the type was computed. The different cases are diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index e73a4c6276..5ec16e84bb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -806,6 +806,12 @@ trait Contexts { self: Analyzer => (e ne null) && (e.owner == scope) && (!settings.isScala212 || e.sym.exists) }) + private def withQualifyingImplicitAlternatives(imp: ImportInfo, name: Name, pre: Type)(f: Symbol => Unit) = + for { + sym <- importedAccessibleSymbol(imp, name, requireExplicit = false, record = false).alternatives + if isQualifyingImplicit(name, sym, pre, imported = true) + } f(sym) + private def collectImplicits(syms: Scope, pre: Type, imported: Boolean = false): List[ImplicitInfo] = for (sym <- syms.toList if isQualifyingImplicit(sym.name, sym, pre, imported)) yield new ImplicitInfo(sym.name, pre, sym) @@ -815,7 +821,7 @@ trait Contexts { self: Analyzer => val pre = if (qual.tpe.typeSymbol.isPackageClass) - // SI-6225 important if the imported symbol is inherited by the the package object. + // SI-6225 important if the imported symbol is inherited by the package object. singleType(qual.tpe, qual.tpe member nme.PACKAGE) else qual.tpe @@ -832,9 +838,9 @@ trait Contexts { self: Analyzer => case ImportSelector(from, _, to, _) :: sels1 => var impls = collect(sels1) filter (info => info.name != from) if (to != nme.WILDCARD) { - for (sym <- importedAccessibleSymbol(imp, to).alternatives) - if (isQualifyingImplicit(to, sym, pre, imported = true)) - impls = new ImplicitInfo(to, pre, sym) :: impls + withQualifyingImplicitAlternatives(imp, to, pre) { sym => + impls = new ImplicitInfo(to, pre, sym) :: impls + } } impls } @@ -958,11 +964,8 @@ trait Contexts { self: Analyzer => /** The symbol with name `name` imported via the import in `imp`, * if any such symbol is accessible from this context. */ - def importedAccessibleSymbol(imp: ImportInfo, name: Name): Symbol = - importedAccessibleSymbol(imp, name, requireExplicit = false) - - private def importedAccessibleSymbol(imp: ImportInfo, name: Name, requireExplicit: Boolean): Symbol = - imp.importedSymbol(name, requireExplicit) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false)) + private def importedAccessibleSymbol(imp: ImportInfo, name: Name, requireExplicit: Boolean, record: Boolean): Symbol = + imp.importedSymbol(name, requireExplicit, record) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false)) /** Is `sym` defined in package object of package `pkg`? * Since sym may be defined in some parent of the package object, @@ -1108,7 +1111,7 @@ trait Contexts { self: Analyzer => def imp2Explicit = imp2 isExplicitImport name def lookupImport(imp: ImportInfo, requireExplicit: Boolean) = - importedAccessibleSymbol(imp, name, requireExplicit) filter qualifies + importedAccessibleSymbol(imp, name, requireExplicit, record = true) filter qualifies // Java: A single-type-import declaration d in a compilation unit c of package p // that imports a type named n shadows, throughout c, the declarations of: @@ -1422,7 +1425,7 @@ trait Contexts { self: Analyzer => /** The symbol with name `name` imported from import clause `tree`. */ - def importedSymbol(name: Name): Symbol = importedSymbol(name, requireExplicit = false) + def importedSymbol(name: Name): Symbol = importedSymbol(name, requireExplicit = false, record = true) private def recordUsage(sel: ImportSelector, result: Symbol) { def posstr = pos.source.file.name + ":" + posOf(sel).line @@ -1432,7 +1435,7 @@ trait Contexts { self: Analyzer => } /** If requireExplicit is true, wildcard imports are not considered. */ - def importedSymbol(name: Name, requireExplicit: Boolean): Symbol = { + def importedSymbol(name: Name, requireExplicit: Boolean, record: Boolean): Symbol = { var result: Symbol = NoSymbol var renamed = false var selectors = tree.selectors @@ -1449,7 +1452,7 @@ trait Contexts { self: Analyzer => if (result == NoSymbol) selectors = selectors.tail } - if (settings.warnUnusedImport && selectors.nonEmpty && result != NoSymbol && pos != NoPosition) + if (record && settings.warnUnusedImport && selectors.nonEmpty && result != NoSymbol && pos != NoPosition) recordUsage(current, result) // Harden against the fallout from bugs like SI-6745 diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index 294ca2aa48..ebc1e76ca1 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -43,6 +43,8 @@ import scala.reflect.ClassTag * * @author Philipp Haller, Heather Miller, Aleksandar Prokopec, Viktor Klang * + * @see [[http://docs.scala-lang.org/overviews/core/futures.html Futures and Promises]] + * * @define multipleCallbacks * Multiple callbacks may be registered; there is no guarantee that they will be * executed in a particular order. diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 4bdb8e6da8..11e740117d 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -56,7 +56,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => new FreeTypeSymbol(name, origin) initFlags flags /** - * This map stores the original owner the the first time the owner of a symbol is re-assigned. + * This map stores the original owner the first time the owner of a symbol is re-assigned. * The original owner of a symbol is needed in some places in the backend. Ideally, owners should * be versioned like the type history. */ @@ -500,7 +500,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => case _ => new StubTermSymbol(this, name.toTermName, missingMessage) } - /** Given a field, construct a term symbol that represents the source construct that gave rise the the field */ + /** Given a field, construct a term symbol that represents the source construct that gave rise the field */ def sugaredSymbolOrSelf = { val getter = getterIn(owner) if (getter == NoSymbol) { diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js index 4dd48675b7..d5e008d289 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js +++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js @@ -752,7 +752,7 @@ $.layout.defaults = { * PANE-SPECIFIC SETTINGS * - options listed below MUST be specified per-pane - they CANNOT be set under 'panes' * - all options under the 'panes' key can also be set specifically for any pane - * - most options under the 'panes' key apply only to 'border-panes' - NOT the the center-pane + * - most options under the 'panes' key apply only to 'border-panes' - NOT the center-pane */ , north: { paneSelector: ".ui-layout-north" @@ -921,7 +921,7 @@ $.layout.backwardCompatibility = { $.extend(true, opts.panes, opts.defaults); delete opts.defaults; } - // rename options in the the options.panes key + // rename options in the options.panes key if (opts.panes) ren( opts.panes ); // rename options inside *each pane key*, eg: options.west $.each($.layout.config.allPanes, function (i, pane) { @@ -5483,4 +5483,4 @@ $.layout.onReady.push( $.layout.browserZoom._init ); -})( jQuery );
\ No newline at end of file +})( jQuery ); diff --git a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala index 093899231e..86900f26c9 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala @@ -248,7 +248,7 @@ trait DiagramFactory extends DiagramDirectiveParser { case _ => Nil }) - // Only show the the non-isolated nodes + // Only show the non-isolated nodes // TODO: Decide if we really want to hide package members, I'm not sure that's a good idea (!!!) // TODO: Does .distinct cause any stability issues? val sourceNodes = edges.map(_._1) diff --git a/test/files/neg/warn-unused-imports.check b/test/files/neg/warn-unused-imports.check index 36c6dd03c3..0a53d7a9cd 100644 --- a/test/files/neg/warn-unused-imports.check +++ b/test/files/neg/warn-unused-imports.check @@ -1,33 +1,55 @@ -warn-unused-imports.scala:57: warning: Unused import +warn-unused-imports_2.scala:133: error: type mismatch; + found : Int(42) + required: Sample.X + f(42) // error + ^ +warn-unused-imports_2.scala:57: warning: Unused import import p1.A // warn ^ -warn-unused-imports.scala:62: warning: Unused import +warn-unused-imports_2.scala:62: warning: Unused import import p1.{ A, B } // warn on A ^ -warn-unused-imports.scala:67: warning: Unused import +warn-unused-imports_2.scala:67: warning: Unused import import p1.{ A, B } // warn on both ^ -warn-unused-imports.scala:67: warning: Unused import +warn-unused-imports_2.scala:67: warning: Unused import import p1.{ A, B } // warn on both ^ -warn-unused-imports.scala:73: warning: Unused import +warn-unused-imports_2.scala:73: warning: Unused import import c._ // warn ^ -warn-unused-imports.scala:78: warning: Unused import +warn-unused-imports_2.scala:78: warning: Unused import import p1._ // warn ^ -warn-unused-imports.scala:85: warning: Unused import +warn-unused-imports_2.scala:85: warning: Unused import import c._ // warn ^ -warn-unused-imports.scala:91: warning: Unused import +warn-unused-imports_2.scala:91: warning: Unused import import p1.c._ // warn ^ -warn-unused-imports.scala:98: warning: Unused import +warn-unused-imports_2.scala:98: warning: Unused import import p1._ // warn ^ -warn-unused-imports.scala:118: warning: Unused import +warn-unused-imports_2.scala:118: warning: Unused import import p1.A // warn ^ -error: No warnings can be incurred under -Xfatal-warnings. -10 warnings found +warn-unused-imports_2.scala:132: warning: Unused import + import Sample.Implicits._ // warn + ^ +warn-unused-imports_2.scala:143: warning: Unused import + import Sample.Implicits.useless // warn + ^ +warn-unused-imports_2.scala:147: warning: Unused import + import java.io.File // warn + ^ +warn-unused-imports_2.scala:148: warning: Unused import + import scala.concurrent.Future // warn + ^ +warn-unused-imports_2.scala:149: warning: Unused import + import scala.concurrent.ExecutionContext.Implicits.global // warn + ^ +warn-unused-imports_2.scala:150: warning: Unused import + import p1.A // warn + ^ +16 warnings found one error found diff --git a/test/files/neg/warn-unused-imports/sample_1.scala b/test/files/neg/warn-unused-imports/sample_1.scala new file mode 100644 index 0000000000..d2f86239db --- /dev/null +++ b/test/files/neg/warn-unused-imports/sample_1.scala @@ -0,0 +1,17 @@ + +import language._ + +object Sample { + trait X + trait Y + + // import of the non-implicit should be unused + object Implicits { + def `int to X`(i: Int): X = null + implicit def `int to Y`(i: Int): Y = null + implicit def useless(i: Int): String = null + } + + def f(x: X) = ??? + def g(y: Y) = ??? +} diff --git a/test/files/neg/warn-unused-imports.scala b/test/files/neg/warn-unused-imports/warn-unused-imports_2.scala index b7a2f1c414..ded1186209 100644 --- a/test/files/neg/warn-unused-imports.scala +++ b/test/files/neg/warn-unused-imports/warn-unused-imports_2.scala @@ -123,3 +123,33 @@ trait Nested { println(new Warn { }) } } + +// test unusage of imports from other compilation units after implicit search +trait Outsiders { + { + //implicit search should not disable warning + import Sample._ + import Sample.Implicits._ // warn + f(42) // error + } + { + import Sample._ + import Sample.Implicits._ // nowarn + g(42) // ok + } + { + import Sample._ + import Sample.Implicits.`int to Y` // nowarn + import Sample.Implicits.useless // warn + g(42) // ok + } + { + import java.io.File // warn + import scala.concurrent.Future // warn + import scala.concurrent.ExecutionContext.Implicits.global // warn + import p1.A // warn + import p1.B // no warn + println("abc".bippy) + //Future("abc".bippy) + } +} diff --git a/test/files/presentation/doc/doc.scala b/test/files/presentation/doc/doc.scala index f2233f1828..ce431910ee 100644 --- a/test/files/presentation/doc/doc.scala +++ b/test/files/presentation/doc/doc.scala @@ -118,6 +118,12 @@ object Test extends InteractiveTest { } } + // The remainder of this test has been found to fail intermittently on Windows + // only. The problem is difficult to isolate and reproduce; see + // https://github.com/scala/scala-dev/issues/72 for details. + // So if we're on Windows, let's just bail out here. + if (scala.util.Properties.isWin) return + // Check inter-classes documentation one-time retrieved ok. val baseSource = findSource("Base.scala") val derivedSource = findSource("Derived.scala") |