diff --git a/community-build/community-projects/shapeless b/community-build/community-projects/shapeless index 8f049cfa67de..613dad5e2346 160000 --- a/community-build/community-projects/shapeless +++ b/community-build/community-projects/shapeless @@ -1 +1 @@ -Subproject commit 8f049cfa67de9c6e6fcca11cefee4f211b3eefe3 +Subproject commit 613dad5e2346eeadeb90d74c3efa408180f8f242 diff --git a/community-build/community-projects/xml-interpolator b/community-build/community-projects/xml-interpolator index 435d9e076531..f3185019a161 160000 --- a/community-build/community-projects/xml-interpolator +++ b/community-build/community-projects/xml-interpolator @@ -1 +1 @@ -Subproject commit 435d9e076531555ebc5bac8f196645a157bc6c11 +Subproject commit f3185019a16182a2fba20523ccfff6665436424a diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 3379ed2dc50c..16b1af74aa96 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -593,7 +593,7 @@ object Contexts { def setDebug: this.type = setSetting(base.settings.Ydebug, true) } - given ops: (c: Context) + given ops: extension (c: Context) with def addNotNullInfo(info: NotNullInfo) = c.withNotNullInfos(c.notNullInfos.extendWith(info)) diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 6dcd33a15df5..de468ac884b8 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -22,16 +22,16 @@ object Flags { type Flag = opaques.Flag - given /*FlagOps*/ { + given extension (x: FlagSet) with - def (x: FlagSet) bits: Long = opaques.toBits(x) + def bits: Long = opaques.toBits(x) /** The union of the given flag sets. * Combining two FlagSets with `|` will give a FlagSet * that has the intersection of the applicability to terms/types * of the two flag sets. It is checked that the intersection is not empty. */ - def (x: FlagSet) | (y: FlagSet): FlagSet = + def | (y: FlagSet): FlagSet = if (x.bits == 0) y else if (y.bits == 0) x else { @@ -42,22 +42,22 @@ object Flags { } /** The intersection of the given flag sets */ - def (x: FlagSet) & (y: FlagSet): FlagSet = FlagSet(x.bits & y.bits) + def & (y: FlagSet): FlagSet = FlagSet(x.bits & y.bits) /** The intersection of a flag set with the complement of another flag set */ - def (x: FlagSet) &~ (y: FlagSet): FlagSet = { + def &~ (y: FlagSet): FlagSet = { val tbits = x.bits & KINDFLAGS if ((tbits & y.bits) == 0) x else FlagSet(tbits | ((x.bits & ~y.bits) & ~KINDFLAGS)) } - def (x: FlagSet) ^ (y: FlagSet) = + def ^ (y: FlagSet) = FlagSet((x.bits | y.bits) & KINDFLAGS | (x.bits ^ y.bits) & ~KINDFLAGS) /** Does the given flag set contain the given flag? * This means that both the kind flags and the carrier bits have non-empty intersection. */ - def (x: FlagSet) is (flag: Flag): Boolean = { + def is (flag: Flag): Boolean = { val fs = x.bits & flag.bits (fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0 } @@ -65,12 +65,12 @@ object Flags { /** Does the given flag set contain the given flag * and at the same time contain none of the flags in the `butNot` set? */ - def (x: FlagSet) is (flag: Flag, butNot: FlagSet): Boolean = x.is(flag) && !x.isOneOf(butNot) + def is (flag: Flag, butNot: FlagSet): Boolean = x.is(flag) && !x.isOneOf(butNot) /** Does the given flag set have a non-empty intersection with another flag set? * This means that both the kind flags and the carrier bits have non-empty intersection. */ - def (x: FlagSet) isOneOf (flags: FlagSet): Boolean = { + def isOneOf (flags: FlagSet): Boolean = { val fs = x.bits & flags.bits (fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0 } @@ -78,12 +78,12 @@ object Flags { /** Does the given flag set have a non-empty intersection with another flag set, * and at the same time contain none of the flags in the `butNot` set? */ - def (x: FlagSet) isOneOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isOneOf(flags) && !x.isOneOf(butNot) + def isOneOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isOneOf(flags) && !x.isOneOf(butNot) /** Does a given flag set have all of the flags of another flag set? * Pre: The intersection of the term/type flags of both sets must be non-empty. */ - def (x: FlagSet) isAllOf (flags: FlagSet): Boolean = { + def isAllOf (flags: FlagSet): Boolean = { val fs = x.bits & flags.bits ((fs & KINDFLAGS) != 0 || flags.bits == 0) && (fs >>> TYPESHIFT) == (flags.bits >>> TYPESHIFT) @@ -93,36 +93,36 @@ object Flags { * and at the same time contain none of the flags in the `butNot` set? * Pre: The intersection of the term/type flags of both sets must be non-empty. */ - def (x: FlagSet) isAllOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isAllOf(flags) && !x.isOneOf(butNot) + def isAllOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isAllOf(flags) && !x.isOneOf(butNot) - def (x: FlagSet) isEmpty: Boolean = (x.bits & ~KINDFLAGS) == 0 + def isEmpty: Boolean = (x.bits & ~KINDFLAGS) == 0 /** Is a given flag set a subset of another flag set? */ - def (x: FlagSet) <= (y: FlagSet): Boolean = (x.bits & y.bits) == x.bits + def <= (y: FlagSet): Boolean = (x.bits & y.bits) == x.bits /** Does the given flag set apply to terms? */ - def (x: FlagSet) isTermFlags: Boolean = (x.bits & TERMS) != 0 + def isTermFlags: Boolean = (x.bits & TERMS) != 0 /** Does the given flag set apply to terms? */ - def (x: FlagSet) isTypeFlags: Boolean = (x.bits & TYPES) != 0 + def isTypeFlags: Boolean = (x.bits & TYPES) != 0 /** The given flag set with all flags transposed to be type flags */ - def (x: FlagSet) toTypeFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TYPES) + def toTypeFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TYPES) /** The given flag set with all flags transposed to be term flags */ - def (x: FlagSet) toTermFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TERMS) + def toTermFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TERMS) /** The given flag set with all flags transposed to be common flags */ - def (x: FlagSet) toCommonFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits | KINDFLAGS) + def toCommonFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits | KINDFLAGS) /** The number of non-kind flags in the given flag set */ - def (x: FlagSet) numFlags: Int = java.lang.Long.bitCount(x.bits & ~KINDFLAGS) + def numFlags: Int = java.lang.Long.bitCount(x.bits & ~KINDFLAGS) /** The lowest non-kind bit set in the given flag set */ - def (x: FlagSet) firstBit: Int = java.lang.Long.numberOfTrailingZeros(x.bits & ~KINDFLAGS) + def firstBit: Int = java.lang.Long.numberOfTrailingZeros(x.bits & ~KINDFLAGS) /** The list of non-empty names of flags with given index idx that are set in the given flag set */ - private def (x: FlagSet) flagString(idx: Int): List[String] = + private def flagString(idx: Int): List[String] = if ((x.bits & (1L << idx)) == 0) Nil else { def halfString(kind: Int) = @@ -134,7 +134,7 @@ object Flags { } /** The list of non-empty names of flags that are set in teh given flag set */ - def (x: FlagSet) flagStrings(privateWithin: String): Seq[String] = { + def flagStrings(privateWithin: String): Seq[String] = { var rawStrings = (2 to MaxFlag).flatMap(x.flagString(_)) // DOTTY problem: cannot drop with (_) if (!privateWithin.isEmpty && !x.is(Protected)) rawStrings = rawStrings :+ "private" @@ -149,8 +149,8 @@ object Flags { } /** The string representation of the given flag set */ - def (x: FlagSet) flagsString: String = x.flagStrings("").mkString(" ") - } + def flagsString: String = x.flagStrings("").mkString(" ") + end given def termFlagSet(x: Long) = FlagSet(TERMS | x) diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index ad5c5d5dc9f0..f3654e1ab53b 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -435,6 +435,7 @@ object StdNames { val eval: N = "eval" val eqlAny: N = "eqlAny" val ex: N = "ex" + val extended: N = "extended" val extension: N = "extension" val experimental: N = "experimental" val f: N = "f" diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 25289c455127..06d8d23f33c8 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2006,7 +2006,7 @@ object Types { val idx = typeParams.indexOf(param) - if (idx < args.length) { + if (0 <= idx && idx < args.length) { val argInfo = args(idx) match { case arg: TypeBounds => val v = param.paramVariance diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 62d9a086eb63..992b98fffbf5 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2046,7 +2046,7 @@ object Parsers { } else simpleExpr() - /** SimpleExpr ::= ‘new’ (ConstrApp [TemplateBody] | TemplateBody) + /** SimpleExpr ::= ‘new’ (ConstrApp [[‘with’] TemplateBody] | TemplateBody) * | BlockExpr * | ‘$’ ‘{’ Block ‘}’ * | Quoted @@ -2141,7 +2141,7 @@ object Parsers { } } - /** SimpleExpr ::= ‘new’ ConstrApp {`with` ConstrApp} [TemplateBody] + /** SimpleExpr ::= ‘new’ ConstrApp {`with` ConstrApp} [[‘with’] TemplateBody] * | ‘new’ TemplateBody */ def newExpr(): Tree = @@ -2150,7 +2150,7 @@ object Parsers { def reposition(t: Tree) = t.withSpan(Span(start, in.lastOffset)) possibleBracesStart() val parents = - if in.token == LBRACE || in.token == WITH then Nil + if in.token == LBRACE then Nil else constrApps(commaOK = false, templateCanFollow = true) colonAtEOLOpt() possibleTemplateStart(isNew = true) @@ -3312,7 +3312,7 @@ object Parsers { } } - /** EnumDef ::= id ClassConstr InheritClauses EnumBody + /** EnumDef ::= id ClassConstr InheritClauses [‘with’] EnumBody */ def enumDef(start: Offset, mods: Modifiers): TypeDef = atSpan(start, nameStart) { val modulName = ident() @@ -3362,42 +3362,36 @@ object Parsers { Template(constr, parents, Nil, EmptyValDef, Nil) } - /** Check that `vparamss` represents a legal collective parameter list for a given extension - */ - def checkExtensionParams(start: Offset, vparamss: List[List[ValDef]]): Unit = vparamss match - case (vparam :: Nil) :: vparamss1 if !vparam.mods.is(Given) => - vparamss1.foreach(_.foreach(vparam => - if !vparam.mods.is(Given) then - syntaxError(em"follow-on parameter in extension clause must be `given`", vparam.span))) - case _ => - syntaxError(em"extension clause must start with a single regular parameter", start) - - def checkExtensionMethod(stat: Tree): Unit = stat match { + def checkExtensionMethod(tparams: List[Tree], stat: Tree): Unit = stat match { case stat: DefDef => if stat.mods.is(Extension) then syntaxError(i"no extension method allowed here since leading parameter was already given", stat.span) - case _ => + else if tparams.nonEmpty && stat.tparams.nonEmpty then + syntaxError(i"extension method cannot have type parameters since some were already given previously", + stat.tparams.head.span) + case stat => syntaxError(i"extension clause can only define methods", stat.span) } /** GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr - * | [GivenSig ‘:’] [ConstrApp {‘,’ ConstrApp }] [TemplateBody] - * | [id ‘:’] ‘extension’ ExtParamClause {GivenParamClause} ExtMethods + * | [GivenSig ‘:’] ConstrApps [[‘with’] TemplateBody] + * | [id ‘:’] ExtParamClause {GivenParamClause} ‘extended’ ‘with’ ExtMethods * GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause} - * ExtParamClause ::= [DefTypeParamClause] DefParamClause {GivenParamClause} + * ExtParamClause ::= [DefTypeParamClause] DefParamClause * ExtMethods ::= [nl] ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’ */ def givenDef(start: Offset, mods: Modifiers, instanceMod: Mod) = atSpan(start, nameStart) { var mods1 = addMod(mods, instanceMod) val hasGivenSig = followingIsGivenSig() - val (name, isExtension) = + val nameStart = in.offset + val (name, isOldExtension) = if isIdent && hasGivenSig then (ident(), in.token == COLON && in.lookaheadIn(nme.extension)) else (EmptyTermName, isIdent(nme.extension)) val gdef = in.endMarkerScope(if name.isEmpty then GIVEN else name) { - if isExtension then + if isOldExtension then if (in.token == COLON) in.nextToken() assert(ident() == nme.extension) val tparams = typeParamClauseOpt(ParamOwner.Def) @@ -3406,72 +3400,64 @@ object Parsers { possibleTemplateStart() val templ = templateBodyOpt( makeConstructor(tparams, extParams :: givenParamss), Nil, Nil) - templ.body.foreach(checkExtensionMethod) + templ.body.foreach(checkExtensionMethod(tparams, _)) ModuleDef(name, templ) else - var tparams: List[TypeDef] = Nil - var vparamss: List[List[ValDef]] = Nil - var hasExtensionParams = false - - def parseParams(isExtension: Boolean): Unit = - if isExtension && (in.token == LBRACKET || in.token == LPAREN) then - hasExtensionParams = true - if tparams.nonEmpty || vparamss.nonEmpty then - syntaxError(i"cannot have parameters before and after `:` in extension") - if in.token == LBRACKET then - tparams = typeParamClause(ParamOwner.Def) - if in.token == LPAREN && followingIsParamOrGivenType() then - val paramsStart = in.offset - vparamss = paramClauses(givenOnly = !isExtension) - if isExtension then - checkExtensionParams(paramsStart, vparamss) - - parseParams(isExtension = false) - val parents = - if in.token == COLON then - in.nextToken() - if in.token == LBRACE - || in.token == WITH - || in.token == LBRACKET - || in.token == LPAREN && followingIsParamOrGivenType() - then - parseParams(isExtension = true) - Nil - else - tokenSeparated(COMMA, constrApp) - else if in.token == SUBTYPE then - if !mods.is(Inline) then - syntaxError("`<:' is only allowed for given with `inline' modifier") - in.nextToken() - TypeBoundsTree(EmptyTree, toplevelTyp()) :: Nil - else if name.isEmpty - && in.token != LBRACE && in.token != WITH - && !hasExtensionParams - then tokenSeparated(COMMA, constrApp) + val hasLabel = !name.isEmpty && in.token == COLON + if hasLabel then in.nextToken() + val tparams = typeParamClauseOpt(ParamOwner.Def) + val paramsStart = in.offset + val vparamss = + if in.token == LPAREN && followingIsParamOrGivenType() + then paramClauses() else Nil - - if in.token == EQUALS && parents.length == 1 && parents.head.isType then + val isExtension = isIdent(nme.extended) + def checkAllGivens(vparamss: List[List[ValDef]], what: String) = + vparamss.foreach(_.foreach(vparam => + if !vparam.mods.is(Given) then syntaxError(em"$what must be `given`", vparam.span))) + if isExtension then + if !name.isEmpty && !hasLabel then + syntaxError(em"name $name of extension clause must be followed by `:`", nameStart) + vparamss match + case (vparam :: Nil) :: vparamss1 if !vparam.mods.is(Given) => + checkAllGivens(vparamss1, "follow-on parameter in extension clause") + case _ => + syntaxError("extension clause must start with a single regular parameter", paramsStart) in.nextToken() - mods1 |= Final - DefDef(name, tparams, vparamss, parents.head, subExpr()) + accept(WITH) + val (self, stats) = templateBody() + stats.foreach(checkExtensionMethod(tparams, _)) + ModuleDef(name, Template(makeConstructor(tparams, vparamss), Nil, Nil, self, stats)) else - parents match - case TypeBoundsTree(_, _) :: _ => syntaxError("`=' expected") - case _ => - possibleTemplateStart() - if hasExtensionParams then - in.observeIndented() + checkAllGivens(vparamss, "parameter of given instance") + val parents = + if hasLabel then + constrApps(commaOK = true, templateCanFollow = true) + else if in.token == SUBTYPE then + if !mods.is(Inline) then + syntaxError("`<:' is only allowed for given with `inline' modifier") + in.nextToken() + TypeBoundsTree(EmptyTree, toplevelTyp()) :: Nil + else + if !(name.isEmpty && tparams.isEmpty && vparamss.isEmpty) then + accept(COLON) + constrApps(commaOK = true, templateCanFollow = true) + if in.token == EQUALS && parents.length == 1 && parents.head.isType then + in.nextToken() + mods1 |= Final + DefDef(name, tparams, vparamss, parents.head, subExpr()) else - tparams = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal)) - vparamss = vparamss.map(_.map(vparam => + parents match + case TypeBoundsTree(_, _) :: _ => syntaxError("`=' expected") + case _ => + possibleTemplateStart() + val tparams1 = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal)) + val vparamss1 = vparamss.map(_.map(vparam => vparam.withMods(vparam.mods &~ Param | ParamAccessor | PrivateLocal))) - val templ = templateBodyOpt(makeConstructor(tparams, vparamss), parents, Nil) - if hasExtensionParams then - templ.body.foreach(checkExtensionMethod) - ModuleDef(name, templ) - else if tparams.isEmpty && vparamss.isEmpty then ModuleDef(name, templ) - else TypeDef(name.toTypeName, templ) - } + val templ = templateBodyOpt(makeConstructor(tparams1, vparamss1), parents, Nil) + if tparams.isEmpty && vparamss.isEmpty then ModuleDef(name, templ) + else TypeDef(name.toTypeName, templ) + } finalizeDef(gdef, mods1, start) } @@ -3505,7 +3491,7 @@ object Parsers { else Nil t :: ts - /** Template ::= InheritClauses [TemplateBody] + /** Template ::= InheritClauses [[‘with’] TemplateBody] * InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}] */ def template(constr: DefDef, isEnum: Boolean = false): Template = { @@ -3548,8 +3534,8 @@ object Parsers { checkNextNotIndented() Template(constr, Nil, Nil, EmptyValDef, Nil) - /** TemplateBody ::= [nl | `with'] `{' TemplateStatSeq `}' - * EnumBody ::= [nl | ‘with’] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’ + /** TemplateBody ::= [nl] `{' TemplateStatSeq `}' + * EnumBody ::= [nl] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’ */ def templateBodyOpt(constr: DefDef, parents: List[Tree], derived: List[Tree]): Template = val (self, stats) = @@ -3560,15 +3546,13 @@ object Parsers { (EmptyValDef, Nil) Template(constr, parents, derived, self, stats) - def templateBody(): (ValDef, List[Tree]) = { + def templateBody(): (ValDef, List[Tree]) = val r = inDefScopeBraces { templateStatSeq() } - if (in.token == WITH) { + if in.token == WITH then syntaxError(EarlyDefinitionsNotSupported()) in.nextToken() template(emptyConstructor) - } r - } /* -------- STATSEQS ------------------------------------------- */ diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala index a01a9874ad77..049074aff748 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -133,8 +133,7 @@ trait Reporting { this: Context => def error(msg: => Message, pos: SourcePosition = NoSourcePosition, sticky: Boolean = false): Unit = { val fullPos = addInlineds(pos) reporter.report(if (sticky) new StickyError(msg, fullPos) else new Error(msg, fullPos)) - if (ctx.settings.YdebugError.value) - Thread.dumpStack() + if ctx.settings.YdebugError.value then Thread.dumpStack() } def error(ex: TypeError, pos: SourcePosition): Unit = { diff --git a/compiler/src/dotty/tools/dotc/typer/Nullables.scala b/compiler/src/dotty/tools/dotc/typer/Nullables.scala index bb5cc87f281b..1f6fe39b2b1d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Nullables.scala +++ b/compiler/src/dotty/tools/dotc/typer/Nullables.scala @@ -137,7 +137,7 @@ object Nullables with // TODO: Add constant pattern if the constant type is not nullable case _ => false - given notNullInfoOps: (infos: List[NotNullInfo]) + given notNullInfoOps: extension (infos: List[NotNullInfo]) with /** Do the current not-null infos imply that `ref` is not null? * Not-null infos are as a history where earlier assertions and retractions replace @@ -161,7 +161,7 @@ object Nullables with then infos else info :: infos - given treeOps: (tree: Tree) + given treeOps: extension (tree: Tree) with /* The `tree` with added nullability attachment */ def withNotNullInfo(info: NotNullInfo): tree.type = @@ -251,7 +251,7 @@ object Nullables with tree.computeNullable() }.traverse(tree) - given assignOps: (tree: Assign) + given assignOps: extension (tree: Assign) with def computeAssignNullable()(given Context): tree.type = tree.lhs match case TrackedRef(ref) => tree.withNotNullInfo(NotNullInfo(Set(), Set(ref))) // TODO: refine with nullability type info diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index c4784d5d4e4e..cd16311d5f8d 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -214,7 +214,7 @@ SimpleExpr ::= Path | ‘$’ ‘{’ Block ‘}’ | Quoted | quoteId // only inside splices - | ‘new’ ConstrApp {`with` ConstrApp} [TemplateBody] New(constr | templ) + | ‘new’ ConstrApp {‘with’ ConstrApp} [[‘with’] TemplateBody] New(constr | templ) | ‘new’ TemplateBody | ‘(’ ExprsInParens ‘)’ Parens(exprs) | SimpleExpr ‘.’ id Select(expr, id) @@ -383,15 +383,15 @@ ClassDef ::= id ClassConstr [Template] ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, , Nil, vparamss, EmptyTree, EmptyTree) as first stat ConstrMods ::= {Annotation} [AccessModifier] ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor -EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template) +EnumDef ::= id ClassConstr InheritClauses [‘with’] EnumBody EnumDef(mods, name, tparams, template) GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr - | [GivenSig ‘:’] [ConstrApp {‘,’ ConstrApp }] [TemplateBody] - | [[id ‘:’] ‘extension’ ExtParamClause {GivenParamClause} - ExtMethods + | [GivenSig ‘:’] ConstrApps [[‘with’] TemplateBody] + | [id ‘:’] ExtParamClause {GivenParamClause} + ‘extended’ ‘with’ ExtMethods GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause} ExtParamClause ::= [DefTypeParamClause] ‘(’ DefParam ‘)’ ExtMethods ::= [nl] ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’ -Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats) +Template ::= InheritClauses [[‘with’] TemplateBody] Template(constr, parents, self, stats) InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}] ConstrApps ::= ConstrApp {(‘,’ | ‘with’) ConstrApp} ConstrApp ::= AnnotType {ParArgumentExprs} Apply(tp, args) @@ -399,8 +399,7 @@ ConstrExpr ::= SelfInvocation | ‘{’ SelfInvocation {semi BlockStat} ‘}’ SelfInvocation ::= ‘this’ ArgumentExprs {ArgumentExprs} -TemplateBody ::= [nl | ‘with’] - ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’ (self, stats) +TemplateBody ::= [nl] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’ (self, stats) TemplateStat ::= Import | Export | {Annotation [nl]} {Modifier} Def diff --git a/docs/docs/reference/contextual/extension-methods.md b/docs/docs/reference/contextual/extension-methods.md index 956a1d620914..933d2ca723e7 100644 --- a/docs/docs/reference/contextual/extension-methods.md +++ b/docs/docs/reference/contextual/extension-methods.md @@ -126,19 +126,19 @@ List(1, 2, 3).second[Int] `given` extensions are given instances that define extension methods and nothing else. Examples: ```scala -given stringOps: extension (xs: Seq[String]) { +given stringOps: (xs: Seq[String]) extended with { def longestStrings: Seq[String] = { val maxLength = xs.map(_.length).max xs.filter(_.length == maxLength) } } -given listOps: extension [T](xs: List[T]) { +given listOps: [T](xs: List[T]) extended with { def second = xs.tail.head def third: T = xs.tail.tail.head } -given extension [T](xs: List[T])(given Ordering[T]) { +given [T](xs: List[T])(given Ordering[T]) extended with { def largest(n: Int) = xs.sorted.takeRight(n) } ``` diff --git a/docs/docs/reference/contextual/motivation.md b/docs/docs/reference/contextual/motivation.md index 89677c0fe08b..f0277de5d014 100644 --- a/docs/docs/reference/contextual/motivation.md +++ b/docs/docs/reference/contextual/motivation.md @@ -29,7 +29,7 @@ Particular criticisms are: 3. The syntax of implicit definitions is too minimal. It consists of a single modifier, `implicit`, that can be attached to a large number of language constructs. A problem with this for newcomers is that it conveys mechanism instead of intent. For instance, a typeclass instance is an implicit object or val if unconditional and an implicit def with implicit parameters referring to some class if conditional. This describes precisely what the implicit definitions translate to -- just drop the `implicit` modifier, and that's it! But the cues that define intent are rather indirect and can be easily misread, as demonstrated by the definitions of `i1` and `i2` above. - 4. The syntax of implicit parameters also has shortcomings. It starts with the position of `implicit` as a pseudo-modifier that applies to a whole parameter section instead of a single parameter. This represents an irregular case with respect to the rest of Scala's syntax. Furthermore, while implicit _parameters_ are designated specifically, arguments are not. Passing an argument to an implicit parameter looks like a regular application `f(arg)`. This is problematic because it means there can be confusion regarding what parameter gets instantiated in a call. For instance, in + 4. The syntax of implicit parameters also has shortcomings. While implicit _parameters_ are designated specifically, arguments are not. Passing an argument to an implicit parameter looks like a regular application `f(arg)`. This is problematic because it means there can be confusion regarding what parameter gets instantiated in a call. For instance, in ```scala def currentMap(implicit ctx: Context): Map[String, Int] ``` diff --git a/docs/docs/reference/contextual/relationship-implicits.md b/docs/docs/reference/contextual/relationship-implicits.md index 318cd5dac8a7..c623cefd4115 100644 --- a/docs/docs/reference/contextual/relationship-implicits.md +++ b/docs/docs/reference/contextual/relationship-implicits.md @@ -61,12 +61,12 @@ The synthesized type names are formed from Tuples are treated as transparent, i.e. a type `F[(X, Y)]` would get the synthesized name `F_X_Y`. Directly implemented function types `A => B` are represented as `A_to_B`. Function types used as arguments to other type constructors are represented as `Function`. -Anonymous given instances that define extension methods without also implementing a type +Anonymous given instances that define extension methods get their name from the name of the first extension method and the toplevel type constructor of its first parameter. For example, the given instance ```scala -given { - def (xs: List[T]) second[T] = ... +given [T] (xs: List[T]) extended with { + def second = ... } ``` gets the synthesized name `given_second_of_List_T`. diff --git a/docs/docs/reference/other-new-features/opaques.md b/docs/docs/reference/other-new-features/opaques.md index f954f51d2d5d..ebf77f696d5d 100644 --- a/docs/docs/reference/other-new-features/opaques.md +++ b/docs/docs/reference/other-new-features/opaques.md @@ -20,10 +20,10 @@ object Logarithms { } // Extension methods define opaque types' public APIs - given logarithmOps: { - def (x: Logarithm) toDouble: Double = math.exp(x) - def (x: Logarithm) + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y)) - def (x: Logarithm) * (y: Logarithm): Logarithm = Logarithm(x + y) + given logarithmOps: (x: Logarithm) extended with { + def toDouble: Double = math.exp(x) + def + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y)) + def * (y: Logarithm): Logarithm = Logarithm(x + y) } } ``` diff --git a/library/src-bootstrapped/scala/IArray.scala b/library/src-bootstrapped/scala/IArray.scala index 3ab5cdfcdc5f..85b7188c49a0 100644 --- a/library/src-bootstrapped/scala/IArray.scala +++ b/library/src-bootstrapped/scala/IArray.scala @@ -4,11 +4,11 @@ import reflect.ClassTag /** An immutable array. An `IArray[T]` has the same representation as an `Array[T]`, * but it cannot be updated. Unlike regular arrays, immutable arrays are covariant. */ -object opaques { +object opaques opaque type IArray[+T] = Array[_ <: T] /** Defines extension methods for immutable arrays */ - given arrayOps: { + given arrayOps: Object with /** The selection operation on an immutable array. * @@ -38,8 +38,8 @@ object opaques { def (arr: IArray[Double]) length: Int = arr.asInstanceOf[Array[Double]].length def (arr: IArray[Object]) length: Int = arr.asInstanceOf[Array[Object]].length def [T](arr: IArray[T]) length: Int = arr.asInstanceOf[Array[T]].length - } -} +end opaques + type IArray[+T] = opaques.IArray[T] object IArray { diff --git a/library/src/scala/internal/quoted/Matcher.scala b/library/src/scala/internal/quoted/Matcher.scala index 2acfeea99207..e480f064b2da 100644 --- a/library/src/scala/internal/quoted/Matcher.scala +++ b/library/src/scala/internal/quoted/Matcher.scala @@ -86,15 +86,15 @@ private[quoted] object Matcher { case _ => notMatched } - private given treeListOps: { + private given treeListOps: extension (scrutinees: List[Tree]) with /** Check that all trees match with =?= and concatenate the results with && */ - def (scrutinees: List[Tree]) =?= (patterns: List[Tree])(given Context, Env): Matching = + def =?= (patterns: List[Tree])(given Context, Env): Matching = matchLists(scrutinees, patterns)(_ =?= _) - } + end treeListOps - private given treeOps: { + private given treeOps: extension (scrutinee0: Tree) with /** Check that the trees match and return the contents from the pattern holes. * Return None if the trees do not match otherwise return Some of a tuple containing all the contents in the holes. @@ -104,7 +104,7 @@ private[quoted] object Matcher { * @param `summon[Env]` Set of tuples containing pairs of symbols (s, p) where s defines a symbol in `scrutinee` which corresponds to symbol p in `pattern`. * @return `None` if it did not match or `Some(tup: Tuple)` if it matched where `tup` contains the contents of the holes. */ - def (scrutinee0: Tree) =?= (pattern0: Tree)(given Context, Env): Matching = { + def =?= (pattern0: Tree)(given Context, Env): Matching = { /** Normalize the tree */ def normalize(tree: Tree): Tree = tree match { @@ -275,7 +275,7 @@ private[quoted] object Matcher { notMatched } } - } + end treeOps private def treeOptMatches(scrutinee: Option[Tree], pattern: Option[Tree])(given Context, Env): Matching = { (scrutinee, pattern) match { diff --git a/library/src/scala/tasty/reflect/CommentOps.scala b/library/src/scala/tasty/reflect/CommentOps.scala index f3efecbac643..3fb13070cbd1 100644 --- a/library/src/scala/tasty/reflect/CommentOps.scala +++ b/library/src/scala/tasty/reflect/CommentOps.scala @@ -2,7 +2,7 @@ package scala.tasty.reflect trait CommentOps extends Core { - given CommentOps: (self: Comment) { + given CommentOps: extension (self: Comment) { /** Raw comment string */ def raw: String = internal.Comment_raw(self) diff --git a/library/src/scala/tasty/reflect/ConstantOps.scala b/library/src/scala/tasty/reflect/ConstantOps.scala index ec6c25b8c567..3623883d429d 100644 --- a/library/src/scala/tasty/reflect/ConstantOps.scala +++ b/library/src/scala/tasty/reflect/ConstantOps.scala @@ -3,7 +3,7 @@ package reflect trait ConstantOps extends Core { - given ConstantOps: (const: Constant) { + given ConstantOps: extension (const: Constant) { def value: Any = internal.Constant_value(const) } diff --git a/library/src/scala/tasty/reflect/ContextOps.scala b/library/src/scala/tasty/reflect/ContextOps.scala index 414324a8bf52..f09fcf353dc7 100644 --- a/library/src/scala/tasty/reflect/ContextOps.scala +++ b/library/src/scala/tasty/reflect/ContextOps.scala @@ -3,7 +3,7 @@ package reflect trait ContextOps extends Core { - given ContextOps: (self: Context) { + given ContextOps: extension (self: Context) { /** Returns the owner of the context */ def owner: Symbol = internal.Context_owner(self) diff --git a/library/src/scala/tasty/reflect/FlagsOps.scala b/library/src/scala/tasty/reflect/FlagsOps.scala index 10b416c33b1f..9588ab37a256 100644 --- a/library/src/scala/tasty/reflect/FlagsOps.scala +++ b/library/src/scala/tasty/reflect/FlagsOps.scala @@ -2,7 +2,7 @@ package scala.tasty.reflect trait FlagsOps extends Core { - given FlagsOps: (self: Flags) { + given FlagsOps: extension (self: Flags) { /** Is the given flag set a subset of this flag sets */ def is(that: Flags): Boolean = internal.Flags_is(self)(that) diff --git a/library/src/scala/tasty/reflect/IdOps.scala b/library/src/scala/tasty/reflect/IdOps.scala index f9fd494f6945..708c905a4403 100644 --- a/library/src/scala/tasty/reflect/IdOps.scala +++ b/library/src/scala/tasty/reflect/IdOps.scala @@ -3,7 +3,7 @@ package reflect trait IdOps extends Core { - given IsOps: (id: Id) { + given IdOps: extension (id: Id) { /** Position in the source code */ def pos(given ctx: Context): Position = internal.Id_pos(id) diff --git a/library/src/scala/tasty/reflect/ImplicitsOps.scala b/library/src/scala/tasty/reflect/ImplicitsOps.scala index 335941ac8e87..a252c351bd04 100644 --- a/library/src/scala/tasty/reflect/ImplicitsOps.scala +++ b/library/src/scala/tasty/reflect/ImplicitsOps.scala @@ -11,7 +11,7 @@ trait ImplicitsOps extends Core { @deprecated("Use _: ImplicitSearchSuccess", "") def unapply(isr: ImplicitSearchSuccess)(given ctx: Context): Option[ImplicitSearchSuccess] = Some(isr) - given SuccessOps: (self: ImplicitSearchSuccess) { + given successOps: extension (self: ImplicitSearchSuccess) { def tree(given ctx: Context): Term = internal.ImplicitSearchSuccess_tree(self) } @@ -21,7 +21,7 @@ trait ImplicitsOps extends Core { @deprecated("Use _: ImplicitSearchFailure", "") def unapply(isr: ImplicitSearchFailure)(given ctx: Context): Option[ImplicitSearchFailure] = Some(isr) - given FailureOps: (self: ImplicitSearchFailure) { + given failureOps: extension (self: ImplicitSearchFailure) { def explanation(given ctx: Context): String = internal.ImplicitSearchFailure_explanation(self) } diff --git a/library/src/scala/tasty/reflect/ImportSelectorOps.scala b/library/src/scala/tasty/reflect/ImportSelectorOps.scala index c955d3b082f0..df88dd036565 100644 --- a/library/src/scala/tasty/reflect/ImportSelectorOps.scala +++ b/library/src/scala/tasty/reflect/ImportSelectorOps.scala @@ -3,7 +3,7 @@ package reflect trait ImportSelectorOps extends Core { - given SimpleSelectorOps: (self: SimpleSelector) { + given simpleSelectorOps: extension (self: SimpleSelector) { def selection(given ctx: Context): Id = internal.SimpleSelector_selection(self) } @@ -13,7 +13,7 @@ trait ImportSelectorOps extends Core { object SimpleSelector def unapply(x: SimpleSelector)(given ctx: Context): Option[Id] = Some(x.selection) - given RenameSelectorOps: (self: RenameSelector) { + given renameSelectorOps: extension (self: RenameSelector) { def from(given ctx: Context): Id = internal.RenameSelector_from(self) @@ -26,7 +26,7 @@ trait ImportSelectorOps extends Core { object RenameSelector def unapply(x: RenameSelector)(given ctx: Context): Option[(Id, Id)] = Some((x.from, x.to)) - given OmitSelectorOps: (self: OmitSelector) { + given omitSelectorOps: extension (self: OmitSelector) { def omitted(given ctx: Context): Id = internal.SimpleSelector_omitted(self) } diff --git a/library/src/scala/tasty/reflect/PositionOps.scala b/library/src/scala/tasty/reflect/PositionOps.scala index eeaf51204df0..f52d9dc4385a 100644 --- a/library/src/scala/tasty/reflect/PositionOps.scala +++ b/library/src/scala/tasty/reflect/PositionOps.scala @@ -2,7 +2,7 @@ package scala.tasty.reflect trait PositionOps extends Core { - given PositionOps: (pos: Position) { + given positionOps: extension (pos: Position) { /** The start offset in the source file */ def start: Int = internal.Position_start(pos) @@ -33,7 +33,7 @@ trait PositionOps extends Core { } - given SourceFileOps: (sourceFile: SourceFile) { + given sourceFileOps: extension (sourceFile: SourceFile) { /** Path to this source file */ def jpath: java.nio.file.Path = internal.SourceFile_jpath(sourceFile) diff --git a/library/src/scala/tasty/reflect/SignatureOps.scala b/library/src/scala/tasty/reflect/SignatureOps.scala index ee16b2cb27f7..8e26005fa655 100644 --- a/library/src/scala/tasty/reflect/SignatureOps.scala +++ b/library/src/scala/tasty/reflect/SignatureOps.scala @@ -9,7 +9,7 @@ trait SignatureOps extends Core { Some((sig.paramSigs, sig.resultSig)) } - given SignatureOps: (sig: Signature) { + given signatureOps: extension (sig: Signature) { /** The signatures of the method parameters. * diff --git a/library/src/scala/tasty/reflect/SymbolOps.scala b/library/src/scala/tasty/reflect/SymbolOps.scala index cceaf785fe17..e3004cc404be 100644 --- a/library/src/scala/tasty/reflect/SymbolOps.scala +++ b/library/src/scala/tasty/reflect/SymbolOps.scala @@ -14,7 +14,7 @@ trait SymbolOps extends Core { selfSymbolOps: FlagsOps => internal.Symbol_noSymbol } - given SymbolOps: (self: Symbol) { + given symbolOps: extension (self: Symbol) { /** Owner of this symbol. The owner is the symbol in which this symbol is defined */ def owner(given ctx: Context): Symbol = internal.Symbol_owner(self) diff --git a/library/src/scala/tasty/reflect/TreeOps.scala b/library/src/scala/tasty/reflect/TreeOps.scala index fa8f771c82df..c015361b3662 100644 --- a/library/src/scala/tasty/reflect/TreeOps.scala +++ b/library/src/scala/tasty/reflect/TreeOps.scala @@ -5,7 +5,7 @@ trait TreeOps extends Core { // ----- Tree ----------------------------------------------------- - given TreeOps: (self: Tree) { + given TreeOps: extension (self: Tree) { /** Position in the source code */ def pos(given ctx: Context): Position = internal.Tree_pos(self) @@ -27,7 +27,7 @@ trait TreeOps extends Core { Some((tree.pid, tree.stats)) } - given PackageClauseOps: (self: PackageClause) { + given PackageClauseOps: extension (self: PackageClause) { def pid(given ctx: Context): Ref = internal.PackageClause_pid(self) def stats(given ctx: Context): List[Tree] = internal.PackageClause_stats(self) } @@ -47,7 +47,7 @@ trait TreeOps extends Core { Some((tree.expr, tree.selectors)) } - given ImportOps: (self: Import) { + given ImportOps: extension (self: Import) { def expr(given ctx: Context): Term = internal.Import_expr(self) def selectors(given ctx: Context): List[ImportSelector] = internal.Import_selectors(self) @@ -67,7 +67,7 @@ trait TreeOps extends Core { @deprecated("Use _: Definition", "") def unapply(x: Definition): Option[Definition] = Some(x) - given DefinitionOps: (self: Definition) { + given DefinitionOps: extension (self: Definition) { def name(given ctx: Context): String = internal.Definition_name(self) } @@ -87,7 +87,7 @@ trait TreeOps extends Core { Some((cdef.name, cdef.constructor, cdef.parents, cdef.derived, cdef.self, cdef.body)) } - given ClassDefOps: (self: ClassDef) { + given ClassDefOps: extension (self: ClassDef) { def constructor(given ctx: Context): DefDef = internal.ClassDef_constructor(self) def parents(given ctx: Context): List[Tree /* Term | TypeTree */] = internal.ClassDef_parents(self) def derived(given ctx: Context): List[TypeTree] = internal.ClassDef_derived(self) @@ -112,7 +112,7 @@ trait TreeOps extends Core { Some((ddef.name, ddef.typeParams, ddef.paramss, ddef.returnTpt, ddef.rhs)) } - given DefDefOps: (self: DefDef) { + given DefDefOps: extension (self: DefDef) { def typeParams(given ctx: Context): List[TypeDef] = internal.DefDef_typeParams(self) def paramss(given ctx: Context): List[List[ValDef]] = internal.DefDef_paramss(self) def returnTpt(given ctx: Context): TypeTree = internal.DefDef_returnTpt(self) // TODO rename to tpt @@ -136,7 +136,7 @@ trait TreeOps extends Core { Some((vdef.name, vdef.tpt, vdef.rhs)) } - given ValDefOps: (self: ValDef) { + given ValDefOps: extension (self: ValDef) { def tpt(given ctx: Context): TypeTree = internal.ValDef_tpt(self) def rhs(given ctx: Context): Option[Term] = internal.ValDef_rhs(self) } @@ -158,7 +158,7 @@ trait TreeOps extends Core { Some((tdef.name, tdef.rhs)) } - given TypeDefOps: (self: TypeDef) { + given TypeDefOps: extension (self: TypeDef) { def rhs(given ctx: Context): Tree /*TypeTree | TypeBoundsTree*/ = internal.TypeDef_rhs(self) } @@ -166,7 +166,7 @@ trait TreeOps extends Core { given (given Context): IsInstanceOf[PackageDef] = internal.isInstanceOfPackageDef - given PackageDefOps: (self: PackageDef) { + given PackageDefOps: extension (self: PackageDef) { def owner(given ctx: Context): PackageDef = internal.PackageDef_owner(self) def members(given ctx: Context): List[Statement] = internal.PackageDef_members(self) } @@ -182,7 +182,7 @@ trait TreeOps extends Core { // ----- Terms ---------------------------------------------------- - given TermOps: (self: Term) { + given TermOps: extension (self: Term) { def tpe(given ctx: Context): Type = internal.Term_tpe(self) def underlyingArgument(given ctx: Context): Term = internal.Term_underlyingArgument(self) def underlying(given ctx: Context): Term = internal.Term_underlying(self) @@ -251,7 +251,7 @@ trait TreeOps extends Core { given (given Context): IsInstanceOf[Ident] = internal.isInstanceOfIdent - given IdentOps: (self: Ident) { + given IdentOps: extension (self: Ident) { def name(given ctx: Context): String = internal.Ident_name(self) } @@ -306,7 +306,7 @@ trait TreeOps extends Core { Some((x.qualifier, x.name)) } - given SelectOps: (self: Select) { + given SelectOps: extension (self: Select) { def qualifier(given ctx: Context): Term = internal.Select_qualifier(self) def name(given ctx: Context): String = internal.Select_name(self) def signature(given ctx: Context): Option[Signature] = internal.Select_signature(self) @@ -334,7 +334,7 @@ trait TreeOps extends Core { Some(x.constant) } - given LiteralOps: (self: Literal) { + given LiteralOps: extension (self: Literal) { def constant(given ctx: Context): Constant = internal.Literal_constant(self) } @@ -359,7 +359,7 @@ trait TreeOps extends Core { } - given ThisOps: (self: This) { + given ThisOps: extension (self: This) { def id(given ctx: Context): Option[Id] = internal.This_id(self) } @@ -383,7 +383,7 @@ trait TreeOps extends Core { def unapply(x: New)(given ctx: Context): Option[TypeTree] = Some(x.tpt) } - given NewOps: (self: New) { + given NewOps: extension (self: New) { def tpt(given ctx: Context): TypeTree = internal.New_tpt(self) } @@ -409,7 +409,7 @@ trait TreeOps extends Core { } - given NamedArgOps: (self: NamedArg) { + given NamedArgOps: extension (self: NamedArg) { def name(given ctx: Context): String = internal.NamedArg_name(self) def value(given ctx: Context): Term = internal.NamedArg_value(self) } @@ -435,7 +435,7 @@ trait TreeOps extends Core { Some((x.fun, x.args)) } - given ApplyOps: (self: Apply) { + given ApplyOps: extension (self: Apply) { def fun(given ctx: Context): Term = internal.Apply_fun(self) def args(given ctx: Context): List[Term] = internal.Apply_args(self) } @@ -462,7 +462,7 @@ trait TreeOps extends Core { } - given TypeApplyOps: (self: TypeApply) { + given TypeApplyOps: extension (self: TypeApply) { def fun(given ctx: Context): Term = internal.TypeApply_fun(self) def args(given ctx: Context): List[TypeTree] = internal.TypeApply_args(self) } @@ -488,7 +488,7 @@ trait TreeOps extends Core { Some((x.qualifier, x.id)) } - given SuperOps: (self: Super) { + given SuperOps: extension (self: Super) { def qualifier(given ctx: Context): Term = internal.Super_qualifier(self) def id(given ctx: Context): Option[Id] = internal.Super_id(self) } @@ -515,7 +515,7 @@ trait TreeOps extends Core { } - given TypedOps: (self: Typed) { + given TypedOps: extension (self: Typed) { def expr(given ctx: Context): Term = internal.Typed_expr(self) def tpt(given ctx: Context): TypeTree = internal.Typed_tpt(self) } @@ -541,7 +541,7 @@ trait TreeOps extends Core { Some((x.lhs, x.rhs)) } - given AssignOps: (self: Assign) { + given AssignOps: extension (self: Assign) { def lhs(given ctx: Context): Term = internal.Assign_lhs(self) def rhs(given ctx: Context): Term = internal.Assign_rhs(self) } @@ -567,7 +567,7 @@ trait TreeOps extends Core { Some((x.statements, x.expr)) } - given BlockOps: (self: Block) { + given BlockOps: extension (self: Block) { def statements(given ctx: Context): List[Statement] = internal.Block_statements(self) def expr(given ctx: Context): Term = internal.Block_expr(self) } @@ -590,7 +590,7 @@ trait TreeOps extends Core { Some((x.meth, x.tpeOpt)) } - given ClosureOps: (self: Closure) { + given ClosureOps: extension (self: Closure) { def meth(given ctx: Context): Term = internal.Closure_meth(self) def tpeOpt(given ctx: Context): Option[Type] = internal.Closure_tpeOpt(self) } @@ -639,7 +639,7 @@ trait TreeOps extends Core { } - given IfOps: (self: If) { + given IfOps: extension (self: If) { def cond(given ctx: Context): Term = internal.If_cond(self) def thenp(given ctx: Context): Term = internal.If_thenp(self) def elsep(given ctx: Context): Term = internal.If_elsep(self) @@ -667,7 +667,7 @@ trait TreeOps extends Core { } - given MatchOps: (self: Match) { + given MatchOps: extension (self: Match) { def scrutinee(given ctx: Context): Term = internal.Match_scrutinee(self) def cases(given ctx: Context): List[CaseDef] = internal.Match_cases(self) } @@ -693,7 +693,7 @@ trait TreeOps extends Core { } - given GivenMatchOps: (self: GivenMatch) { + given GivenMatchOps: extension (self: GivenMatch) { def cases(given ctx: Context): List[CaseDef] = internal.GivenMatch_cases(self) } @@ -719,7 +719,7 @@ trait TreeOps extends Core { } - given TryOps: (self: Try) { + given TryOps: extension (self: Try) { def body(given ctx: Context): Term = internal.Try_body(self) def cases(given ctx: Context): List[CaseDef] = internal.Try_cases(self) def finalizer(given ctx: Context): Option[Term] = internal.Try_finalizer(self) @@ -746,7 +746,7 @@ trait TreeOps extends Core { } - given ReturnOps: (self: Return) { + given ReturnOps: extension (self: Return) { def expr(given ctx: Context): Term = internal.Return_expr(self) } @@ -769,7 +769,7 @@ trait TreeOps extends Core { } - given RepeatedOps: (self: Repeated) { + given RepeatedOps: extension (self: Repeated) { def elems(given ctx: Context): List[Term] = internal.Repeated_elems(self) def elemtpt(given ctx: Context): TypeTree = internal.Repeated_elemtpt(self) } @@ -793,7 +793,7 @@ trait TreeOps extends Core { } - given InlinedOps: (self: Inlined) { + given InlinedOps: extension (self: Inlined) { def call(given ctx: Context): Option[Tree /* Term | TypeTree */] = internal.Inlined_call(self) def bindings(given ctx: Context): List[Definition] = internal.Inlined_bindings(self) def body(given ctx: Context): Term = internal.Inlined_body(self) @@ -818,7 +818,7 @@ trait TreeOps extends Core { } - given SelectOuterOps: (self: SelectOuter) { + given SelectOuterOps: extension (self: SelectOuter) { def qualifier(given ctx: Context): Term = internal.SelectOuter_qualifier(self) def level(given ctx: Context): Int = internal.SelectOuter_level(self) } @@ -844,14 +844,14 @@ trait TreeOps extends Core { } - given WhileOps: (self: While) { + given WhileOps: extension (self: While) { def cond(given ctx: Context): Term = internal.While_cond(self) def body(given ctx: Context): Term = internal.While_body(self) } // ----- TypeTrees ------------------------------------------------ - given TypeTreeOps: (self: TypeTree) { + given TypeTreeOps: extension (self: TypeTree) { /** Type of this type tree */ def tpe(given ctx: Context): Type = internal.TypeTree_tpe(self) } @@ -879,7 +879,7 @@ trait TreeOps extends Core { given (given Context): IsInstanceOf[TypeIdent] = internal.isInstanceOfTypeIdent - given TypeIdentOps: (self: TypeIdent) { + given TypeIdentOps: extension (self: TypeIdent) { def name(given ctx: Context): String = internal.TypeIdent_name(self) } @@ -909,7 +909,7 @@ trait TreeOps extends Core { Some((x.qualifier, x.name)) } - given TypeSelectOps: (self: TypeSelect) { + given TypeSelectOps: extension (self: TypeSelect) { def qualifier(given ctx: Context): Term = internal.TypeSelect_qualifier(self) def name(given ctx: Context): String = internal.TypeSelect_name(self) } @@ -928,7 +928,7 @@ trait TreeOps extends Core { Some((x.qualifier, x.name)) } - given ProjectionOps: (self: Projection) { + given ProjectionOps: extension (self: Projection) { def qualifier(given ctx: Context): TypeTree = internal.Projection_qualifier(self) def name(given ctx: Context): String = internal.Projection_name(self) } @@ -949,7 +949,7 @@ trait TreeOps extends Core { Some(x.ref) } - given SingletonOps: (self: Singleton) { + given SingletonOps: extension (self: Singleton) { def ref(given ctx: Context): Term = internal.Singleton_ref(self) } @@ -967,7 +967,7 @@ trait TreeOps extends Core { Some((x.tpt, x.refinements)) } - given RefinedOps: (self: Refined) { + given RefinedOps: extension (self: Refined) { def tpt(given ctx: Context): TypeTree = internal.Refined_tpt(self) def refinements(given ctx: Context): List[Definition] = internal.Refined_refinements(self) } @@ -987,7 +987,7 @@ trait TreeOps extends Core { Some((x.tpt, x.args)) } - given AppliedOps: (self: Applied) { + given AppliedOps: extension (self: Applied) { def tpt(given ctx: Context): TypeTree = internal.Applied_tpt(self) def args(given ctx: Context): List[Tree /*TypeTree | TypeBoundsTree*/] = internal.Applied_args(self) } @@ -1008,7 +1008,7 @@ trait TreeOps extends Core { Some((x.arg, x.annotation)) } - given AnnotatedOps: (self: Annotated) { + given AnnotatedOps: extension (self: Annotated) { def arg(given ctx: Context): TypeTree = internal.Annotated_arg(self) def annotation(given ctx: Context): Term = internal.Annotated_annotation(self) } @@ -1029,7 +1029,7 @@ trait TreeOps extends Core { Some((x.bound, x.selector, x.cases)) } - given MatchTypeTreeOps: (self: MatchTypeTree) { + given MatchTypeTreeOps: extension (self: MatchTypeTree) { def bound(given ctx: Context): Option[TypeTree] = internal.MatchTypeTree_bound(self) def selector(given ctx: Context): TypeTree = internal.MatchTypeTree_selector(self) def cases(given ctx: Context): List[TypeCaseDef] = internal.MatchTypeTree_cases(self) @@ -1051,7 +1051,7 @@ trait TreeOps extends Core { Some(x.result) } - given ByNameOps: (self: ByName) { + given ByNameOps: extension (self: ByName) { def result(given ctx: Context): TypeTree = internal.ByName_result(self) } @@ -1070,7 +1070,7 @@ trait TreeOps extends Core { Some((tree.tparams, tree.body)) } - given LambdaTypeTreeOps: (self: LambdaTypeTree) { + given LambdaTypeTreeOps: extension (self: LambdaTypeTree) { def tparams(given ctx: Context): List[TypeDef] = internal.Lambdatparams(self) def body(given ctx: Context): Tree /*TypeTree | TypeBoundsTree*/ = internal.Lambdabody(self) } @@ -1089,7 +1089,7 @@ trait TreeOps extends Core { Some((x.name, x.body)) } - given TypeBindOps: (self: TypeBind) { + given TypeBindOps: extension (self: TypeBind) { def name(given ctx: Context): String = internal.TypeBind_name(self) def body(given ctx: Context): Tree /*TypeTree | TypeBoundsTree*/ = internal.TypeBind_body(self) } @@ -1109,14 +1109,14 @@ trait TreeOps extends Core { Some((x.aliases, x.tpt)) } - given TypeBlockOps: (self: TypeBlock) { + given TypeBlockOps: extension (self: TypeBlock) { def aliases(given ctx: Context): List[TypeDef] = internal.TypeBlock_aliases(self) def tpt(given ctx: Context): TypeTree = internal.TypeBlock_tpt(self) } // ----- TypeBoundsTrees ------------------------------------------------ - given TypeBoundsTreeOps: (self: TypeBoundsTree) { + given TypeBoundsTreeOps: extension (self: TypeBoundsTree) { def tpe(given ctx: Context): TypeBounds = internal.TypeBoundsTree_tpe(self) def low(given ctx: Context): TypeTree = internal.TypeBoundsTree_low(self) def hi(given ctx: Context): TypeTree = internal.TypeBoundsTree_hi(self) @@ -1133,7 +1133,7 @@ trait TreeOps extends Core { Some((x.low, x.hi)) } - given WildcardTypeTreeOps: (self: WildcardTypeTree) { + given WildcardTypeTreeOps: extension (self: WildcardTypeTree) { def tpe(given ctx: Context): TypeOrBounds = internal.WildcardTypeTree_tpe(self) } @@ -1151,7 +1151,7 @@ trait TreeOps extends Core { // ----- CaseDefs ------------------------------------------------ - given CaseDefOps: (caseDef: CaseDef) { + given CaseDefOps: extension (caseDef: CaseDef) { def pattern(given ctx: Context): Tree = internal.CaseDef_pattern(caseDef) def guard(given ctx: Context): Option[Term] = internal.CaseDef_guard(caseDef) def rhs(given ctx: Context): Term = internal.CaseDef_rhs(caseDef) @@ -1174,7 +1174,7 @@ trait TreeOps extends Core { Some((x.pattern, x.guard, x.rhs)) } - given TypeCaseDefOps: (caseDef: TypeCaseDef) { + given TypeCaseDefOps: extension (caseDef: TypeCaseDef) { def pattern(given ctx: Context): TypeTree = internal.TypeCaseDef_pattern(caseDef) def rhs(given ctx: Context): TypeTree = internal.TypeCaseDef_rhs(caseDef) } @@ -1213,7 +1213,7 @@ trait TreeOps extends Core { Some((pattern.name, pattern.pattern)) } - given BindOps: (bind: Bind) { + given BindOps: extension (bind: Bind) { def name(given ctx: Context): String = internal.Tree_Bind_name(bind) def pattern(given ctx: Context): Tree = internal.Tree_Bind_pattern(bind) } @@ -1232,7 +1232,7 @@ trait TreeOps extends Core { Some((x.fun, x.implicits, x.patterns)) } - given UnapplyOps: (unapply: Unapply) { + given UnapplyOps: extension (unapply: Unapply) { def fun(given ctx: Context): Term = internal.Tree_Unapply_fun(unapply) def implicits(given ctx: Context): List[Term] = internal.Tree_Unapply_implicits(unapply) def patterns(given ctx: Context): List[Tree] = internal.Tree_Unapply_patterns(unapply) @@ -1253,7 +1253,7 @@ trait TreeOps extends Core { Some(x.patterns) } - given AlternativesOps: (alternatives: Alternatives) { + given AlternativesOps: extension (alternatives: Alternatives) { def patterns(given ctx: Context): List[Tree] = internal.Tree_Alternatives_patterns(alternatives) } diff --git a/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala b/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala index d05575a83fcc..bcaf2d747dcf 100644 --- a/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala +++ b/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala @@ -7,7 +7,7 @@ trait TypeOrBoundsOps extends Core { def typeOf[T: scala.quoted.Type]: Type - given TypeOps: (self: Type) { + given TypeOps: extension (self: Type) { /** Is `self` type the same as `that` type? * This is the case iff `self <:< that` and `that <:< self`. @@ -92,7 +92,7 @@ trait TypeOrBoundsOps extends Core { def unapply(x: ConstantType)(given ctx: Context): Option[Constant] = Some(x.constant) } - given ConstantTypeOps: (self: ConstantType) { + given ConstantTypeOps: extension (self: ConstantType) { def constant(given ctx: Context): Constant = internal.ConstantType_constant(self) } @@ -109,7 +109,7 @@ trait TypeOrBoundsOps extends Core { Some((x.qualifier, x.name)) } - given TermRefOps: (self: TermRef) { + given TermRefOps: extension (self: TermRef) { def qualifier(given ctx: Context): TypeOrBounds /* Type | NoPrefix */ = internal.TermRef_qualifier(self) def name(given ctx: Context): String = internal.TermRef_name(self) } @@ -125,7 +125,7 @@ trait TypeOrBoundsOps extends Core { Some((x.qualifier, x.name)) } - given TypeRefOps: (self: TypeRef) { + given TypeRefOps: extension (self: TypeRef) { def qualifier(given ctx: Context): TypeOrBounds /* Type | NoPrefix */ = internal.TypeRef_qualifier(self) def name(given ctx: Context): String = internal.TypeRef_name(self) } @@ -141,7 +141,7 @@ trait TypeOrBoundsOps extends Core { Some((x.thistpe, x.supertpe)) } - given SuperTypeOps: (self: SuperType) { + given SuperTypeOps: extension (self: SuperType) { def thistpe(given ctx: Context): Type = internal.SuperType_thistpe(self) def supertpe(given ctx: Context): Type = internal.SuperType_supertpe(self) } @@ -157,7 +157,7 @@ trait TypeOrBoundsOps extends Core { Some((x.parent, x.name, x.info)) } - given RefinementOps: (self: Refinement) { + given RefinementOps: extension (self: Refinement) { def parent(given ctx: Context): Type = internal.Refinement_parent(self) def name(given ctx: Context): String = internal.Refinement_name(self) def info(given ctx: Context): TypeOrBounds = internal.Refinement_info(self) @@ -176,7 +176,7 @@ trait TypeOrBoundsOps extends Core { Some((x.tycon, x.args)) } - given AppliedTypeOps: (self: AppliedType) { + given AppliedTypeOps: extension (self: AppliedType) { def tycon(given ctx: Context): Type = internal.AppliedType_tycon(self) def args(given ctx: Context): List[TypeOrBounds /* Type | TypeBounds */] = internal.AppliedType_args(self) } @@ -192,7 +192,7 @@ trait TypeOrBoundsOps extends Core { Some((x.underlying, x.annot)) } - given AnnotatedTypeOps: (self: AnnotatedType) { + given AnnotatedTypeOps: extension (self: AnnotatedType) { def underlying(given ctx: Context): Type = internal.AnnotatedType_underlying(self) def annot(given ctx: Context): Term = internal.AnnotatedType_annot(self) } @@ -208,7 +208,7 @@ trait TypeOrBoundsOps extends Core { Some((x.left, x.right)) } - given AndTypeOps: (self: AndType) { + given AndTypeOps: extension (self: AndType) { def left(given ctx: Context): Type = internal.AndType_left(self) def right(given ctx: Context): Type = internal.AndType_right(self) } @@ -224,7 +224,7 @@ trait TypeOrBoundsOps extends Core { Some((x.left, x.right)) } - given OrTypeOps: (self: OrType) { + given OrTypeOps: extension (self: OrType) { def left(given ctx: Context): Type = internal.OrType_left(self) def right(given ctx: Context): Type = internal.OrType_right(self) } @@ -240,7 +240,7 @@ trait TypeOrBoundsOps extends Core { Some((x.bound, x.scrutinee, x.cases)) } - given MatchTypeOps: (self: MatchType) { + given MatchTypeOps: extension (self: MatchType) { def bound(given ctx: Context): Type = internal.MatchType_bound(self) def scrutinee(given ctx: Context): Type = internal.MatchType_scrutinee(self) def cases(given ctx: Context): List[Type] = internal.MatchType_cases(self) @@ -256,7 +256,7 @@ trait TypeOrBoundsOps extends Core { def unapply(x: ByNameType)(given ctx: Context): Option[Type] = Some(x.underlying) } - given ByNameTypeOps: (self: ByNameType) { + given ByNameTypeOps: extension (self: ByNameType) { def underlying(given ctx: Context): Type = internal.ByNameType_underlying(self) } @@ -271,7 +271,7 @@ trait TypeOrBoundsOps extends Core { Some((x.binder, x.paramNum)) } - given ParamRefOps: (self: ParamRef) { + given ParamRefOps: extension (self: ParamRef) { def binder(given ctx: Context): LambdaType[TypeOrBounds] = internal.ParamRef_binder(self) def paramNum(given ctx: Context): Int = internal.ParamRef_paramNum(self) } @@ -286,7 +286,7 @@ trait TypeOrBoundsOps extends Core { def unapply(x: ThisType)(given ctx: Context): Option[Type] = Some(x.tref) } - given ThisTypeOps: (self: ThisType) { + given ThisTypeOps: extension (self: ThisType) { def tref(given ctx: Context): Type = internal.ThisType_tref(self) } @@ -300,7 +300,7 @@ trait TypeOrBoundsOps extends Core { def unapply(x: RecursiveThis)(given ctx: Context): Option[RecursiveType] = Some(x.binder) } - given RecursiveThisOps: (self: RecursiveThis) { + given RecursiveThisOps: extension (self: RecursiveThis) { def binder(given ctx: Context): RecursiveType = internal.RecursiveThis_binder(self) } @@ -314,7 +314,7 @@ trait TypeOrBoundsOps extends Core { def unapply(x: RecursiveType)(given ctx: Context): Option[Type] = Some(x.underlying) } - given RecursiveTypeOps: (self: RecursiveType) { + given RecursiveTypeOps: extension (self: RecursiveType) { def underlying(given ctx: Context): Type = internal.RecursiveType_underlying(self) } @@ -329,7 +329,7 @@ trait TypeOrBoundsOps extends Core { Some((x.paramNames, x.paramTypes, x.resType)) } - given MethodTypeOps: (self: MethodType) { + given MethodTypeOps: extension (self: MethodType) { def isImplicit: Boolean = internal.MethodType_isImplicit(self) def isErased: Boolean = internal.MethodType_isErased(self) def paramNames(given ctx: Context): List[String] = internal.MethodType_paramNames(self) @@ -348,7 +348,7 @@ trait TypeOrBoundsOps extends Core { Some((x.paramNames, x.paramBounds, x.resType)) } - given PolyTypeOps: (self: PolyType) { + given PolyTypeOps: extension (self: PolyType) { def paramNames(given ctx: Context): List[String] = internal.PolyType_paramNames(self) def paramBounds(given ctx: Context): List[TypeBounds] = internal.PolyType_paramBounds(self) def resType(given ctx: Context): Type = internal.PolyType_resType(self) @@ -365,7 +365,7 @@ trait TypeOrBoundsOps extends Core { Some((x.paramNames, x.paramBounds, x.resType)) } - given TypeLambdaOps: (self: TypeLambda) { + given TypeLambdaOps: extension (self: TypeLambda) { def paramNames(given ctx: Context): List[String] = internal.TypeLambda_paramNames(self) def paramBounds(given ctx: Context): List[TypeBounds] = internal.TypeLambda_paramBounds(self) def resType(given ctx: Context): Type = internal.TypeLambda_resType(self) @@ -383,7 +383,7 @@ trait TypeOrBoundsOps extends Core { def unapply(x: TypeBounds)(given ctx: Context): Option[(Type, Type)] = Some((x.low, x.hi)) } - given TypeBoundsOps: (self: TypeBounds) { + given TypeBoundsOps: extension (self: TypeBounds) { def low(given ctx: Context): Type = internal.TypeBounds_low(self) def hi(given ctx: Context): Type = internal.TypeBounds_hi(self) } diff --git a/tests/neg/extension-methods.scala b/tests/neg/extension-methods.scala index dc613cfdede2..4eefd041f624 100644 --- a/tests/neg/extension-methods.scala +++ b/tests/neg/extension-methods.scala @@ -10,7 +10,7 @@ object Test { "".l2 // error 1.l1 // error - given extension [T](xs: List[T]) { + given [T](xs: List[T]) extended with { def (x: Int) f1: T = ??? // error: No extension method allowed here, since collective parameters are given def f2[T]: T = ??? // error: T is already defined as type T def f3(xs: List[T]) = ??? // error: xs is already defined as value xs diff --git a/tests/neg/extmethod-overload.scala b/tests/neg/extmethod-overload.scala index 1471c165d3c1..ecf6afc73402 100644 --- a/tests/neg/extmethod-overload.scala +++ b/tests/neg/extmethod-overload.scala @@ -1,14 +1,14 @@ object Test { - given A: { - def (x: Int) |+| (y: Int) = x + y - } - given B: { - def (x: Int) |+| (y: String) = x + y.length + given a: (x: Int) extended with + def |+| (y: Int) = x + y + + given b: (x: Int) extended with { + def |+| (y: String) = x + y.length } assert((1 |+| 2) == 3) // error ambiguous locally { - import B.|+| + import b.|+| assert((1 |+| "2") == 2) // OK } } \ No newline at end of file diff --git a/tests/neg/i5455.scala b/tests/neg/i5455.scala index dfccfdc6aaf5..c73da95e2062 100644 --- a/tests/neg/i5455.scala +++ b/tests/neg/i5455.scala @@ -11,7 +11,7 @@ object Library { def toInt(n: Nat): Int = n } - given extension (x: Nat) + given (x: Nat) extended with def * (y: Nat): Nat = x * y def toInt: Int = x } diff --git a/tests/neg/i6801.scala b/tests/neg/i6801.scala index 06f922fd4603..94e417e7719c 100644 --- a/tests/neg/i6801.scala +++ b/tests/neg/i6801.scala @@ -1,5 +1,5 @@ -given MyNumericOps[T]: { - def (x: T) +(y: T)(given n: Numeric[T]): T = n.plus(x,y) +given myNumericOps: [T](x: T) extended with { + def + (y: T)(given n: Numeric[T]): T = n.plus(x,y) } def foo[T: Numeric](x: T) = 1f + x // error: no implicit argument of type Numeric[Any] def bar[T: Numeric](x: T) = x + 1f // error: no implicit argument of type Numeric[Any] \ No newline at end of file diff --git a/tests/neg/i6900.scala b/tests/neg/i6900.scala new file mode 100644 index 000000000000..7e696e320828 --- /dev/null +++ b/tests/neg/i6900.scala @@ -0,0 +1,15 @@ +object Test2 { + + // Works with extension method + given [A](a: A) extended with + def foo[C]: C => A = _ => a // error: extension method cannot have type parameters + + 1.foo.foo + + // ... but have to pass 2 parameters + 1.foo.foo[Any => Int, String] + 1.foo[Int, String].foo + 1.foo[Int, String].foo[String => Int, String] + +} + diff --git a/tests/neg/i7529.scala b/tests/neg/i7529.scala index efdaca97c40b..974d59b268b0 100644 --- a/tests/neg/i7529.scala +++ b/tests/neg/i7529.scala @@ -1,4 +1,4 @@ -given fooOps: [A](a: A) with +given fooOps: [A](a: A) extended with @nonsense // error: not found: nonsense def foo = ??? \ No newline at end of file diff --git a/tests/neg/new-with.scala b/tests/neg/new-with.scala new file mode 100644 index 000000000000..a4a18e2406d5 --- /dev/null +++ b/tests/neg/new-with.scala @@ -0,0 +1 @@ +val x = new with { } // error \ No newline at end of file diff --git a/tests/pos/i6900.scala b/tests/pos/i6900.scala index 63e01e3550ed..3c3b23c11b9f 100644 --- a/tests/pos/i6900.scala +++ b/tests/pos/i6900.scala @@ -1,8 +1,35 @@ -object Test { - given bla[A]: { def [C](a: A) foo: C => A = _ => a } +object Test1 { + trait Foo[A] with + def foo[C]: C => A + + // Works with old-style conversion + implicit def i2f[A](a: A): Foo[A] = new Foo[A] with + def foo[C]: C => A = _ => a + + // But not with newstyle + /* + given [A]: Conversion[A, Foo[A]] with + def apply(a: A) = new Foo[A] with + def foo[C]: C => A = _ => a + */ 1.foo.foo 1.foo.foo[String] 1.foo[String].foo 1.foo[String].foo[String] } +object Test2 { + + // Works with extension method + given [A, C](a: A) extended with + def foo: C => A = _ => a + + 1.foo.foo + + // ... but have to pass 2 parameters + 1.foo.foo[Any => Int, String] + 1.foo[Int, String].foo + 1.foo[Int, String].foo[String => Int, String] + +} + diff --git a/tests/pos/i7084.scala b/tests/pos/i7084.scala index 044ea8e06ec3..b76042ee431c 100644 --- a/tests/pos/i7084.scala +++ b/tests/pos/i7084.scala @@ -2,8 +2,8 @@ object Test { type Foo - given { - def (y: Any) g(given Foo): Any = ??? + given (y: Any) extended with { + def g(given Foo): Any = ??? } def f(x: Any)(given Foo): Any = { diff --git a/tests/pos/i7087.scala b/tests/pos/i7087.scala index 03e939ef7efd..c6340d61730f 100644 --- a/tests/pos/i7087.scala +++ b/tests/pos/i7087.scala @@ -6,8 +6,8 @@ type F[T] = T match { case G[a] => String } -given { - def [T](tup: T) g (given Foo: F[T]) = ??? +given [T](tup: T) extended with { + def g(given Foo: F[T]) = ??? } def f(x: G[Int])(given Foo: String) = x.g \ No newline at end of file diff --git a/tests/pos/implicit-scope.scala b/tests/pos/implicit-scope.scala index 219daa1d62df..813b6b42775f 100644 --- a/tests/pos/implicit-scope.scala +++ b/tests/pos/implicit-scope.scala @@ -9,9 +9,9 @@ object A { type FlagSet = opaques.FlagSet def FlagSet(bits: Long): FlagSet = opaques.FlagSet(bits) - given { - def (xs: FlagSet) bits: Long = opaques.toBits(xs) - def (xs: FlagSet) | (ys: FlagSet): FlagSet = FlagSet(xs.bits | ys.bits) + given (xs: FlagSet) extended with { + def bits: Long = opaques.toBits(xs) + def | (ys: FlagSet): FlagSet = FlagSet(xs.bits | ys.bits) } } diff --git a/tests/pos/matrixOps.scala b/tests/pos/matrixOps.scala index c7d800c65a0a..067d23830877 100644 --- a/tests/pos/matrixOps.scala +++ b/tests/pos/matrixOps.scala @@ -3,7 +3,7 @@ object Test with type Matrix = Array[Array[Double]] type Vector = Array[Double] - given extension (m: Matrix) + given (m: Matrix) extended with def nRows = m.length def nCols = m(0).length def row(i: Int): Vector = m(i) diff --git a/tests/pos/mirror-implicit-scope.scala b/tests/pos/mirror-implicit-scope.scala index c06a6d21d604..a4c2dbcd7b3a 100644 --- a/tests/pos/mirror-implicit-scope.scala +++ b/tests/pos/mirror-implicit-scope.scala @@ -3,15 +3,15 @@ import scala.deriving._ object Test { object K0 { type Generic[T] = Mirror { type Scope = K0.type ; type MirroredType = T ; type MirroredElemTypes } - given { - inline def [T <: Product](gen: Generic[T]) toRepr (t: T): gen.MirroredElemTypes = Tuple.fromProduct(t).asInstanceOf + given [T <: Product](gen: Generic[T]) extended with { + inline def toRepr (t: T): gen.MirroredElemTypes = Tuple.fromProduct(t).asInstanceOf } } object K1 { type Generic[F[_]] = Mirror { type Scope = K1.type ; type MirroredType = F ; type MirroredElemTypes[_] } - given { - inline def [F[_] <: Product, T](gen: Generic[F]) toRepr (t: F[T]): gen.MirroredElemTypes[T] = Tuple.fromProduct(t).asInstanceOf + given [F[_] <: Product, T](gen: Generic[F]) extended with { + inline def toRepr (t: F[T]): gen.MirroredElemTypes[T] = Tuple.fromProduct(t).asInstanceOf } } diff --git a/tests/pos/multi-given.scala b/tests/pos/multi-given.scala index b3d8e59626c1..97092fc7ae00 100644 --- a/tests/pos/multi-given.scala +++ b/tests/pos/multi-given.scala @@ -5,4 +5,6 @@ trait C def fancy(given a: A, b: B, c: C) = "Fancy!" def foo(implicit a: A, b: B, c: C) = "foo" -given A, B {} \ No newline at end of file +given A, B {} + +given ops: A with B {} \ No newline at end of file diff --git a/tests/pos/reference/delegates.scala b/tests/pos/reference/delegates.scala index 2c398e4d3e66..6b9702375e9c 100644 --- a/tests/pos/reference/delegates.scala +++ b/tests/pos/reference/delegates.scala @@ -39,12 +39,12 @@ object Instances extends Common with if (fst != 0) fst else xs1.compareTo(ys1) end listOrd - given stringOps: (xs: Seq[String]) + given stringOps: (xs: Seq[String]) extended with def longestStrings: Seq[String] = val maxLength = xs.map(_.length).max xs.filter(_.length == maxLength) - given extension [T](xs: List[T]) + given [T](xs: List[T]) extended with def second = xs.tail.head def third = xs.tail.tail.head @@ -133,7 +133,7 @@ object PostConditions with def result[T](given x: WrappedResult[T]): T = x - given extension [T](x: T) + given [T](x: T) extended with def ensuring(condition: (given WrappedResult[T]) => Boolean): T = assert(condition(given x)) x @@ -153,12 +153,12 @@ object AnonymousInstances extends Common with val fst = x.compareTo(y) if (fst != 0) fst else xs1.compareTo(ys1) - given extension (xs: Seq[String]) + given (xs: Seq[String]) extended with def longestStrings: Seq[String] = val maxLength = xs.map(_.length).max xs.filter(_.length == maxLength) - given extension [T](xs: List[T]) + given [T](xs: List[T]) extended with def second = xs.tail.head given [From, To](given c: Convertible[From, To]) : Convertible[List[From], List[To]] with diff --git a/tests/pos/reference/extension-methods.scala b/tests/pos/reference/extension-methods.scala index 343ae7149128..d8e3d566a615 100644 --- a/tests/pos/reference/extension-methods.scala +++ b/tests/pos/reference/extension-methods.scala @@ -41,19 +41,19 @@ object ExtMethods with List(1, 2, 3).second[Int] - given stringOps: extension (xs: Seq[String]) { + given stringOps: (xs: Seq[String]) extended with { def longestStrings: Seq[String] = { val maxLength = xs.map(_.length).max xs.filter(_.length == maxLength) } } - given listOps: extension [T](xs: List[T]) with + given listOps: [T](xs: List[T]) extended with def second = xs.tail.head def third: T = xs.tail.tail.head - given extension [T](xs: List[T])(given Ordering[T]) with + given [T](xs: List[T])(given Ordering[T]) extended with def largest(n: Int) = xs.sorted.takeRight(n) given stringOps1: AnyRef { diff --git a/tests/pos/reference/opaque.scala b/tests/pos/reference/opaque.scala index 86b1eb7d04ae..617fbbe17b2d 100644 --- a/tests/pos/reference/opaque.scala +++ b/tests/pos/reference/opaque.scala @@ -12,10 +12,10 @@ object Logarithms { } // Extension methods define opaque types' public APIs - given { - def (x: Logarithm) toDouble: Double = math.exp(x) - def (x: Logarithm) + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y)) - def (x: Logarithm) * (y: Logarithm): Logarithm = Logarithm(x + y) + given (x: Logarithm) extended with { + def toDouble: Double = math.exp(x) + def + (y: Logarithm): Logarithm = Logarithm(math.exp(x) + math.exp(y)) + def * (y: Logarithm): Logarithm = Logarithm(x + y) } } diff --git a/tests/pos/tasty-reflect-opaque-api-proto.scala b/tests/pos/tasty-reflect-opaque-api-proto.scala index a07bd8528273..089e3c28437d 100644 --- a/tests/pos/tasty-reflect-opaque-api-proto.scala +++ b/tests/pos/tasty-reflect-opaque-api-proto.scala @@ -10,7 +10,7 @@ class Reflect(val internal: CompilerInterface) { opaque type Term <: Tree = internal.Term object Tree { - given Ops: (tree: Tree) { + given ops: (tree: Tree) extended with { def show: String = ??? } } diff --git a/tests/run/extension-specificity.scala b/tests/run/extension-specificity.scala index dce5942b5682..35ac40ff1e3a 100644 --- a/tests/run/extension-specificity.scala +++ b/tests/run/extension-specificity.scala @@ -1,10 +1,10 @@ class A class B extends A -given a: extension (x: A) with +given a: (x: A) extended with def foo: Int = 1 -given b: extension (x: B) with +given b: (x: B) extended with def foo: Int = 2 @main def Test = diff --git a/tests/run/extmethod-overload.scala b/tests/run/extmethod-overload.scala index dd0fe7352eb7..fe80ccebf54a 100644 --- a/tests/run/extmethod-overload.scala +++ b/tests/run/extmethod-overload.scala @@ -22,7 +22,7 @@ object Test extends App { // Test with extension methods in given object object test1 { - given Foo: { + given Foo: AnyRef { def (x: Int) |+| (y: Int) = x + y def (x: Int) |+| (y: String) = x + y.length @@ -97,8 +97,8 @@ object Test extends App { def (x: Int) yy (y: Int) = x + y } - given { - def (x: Int) yy (y: Int) = x - y + given (x: Int) extended with { + def yy (y: Int) = x - y } import D._ diff --git a/tests/run/extmethods2.scala b/tests/run/extmethods2.scala index 70cb2e108476..4264b7d8b1eb 100644 --- a/tests/run/extmethods2.scala +++ b/tests/run/extmethods2.scala @@ -2,7 +2,7 @@ object Test extends App { class TC - given stringListOps(given TC): { + given stringListOps(given TC): Object { type T = List[String] def (x: T) foo (y: T) = (x ++ y, summon[TC]) def (x: T) bar (y: Int) = (x(0)(y), summon[TC]) @@ -16,13 +16,15 @@ object Test extends App { test(given TC()) object A { - given listOps: [T](xs: List[T]) { + given listOps: [T](xs: List[T]) extended with { def second: T = xs.tail.head def third: T = xs.tail.tail.head def concat(ys: List[T]) = xs ++ ys - def zipp[U](ys: List[U]): List[(T, U)] = xs.zip(ys) } - given extension (xs: List[Int]) { + given polyListOps: [T, U](xs: List[T]) extended with { + def zipp(ys: List[U]): List[(T, U)] = xs.zip(ys) + } + given (xs: List[Int]) extended with { def prod = (1 /: xs)(_ * _) } } diff --git a/tests/run/i6902.scala b/tests/run/i6902.scala index 5996a36a09a0..e3a40dd02f1e 100644 --- a/tests/run/i6902.scala +++ b/tests/run/i6902.scala @@ -1,6 +1,6 @@ object Test { - given [A]: { def (a: A) <<< : A = a } - given { def (b: Int) <<<< : Int = b } + given [A](a: A) extended with { def <<< : A = a } + given (b: Int) extended with { def <<<< : Int = b } def main(args: Array[String]): Unit = { 1.<<< diff --git a/tests/run/instances-anonymous.scala b/tests/run/instances-anonymous.scala index 4e7d375df890..4d4774e98bf1 100644 --- a/tests/run/instances-anonymous.scala +++ b/tests/run/instances-anonymous.scala @@ -8,15 +8,15 @@ object Test extends App { case class Circle(x: Double, y: Double, radius: Double) - given { - def (c: Circle) circumference: Double = c.radius * math.Pi * 2 + given (c: Circle) extended with { + def circumference: Double = c.radius * math.Pi * 2 } val circle = new Circle(1, 1, 2.0) println(circle.circumference) - given { + given AnyRef { def (xs: Seq[String]) longestStrings: Seq[String] = { val maxLength = xs.map(_.length).max xs.filter(_.length == maxLength) @@ -25,14 +25,14 @@ object Test extends App { val names = List("hi", "hello", "world") assert(names.longestStrings == List("hello", "world")) - given { - def [T](xs: Seq[T]) second = xs.tail.head + given [T](xs: Seq[T]) extended with { + def second = xs.tail.head } assert(names.longestStrings.second == "world") - given { - def [T](xs: List[List[T]]) flattened = xs.foldLeft[List[T]](Nil)(_ ++ _) + given [T](xs: List[List[T]]) extended with { + def flattened = xs.foldLeft[List[T]](Nil)(_ ++ _) } assert(List(names, List("!")).flattened == names :+ "!") diff --git a/tests/run/instances.scala b/tests/run/instances.scala index aeb85d01d624..0778d8a4fed5 100644 --- a/tests/run/instances.scala +++ b/tests/run/instances.scala @@ -8,14 +8,14 @@ object Test extends App { case class Circle(x: Double, y: Double, radius: Double) - given circleOps: extension (c: Circle) with + given circleOps: (c: Circle) extended with def circumference: Double = c.radius * math.Pi * 2 val circle = new Circle(1, 1, 2.0) assert(circle.circumference == circleOps.circumference(circle)) - given stringOps: extension (xs: Seq[String]) with + given stringOps: (xs: Seq[String]) extended with def longestStrings: Seq[String] = val maxLength = xs.map(_.length).max xs.filter(_.length == maxLength) @@ -23,16 +23,16 @@ object Test extends App { val names = List("hi", "hello", "world") assert(names.longestStrings == List("hello", "world")) - given extension [T](xs: Seq[T]) with + given [T](xs: Seq[T]) extended with def second = xs.tail.head assert(names.longestStrings.second == "world") - given listListOps: extension [T](xs: List[List[T]]) with + given listListOps: [T](xs: List[List[T]]) extended with def flattened = xs.foldLeft[List[T]](Nil)(_ ++ _) // A right associative op. Note: can't use given extension for this! - given prepend: { + given prepend: AnyRef { def [T](x: T) :: (xs: Seq[T]) = x +: xs }