Skip to content

Fix implicit conversion warnings #5886

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 11, 2019
16 changes: 9 additions & 7 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,6 @@ object desugar {
val isObject = mods.is(Module)
val isCaseClass = mods.is(Case) && !isObject
val isCaseObject = mods.is(Case) && isObject
val isImplicit = mods.is(Implicit)
val isInstance = isImplicit && mods.mods.exists(_.isInstanceOf[Mod.Instance])
val isEnum = mods.isEnumClass && !mods.is(Module)
def isEnumCase = mods.isEnumCase
val isValueClass = parents.nonEmpty && isAnyVal(parents.head)
Expand Down Expand Up @@ -394,7 +392,7 @@ object desugar {
if (isEnum) {
val (enumCases, enumStats) = stats.partition(DesugarEnums.isEnumCase)
val enumCompanionRef = new TermRefTree()
val enumImport = Import(enumCompanionRef, enumCases.flatMap(caseIds))
val enumImport = Import(impliedOnly = false, enumCompanionRef, enumCases.flatMap(caseIds))
(enumImport :: enumStats, enumCases, enumCompanionRef)
}
else (stats, Nil, EmptyTree)
Expand Down Expand Up @@ -666,17 +664,21 @@ object desugar {
// synthetic implicit C[Ts](p11: T11, ..., p1N: T1N) ... (pM1: TM1, ..., pMN: TMN): C[Ts] =
// new C[Ts](p11, ..., p1N) ... (pM1, ..., pMN) =
val implicitWrappers =
if (!isImplicit)
if (!mods.is(ImplicitOrImplied))
Nil
else if (ctx.owner is Package) {
ctx.error(TopLevelImplicitClass(cdef), cdef.sourcePos)
Nil
}
else if (mods.is(Trait)) {
ctx.error(TypesAndTraitsCantBeImplicit(), cdef.sourcePos)
Nil
}
else if (isCaseClass) {
ctx.error(ImplicitCaseClass(cdef), cdef.sourcePos)
Nil
}
else if (arity != 1 && !isInstance) {
else if (arity != 1 && !mods.is(Implied)) {
ctx.error(ImplicitClassPrimaryConstructorArity(), cdef.sourcePos)
Nil
}
Expand All @@ -690,7 +692,7 @@ object desugar {
// implicit wrapper is typechecked in same scope as constructor, so
// we can reuse the constructor parameters; no derived params are needed.
DefDef(className.toTermName, constrTparams, defParamss, classTypeRef, creatorExpr)
.withMods(companionMods | Synthetic | Implicit | Final)
.withMods(companionMods | mods.flags.toTermFlags & ImplicitOrImplied | Synthetic | Final)
.withSpan(cdef.span) :: Nil
}

Expand Down Expand Up @@ -1043,7 +1045,7 @@ object desugar {
def needsObject(stat: Tree) = stat match {
case _: ValDef | _: PatDef | _: DefDef => true
case stat: ModuleDef =>
stat.mods.is(Implicit) || opaqueNames.contains(stat.name.stripModuleClassSuffix.toTypeName)
stat.mods.is(ImplicitOrImplied) || opaqueNames.contains(stat.name.stripModuleClassSuffix.toTypeName)
case stat: TypeDef => !stat.isClassDef || stat.mods.is(Implicit)
case _ => false
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
def statPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
case EmptyTree
| TypeDef(_, _)
| Import(_, _)
| Import(_, _, _)
| DefDef(_, _, _, _, _) =>
Pure
case vdef @ ValDef(_, _, _) =>
Expand Down
14 changes: 7 additions & 7 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ object Trees {
* where a selector is either an untyped `Ident`, `name` or
* an untyped thicket consisting of `name` and `rename`.
*/
case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @constructorOnly src: SourceFile)
case class Import[-T >: Untyped] private[ast] (impliedOnly: Boolean, expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @constructorOnly src: SourceFile)
extends DenotingTree[T] {
type ThisTree[-T >: Untyped] = Import[T]
}
Expand Down Expand Up @@ -1156,9 +1156,9 @@ object Trees {
case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (derived eq tree.derived) && (self eq tree.self) && (body eq tree.unforcedBody) => tree
case tree => finalize(tree, untpd.Template(constr, parents, derived, self, body)(tree.source))
}
def Import(tree: Tree)(expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match {
case tree: Import if (expr eq tree.expr) && (selectors eq tree.selectors) => tree
case _ => finalize(tree, untpd.Import(expr, selectors)(tree.source))
def Import(tree: Tree)(impliedOnly: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match {
case tree: Import if (impliedOnly == tree.impliedOnly) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree
case _ => finalize(tree, untpd.Import(impliedOnly, expr, selectors)(tree.source))
}
def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match {
case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree
Expand Down Expand Up @@ -1303,8 +1303,8 @@ object Trees {
cpy.TypeDef(tree)(name, transform(rhs))
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
cpy.Template(tree)(transformSub(constr), transform(tree.parents), Nil, transformSub(self), transformStats(tree.body))
case Import(expr, selectors) =>
cpy.Import(tree)(transform(expr), selectors)
case Import(impliedOnly, expr, selectors) =>
cpy.Import(tree)(impliedOnly, transform(expr), selectors)
case PackageDef(pid, stats) =>
cpy.PackageDef(tree)(transformSub(pid), transformStats(stats)(localCtx))
case Annotated(arg, annot) =>
Expand Down Expand Up @@ -1427,7 +1427,7 @@ object Trees {
this(x, rhs)
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
this(this(this(this(x, constr), parents), self), tree.body)
case Import(expr, selectors) =>
case Import(impliedOnly, expr, selectors) =>
this(x, expr)
case PackageDef(pid, stats) =>
this(this(x, pid), stats)(localCtx)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Block(cdef :: Nil, New(cls.typeRef, Nil))
}

def Import(expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import =
ta.assignType(untpd.Import(expr, selectors), ctx.newImportSymbol(ctx.owner, expr))
def Import(impliedOnly: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import =
ta.assignType(untpd.Import(impliedOnly, expr, selectors), ctx.newImportSymbol(ctx.owner, expr))

def PackageDef(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef =
ta.assignType(untpd.PackageDef(pid, stats), pid)
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {

case class Var()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Mutable)

case class Implicit()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.ImplicitCommon)
case class Implicit()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implicit)

case class Given()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.ImplicitCommon | Flags.Given)
case class Given()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implicit | Flags.Given)

case class Erased()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Erased)

Expand All @@ -152,7 +152,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {

case class Enum()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Enum)

case class Instance()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implicit)
case class Instance()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implied)
}

/** Modifiers and annotations for definitions
Expand Down Expand Up @@ -326,7 +326,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def Template(constr: DefDef, parents: List[Tree], derived: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceFile): Template =
if (derived.isEmpty) new Template(constr, parents, self, body)
else new DerivingTemplate(constr, parents ++ derived, self, body, derived.length)
def Import(expr: Tree, selectors: List[Tree])(implicit src: SourceFile): Import = new Import(expr, selectors)
def Import(impliedOnly: Boolean, expr: Tree, selectors: List[Tree])(implicit src: SourceFile): Import = new Import(impliedOnly, expr, selectors)
def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceFile): PackageDef = new PackageDef(pid, stats)
def Annotated(arg: Tree, annot: Tree)(implicit src: SourceFile): Annotated = new Annotated(arg, annot)

Expand Down
6 changes: 4 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Scopes._
import Uniques._
import ast.Trees._
import ast.untpd
import Flags.ImplicitOrImplied
import util.{FreshNameCreator, NoSource, SimpleIdentityMap, SourceFile}
import typer.{Implicits, ImportInfo, Inliner, NamerContextOps, SearchHistory, SearchRoot, TypeAssigner, Typer}
import Implicits.ContextualImplicits
Expand Down Expand Up @@ -214,7 +215,7 @@ object Contexts {
implicitsCache = {
val implicitRefs: List[ImplicitRef] =
if (isClassDefContext)
try owner.thisType.implicitMembers
try owner.thisType.implicitMembers(ImplicitOrImplied)
catch {
case ex: CyclicReference => Nil
}
Expand Down Expand Up @@ -404,7 +405,8 @@ object Contexts {
case ref: RefTree[_] => Some(ref.name.asTermName)
case _ => None
}
ctx.fresh.setImportInfo(new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt))
ctx.fresh.setImportInfo(
new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt, imp.impliedOnly))
}

/** Does current phase use an erased types interpretation? */
Expand Down
20 changes: 12 additions & 8 deletions compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ object Flags {
*/
case class FlagConjunction(bits: Long) {
override def toString: String = FlagSet(bits).toString
def | (fs: FlagSet): FlagConjunction = FlagConjunction((FlagSet(bits) | fs).bits)
}

def termFlagConjunction(x: Long) = FlagConjunction(TERMS | x)
Expand Down Expand Up @@ -242,8 +243,8 @@ object Flags {
final val TypeParam: FlagSet = Param.toTypeFlags

/** Labeled with `implicit` modifier (implicit value) */
final val ImplicitCommon: FlagSet = commonFlag(9, "implicit")
final val Implicit: FlagSet = ImplicitCommon.toTermFlags
final val Implicit: FlagSet = commonFlag(9, "implicit")
final val ImplicitTerm: FlagSet = Implicit.toTermFlags

/** Labeled with `lazy` (a lazy val). */
final val Lazy: FlagSet = termFlag(10, "lazy")
Expand Down Expand Up @@ -384,6 +385,8 @@ object Flags {
/** Symbol is a Java default method */
final val DefaultMethod: FlagSet = termFlag(38, "<defaultmethod>")

final val Implied: FlagSet = commonFlag(39, "implied")

/** Symbol is an enum class or enum case (if used with case) */
final val Enum: FlagSet = commonFlag(40, "<enum>")

Expand Down Expand Up @@ -460,7 +463,7 @@ object Flags {

/** Flags representing source modifiers */
private val CommonSourceModifierFlags: FlagSet =
commonFlags(Private, Protected, Final, Case, Implicit, Override, JavaStatic)
commonFlags(Private, Protected, Final, Case, Implicit, Implied, Override, JavaStatic)

final val TypeSourceModifierFlags: FlagSet =
CommonSourceModifierFlags.toTypeFlags | Abstract | Sealed | Opaque
Expand All @@ -485,7 +488,7 @@ object Flags {
HigherKinded.toCommonFlags | Param | ParamAccessor.toCommonFlags |
Scala2ExistentialCommon | MutableOrOpaque | Touched | JavaStatic |
CovariantOrOuter | ContravariantOrLabel | CaseAccessor.toCommonFlags |
Extension.toCommonFlags | NonMember | ImplicitCommon | Permanent | Synthetic |
Extension.toCommonFlags | NonMember | Implicit | Implied | Permanent | Synthetic |
SuperAccessorOrScala2x | Inline

/** Flags that are not (re)set when completing the denotation, or, if symbol is
Expand Down Expand Up @@ -541,7 +544,7 @@ object Flags {

/** Flags that can apply to a module val */
final val RetainedModuleValFlags: FlagSet = RetainedModuleValAndClassFlags |
Override | Final | Method | Implicit | Lazy |
Override | Final | Method | Implicit | Implied | Lazy |
Accessor | AbsOverride | StableRealizable | Captured | Synchronized | Erased

/** Flags that can apply to a module class */
Expand Down Expand Up @@ -586,6 +589,10 @@ object Flags {
/** An inline method or inline argument proxy */
final val InlineOrProxy: FlagSet = Inline | InlineProxy

final val ImplicitOrImplied = Implicit | Implied

final val ImplicitOrImpliedTerm = ImplicitOrImplied.toTermFlags

/** Assumed to be pure */
final val StableOrErased: FlagSet = StableRealizable | Erased

Expand All @@ -601,9 +608,6 @@ object Flags {
/** An inline method */
final val InlineMethod: FlagConjunction = allOf(Inline, Method)

/** An implicit inline method */
final val ImplicitInlineMethod: FlagConjunction = allOf(Inline, Implicit, Method)

/** An inline parameter */
final val InlineParam: FlagConjunction = allOf(Inline, Param)

Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Scopes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ package core

import Symbols._
import Types.{TermRef, NoPrefix}
import Flags.Implicit
import Flags._
import Names._
import Contexts._
import Denotations._
Expand Down Expand Up @@ -409,7 +409,7 @@ object Scopes {
var irefs = new mutable.ListBuffer[TermRef]
var e = lastEntry
while (e ne null) {
if (e.sym is Implicit) {
if (e.sym is ImplicitOrImplied) {
val d = e.sym.denot
irefs += TermRef(NoPrefix, d.symbol.asTerm).withDenot(d)
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1873,7 +1873,8 @@ object SymDenotations {
val ownSyms =
if (keepOnly eq implicitFilter)
if (this is Package) Iterator.empty
else info.decls.iterator filter (_ is Implicit)
// implicits in package objects are added by the overriding `memberNames` in `PackageClassDenotation`
else info.decls.iterator filter (_ is ImplicitOrImplied)
else info.decls.iterator
for (sym <- ownSyms) maybeAdd(sym.name)
names
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/TypeErrors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import config.Printers.cyclicErrors
class TypeError(msg: String) extends Exception(msg) {
def this() = this("")
def toMessage(implicit ctx: Context): Message = super.getMessage
override def getMessage: String = throw new Exception("Use toMessage instead for TypeError")
override def getMessage: String = super.getMessage
}

class MalformedType(pre: Type, denot: Denotation, absMembers: Set[Name]) extends TypeError {
Expand Down Expand Up @@ -137,7 +137,7 @@ class CyclicReference private (val denot: SymDenotation) extends TypeError {
}
}
// Give up and give generic errors.
else if (cycleSym.is(Implicit, butNot = Method) && cycleSym.owner.isTerm)
else if (cycleSym.is(ImplicitOrImplied, butNot = Method) && cycleSym.owner.isTerm)
CyclicReferenceInvolvingImplicit(cycleSym)
else
CyclicReferenceInvolving(denot)
Expand Down
9 changes: 6 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -787,10 +787,13 @@ object Types {
(name, buf) => buf += member(name).asSingleDenotation)
}

/** The set of implicit members of this type */
final def implicitMembers(implicit ctx: Context): List[TermRef] = track("implicitMembers") {
/** The set of implicit term members of this type
* @param kind A subset of {Implicit, Implied} that sepcifies what kind of implicit should
* be returned
*/
final def implicitMembers(kind: FlagSet)(implicit ctx: Context): List[TermRef] = track("implicitMembers") {
memberDenots(implicitFilter,
(name, buf) => buf ++= member(name).altsWith(_ is Implicit))
(name, buf) => buf ++= member(name).altsWith(_.is(ImplicitOrImpliedTerm & kind)))
.toList.map(d => TermRef(this, d.symbol.asTerm))
}

Expand Down
8 changes: 6 additions & 2 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Standard-Section: "ASTs" TopLevelStat*
ValOrDefDef
TYPEDEF Length NameRef (type_Term | Template) Modifier*
OBJECTDEF Length NameRef Template Modifier*
IMPORT Length qual_Term Selector*
IMPORT Length [IMPLIED] qual_Term Selector*
ValOrDefDef = VALDEF Length NameRef type_Term rhs_Term? Modifier*
DEFDEF Length NameRef TypeParam* Params* returnType_Term rhs_Term?
Modifier*
Expand Down Expand Up @@ -180,6 +180,7 @@ Standard-Section: "ASTs" TopLevelStat*
SEALED
CASE
IMPLICIT
IMPLIED
ERASED
LAZY
OVERRIDE
Expand Down Expand Up @@ -324,7 +325,8 @@ object TastyFormat {
final val OPAQUE = 35
final val EXTENSION = 36
final val GIVEN = 37
final val PARAMsetter = 38
final val IMPLIED = 38
final val PARAMsetter = 39

// Cat. 2: tag Nat

Expand Down Expand Up @@ -475,6 +477,7 @@ object TastyFormat {
| SEALED
| CASE
| IMPLICIT
| IMPLIED
| ERASED
| LAZY
| OVERRIDE
Expand Down Expand Up @@ -535,6 +538,7 @@ object TastyFormat {
case SEALED => "SEALED"
case CASE => "CASE"
case IMPLICIT => "IMPLICIT"
case IMPLIED => "IMPLIED"
case ERASED => "ERASED"
case LAZY => "LAZY"
case OVERRIDE => "OVERRIDE"
Expand Down
9 changes: 7 additions & 2 deletions compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,13 @@ class TreePickler(pickler: TastyPickler) {
}
pickleStats(tree.constr :: rest)
}
case Import(expr, selectors) =>
case Import(impliedOnly, expr, selectors) =>
writeByte(IMPORT)
withLength { pickleTree(expr); pickleSelectors(selectors) }
withLength {
if (impliedOnly) writeByte(IMPLIED)
pickleTree(expr)
pickleSelectors(selectors)
}
case PackageDef(pid, stats) =>
writeByte(PACKAGE)
withLength { pickleType(pid.tpe); pickleStats(stats) }
Expand Down Expand Up @@ -646,6 +650,7 @@ class TreePickler(pickler: TastyPickler) {
if (flags is Scala2x) writeByte(SCALA2X)
if (isTerm) {
if (flags is Implicit) writeByte(IMPLICIT)
if (flags is Implied) writeByte(IMPLIED)
if (flags is Erased) writeByte(ERASED)
if (flags.is(Lazy, butNot = Module)) writeByte(LAZY)
if (flags is AbsOverride) { writeByte(ABSTRACT); writeByte(OVERRIDE) }
Expand Down
Loading