Skip to content

Commit cd33fa4

Browse files
committed
witness -> instance
# Conflicts: # compiler/src/dotty/tools/dotc/parsing/Parsers.scala
1 parent 2febab1 commit cd33fa4

20 files changed

+401
-412
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ object desugar {
341341
val isCaseClass = mods.is(Case) && !mods.is(Module)
342342
val isCaseObject = mods.is(Case) && mods.is(Module)
343343
val isImplicit = mods.is(Implicit)
344-
val isWitness = isImplicit && mods.mods.exists(_.isInstanceOf[Mod.Witness])
344+
val isInstance = isImplicit && mods.mods.exists(_.isInstanceOf[Mod.Instance])
345345
val isEnum = mods.isEnumClass && !mods.is(Module)
346346
def isEnumCase = mods.isEnumCase
347347
val isValueClass = parents.nonEmpty && isAnyVal(parents.head)
@@ -669,7 +669,7 @@ object desugar {
669669
ctx.error(ImplicitCaseClass(cdef), cdef.sourcePos)
670670
Nil
671671
}
672-
else if (arity != 1 && !isWitness) {
672+
else if (arity != 1 && !isInstance) {
673673
ctx.error(ImplicitClassPrimaryConstructorArity(), cdef.sourcePos)
674674
Nil
675675
}
@@ -805,11 +805,11 @@ object desugar {
805805
/** The normalized name of `mdef`. This means
806806
* 1. Check that the name does not redefine a Scala core class.
807807
* If it does redefine, issue an error and return a mangled name instead of the original one.
808-
* 2. If the name is missing (this can be the case for witnesses), invent one instead.
808+
* 2. If the name is missing (this can be the case for instance definitions), invent one instead.
809809
*/
810810
def normalizeClassName(mdef: MemberDef, impl: Template)(implicit ctx: Context): TypeName = {
811811
var name = mdef.name.toTypeName
812-
if (name.isEmpty) name = s"${inventName(impl)}_witness".toTypeName
812+
if (name.isEmpty) name = s"${inventName(impl)}_instance".toTypeName
813813
if (ctx.owner == defn.ScalaPackageClass && defn.reservedScalaClassNames.contains(name)) {
814814
def kind = if (name.isTypeName) "class" else "object"
815815
ctx.error(em"illegal redefinition of standard $kind $name", mdef.sourcePos)
@@ -818,7 +818,7 @@ object desugar {
818818
name
819819
}
820820

821-
/** Invent a name for an anonymous witness with template `impl`.
821+
/** Invent a name for an anonymous instance with template `impl`.
822822
*/
823823
private def inventName(impl: Template)(implicit ctx: Context): String =
824824
if (impl.parents.isEmpty)
@@ -829,7 +829,7 @@ object desugar {
829829
case Some(DefDef(name, _, (vparam :: _) :: _, _, _)) =>
830830
s"${name}_of_${inventTypeName(vparam.tpt)}"
831831
case _ =>
832-
ctx.error(i"anonymous witness must have `for` part or must define at least one extension method", impl.pos)
832+
ctx.error(i"anonymous instance must have `for` part or must define at least one extension method", impl.pos)
833833
nme.ERROR.toString
834834
}
835835
else

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
150150

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

153-
case class Witness()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implicit)
153+
case class Instance()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implicit)
154154
}
155155

156156
/** Modifiers and annotations for definitions

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,7 +2133,7 @@ object Parsers {
21332133
*/
21342134
def paramClauses(ofClass: Boolean = false,
21352135
ofCaseClass: Boolean = false,
2136-
ofWitness: Boolean = false): List[List[ValDef]] = {
2136+
ofInstance: Boolean = false): List[List[ValDef]] = {
21372137
def recur(firstClause: Boolean): List[List[ValDef]] = {
21382138
val initialMods =
21392139
if (in.token == WITH) {
@@ -2142,7 +2142,7 @@ object Parsers {
21422142
}
21432143
else EmptyModifiers
21442144
newLineOptWhenFollowedBy(LPAREN)
2145-
if (initialMods.is(Contextual) || in.token == LPAREN && !ofWitness) {
2145+
if (initialMods.is(Contextual) || in.token == LPAREN && !ofInstance) {
21462146
val params = paramClause(
21472147
ofClass = ofClass,
21482148
ofCaseClass = ofCaseClass,
@@ -2427,7 +2427,7 @@ object Parsers {
24272427
/** TmplDef ::= ([`case'] ‘class’ | trait’) ClassDef
24282428
* | [`case'] `object' ObjectDef
24292429
* | ‘enum’ EnumDef
2430-
* | ‘witness’ WitnessDef
2430+
* | ‘instance’ InstanceDef
24312431
*/
24322432
def tmplDef(start: Int, mods: Modifiers): Tree = {
24332433
in.token match {
@@ -2443,8 +2443,8 @@ object Parsers {
24432443
objectDef(start, posMods(start, mods | Case | Module))
24442444
case ENUM =>
24452445
enumDef(start, mods, atSpan(in.skipToken()) { Mod.Enum() })
2446-
case WITNESS =>
2447-
witnessDef(start, mods, atSpan(in.skipToken()) { Mod.Witness() })
2446+
case INSTANCE =>
2447+
instanceDef(start, mods, atSpan(in.skipToken()) { Mod.Instance() })
24482448
case _ =>
24492449
syntaxErrorOrIncomplete(ExpectedStartOfTopLevelDefinition())
24502450
EmptyTree
@@ -2540,16 +2540,16 @@ object Parsers {
25402540
Template(constr, parents, Nil, EmptyValDef, Nil)
25412541
}
25422542

2543-
/** WitnessDef ::= [id] WitnessParams [‘for’ ConstrApps] [TemplateBody]
2544-
* | id WitnessParams ‘:’ Type ‘=’ Expr
2545-
* | id ‘:’ ‘=>’ Type ‘=’ Expr
2546-
* | id ‘=’ Expr
2547-
* WitnessParams ::= [DefTypeParamClause] {‘with’ ‘(’ [DefParams] ‘)}
2543+
/** InstanceDef ::= [id] InstanceParams [‘for’ ConstrApps] [TemplateBody]
2544+
* | id InstanceParams ‘:’ Type ‘=’ Expr
2545+
* | id ‘:’ ‘=>’ Type ‘=’ Expr
2546+
* | id ‘=’ Expr
2547+
* InstanceParams ::= [DefTypeParamClause] {‘with’ ‘(’ [DefParams] ‘)}
25482548
*/
2549-
def witnessDef(start: Offset, mods: Modifiers, witnessMod: Mod) = atPos(start, nameStart) {
2549+
def instanceDef(start: Offset, mods: Modifiers, instanceMod: Mod) = atPos(start, nameStart) {
25502550
val name = if (isIdent && !isIdent(nme.of)) ident() else EmptyTermName
25512551
val tparams = typeParamClauseOpt(ParamOwner.Def)
2552-
val vparamss = paramClauses(ofWitness = true)
2552+
val vparamss = paramClauses(ofInstance = true)
25532553
val parents =
25542554
if (isIdent(nme.of)) {
25552555
in.nextToken()
@@ -2559,7 +2559,7 @@ object Parsers {
25592559
newLineOptWhenFollowedBy(LBRACE)
25602560
if (name.isEmpty && in.token != LBRACE)
25612561
syntaxErrorOrIncomplete(ExpectedTokenButFound(LBRACE, in.token))
2562-
var mods1 = addMod(mods, witnessMod)
2562+
var mods1 = addMod(mods, instanceMod)
25632563
val wdef =
25642564
if (in.token == LBRACE) {
25652565
val templ = templateBodyOpt(makeConstructor(tparams, vparamss), parents, isEnum = false)

compiler/src/dotty/tools/dotc/parsing/Tokens.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ object Tokens extends TokensCommon {
180180
final val ENUM = 62; enter(ENUM, "enum")
181181
final val ERASED = 63; enter(ERASED, "erased")
182182
final val INSTANCE = 64; enter(INSTANCE, "instance")
183-
final val WITNESS = 65; enter(WITNESS, "witness")
184183

185184
/** special symbols */
186185
final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
@@ -202,7 +201,7 @@ object Tokens extends TokensCommon {
202201
/** XML mode */
203202
final val XMLSTART = 96; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate
204203

205-
final val alphaKeywords: TokenSet = tokenRange(IF, WITNESS)
204+
final val alphaKeywords: TokenSet = tokenRange(IF, INSTANCE)
206205
final val symbolicKeywords: TokenSet = tokenRange(USCORE, VIEWBOUND)
207206
final val symbolicTokens: TokenSet = tokenRange(COMMA, VIEWBOUND)
208207
final val keywords: TokenSet = alphaKeywords | symbolicKeywords
@@ -225,7 +224,7 @@ object Tokens extends TokensCommon {
225224

226225
final val templateIntroTokens: TokenSet = BitSet(CLASS, TRAIT, OBJECT, ENUM, CASECLASS, CASEOBJECT)
227226

228-
final val dclIntroTokens: TokenSet = BitSet(DEF, VAL, VAR, TYPE, WITNESS)
227+
final val dclIntroTokens: TokenSet = BitSet(DEF, VAL, VAR, TYPE, INSTANCE)
229228

230229
final val defIntroTokens: TokenSet = templateIntroTokens | dclIntroTokens
231230

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ trait NamerContextOps { this: Context =>
132132

133133
/** The method type corresponding to given parameters and result type */
134134
def methodType(typeParams: List[Symbol], valueParamss: List[List[Symbol]], resultType: Type,
135-
isJava: Boolean = false, isWitness: Boolean = false)(implicit ctx: Context): Type = {
135+
isJava: Boolean = false, isInstance: Boolean = false)(implicit ctx: Context): Type = {
136136
val monotpe =
137137
(valueParamss :\ resultType) { (params, resultType) =>
138138
val (isImplicit, isErased, isContextual) =
139-
if (params.isEmpty) (isWitness, false, false)
139+
if (params.isEmpty) (isInstance, false, false)
140140
else (params.head is Implicit, params.head is Erased, params.head.is(Contextual))
141141
val make = MethodType.maker(isJava = isJava, isImplicit = isImplicit, isErased = isErased, isContextual = isContextual)
142142
if (isJava)
@@ -1302,7 +1302,7 @@ class Namer { typer: Typer =>
13021302
def wrapMethType(restpe: Type): Type = {
13031303
instantiateDependent(restpe, typeParams, termParamss)
13041304
ctx.methodType(tparams map symbolOfTree, termParamss, restpe,
1305-
isJava = ddef.mods is JavaDefined, isWitness = ddef.mods.hasMod(classOf[Mod.Witness]))
1305+
isJava = ddef.mods is JavaDefined, isInstance = ddef.mods.hasMod(classOf[Mod.Instance]))
13061306
}
13071307
if (isConstructor) {
13081308
// set result type tree to unit, but take the current class as result type of the symbol

compiler/test/dotc/run-test-pickling.blacklist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ typeclass-derivation2a.scala
1010
typeclass-derivation3.scala
1111
derive-generic.scala
1212
deriving-interesting-prefixes.scala
13-
witnesses.scala
14-
witnesses-anonymous.scala
13+
instances.scala
14+
instances-anonymous.scala

docs/docs/internals/syntax.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,11 @@ ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses
368368
ConstrMods ::= {Annotation} [AccessModifier]
369369
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
370370
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
371-
WitnessDef ::= [id] WitnessParams [‘for’ ConstrApps] [TemplateBody]
372-
| id WitnessParams ‘:’ Type ‘=’ Expr
371+
InstanceDef ::= [id] InstanceParams [‘of’ ConstrApps] [TemplateBody]
372+
| id InstanceParams ‘:’ Type ‘=’ Expr
373373
| id ‘:’ ‘=>’ Type ‘=’ Expr
374374
| id ‘=’ Expr
375-
WitnessParams ::= [DefTypeParamClause] {‘with’ ‘(’ [DefParams] ‘)'}
375+
InstanceParams ::= [DefTypeParamClause] {‘with’ ‘(’ [DefParams] ‘)'}
376376
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)
377377
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
378378
ConstrApps ::= ConstrApp {‘with’ ConstrApp}

docs/docs/reference/witnesses/witness-params.md renamed to docs/docs/reference/instances/context-params.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ Implementing postconditions via `ensuring`:
8484
object PostConditions {
8585
opaque type WrappedResult[T] = T
8686

87-
private witness WrappedResult {
87+
private instance WrappedResult {
8888
def apply[T](x: T): WrappedResult[T] = x
8989
def (x: WrappedResult[T]) unwrap[T]: T = x
9090
}
9191

9292
def result[T] with (wrapped: WrappedResult[T]): T = wrapped.unwrap
9393

94-
witness {
94+
instance {
9595
def (x: T) ensuring[T] (condition: WrappedResult[T] |=> Boolean): T = {
9696
assert(condition with WrappedResult(x))
9797
x

docs/docs/reference/witnesses/discussion.md renamed to docs/docs/reference/instances/discussion.md

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ title: "Discussion"
55

66
## Summary
77

8-
The witness proposal consists of two main parts:
8+
The instance proposal consists of two main parts:
99

10-
- Define a new [high-level syntax for witnesses](./witnesses.html) that works out better the intent underlying implicit definitions.
11-
- Define a [new syntax for implicit parameters](./witness-params.html) that aligns formal parameters and arguments.
12-
- Define [abstract and alias witnesses](./replacing-implicits.html) and replace all existing usages of `implicit` in the language.
10+
- Define a new [high-level syntax for instance definitions](./instance-defs.html) that works out better the intent underlying implicit definitions.
11+
- Define a [new syntax for implicit parameters](./context-params.html) that aligns formal parameters and arguments.
12+
- Define [abstract and alias instances](./replacing-implicits.html) and replace all existing usages of `implicit` in the language.
1313

1414

1515
## Migration
1616

17-
New and old syntax would co-exist initially. Rewrite rules could rewrite old syntax to new automatically. This is trivial in the case of implicit parameters and implicit function types. It is a bit more involved in the case of implicit definitions, since more extensive pattern matching is required to recognize a definition that can be rewritten to a witness.
17+
New and old syntax would co-exist initially. Rewrite rules could rewrite old syntax to new automatically. This is trivial in the case of implicit parameters and implicit function types. It is a bit more involved in the case of implicit definitions, since more extensive pattern matching is required to recognize a definition that can be rewritten to a instance.
1818

1919
To make gradual change possible, we allow the new `with` application syntax also for
2020
old style implicit parameters.
@@ -28,17 +28,17 @@ treated the same in Scala 2 and 3. We therefore opt to map context bounds to old
2828
- Step 2: Remove ability to pass context bound arguments directly.
2929
- Step 3: Map context bounds to context parameters.
3030

31-
The third part (replacing existing implicits) should be adopted well after the first two parts are implemented. Alias and abstract witnesses could be introduced together with the other witness definitions, but could also come later.
31+
The third part (replacing existing implicits) should be adopted well after the first two parts are implemented. Alias and abstract instances could be introduced together with the other instance definitions, but could also come later.
3232

3333
## Discussion
3434

3535
This is a rather sweeping proposal, which will affect most Scala code. Here are some supporting arguments and a summary of alternatives that were considered.
3636

37-
The witness definition syntax makes the definition of implicit instances clearer and more concise. People have repeatedly asked for specific "typeclass syntax" in Scala. I believe that witnesses together with extension methods address this ask quite well.
37+
The instance definition syntax makes the definition of implicit instances clearer and more concise. People have repeatedly asked for specific "typeclass syntax" in Scala. I believe that instance definitions together with extension methods address this ask quite well.
3838

3939
Probably the most far reaching and contentious changes affect implicit parameters. There might be resistance to change, because the existing scheme seems to work "well enough". However, I believe there is a price to pay for the status quo. The need to write `.apply` occasionally to force implicit arguments is already bad. Worse is the fact that implicits always have to come last, which makes useful program patterns much more cumbersome than before and makes the language less regular.
4040

41-
Several alternatives to the proposed syntax changes for implicit parameters were considered:
41+
Two alternatives to the proposed syntax changes for implicit parameters were considered:
4242

4343
1. Leave `implicit` parameters as they are. This suffers from the problems stated
4444
in the [motivation section](./motivation.md).
@@ -47,11 +47,6 @@ Several alternatives to the proposed syntax changes for implicit parameters were
4747
construct an extensive explicit argument tree to figure out what went wrong with a missing
4848
implicit. Another issue is that migration from old to new scheme would be tricky and
4949
would likely take multiple language versions.
50-
3. Split the meanings of implicitly passed parameters and witness parameters. Use prefix ‘.’ as a syntax to indicate that an argument for a parameter can be passed explicitly. Use
51-
`witness` as a parameter modifier to indicate that the parameter is available as a witness.
52-
This scheme admits some new patterns, such as an explicit parameter that can be
53-
used as a witness, or an implicitly passed parameter that is not a witness itself.
54-
But the syntax looks unfamiliar and suffers from the choice paradox.
5550

56-
A contentious point is whether we want abstract and alias witnesses. As an alternative, one would could also keep the current syntax for implicit vals and defs, which can express the same concepts. The main advantage to introduce abstract and alias witnesses is that it would
51+
A contentious point is whether we want abstract and alias instances. As an alternative, one would could also keep the current syntax for implicit vals and defs, which can express the same concepts. The main advantage to introduce abstract and alias instances is that it would
5752
allow us to drop implicit definitions altogether.

0 commit comments

Comments
 (0)