Skip to content

Commit a198e48

Browse files
authored
Merge pull request #5868 from dotty-staging/add-import-implied
Import Implied
2 parents e89f1fe + cd1c914 commit a198e48

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+273
-139
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,6 @@ object desugar {
344344
val isObject = mods.is(Module)
345345
val isCaseClass = mods.is(Case) && !isObject
346346
val isCaseObject = mods.is(Case) && isObject
347-
val isImplicit = mods.is(Implicit)
348-
val isInstance = isImplicit && mods.mods.exists(_.isInstanceOf[Mod.Instance])
349347
val isEnum = mods.isEnumClass && !mods.is(Module)
350348
def isEnumCase = mods.isEnumCase
351349
val isValueClass = parents.nonEmpty && isAnyVal(parents.head)
@@ -394,7 +392,7 @@ object desugar {
394392
if (isEnum) {
395393
val (enumCases, enumStats) = stats.partition(DesugarEnums.isEnumCase)
396394
val enumCompanionRef = new TermRefTree()
397-
val enumImport = Import(enumCompanionRef, enumCases.flatMap(caseIds))
395+
val enumImport = Import(impliedOnly = false, enumCompanionRef, enumCases.flatMap(caseIds))
398396
(enumImport :: enumStats, enumCases, enumCompanionRef)
399397
}
400398
else (stats, Nil, EmptyTree)
@@ -666,17 +664,21 @@ object desugar {
666664
// synthetic implicit C[Ts](p11: T11, ..., p1N: T1N) ... (pM1: TM1, ..., pMN: TMN): C[Ts] =
667665
// new C[Ts](p11, ..., p1N) ... (pM1, ..., pMN) =
668666
val implicitWrappers =
669-
if (!isImplicit)
667+
if (!mods.is(ImplicitOrImplied))
670668
Nil
671669
else if (ctx.owner is Package) {
672670
ctx.error(TopLevelImplicitClass(cdef), cdef.sourcePos)
673671
Nil
674672
}
673+
else if (mods.is(Trait)) {
674+
ctx.error(TypesAndTraitsCantBeImplicit(), cdef.sourcePos)
675+
Nil
676+
}
675677
else if (isCaseClass) {
676678
ctx.error(ImplicitCaseClass(cdef), cdef.sourcePos)
677679
Nil
678680
}
679-
else if (arity != 1 && !isInstance) {
681+
else if (arity != 1 && !mods.is(Implied)) {
680682
ctx.error(ImplicitClassPrimaryConstructorArity(), cdef.sourcePos)
681683
Nil
682684
}
@@ -690,7 +692,7 @@ object desugar {
690692
// implicit wrapper is typechecked in same scope as constructor, so
691693
// we can reuse the constructor parameters; no derived params are needed.
692694
DefDef(className.toTermName, constrTparams, defParamss, classTypeRef, creatorExpr)
693-
.withMods(companionMods | Synthetic | Implicit | Final)
695+
.withMods(companionMods | mods.flags.toTermFlags & ImplicitOrImplied | Synthetic | Final)
694696
.withSpan(cdef.span) :: Nil
695697
}
696698

@@ -1043,7 +1045,7 @@ object desugar {
10431045
def needsObject(stat: Tree) = stat match {
10441046
case _: ValDef | _: PatDef | _: DefDef => true
10451047
case stat: ModuleDef =>
1046-
stat.mods.is(Implicit) || opaqueNames.contains(stat.name.stripModuleClassSuffix.toTypeName)
1048+
stat.mods.is(ImplicitOrImplied) || opaqueNames.contains(stat.name.stripModuleClassSuffix.toTypeName)
10471049
case stat: TypeDef => !stat.isClassDef || stat.mods.is(Implicit)
10481050
case _ => false
10491051
}

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
358358
def statPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
359359
case EmptyTree
360360
| TypeDef(_, _)
361-
| Import(_, _)
361+
| Import(_, _, _)
362362
| DefDef(_, _, _, _, _) =>
363363
Pure
364364
case vdef @ ValDef(_, _, _) =>

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ object Trees {
762762
* where a selector is either an untyped `Ident`, `name` or
763763
* an untyped thicket consisting of `name` and `rename`.
764764
*/
765-
case class Import[-T >: Untyped] private[ast] (expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @constructorOnly src: SourceFile)
765+
case class Import[-T >: Untyped] private[ast] (impliedOnly: Boolean, expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @constructorOnly src: SourceFile)
766766
extends DenotingTree[T] {
767767
type ThisTree[-T >: Untyped] = Import[T]
768768
}
@@ -1156,9 +1156,9 @@ object Trees {
11561156
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
11571157
case tree => finalize(tree, untpd.Template(constr, parents, derived, self, body)(tree.source))
11581158
}
1159-
def Import(tree: Tree)(expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match {
1160-
case tree: Import if (expr eq tree.expr) && (selectors eq tree.selectors) => tree
1161-
case _ => finalize(tree, untpd.Import(expr, selectors)(tree.source))
1159+
def Import(tree: Tree)(impliedOnly: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match {
1160+
case tree: Import if (impliedOnly == tree.impliedOnly) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree
1161+
case _ => finalize(tree, untpd.Import(impliedOnly, expr, selectors)(tree.source))
11621162
}
11631163
def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match {
11641164
case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree
@@ -1303,8 +1303,8 @@ object Trees {
13031303
cpy.TypeDef(tree)(name, transform(rhs))
13041304
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
13051305
cpy.Template(tree)(transformSub(constr), transform(tree.parents), Nil, transformSub(self), transformStats(tree.body))
1306-
case Import(expr, selectors) =>
1307-
cpy.Import(tree)(transform(expr), selectors)
1306+
case Import(impliedOnly, expr, selectors) =>
1307+
cpy.Import(tree)(impliedOnly, transform(expr), selectors)
13081308
case PackageDef(pid, stats) =>
13091309
cpy.PackageDef(tree)(transformSub(pid), transformStats(stats)(localCtx))
13101310
case Annotated(arg, annot) =>
@@ -1427,7 +1427,7 @@ object Trees {
14271427
this(x, rhs)
14281428
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
14291429
this(this(this(this(x, constr), parents), self), tree.body)
1430-
case Import(expr, selectors) =>
1430+
case Import(impliedOnly, expr, selectors) =>
14311431
this(x, expr)
14321432
case PackageDef(pid, stats) =>
14331433
this(this(x, pid), stats)(localCtx)

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
329329
Block(cdef :: Nil, New(cls.typeRef, Nil))
330330
}
331331

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

335335
def PackageDef(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef =
336336
ta.assignType(untpd.PackageDef(pid, stats), pid)

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
130130

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

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

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

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

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

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

155-
case class Instance()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implicit)
155+
case class Instance()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implied)
156156
}
157157

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

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Scopes._
1313
import Uniques._
1414
import ast.Trees._
1515
import ast.untpd
16+
import Flags.ImplicitOrImplied
1617
import util.{FreshNameCreator, NoSource, SimpleIdentityMap, SourceFile}
1718
import typer.{Implicits, ImportInfo, Inliner, NamerContextOps, SearchHistory, SearchRoot, TypeAssigner, Typer}
1819
import Implicits.ContextualImplicits
@@ -214,7 +215,7 @@ object Contexts {
214215
implicitsCache = {
215216
val implicitRefs: List[ImplicitRef] =
216217
if (isClassDefContext)
217-
try owner.thisType.implicitMembers
218+
try owner.thisType.implicitMembers(ImplicitOrImplied)
218219
catch {
219220
case ex: CyclicReference => Nil
220221
}
@@ -404,7 +405,8 @@ object Contexts {
404405
case ref: RefTree[_] => Some(ref.name.asTermName)
405406
case _ => None
406407
}
407-
ctx.fresh.setImportInfo(new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt))
408+
ctx.fresh.setImportInfo(
409+
new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt, imp.impliedOnly))
408410
}
409411

410412
/** Does current phase use an erased types interpretation? */

compiler/src/dotty/tools/dotc/core/Flags.scala

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ object Flags {
130130
*/
131131
case class FlagConjunction(bits: Long) {
132132
override def toString: String = FlagSet(bits).toString
133+
def | (fs: FlagSet): FlagConjunction = FlagConjunction((FlagSet(bits) | fs).bits)
133134
}
134135

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

244245
/** Labeled with `implicit` modifier (implicit value) */
245-
final val ImplicitCommon: FlagSet = commonFlag(9, "implicit")
246-
final val Implicit: FlagSet = ImplicitCommon.toTermFlags
246+
final val Implicit: FlagSet = commonFlag(9, "implicit")
247+
final val ImplicitTerm: FlagSet = Implicit.toTermFlags
247248

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

388+
final val Implied: FlagSet = commonFlag(39, "implied")
389+
387390
/** Symbol is an enum class or enum case (if used with case) */
388391
final val Enum: FlagSet = commonFlag(40, "<enum>")
389392

@@ -460,7 +463,7 @@ object Flags {
460463

461464
/** Flags representing source modifiers */
462465
private val CommonSourceModifierFlags: FlagSet =
463-
commonFlags(Private, Protected, Final, Case, Implicit, Override, JavaStatic)
466+
commonFlags(Private, Protected, Final, Case, Implicit, Implied, Override, JavaStatic)
464467

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

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

542545
/** Flags that can apply to a module val */
543546
final val RetainedModuleValFlags: FlagSet = RetainedModuleValAndClassFlags |
544-
Override | Final | Method | Implicit | Lazy |
547+
Override | Final | Method | Implicit | Implied | Lazy |
545548
Accessor | AbsOverride | StableRealizable | Captured | Synchronized | Erased
546549

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

592+
final val ImplicitOrImplied = Implicit | Implied
593+
594+
final val ImplicitOrImpliedTerm = ImplicitOrImplied.toTermFlags
595+
589596
/** Assumed to be pure */
590597
final val StableOrErased: FlagSet = StableRealizable | Erased
591598

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

604-
/** An implicit inline method */
605-
final val ImplicitInlineMethod: FlagConjunction = allOf(Inline, Implicit, Method)
606-
607611
/** An inline parameter */
608612
final val InlineParam: FlagConjunction = allOf(Inline, Param)
609613

compiler/src/dotty/tools/dotc/core/Scopes.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ package core
99

1010
import Symbols._
1111
import Types.{TermRef, NoPrefix}
12-
import Flags.Implicit
12+
import Flags._
1313
import Names._
1414
import Contexts._
1515
import Denotations._
@@ -409,7 +409,7 @@ object Scopes {
409409
var irefs = new mutable.ListBuffer[TermRef]
410410
var e = lastEntry
411411
while (e ne null) {
412-
if (e.sym is Implicit) {
412+
if (e.sym is ImplicitOrImplied) {
413413
val d = e.sym.denot
414414
irefs += TermRef(NoPrefix, d.symbol.asTerm).withDenot(d)
415415
}

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1873,7 +1873,8 @@ object SymDenotations {
18731873
val ownSyms =
18741874
if (keepOnly eq implicitFilter)
18751875
if (this is Package) Iterator.empty
1876-
else info.decls.iterator filter (_ is Implicit)
1876+
// implicits in package objects are added by the overriding `memberNames` in `PackageClassDenotation`
1877+
else info.decls.iterator filter (_ is ImplicitOrImplied)
18771878
else info.decls.iterator
18781879
for (sym <- ownSyms) maybeAdd(sym.name)
18791880
names

compiler/src/dotty/tools/dotc/core/TypeErrors.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import config.Printers.cyclicErrors
1818
class TypeError(msg: String) extends Exception(msg) {
1919
def this() = this("")
2020
def toMessage(implicit ctx: Context): Message = super.getMessage
21-
override def getMessage: String = throw new Exception("Use toMessage instead for TypeError")
21+
override def getMessage: String = super.getMessage
2222
}
2323

2424
class MalformedType(pre: Type, denot: Denotation, absMembers: Set[Name]) extends TypeError {
@@ -137,7 +137,7 @@ class CyclicReference private (val denot: SymDenotation) extends TypeError {
137137
}
138138
}
139139
// Give up and give generic errors.
140-
else if (cycleSym.is(Implicit, butNot = Method) && cycleSym.owner.isTerm)
140+
else if (cycleSym.is(ImplicitOrImplied, butNot = Method) && cycleSym.owner.isTerm)
141141
CyclicReferenceInvolvingImplicit(cycleSym)
142142
else
143143
CyclicReferenceInvolving(denot)

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -787,10 +787,13 @@ object Types {
787787
(name, buf) => buf += member(name).asSingleDenotation)
788788
}
789789

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

compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Standard-Section: "ASTs" TopLevelStat*
5858
ValOrDefDef
5959
TYPEDEF Length NameRef (type_Term | Template) Modifier*
6060
OBJECTDEF Length NameRef Template Modifier*
61-
IMPORT Length qual_Term Selector*
61+
IMPORT Length [IMPLIED] qual_Term Selector*
6262
ValOrDefDef = VALDEF Length NameRef type_Term rhs_Term? Modifier*
6363
DEFDEF Length NameRef TypeParam* Params* returnType_Term rhs_Term?
6464
Modifier*
@@ -180,6 +180,7 @@ Standard-Section: "ASTs" TopLevelStat*
180180
SEALED
181181
CASE
182182
IMPLICIT
183+
IMPLIED
183184
ERASED
184185
LAZY
185186
OVERRIDE
@@ -324,7 +325,8 @@ object TastyFormat {
324325
final val OPAQUE = 35
325326
final val EXTENSION = 36
326327
final val GIVEN = 37
327-
final val PARAMsetter = 38
328+
final val IMPLIED = 38
329+
final val PARAMsetter = 39
328330

329331
// Cat. 2: tag Nat
330332

@@ -475,6 +477,7 @@ object TastyFormat {
475477
| SEALED
476478
| CASE
477479
| IMPLICIT
480+
| IMPLIED
478481
| ERASED
479482
| LAZY
480483
| OVERRIDE
@@ -535,6 +538,7 @@ object TastyFormat {
535538
case SEALED => "SEALED"
536539
case CASE => "CASE"
537540
case IMPLICIT => "IMPLICIT"
541+
case IMPLIED => "IMPLIED"
538542
case ERASED => "ERASED"
539543
case LAZY => "LAZY"
540544
case OVERRIDE => "OVERRIDE"

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,13 @@ class TreePickler(pickler: TastyPickler) {
532532
}
533533
pickleStats(tree.constr :: rest)
534534
}
535-
case Import(expr, selectors) =>
535+
case Import(impliedOnly, expr, selectors) =>
536536
writeByte(IMPORT)
537-
withLength { pickleTree(expr); pickleSelectors(selectors) }
537+
withLength {
538+
if (impliedOnly) writeByte(IMPLIED)
539+
pickleTree(expr)
540+
pickleSelectors(selectors)
541+
}
538542
case PackageDef(pid, stats) =>
539543
writeByte(PACKAGE)
540544
withLength { pickleType(pid.tpe); pickleStats(stats) }
@@ -646,6 +650,7 @@ class TreePickler(pickler: TastyPickler) {
646650
if (flags is Scala2x) writeByte(SCALA2X)
647651
if (isTerm) {
648652
if (flags is Implicit) writeByte(IMPLICIT)
653+
if (flags is Implied) writeByte(IMPLIED)
649654
if (flags is Erased) writeByte(ERASED)
650655
if (flags.is(Lazy, butNot = Module)) writeByte(LAZY)
651656
if (flags is AbsOverride) { writeByte(ABSTRACT); writeByte(OVERRIDE) }

0 commit comments

Comments
 (0)