From 14acdc06067a202f381fa9066a961cebb1314d6a Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 28 Sep 2024 14:58:05 +0200 Subject: [PATCH 1/9] Implement SIP 64 as non-experimental --- .../src/dotty/tools/dotc/ast/Desugar.scala | 2 +- compiler/src/dotty/tools/dotc/ast/untpd.scala | 1 - .../dotty/tools/dotc/parsing/Parsers.scala | 20 ++++++-------- .../tools/dotc/printing/RefinedPrinter.scala | 4 ++- docs/_docs/internals/syntax.md | 10 +++++-- docs/_docs/reference/syntax.md | 27 +++++++++++++++---- library/src/scala/compiletime/package.scala | 1 - .../AutoImplementAbstractMembersSuite.scala | 4 ++- tests/neg/empty-given.scala | 4 +-- tests/neg/i12348.check | 6 ++--- .../stdlibExperimentalDefinitions.scala | 1 - tests/warn/abstract-givens-new.check | 6 +---- tests/warn/abstract-givens-new.scala | 3 ++- 13 files changed, 53 insertions(+), 36 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 5c468721fd43..e1a6b97fc7d3 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1261,7 +1261,7 @@ object desugar { str.toTermName.asSimpleName /** Extract a synthesized given name from a type tree. This is used for - * both anonymous givens and (under x.modularity) deferred givens. + * both anonymous givens and deferred givens. * @param followArgs if true include argument types in the name */ private class NameExtractor(followArgs: Boolean) extends UntypedTreeAccumulator[String] { diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 60309d4d83bd..935e42d5e05c 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -119,7 +119,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @constructorOnly src: SourceFile) extends DefTree case class ExtMethods(paramss: List[ParamClause], methods: List[Tree])(implicit @constructorOnly src: SourceFile) extends Tree case class ContextBoundTypeTree(tycon: Tree, paramName: TypeName, ownName: TermName)(implicit @constructorOnly src: SourceFile) extends Tree - // `paramName: tycon as ownName`, ownName != EmptyTermName only under x.modularity case class MacroTree(expr: Tree)(implicit @constructorOnly src: SourceFile) extends Tree case class ImportSelector(imported: Ident, renamed: Tree = EmptyTree, bound: Tree = EmptyTree)(implicit @constructorOnly src: SourceFile) extends Tree { diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 8a173faa3cec..5af9b105a5c1 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -994,8 +994,8 @@ object Parsers { skipParams() lookahead.isColon && { - !in.featureEnabled(Feature.modularity) - || { // with modularity language import, a `:` at EOL after an identifier represents a single identifier given + !sourceVersion.isAtLeast(`3.6`) + || { // in the new given syntax, a `:` at EOL after an identifier represents a single identifier given // Example: // given C: // def f = ... @@ -1833,7 +1833,7 @@ object Parsers { infixOps(t, canStartInfixTypeTokens, operand, Location.ElseWhere, ParseKind.Type, isOperator = !followingIsVararg() && !isPureArrow - && !(isIdent(nme.as) && in.featureEnabled(Feature.modularity)) + && !(isIdent(nme.as) && sourceVersion.isAtLeast(`3.6`)) && nextCanFollowOperator(canStartInfixTypeTokens)) /** RefinedType ::= WithType {[nl] Refinement} [`^` CaptureSet] @@ -2226,18 +2226,19 @@ object Parsers { def contextBound(pname: TypeName): Tree = val t = toplevelTyp() val ownName = - if isIdent(nme.as) && in.featureEnabled(Feature.modularity) then + if isIdent(nme.as) && sourceVersion.isAtLeast(`3.6`) then in.nextToken() ident() else EmptyTermName ContextBoundTypeTree(t, pname, ownName) - /** ContextBounds ::= ContextBound | `{` ContextBound {`,` ContextBound} `}` + /** ContextBounds ::= ContextBound [`:` ContextBounds] + * | `{` ContextBound {`,` ContextBound} `}` */ def contextBounds(pname: TypeName): List[Tree] = if in.isColon then in.nextToken() - if in.token == LBRACE && in.featureEnabled(Feature.modularity) + if in.token == LBRACE && sourceVersion.isAtLeast(`3.6`) then inBraces(commaSeparated(() => contextBound(pname))) else contextBound(pname) :: contextBounds(pname) else if in.token == VIEWBOUND then @@ -4189,7 +4190,7 @@ object Parsers { def givenDef(start: Offset, mods: Modifiers, givenMod: Mod) = atSpan(start, nameStart) { var mods1 = addMod(mods, givenMod) val nameStart = in.offset - var newSyntaxAllowed = in.featureEnabled(Feature.modularity) + var newSyntaxAllowed = sourceVersion.isAtLeast(`3.6`) val hasEmbeddedColon = !in.isColon && followingIsGivenDefWithColon() val name = if isIdent && hasEmbeddedColon then ident() else EmptyTermName @@ -4293,11 +4294,6 @@ object Parsers { // old-style abstract given if name.isEmpty then syntaxError(em"Anonymous given cannot be abstract, or maybe you want to define a concrete given and are missing a `()` argument?", in.lastOffset) - if newSyntaxAllowed then - warning( - em"""This defines an abstract given, which is deprecated. Use a `deferred` given instead. - |Or, if you intend to define a concrete given, follow the type with `()` arguments.""", - in.lastOffset) DefDef(name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree) else // structural instance diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index ea729e9549d5..b229c7ec29d9 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -24,6 +24,8 @@ import TypeApplications.* import NameKinds.{WildcardParamName, DefaultGetterName} import util.Chars.isOperatorPart import config.{Config, Feature} +import config.Feature.sourceVersion +import config.SourceVersion.* import dotty.tools.dotc.util.SourcePosition import dotty.tools.dotc.ast.untpd.{MemberDef, Modifiers, PackageDef, RefTree, Template, TypeDef, ValOrDefDef} @@ -751,7 +753,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case GenAlias(pat, expr) => toText(pat) ~ " = " ~ toText(expr) case ContextBounds(bounds, cxBounds) => - if Feature.enabled(Feature.modularity) then + if sourceVersion.isAtLeast(`3.6`) then def boundsText(bounds: Tree) = bounds match case ContextBoundTypeTree(tpt, _, ownName) => toText(tpt) ~ (" as " ~ toText(ownName) `provided` !ownName.isEmpty) diff --git a/docs/_docs/internals/syntax.md b/docs/_docs/internals/syntax.md index f82e9c998b4d..0cde7bc127aa 100644 --- a/docs/_docs/internals/syntax.md +++ b/docs/_docs/internals/syntax.md @@ -223,7 +223,9 @@ TypeArgs ::= ‘[’ Types ‘]’ Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>> ds TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi) TypeAndCtxBounds ::= TypeBounds [‘:’ ContextBounds] ContextBounds(typeBounds, tps) -ContextBounds ::= ContextBound | '{' ContextBound {',' ContextBound} '}' +ContextBounds ::= ContextBound + | ContextBound `:` ContextBounds -- to be deprecated + | '{' ContextBound {',' ContextBound} '}' ContextBound ::= Type ['as' id] Types ::= Type {‘,’ Type} NamesAndTypes ::= NameAndType {‘,’ NameAndType} @@ -464,7 +466,7 @@ TypeDef ::= id [HkTypeParamClause] {FunParamClause} TypeAndCtxBounds TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef | [‘case’] ‘object’ ObjectDef | ‘enum’ EnumDef - | ‘given’ GivenDef + | ‘given’ (GivenDef | OldGivenDef) ClassDef ::= id ClassConstr [Template] ClassDef(mods, name, tparams, templ) ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, , Nil, vparamss, EmptyTree, EmptyTree) as first stat ConstrMods ::= {Annotation} [AccessModifier] @@ -483,6 +485,10 @@ GivenConditional ::= DefTypeParamClause | GivenType GivenType ::= AnnotType1 {id [nl] AnnotType1} +OldGivenDef ::= [OldGivenSig] (AnnotType [‘=’ Expr] | StructuralInstance) -- syntax up to Scala 3.5, to be deprecated in the future +OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present +StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody] + Extension ::= ‘extension’ [DefTypeParamClause] {UsingParamClause} ‘(’ DefTermParam ‘)’ {UsingParamClause} ExtMethods ExtMethods ::= ExtMethod | [nl] <<< ExtMethod {semi ExtMethod} >>> diff --git a/docs/_docs/reference/syntax.md b/docs/_docs/reference/syntax.md index 5d984c762a89..adf25c9342fa 100644 --- a/docs/_docs/reference/syntax.md +++ b/docs/_docs/reference/syntax.md @@ -214,7 +214,11 @@ ParamValueType ::= Type [‘*’] TypeArgs ::= ‘[’ Types ‘]’ Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>> TypeBounds ::= [‘>:’ Type] [‘<:’ Type] -TypeAndCtxBounds ::= TypeBounds {‘:’ Type} +TypeAndCtxBounds ::= TypeBounds [‘:’ ContextBounds] +ContextBounds ::= ContextBound + | ContextBound `:` ContextBounds -- to be deprecated + | '{' ContextBound {',' ContextBound} '}' +ContextBound ::= Type ['as' id] Types ::= Type {‘,’ Type} ``` @@ -437,16 +441,29 @@ TypeDef ::= id [HkTypeParamClause] {FunParamClause}TypeBounds TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef | [‘case’] ‘object’ ObjectDef | ‘enum’ EnumDef - | ‘given’ GivenDef + | ‘given’ (GivenDef | OldGivenDef) ClassDef ::= id ClassConstr [Template] ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses ConstrMods ::= {Annotation} [AccessModifier] ObjectDef ::= id [Template] EnumDef ::= id ClassConstr InheritClauses EnumBody -GivenDef ::= [GivenSig] (AnnotType [‘=’ Expr] | StructuralInstance) -GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present -GivenType ::= AnnotType {id [nl] AnnotType} + +GivenDef ::= [id ':'] GivenSig +GivenSig ::= GivenImpl + | '(' ')' '=>' GivenImpl + | GivenConditional '=>' GivenSig +GivenImpl ::= GivenType ([‘=’ Expr] | TemplateBody) + | ConstrApps TemplateBody +GivenConditional ::= DefTypeParamClause + | DefTermParamClause + | '(' FunArgTypes ')' + | GivenType +GivenType ::= AnnotType1 {id [nl] AnnotType1} + +OldGivenDef ::= [OldGivenSig] (AnnotType [‘=’ Expr] | StructuralInstance) -- syntax up to Scala 3.5, to be deprecated in the future +OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody] + Extension ::= ‘extension’ [DefTypeParamClause] {UsingParamClause} ‘(’ DefTermParam ‘)’ {UsingParamClause} ExtMethods ExtMethods ::= ExtMethod | [nl] <<< ExtMethod {semi ExtMethod} >>> diff --git a/library/src/scala/compiletime/package.scala b/library/src/scala/compiletime/package.scala index a3896a1eeb06..8215ae2452a3 100644 --- a/library/src/scala/compiletime/package.scala +++ b/library/src/scala/compiletime/package.scala @@ -52,7 +52,6 @@ def uninitialized: Nothing = ??? * that implement the enclosing trait and that do not contain an explicit overriding * definition of that given. */ -@experimental @compileTimeOnly("`deferred` can only be used as the right hand side of a given definition in a trait") def deferred: Nothing = ??? diff --git a/presentation-compiler/test/dotty/tools/pc/tests/edit/AutoImplementAbstractMembersSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/edit/AutoImplementAbstractMembersSuite.scala index ffe4e293ba30..2df69cc85af2 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/edit/AutoImplementAbstractMembersSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/edit/AutoImplementAbstractMembersSuite.scala @@ -1089,11 +1089,13 @@ class AutoImplementAbstractMembersSuite extends BaseCodeActionSuite: | def foo(x: Int): Int | def bar(x: String): String | - |given Foo with + |given Foo { | | override def foo(x: Int): Int = ??? | | override def bar(x: String): String = ??? + | + |} |""".stripMargin ) diff --git a/tests/neg/empty-given.scala b/tests/neg/empty-given.scala index 10daf5ac009a..cf7566724cc2 100644 --- a/tests/neg/empty-given.scala +++ b/tests/neg/empty-given.scala @@ -1,3 +1,3 @@ -given { // error +given { def foo = 1 // error -} // error \ No newline at end of file +} \ No newline at end of file diff --git a/tests/neg/i12348.check b/tests/neg/i12348.check index 55806fa5ca1b..8d0a24a60308 100644 --- a/tests/neg/i12348.check +++ b/tests/neg/i12348.check @@ -1,4 +1,4 @@ --- [E040] Syntax Error: tests/neg/i12348.scala:2:15 -------------------------------------------------------------------- +-- [E040] Syntax Error: tests/neg/i12348.scala:2:16 -------------------------------------------------------------------- 2 | given inline x: Int = 0 // error - | ^ - | 'with' expected, but identifier found + | ^ + | an identifier expected, but ':' found diff --git a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala index 15ccd38f860c..e28c2240a414 100644 --- a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala @@ -83,7 +83,6 @@ val experimentalDefinitionInLibrary = Set( // New feature: modularity "scala.Precise", "scala.annotation.internal.WitnessNames", - "scala.compiletime.package$package$.deferred", "scala.runtime.stdLibPatches.Predef$.is", // New feature: functions with erased parameters. diff --git a/tests/warn/abstract-givens-new.check b/tests/warn/abstract-givens-new.check index 197d9bcb4f3e..8b137891791f 100644 --- a/tests/warn/abstract-givens-new.check +++ b/tests/warn/abstract-givens-new.check @@ -1,5 +1 @@ --- Warning: tests/warn/abstract-givens-new.scala:7:22 ------------------------------------------------------------------ -7 | given intC: Int is C // warn - | ^ - | This defines an abstract given, which is deprecated. Use a `deferred` given instead. - | Or, if you intend to define a concrete given, follow the type with `()` arguments. + diff --git a/tests/warn/abstract-givens-new.scala b/tests/warn/abstract-givens-new.scala index b38fd11c4458..2ecf700f18f7 100644 --- a/tests/warn/abstract-givens-new.scala +++ b/tests/warn/abstract-givens-new.scala @@ -4,6 +4,7 @@ class C: trait T: given Int is C // ok - given intC: Int is C // warn + given intC: Int is C // ok for now, will be warning given intC2: (Int is C)() // ok given intC3: Int is C {} // also ok + From 3fd727d2cb6f5284db529fbbad202a6f91d0a979 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 28 Sep 2024 18:17:20 +0200 Subject: [PATCH 2/9] Under -source future, warn if old given and context bound syntax is used --- .../tools/dotc/config/MigrationVersion.scala | 1 + .../tools/dotc/config/SourceVersion.scala | 2 ++ .../dotty/tools/dotc/parsing/Parsers.scala | 22 +++++++++++++++- .../neg/context-bounds-migration-future.check | 4 +++ tests/neg/infix.scala | 2 +- tests/neg/tracked.check | 8 +++--- tests/neg/tracked.scala | 2 +- tests/warn/abstract-givens-new.check | 6 ++++- tests/warn/abstract-givens-new.scala | 2 +- tests/warn/old-givens.check | 25 +++++++++++++++++++ tests/warn/old-givens.scala | 18 +++++++++++++ 11 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 tests/warn/old-givens.check create mode 100644 tests/warn/old-givens.scala diff --git a/compiler/src/dotty/tools/dotc/config/MigrationVersion.scala b/compiler/src/dotty/tools/dotc/config/MigrationVersion.scala index 2a4e252fa695..3da716abbc40 100644 --- a/compiler/src/dotty/tools/dotc/config/MigrationVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/MigrationVersion.scala @@ -30,6 +30,7 @@ enum MigrationVersion(val warnFrom: SourceVersion, val errorFrom: SourceVersion) case ImportRename extends MigrationVersion(future, future) case ParameterEnclosedByParenthesis extends MigrationVersion(future, future) case XmlLiteral extends MigrationVersion(future, future) + case GivenSyntax extends MigrationVersion(future, never) require(warnFrom.ordinal <= errorFrom.ordinal) diff --git a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala index caf1187614b7..3b2e2d420d4f 100644 --- a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala @@ -16,6 +16,8 @@ enum SourceVersion: // !!! Keep in sync with scala.runtime.stdlibPatches.language !!! case `future-migration`, `future` + case `never` // needed for MigrationVersion.errorFrom if we never want to issue an error + val isMigrating: Boolean = toString.endsWith("-migration") def stable: SourceVersion = diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 5af9b105a5c1..f94c14079f59 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2240,7 +2240,16 @@ object Parsers { in.nextToken() if in.token == LBRACE && sourceVersion.isAtLeast(`3.6`) then inBraces(commaSeparated(() => contextBound(pname))) - else contextBound(pname) :: contextBounds(pname) + else + val bound = contextBound(pname) + val rest = + if in.isColon then + report.errorOrMigrationWarning( + em"Multiple context bounds should be enclosed in `{ ... }`", + in.sourcePos(), MigrationVersion.GivenSyntax) + contextBounds(pname) + else Nil + bound :: rest else if in.token == VIEWBOUND then report.errorOrMigrationWarning( em"view bounds `<%' are no longer supported, use a context bound `:' instead", @@ -4261,6 +4270,9 @@ object Parsers { in.nextToken() newSignature() else if hasEmbeddedColon then + report.errorOrMigrationWarning( + em"This old given syntax is no longer supported; use `=>` instead of `:`", + in.sourcePos(), MigrationVersion.GivenSyntax) newSyntaxAllowed = false val tparamsOld = typeParamClauseOpt(ParamOwner.Given) newLineOpt() @@ -4294,6 +4306,11 @@ object Parsers { // old-style abstract given if name.isEmpty then syntaxError(em"Anonymous given cannot be abstract, or maybe you want to define a concrete given and are missing a `()` argument?", in.lastOffset) + if newSyntaxAllowed then + report.errorOrMigrationWarning( + em"""This defines an abstract given, which is no longer supported. Use a `deferred` given instead. + |Or, if you intend to define a concrete given, follow the type with `()` arguments.""", + in.sourcePos(in.lastOffset), MigrationVersion.GivenSyntax) DefDef(name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree) else // structural instance @@ -4483,6 +4500,9 @@ object Parsers { /** with Template, with EOL interpreted */ def withTemplate(constr: DefDef, parents: List[Tree]): Template = + report.errorOrMigrationWarning( + em"Given member definitions starting with `with` are no longer supported; use `{...}` or `:` followed by newline instead", + in.sourcePos(), MigrationVersion.GivenSyntax) accept(WITH) val (self, stats) = templateBody(parents, rewriteWithColon = false) Template(constr, parents, Nil, self, stats) diff --git a/tests/neg/context-bounds-migration-future.check b/tests/neg/context-bounds-migration-future.check index f56da5d6b28d..f517a1e335c9 100644 --- a/tests/neg/context-bounds-migration-future.check +++ b/tests/neg/context-bounds-migration-future.check @@ -4,3 +4,7 @@ | method foo does not take more parameters | | longer explanation available when compiling with `-explain` +-- Warning: tests/neg/context-bounds-migration-future.scala:6:6 -------------------------------------------------------- +6 |given [T]: C[T] = C[T]() + | ^ + | This old given syntax is no longer supported; use `=>` instead of `:` diff --git a/tests/neg/infix.scala b/tests/neg/infix.scala index dda638c829f9..bfd68a17e656 100644 --- a/tests/neg/infix.scala +++ b/tests/neg/infix.scala @@ -8,7 +8,7 @@ class C: def +(x: Int): Int = ??? object C: - given AnyRef with + given AnyRef: extension (x: C) infix def iop (y: Int) = ??? def mop (y: Int) = ??? diff --git a/tests/neg/tracked.check b/tests/neg/tracked.check index ae734e7aa0b4..14a4d2a08300 100644 --- a/tests/neg/tracked.check +++ b/tests/neg/tracked.check @@ -22,10 +22,10 @@ 17 | tracked type T = Int // error // error | ^^^^ | end of statement expected but 'type' found --- Error: tests/neg/tracked.scala:20:29 -------------------------------------------------------------------------------- -20 | given g2(using tracked val x: Int): C = C(x) // error - | ^^^^^^^^^^^^^^^^^^ - | method parameter x may not be a `val` +-- Error: tests/neg/tracked.scala:20:25 -------------------------------------------------------------------------------- +20 | given g2: (tracked val x: Int) => C = C(x) // error + | ^^^^^^^^^^^^^^^^^^ + | method parameter x may not be a `val` -- Error: tests/neg/tracked.scala:4:21 --------------------------------------------------------------------------------- 4 |class C2(tracked var x: Int) // error | ^ diff --git a/tests/neg/tracked.scala b/tests/neg/tracked.scala index 8d315a7b89ac..9f874ca3c0da 100644 --- a/tests/neg/tracked.scala +++ b/tests/neg/tracked.scala @@ -17,4 +17,4 @@ object D: tracked type T = Int // error // error object E: - given g2(using tracked val x: Int): C = C(x) // error + given g2: (tracked val x: Int) => C = C(x) // error diff --git a/tests/warn/abstract-givens-new.check b/tests/warn/abstract-givens-new.check index 8b137891791f..a33a109db1b4 100644 --- a/tests/warn/abstract-givens-new.check +++ b/tests/warn/abstract-givens-new.check @@ -1 +1,5 @@ - +-- Warning: tests/warn/abstract-givens-new.scala:7:22 ------------------------------------------------------------------ +7 | given intC: Int is C // warn + | ^ + | This defines an abstract given, which is no longer supported. Use a `deferred` given instead. + | Or, if you intend to define a concrete given, follow the type with `()` arguments. diff --git a/tests/warn/abstract-givens-new.scala b/tests/warn/abstract-givens-new.scala index 2ecf700f18f7..c18ebe46acf7 100644 --- a/tests/warn/abstract-givens-new.scala +++ b/tests/warn/abstract-givens-new.scala @@ -4,7 +4,7 @@ class C: trait T: given Int is C // ok - given intC: Int is C // ok for now, will be warning + given intC: Int is C // warn given intC2: (Int is C)() // ok given intC3: Int is C {} // also ok diff --git a/tests/warn/old-givens.check b/tests/warn/old-givens.check new file mode 100644 index 000000000000..ec237ae8fd93 --- /dev/null +++ b/tests/warn/old-givens.check @@ -0,0 +1,25 @@ +-- Warning: tests/warn/old-givens.scala:8:20 --------------------------------------------------------------------------- +8 | given intC: C[Int] // warn + | ^ + | This defines an abstract given, which is no longer supported. Use a `deferred` given instead. + | Or, if you intend to define a concrete given, follow the type with `()` arguments. +-- Warning: tests/warn/old-givens.scala:11:8 --------------------------------------------------------------------------- +11 | given [T]: Ord[T] with // warn // warn + | ^ + | This old given syntax is no longer supported; use `=>` instead of `:` +-- Warning: tests/warn/old-givens.scala:11:20 -------------------------------------------------------------------------- +11 | given [T]: Ord[T] with // warn // warn + | ^ + |Given member definitions starting with `with` are no longer supported; use `{...}` or `:` followed by newline instead +-- Warning: tests/warn/old-givens.scala:14:8 --------------------------------------------------------------------------- +14 | given [T](using Ord[T]): Ord[List[T]] with // warn // warn + | ^ + | This old given syntax is no longer supported; use `=>` instead of `:` +-- Warning: tests/warn/old-givens.scala:14:40 -------------------------------------------------------------------------- +14 | given [T](using Ord[T]): Ord[List[T]] with // warn // warn + | ^ + |Given member definitions starting with `with` are no longer supported; use `{...}` or `:` followed by newline instead +-- Warning: tests/warn/old-givens.scala:17:15 -------------------------------------------------------------------------- +17 | def f[T: Ord : C]() = ??? // warn + | ^ + | Multiple context bounds should be enclosed in `{ ... }` diff --git a/tests/warn/old-givens.scala b/tests/warn/old-givens.scala new file mode 100644 index 000000000000..83e650df47d3 --- /dev/null +++ b/tests/warn/old-givens.scala @@ -0,0 +1,18 @@ +//> using options -source future +trait Ord[T]: + def compare(x: T, y: T): Boolean + +class C[T] + +trait T: + given intC: C[Int] // warn + given intC2: C[Int] () // OK + + given [T]: Ord[T] with // warn // warn + def compare(x: T, y: T): Boolean = ??? + + given [T](using Ord[T]): Ord[List[T]] with // warn // warn + def compare(x: List[T], y: List[T]): Boolean = ??? + + def f[T: Ord : C]() = ??? // warn + From 20e942ba03eb44ec9580dcb1ce1e6a323e24853e Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 28 Sep 2024 18:51:24 +0200 Subject: [PATCH 3/9] Allow context bounds on type members in 3.6 It was forgotten before to enable this. --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index f94c14079f59..978c89398ecc 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -4024,7 +4024,7 @@ object Parsers { case SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | OUTDENT | EOF => makeTypeDef(typeAndCtxBounds(tname)) case _ if (staged & StageKind.QuotedPattern) != 0 - || in.featureEnabled(Feature.modularity) && in.isColon => + || sourceVersion.isAtLeast(`3.6`) && in.isColon => makeTypeDef(typeAndCtxBounds(tname)) case _ => syntaxErrorOrIncomplete(ExpectedTypeBoundOrEquals(in.token)) From 3cff3be904dfd08afb08fc2cf7e808a9d89a8d7a Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 28 Sep 2024 19:16:12 +0200 Subject: [PATCH 4/9] Drop modularity import from tests that no longer need it. --- tests/neg/cb-companion-leaks.scala | 2 +- tests/neg/deferred-givens.scala | 2 +- tests/neg/deferredSummon.scala | 2 +- tests/pos-custom-args/captures/logger.scala | 1 - tests/pos-custom-args/captures/nested-classes.scala | 1 - tests/pos/FromString-cb-companion.scala | 2 +- tests/pos/FromString-typeparam.scala | 1 - tests/pos/cb-companion-joins.scala | 1 - tests/pos/deferred-givens-singletons.scala | 2 +- tests/pos/deferred-givens.scala | 2 +- tests/pos/dep-context-bounds.scala | 2 +- tests/pos/i21189-alt.scala | 2 -- tests/pos/i21189.scala | 2 -- tests/pos/typeclasses-arrow0.scala | 2 -- tests/run/Providers.scala | 1 - tests/run/byname-given.scala | 2 -- 16 files changed, 7 insertions(+), 20 deletions(-) diff --git a/tests/neg/cb-companion-leaks.scala b/tests/neg/cb-companion-leaks.scala index 07155edb05dc..d9d8f3d6d19b 100644 --- a/tests/neg/cb-companion-leaks.scala +++ b/tests/neg/cb-companion-leaks.scala @@ -1,4 +1,4 @@ -//> using options -language:experimental.modularity -source future -explain +//> using options -language:experimental.modularity -explain class C[Self] diff --git a/tests/neg/deferred-givens.scala b/tests/neg/deferred-givens.scala index 8a1bcb2b50fc..4de79120a1c7 100644 --- a/tests/neg/deferred-givens.scala +++ b/tests/neg/deferred-givens.scala @@ -1,4 +1,4 @@ -//> using options -language:experimental.modularity -source future + import compiletime.deferred class Ctx diff --git a/tests/neg/deferredSummon.scala b/tests/neg/deferredSummon.scala index cddde82535fb..39a775cf78bf 100644 --- a/tests/neg/deferredSummon.scala +++ b/tests/neg/deferredSummon.scala @@ -1,4 +1,4 @@ -//> using options -language:experimental.modularity + object Test: given Int = compiletime.deferred // error diff --git a/tests/pos-custom-args/captures/logger.scala b/tests/pos-custom-args/captures/logger.scala index 81eeb521fee5..c2cfed0462b6 100644 --- a/tests/pos-custom-args/captures/logger.scala +++ b/tests/pos-custom-args/captures/logger.scala @@ -1,5 +1,4 @@ import language.experimental.saferExceptions -import language.experimental.modularity class FileSystem extends caps.Capability diff --git a/tests/pos-custom-args/captures/nested-classes.scala b/tests/pos-custom-args/captures/nested-classes.scala index 4a76a88c03ff..1c624d37cee1 100644 --- a/tests/pos-custom-args/captures/nested-classes.scala +++ b/tests/pos-custom-args/captures/nested-classes.scala @@ -1,5 +1,4 @@ import language.experimental.captureChecking -import language.experimental.modularity import annotation.{capability, constructorOnly} class IO extends caps.Capability diff --git a/tests/pos/FromString-cb-companion.scala b/tests/pos/FromString-cb-companion.scala index d086420761ee..de525629a028 100644 --- a/tests/pos/FromString-cb-companion.scala +++ b/tests/pos/FromString-cb-companion.scala @@ -1,4 +1,4 @@ -//> using options -language:experimental.modularity -source future +//> using options -language:experimental.modularity trait FromString[Self]: def fromString(s: String): Self diff --git a/tests/pos/FromString-typeparam.scala b/tests/pos/FromString-typeparam.scala index 893bcfd3decc..a989e679cd94 100644 --- a/tests/pos/FromString-typeparam.scala +++ b/tests/pos/FromString-typeparam.scala @@ -1,4 +1,3 @@ -//> using options -language:experimental.modularity -source future trait FromString[A]: def fromString(s: String): A diff --git a/tests/pos/cb-companion-joins.scala b/tests/pos/cb-companion-joins.scala index 97e0a8a7e4ac..91df784bb2ce 100644 --- a/tests/pos/cb-companion-joins.scala +++ b/tests/pos/cb-companion-joins.scala @@ -1,5 +1,4 @@ import language.experimental.modularity -import language.future trait M[Self]: extension (x: Self) def combine (y: Self): String diff --git a/tests/pos/deferred-givens-singletons.scala b/tests/pos/deferred-givens-singletons.scala index 60a881340b75..c03bd59ccf20 100644 --- a/tests/pos/deferred-givens-singletons.scala +++ b/tests/pos/deferred-givens-singletons.scala @@ -1,4 +1,4 @@ -//> using options -language:experimental.modularity -source future +// //> using options -language:experimental.modularity -source future import compiletime.* trait A: diff --git a/tests/pos/deferred-givens.scala b/tests/pos/deferred-givens.scala index 0ad751fcc7e0..68980a92f602 100644 --- a/tests/pos/deferred-givens.scala +++ b/tests/pos/deferred-givens.scala @@ -1,4 +1,4 @@ -//> using options -language:experimental.modularity -source future + import compiletime.* class Ord[Elem] given Ord[Double]() diff --git a/tests/pos/dep-context-bounds.scala b/tests/pos/dep-context-bounds.scala index c724d92e9809..d89bec5d85ee 100644 --- a/tests/pos/dep-context-bounds.scala +++ b/tests/pos/dep-context-bounds.scala @@ -1,4 +1,4 @@ -//> using options -language:experimental.modularity -source future +//> using options -language:experimental.modularity trait A: type Self diff --git a/tests/pos/i21189-alt.scala b/tests/pos/i21189-alt.scala index 10a55ec25185..d99a95f0d67e 100644 --- a/tests/pos/i21189-alt.scala +++ b/tests/pos/i21189-alt.scala @@ -1,5 +1,3 @@ -//> using options -source:future -language:experimental.modularity - class MySortedSet[T : Ord] extends SortedSet[T] trait Ord[T] diff --git a/tests/pos/i21189.scala b/tests/pos/i21189.scala index ea27f88402de..556f470945eb 100644 --- a/tests/pos/i21189.scala +++ b/tests/pos/i21189.scala @@ -1,5 +1,3 @@ -//> using options -source:future -language:experimental.modularity - class MySortedSet[T : Ord] extends SortedSet[T] trait Ord[T] diff --git a/tests/pos/typeclasses-arrow0.scala b/tests/pos/typeclasses-arrow0.scala index d7d85e6b7400..279d2367e185 100644 --- a/tests/pos/typeclasses-arrow0.scala +++ b/tests/pos/typeclasses-arrow0.scala @@ -1,5 +1,3 @@ -//> using options -language:experimental.modularity -source future - class Common: trait Ord[A]: diff --git a/tests/run/Providers.scala b/tests/run/Providers.scala index 8c5bf20bc02e..445781c49987 100644 --- a/tests/run/Providers.scala +++ b/tests/run/Providers.scala @@ -1,4 +1,3 @@ -import language.experimental.modularity import compiletime.constValue import compiletime.ops.int.S diff --git a/tests/run/byname-given.scala b/tests/run/byname-given.scala index d18ebb221a68..05d0d652ff68 100644 --- a/tests/run/byname-given.scala +++ b/tests/run/byname-given.scala @@ -1,5 +1,3 @@ -//> using options -language:experimental.modularity -source future - @main def Test = var x: Int = 0 given () => Int = x From ca6b8f7c3ed79848a57a299265dd86f20f69e5f8 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 29 Sep 2024 20:08:40 +0200 Subject: [PATCH 5/9] Make never an illegal source version --- compiler/src/dotty/tools/dotc/config/SourceVersion.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala index 3b2e2d420d4f..3a7285751827 100644 --- a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala @@ -34,7 +34,7 @@ object SourceVersion extends Property.Key[SourceVersion]: def defaultSourceVersion = `3.6` /** language versions that may appear in a language import, are deprecated, but not removed from the standard library. */ - val illegalSourceVersionNames = List("3.1-migration").map(_.toTermName) + val illegalSourceVersionNames = List("3.1-migration", "never").map(_.toTermName) /** language versions that the compiler recognises. */ val validSourceVersionNames = values.toList.map(_.toString.toTermName) From 0c721dcffb473b92c71e58569090313577f5368c Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 30 Sep 2024 11:31:57 +0200 Subject: [PATCH 6/9] Update docs to new conventions Also: Some reshuffling and editing of existing material. --- .../contextual/by-name-context-parameters.md | 2 +- .../reference/contextual/context-bounds.md | 193 +++++++- .../_docs/reference/contextual/conversions.md | 2 +- .../reference/contextual/deferred-givens.md | 57 +++ .../reference/contextual/derivation-macro.md | 4 +- docs/_docs/reference/contextual/derivation.md | 26 +- .../reference/contextual/extension-methods.md | 2 +- .../reference/contextual/given-imports.md | 2 +- docs/_docs/reference/contextual/givens.md | 181 ++------ .../_docs/reference/contextual/more-givens.md | 204 +++++++++ .../contextual/multiversal-equality.md | 2 +- .../reference/contextual/previous-givens.md | 233 ++++++++++ .../contextual/relationship-implicits.md | 10 +- .../reference/contextual/type-classes.md | 36 +- .../reference/contextual/using-clauses.md | 2 +- docs/_docs/reference/enums/enums.md | 12 +- .../experimental/erased-defs-spec.md | 6 +- .../experimental/numeric-literals.md | 4 +- .../reference/experimental/typeclasses.md | 431 +----------------- .../reference/metaprogramming/macros-spec.md | 2 +- .../_docs/reference/metaprogramming/macros.md | 4 +- docs/sidebar.yml | 4 + 22 files changed, 764 insertions(+), 655 deletions(-) create mode 100644 docs/_docs/reference/contextual/deferred-givens.md create mode 100644 docs/_docs/reference/contextual/more-givens.md create mode 100644 docs/_docs/reference/contextual/previous-givens.md diff --git a/docs/_docs/reference/contextual/by-name-context-parameters.md b/docs/_docs/reference/contextual/by-name-context-parameters.md index 7c517abe9406..e903ac2642c3 100644 --- a/docs/_docs/reference/contextual/by-name-context-parameters.md +++ b/docs/_docs/reference/contextual/by-name-context-parameters.md @@ -12,7 +12,7 @@ trait Codec[T]: given intCodec: Codec[Int] = ??? -given optionCodec[T](using ev: => Codec[T]): Codec[Option[T]] with +given optionCodec: [T] => (ev: => Codec[T]) => Codec[Option[T]]: def write(xo: Option[T]) = xo match case Some(x) => ev.write(x) case None => diff --git a/docs/_docs/reference/contextual/context-bounds.md b/docs/_docs/reference/contextual/context-bounds.md index 11d57c8cbd52..ef32dc7b08c2 100644 --- a/docs/_docs/reference/contextual/context-bounds.md +++ b/docs/_docs/reference/contextual/context-bounds.md @@ -4,50 +4,205 @@ title: "Context Bounds" nightlyOf: https://docs.scala-lang.org/scala3/reference/contextual/context-bounds.html --- -A context bound is a shorthand for expressing the common pattern of a context parameter that depends on a type parameter. Using a context bound, the `maximum` function of the last section can be written like this: +A context bound is a shorthand for expressing the common pattern of a context parameter that depends on a type parameter. These patterns are commonplace when modelling type classes in Scala. Using a context bound, the `maximum` function of the [last section](./using-clauses.md) can be written like this: ```scala def maximum[T: Ord](xs: List[T]): T = xs.reduceLeft(max) ``` -A bound like `: Ord` on a type parameter `T` of a method or class indicates a context parameter `using Ord[T]`. The context parameter(s) generated from context bounds -are added as follows: +A bound like `: Ord` on a type parameter `T` of a method or class indicates a context parameter `using Ord[T]`, which is added to the signature of the enclosing method. The generated parameter is called a _witness_ for the context bound. - - If the method parameters end in an implicit parameter list or using clause, - context parameters are added in front of that list. - - Otherwise they are added as a separate parameter clause at the end. - -Example: +For instance the `maximum` method above expands to +```scala +def maximum[T](xs: List[T])(using Ord[T]): T = ... +``` +Context bounds can be combined with subtype bounds. If both are present, subtype bounds come first, e.g. ```scala -def f[T: C1 : C2, U: C3](x: T)(using y: U, z: V): R +def f[T <: B : C](x: T): R = ... ``` -would expand to +## Named Context Bounds +A context bound can be given a name with an `as` clause. For example, assume the following trait definitions. +```scala + trait SemiGroup[A]: + extension (x: A) def combine(y: A): A + + trait Monoid[A] extends SemiGroup[A]: + def unit: A +``` +We can write `reduce` function over lists of monoid instances like this: ```scala -def f[T, U](x: T)(using _: C1[T], _: C2[T], _: C3[U], y: U, z: V): R + def reduce[A: Monoid as m](xs: List[A]): A = + xs.foldLeft(m.unit)(_ `combine` _) ``` +We use `as x` after the type of a context bound to bind the instance to `x`. This is analogous to import renaming, which also introduces a new name for something that comes before. -Context bounds can be combined with subtype bounds. If both are present, subtype bounds come first, e.g. +In a context bound with a naming clause the witness parameter carries the given name. For instance the expanded signature of `reduce` would be +```scala + def reduce[A](xs: List[A])(using m: Monoid[A]): A +``` +Since the context parameter now has a name, it can be referred +to in the body of `reduce`. An example is the `m.unit` reference in the definition above. + +If the context bound does not carry an `as` clause, the generated witness parameter gets a compiler-synthesized name. However, a [currently experimental +language extension](../experimental/default-names-context-bounds.md) would in this case give the context parameter the same name as the bound type parameter. + +Named context bounds were introduced in Scala 3.6. + +## Aggregate Context Bounds +A type parameter can have several context bounds. If there are multiple bounds, they are written inside braces `{...}`. Example: ```scala -def g[T <: B : C](x: T): R = ... + trait: + def showMax[X : {Ord, Show}](x: X, y: X): String + class B extends A: + def showMax[X : {Ord as ordering, Show as show}](x: X, y: X): String = + show.asString(ordering.max(x, y)) ``` -## Migration +This syntax is valid from Scala 3.6. The previous syntax used +chains of `:` clauses, as in `[X : Ord : Show]`. This syntax is still available but will be deprecated and removed over time. -To ease migration, context bounds in Dotty map in Scala 3.0 to old-style implicit parameters -for which arguments can be passed either with a `(using ...)` clause or with a normal application. From Scala 3.1 on, they will map to context parameters instead, as is described above. +## Placement of Generated Context Parameters -If the source version is `future-migration`, any pairing of an evidence +The witness context parameter(s) generated from context bounds are added as follows: + + 1. If one of the bounds is referred to by its name in a subsequent parameter clause, the context bounds are mapped to a using clause immediately preceding the first such parameter clause. + 2. Otherwise, if the last parameter clause is a using (or implicit) clause, merge all parameters arising from context bounds in front of that clause, creating a single using clause. + 3. Otherwise, let the parameters arising from context bounds form a new using clause at the end. + +Rules (2) and (3) match Scala 2's rules. Rule (1) is new but since context bounds so far could not be referred to, it does not apply to legacy code. Therefore, binary compatibility with Scala 2 and earlier Scala 3 versions is maintained. + +**Examples:** + + 1. By rule 3, + ```scala + def f[T: {C1, C2}](x: T): R + ``` + expands to + ```scala + def f[T](x: T)(using C1, C2): R + ``` + Equally by rule 3, + ```scala + def f[T: {C1 as c1, C2 as c2}](x: T): R + ``` + expands to + ```scala + def f[T](x: T)(using c1: C1, c2: C2): R + + 2. By rule 2, + ```scala + def f[T: {C1, C2}, U: C3](x: T)(using y: U, z: V): R + ``` + expands to + ```scala + def f[T, U](x: T)(using _: C1[T], _: C2[T], _: C3[U], y: U, z: V): R + ``` + The same expansion occurs if `y` and `z` are Scala 2 style `implicit` parameters. + 3. Assume the following trait definition: + ```scala + trait Parser[P]: + type Input + type Result + ``` + Here is a method `run` that runs a parser on an input of the required type: + ```scala + def run[P : Parser as p](in: p.Input): p.Result + ``` + By rule 1, this method definition is expanded to: + ```scala + def run[P](using p: Parser[P]](in: p.Input): p.Result + ``` + Note that the `using` clause is placed in front of the explicit parameter clause `(in: p.Result)` so that + the type `p.Result` can legally refer to the context parameter `p`. + +### Migration + +To ease migration, context bounds map in Scala 3.0 - 3.5 to old-style implicit parameters +for which arguments can be passed either with a `(using ...)` clause or with a normal application. From Scala 3.6 on, they will map to context parameters instead, as is described above. + +If the source version is `3.6-migration`, any pairing of an evidence context parameter stemming from a context bound with a normal argument will give a migration warning. The warning indicates that a `(using ...)` clause is needed instead. The rewrite can be done automatically under `-rewrite`. +## Context Bounds for Polymorphic Functions + +From Scala 3.6 on, context bounds can also be used in polymorphic function types and polymorphic function literals: + +```scala +type Comparer = [X: Ord] => (x: X, y: X) => Boolean +val less: Comparer = [X: Ord as ord] => (x: X, y: X) => + ord.compare(x, y) < 0 +``` + +The expansion of such context bounds is analogous to the expansion in method types, except that instead of adding a using clause in a method, we insert a [context function type](./context-functions.md). + +For instance, the `type` and `val` definitions above would expand to +```scala +type Comparer = [X] => (x: X, y: X) => Ord[X] ?=> Boolean +val less: Comparer = [X] => (x: X, y: X) => (ord: Ord[X]) ?=> + ord.compare(x, y) < 0 +``` + +The expansion of using clauses does look inside alias types. For instance, +here is a variation of the previous example that uses a parameterized type alias: +```scala +type Cmp[X] = (x: X, y: X) => Ord[X] ?=> Boolean +type Comparer2 = [X: Ord] => Cmp[X] +``` +The expansion of the right hand side of `Comparer2` expands the `Cmp[X]` alias +and then inserts the context function at the same place as what's done for `Comparer`. + +### Context Bounds for Type Members + +From Scala 3.6 on, context bounds can not only used for type parameters but also for abstract type members. + +**Example**: + +```scala + class Collection: + type Element: Ord +``` + +These context bounds have to expand differently from context bounds for type parameters since there is no parameter list to accommodate any generated witnesses. Instead, context bounds for abstract types map to +[deferred givens](./deferred-givens.md). + +For instance, the `Collection` class above expands to: +```scala + class Collection: + type Element + given Ord[Element] = deferred +``` +As is explain in the [section on deferred givens](./deferred-givens.md), `deferred` is a special name defined in the `scala.compiletime` package. + + ## Syntax +The new syntax of context bounds is as follows: + ```ebnf -TypeParamBounds ::= [SubtypeBounds] {ContextBound} -ContextBound ::= ‘:’ Type +TypeParamBounds ::= TypeAndCtxBounds +TypeAndCtxBounds ::= TypeBounds [‘:’ ContextBounds] +ContextBounds ::= ContextBound + | '{' ContextBound {',' ContextBound} '}' +ContextBound ::= Type ['as' id] ``` + +The syntax of function types and function literals +is generalized as follows to allow context bounds for generic type parameters. + +```ebnf +FunType ::= FunTypeArgs (‘=>’ | ‘?=>’) Type + | DefTypeParamClause '=>' Type +FunExpr ::= FunParams (‘=>’ | ‘?=>’) Expr + | DefTypeParamClause ‘=>’ Expr +``` +The syntax for abstract type members is generalized as follows to allow context bounds: + +```scala +TypeDef ::= id [TypeParamClause] TypeAndCtxBounds +``` \ No newline at end of file diff --git a/docs/_docs/reference/contextual/conversions.md b/docs/_docs/reference/contextual/conversions.md index 1ce8d42074e7..cb063b949a71 100644 --- a/docs/_docs/reference/contextual/conversions.md +++ b/docs/_docs/reference/contextual/conversions.md @@ -12,7 +12,7 @@ abstract class Conversion[-T, +U] extends (T => U): ``` For example, here is an implicit conversion from `String` to `Token`: ```scala -given Conversion[String, Token] with +given Conversion[String, Token]: def apply(str: String): Token = new KeyWord(str) ``` Using an alias this can be expressed more concisely as: diff --git a/docs/_docs/reference/contextual/deferred-givens.md b/docs/_docs/reference/contextual/deferred-givens.md new file mode 100644 index 000000000000..232c15afda35 --- /dev/null +++ b/docs/_docs/reference/contextual/deferred-givens.md @@ -0,0 +1,57 @@ +--- +layout: doc-page +title: "Deferred Givens" +nightlyOf: https://docs.scala-lang.org/scala3/reference/contextual/deferred-givens.html +--- + +Scala 3.6 introduces a new way to implement a given definition in a trait like this: +```scala +given T = deferred +``` +Such givens can be implemented automatically in subclasses. `deferred` is a new method in the `scala.compiletime` package, which can appear only as the right hand side of a given defined in a trait. Any class implementing that trait will provide an implementation of this given. If a definition is not provided explicitly, it will be synthesized by searching for a given of type `T` in the scope of the inheriting class. Specifically, the scope in which this given will be searched is the environment of that class augmented by its parameters but not containing its members (since that would lead to recursive resolutions). If an implementation _is_ provided explicitly, it counts as an override of a concrete definition and needs an `override` modifier. + +Deferred givens allow a clean implementation of context bounds in traits, +as in the following example: +```scala +trait Sorted: + type Element : Ord + +class SortedSet[A : Ord as ord] extends Sorted: + type Element = A +``` +The compiler expands this to the following implementation. +```scala +trait Sorted: + type Element + given Ord[Element] = compiletime.deferred + +class SortedSet[A](using ord: Ord[A]) extends Sorted: + type Element = A + override given Ord[Element] = ord +``` + +The using clause in class `SortedSet` provides an implementation for the deferred given in trait `Sorted`. + +One can also provide an explicit implementation of a deferred given, as in the following example: + +```scala +class SortedString[A] extends Sorted: + type Element = String + override given Ord[String] = ... +``` + +Note that the implementing given needs an `override` modifier since the `deferred` given in class `Sorted` counts as a concrete (i.e. not abstract) definition. In a sense, the `deferred` right hand side in `Sorted` is like a (magic, compiler-supported) macro, with the peculiarity that the macro's implementation also affects subclasses. + +## Abstract Givens + +A given may also be an abstract member, with the restriction that it must have an explicit name. Example: + +```scala +trait HasOrd[T]: + given ord: Ord[T] +``` +An abstract given has the form `given name: Type` without a right-hand side or arguments to the type. + +Since Scala 3.6, abstract givens are made redundant by deferred givens. Deferred givens can replace abstract givens. They have better ergonomics, since deferred givens get naturally implemented in inheriting classes, so there is no longer any need for boilerplate to fill in definitions of abstract givens. + +It is therefore recommended that software architectures relying on abstract givens be migrated to use deferred givens instead. Abstract givens are still supported in Scala 3.6, but will likely be deprecated and phased out over time. diff --git a/docs/_docs/reference/contextual/derivation-macro.md b/docs/_docs/reference/contextual/derivation-macro.md index 4b8dcffec846..6540a5d68a4b 100644 --- a/docs/_docs/reference/contextual/derivation-macro.md +++ b/docs/_docs/reference/contextual/derivation-macro.md @@ -135,10 +135,10 @@ trait Eq[T]: def eqv(x: T, y: T): Boolean object Eq: - given Eq[String] with + given Eq[String]: def eqv(x: String, y: String) = x == y - given Eq[Int] with + given Eq[Int]: def eqv(x: Int, y: Int) = x == y def eqProduct[T](body: (T, T) => Boolean): Eq[T] = diff --git a/docs/_docs/reference/contextual/derivation.md b/docs/_docs/reference/contextual/derivation.md index ed0e005c1bd4..cbf736d88034 100644 --- a/docs/_docs/reference/contextual/derivation.md +++ b/docs/_docs/reference/contextual/derivation.md @@ -19,9 +19,9 @@ The `derives` clause generates the following given instances for the `Eq`, `Orde companion object of `Tree`: ```scala -given [T: Eq] : Eq[Tree[T]] = Eq.derived -given [T: Ordering] : Ordering[Tree[T]] = Ordering.derived -given [T: Show] : Show[Tree[T]] = Show.derived +given [T: Eq] => Eq[Tree[T]] = Eq.derived +given [T: Ordering] => Ordering[Tree[T]] = Ordering.derived +given [T: Show] => Show[Tree[T]] = Show.derived ``` We say that `Tree` is the _deriving type_ and that the `Eq`, `Ordering` and `Show` instances are _derived instances_. @@ -29,7 +29,7 @@ We say that `Tree` is the _deriving type_ and that the `Eq`, `Ordering` and `Sho **Note:** `derived` can be used manually, this is useful when you do not have control over the definition. For example we can implement `Ordering` for `Option`s like so: ```scala -given [T: Ordering]: Ordering[Option[T]] = Ordering.derived +given [T: Ordering] => Ordering[Option[T]] = Ordering.derived ``` It is discouraged to directly refer to the `derived` member if you can use a `derives` clause instead. @@ -44,7 +44,7 @@ For a class/trait/object/enum `DerivingType[T_1, ..., T_N] derives TC`, a derive The general "shape" of the derived instance is as follows: ```scala -given [...](using ...): TC[ ... DerivingType[...] ... ] = TC.derived +given [...] => (...) => TC[ ... DerivingType[...] ... ] = TC.derived ``` `TC.derived` should be an expression that conforms to the expected type on the left, potentially elaborated using term and/or type inference. @@ -62,7 +62,7 @@ There are two further cases depending on the kinds of arguments: The generated instance is then: ```scala -given [T_1: TC, ..., T_N: TC]: TC[DerivingType[T_1, ..., T_N]] = TC.derived +given [T_1: TC, ..., T_N: TC] => TC[DerivingType[T_1, ..., T_N]] = TC.derived ``` This is the most common case, and is the one that was highlighted in the introduction. @@ -92,7 +92,7 @@ This section covers cases where you can pair arguments of `F` and `DerivingType` The general shape will then be: ```scala -given [...]: TC[ [...] =>> DerivingType[...] ] = TC.derived +given [...] => TC[ [...] =>> DerivingType[...] ] = TC.derived ``` Where of course `TC` and `DerivingType` are applied to types of the correct kind. @@ -114,7 +114,7 @@ given TC[ [A_1, ..., A_K] =>> DerivingType ] = TC.derived If `F` takes fewer arguments than `DerivingType` (`K < N`), we fill in the remaining leftmost slots with type parameters of the given: ```scala -given [T_1, ... T_(N-K)]: TC[[A_1, ..., A_K] =>> DerivingType[T_1, ... T_(N-K), A_1, ..., A_K]] = TC.derived +given [T_1, ... T_(N-K)] => TC[[A_1, ..., A_K] =>> DerivingType[T_1, ... T_(N-K), A_1, ..., A_K]] = TC.derived ``` ### `TC` is the `CanEqual` type class @@ -142,7 +142,7 @@ generates the following given instance: ```scala object MyClass: ... - given [A_L, A_R, G_L[_], G_R[_]](using CanEqual[A_L, A_R]): CanEqual[MyClass[A_L, G_L], MyClass[A_R, G_R]] = CanEqual.derived + given [A_L, A_R, G_L[_], G_R[_]] => CanEqual[A_L, A_R] => CanEqual[MyClass[A_L, G_L], MyClass[A_R, G_R]] = CanEqual.derived ``` ### `TC` is not valid for automatic derivation @@ -419,7 +419,7 @@ trait Eq[T]: def eqv(x: T, y: T): Boolean object Eq: - given Eq[Int] with + given Eq[Int]: def eqv(x: Int, y: Int) = x == y def check(x: Any, y: Any, elem: Eq[?]): Boolean = @@ -468,7 +468,7 @@ In this case the code that is generated by the inline expansion for the derived following, after a little polishing, ```scala -given derived$Eq[T](using eqT: Eq[T]): Eq[Lst[T]] = +given derived$Eq[T] => (eqT: Eq[T]) => Eq[Lst[T]] = eqSum(summon[Mirror.Of[Lst[T]]], {/* cached lazily */ List( eqProduct(summon[Mirror.Of[Cns[T]]], {/* cached lazily */ @@ -491,12 +491,12 @@ As a third example, using a higher-level library such as Shapeless, the type cla `derived` method as, ```scala -given eqSum[A](using inst: => K0.CoproductInstances[Eq, A]): Eq[A] with +given eqSum: [A] => (inst: => K0.CoproductInstances[Eq, A]) => Eq[A]: def eqv(x: A, y: A): Boolean = inst.fold2(x, y)(false)( [t] => (eqt: Eq[t], t0: t, t1: t) => eqt.eqv(t0, t1) ) -given eqProduct[A](using inst: => K0.ProductInstances[Eq, A]): Eq[A] with +given eqProduct: [A] => (inst: => K0.ProductInstances[Eq, A]) => Eq[A]: def eqv(x: A, y: A): Boolean = inst.foldLeft2(x, y)(true: Boolean)( [t] => (acc: Boolean, eqt: Eq[t], t0: t, t1: t) => Complete(!eqt.eqv(t0, t1))(false)(true) diff --git a/docs/_docs/reference/contextual/extension-methods.md b/docs/_docs/reference/contextual/extension-methods.md index 8b9a3df5b84c..2aaa6a90e536 100644 --- a/docs/_docs/reference/contextual/extension-methods.md +++ b/docs/_docs/reference/contextual/extension-methods.md @@ -225,7 +225,7 @@ object List: extension [T](xs: List[List[T]]) def flatten: List[T] = xs.foldLeft(List.empty[T])(_ ++ _) - given [T: Ordering]: Ordering[List[T]] with + given [T: Ordering] => Ordering[List[T]]: extension (xs: List[T]) def < (ys: List[T]): Boolean = ... end List diff --git a/docs/_docs/reference/contextual/given-imports.md b/docs/_docs/reference/contextual/given-imports.md index 28442581e408..c9247b01183f 100644 --- a/docs/_docs/reference/contextual/given-imports.md +++ b/docs/_docs/reference/contextual/given-imports.md @@ -61,7 +61,7 @@ For instance, assuming the object ```scala object Instances: given intOrd: Ordering[Int] = ... - given listOrd[T: Ordering]: Ordering[List[T]] = ... + given listOrd: [T: Ordering] => Ordering[List[T]] = ... given ec: ExecutionContext = ... given im: Monoid[Int] = ... ``` diff --git a/docs/_docs/reference/contextual/givens.md b/docs/_docs/reference/contextual/givens.md index 5499fc39b53c..b7be460c9a34 100644 --- a/docs/_docs/reference/contextual/givens.md +++ b/docs/_docs/reference/contextual/givens.md @@ -14,28 +14,25 @@ trait Ord[T]: def < (y: T) = compare(x, y) < 0 def > (y: T) = compare(x, y) > 0 -given intOrd: Ord[Int] with +given intOrd: Ord[Int]: def compare(x: Int, y: Int) = if x < y then -1 else if x > y then +1 else 0 -given listOrd[T](using ord: Ord[T]): Ord[List[T]] with +given listOrd: [T: Ord] => Ord[List[T]]: def compare(xs: List[T], ys: List[T]): Int = (xs, ys) match case (Nil, Nil) => 0 case (Nil, _) => -1 case (_, Nil) => +1 case (x :: xs1, y :: ys1) => - val fst = ord.compare(x, y) + val fst = summon[Ord[T]].compare(x, y) if fst != 0 then fst else compare(xs1, ys1) ``` This code defines a trait `Ord` with two given instances. `intOrd` defines a given for the type `Ord[Int]` whereas `listOrd[T]` defines givens -for `Ord[List[T]]` for all types `T` that come with a given instance for `Ord[T]` -themselves. The `using` clause in `listOrd` defines a condition: There must be a -given of type `Ord[T]` for a given of type `Ord[List[T]]` to exist. -Such conditions are expanded by the compiler to [context parameters](./using-clauses.md). +for `Ord[List[T]]` for all types `T` that come with a given instance for `Ord[T]`. The clause `[T: Ord]` is a [context bound](./context-bounds.md) which defines a condition: There must be a given of type `Ord[T]` for a given of type `Ord[List[T]]` to exist. Such conditions are expanded by the compiler to [context parameters](./using-clauses.md). ## Anonymous Givens @@ -43,9 +40,9 @@ The name of a given can be left out. So the definitions of the last section can also be expressed like this: ```scala -given Ord[Int] with +given Ord[Int]: ... -given [T](using Ord[T]): Ord[List[T]] with +given [T: Ord] => Ord[List[T]]: ... ``` @@ -60,8 +57,7 @@ given_Ord_List ``` The precise rules for synthesizing names are found [here](./relationship-implicits.html#anonymous-given-instances). These rules do not guarantee absence of name conflicts between -given instances of types that are "too similar". To avoid conflicts one can -use named instances. +given instances of types that are "too similar". To avoid conflicts one can use named instances. **Note:** To ensure robust binary compatibility, publicly available libraries should prefer named instances. @@ -82,152 +78,41 @@ Alias givens can be anonymous as well, e.g. ```scala given Position = enclosingTree.position -given (using config: Config): Factory = MemoizingFactory(config) -``` - -An alias given can have type parameters and context parameters just like any other given, -but it can only implement a single type. - -## Abstract Givens - -A given may be an abstract member, with the restriction that it must have an explicit name. - -```scala -trait HasOrd[T]: - given ord: Ord[T] -``` - -## More Structural Givens - -If an alias given instance is analogous to a lazy val, -and a structural given instance is analogous to an object, -albeit an object with an explicit type, -then a structural given may also be specified without an explicit type: - -```scala -class IntOrd extends Ord[Int]: - def compare(x: Int, y: Int) = - if x < y then -1 else if x > y then +1 else 0 - -given IntOrd() -``` - -Compare this syntax to: - -```scala -object intOrd extends IntOrd() -``` - -The empty parentheses are optional in the extends clause when defining a class, -but are required when defining a given. - -Further mixins are allowed as usual: - -```scala -given IntOrd() with OrdOps[Int] -``` - -## Given Macros - -Given aliases can have the `inline` and `transparent` modifiers. -Example: - -```scala -transparent inline given mkAnnotations[A, T]: Annotations[A, T] = ${ - // code producing a value of a subtype of Annotations -} -``` - -Since `mkAnnotations` is `transparent`, the type of an application is the type of its right-hand side, which can be a proper subtype of the declared result type `Annotations[A, T]`. - -Given instances can have the `inline` but not `transparent` modifiers as their type is already known from the signature. -Example: - -```scala -trait Show[T] { - inline def show(x: T): String -} - -inline given Show[Foo] with { - /*transparent*/ inline def show(x: Foo): String = ${ ... } -} - -def app = - // inlines `show` method call and removes the call to `given Show[Foo]` - summon[Show[Foo]].show(foo) -``` -Note that the inline methods within the given instances may be `transparent`. - -The inlining of given instances will not inline/duplicate the implementation of the given, it will just inline the instantiation of that instance. -This is used to help dead code elimination of the given instances that are not used after inlining. - - -## Pattern-Bound Given Instances - -Given instances can also appear in patterns. Example: - -```scala -for given Context <- applicationContexts do - -pair match - case (ctx @ given Context, y) => ... -``` - -In the first fragment above, anonymous given instances for class `Context` are established by enumerating over `applicationContexts`. In the second fragment, a given `Context` -instance named `ctx` is established by matching against the first half of the `pair` selector. - -In each case, a pattern-bound given instance consists of `given` and a type `T`. The pattern matches exactly the same selectors as the type ascription pattern `_: T`. - -## Negated Givens - -Scala 2's somewhat puzzling behavior with respect to ambiguity has been exploited to implement the analogue of a "negated" search in implicit resolution, -where a query Q1 fails if some other query Q2 succeeds and Q1 succeeds if Q2 fails. With the new cleaned up behavior these techniques no longer work. -But the new special type [`scala.util.NotGiven`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) now implements negation directly. - -For any query type `Q`, [`NotGiven[Q]`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) succeeds if and only if the implicit -search for `Q` fails, for example: - -```scala -import scala.util.NotGiven - -trait Tagged[A] - -case class Foo[A](value: Boolean) -object Foo: - given fooTagged[A](using Tagged[A]): Foo[A] = Foo(true) - given fooNotTagged[A](using NotGiven[Tagged[A]]): Foo[A] = Foo(false) - -@main def test(): Unit = - given Tagged[Int]() - assert(summon[Foo[Int]].value) // fooTagged is found - assert(!summon[Foo[String]].value) // fooNotTagged is found ``` ## Given Instance Initialization -A given instance without type or context parameters is initialized on-demand, the first -time it is accessed. If a given has type or context parameters, a fresh instance -is created for each reference. +An unconditional given instance without parameters is initialized on-demand, the first +time it is accessed. If the given is a simple alias to some immutable value, the given is implemented as a simple forwarder, without incurring the cost of a field to hold a cached value. If a given is conditional, a fresh instance is created for each reference. ## Syntax -Here is the syntax for given instances: +Here is the full syntax for given instances. Some of these forms of givens are explained on a separate page on [Other Forms of Givens](../more-givens.md). ```ebnf -TmplDef ::= ... - | ‘given’ GivenDef -GivenDef ::= [GivenSig] StructuralInstance - | [GivenSig] AnnotType ‘=’ Expr - | [GivenSig] AnnotType -GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ TemplateBody] +Here is the complete context-free syntax for all proposed features. +``` +TmplDef ::= ... | 'given' GivenDef +GivenDef ::= [id ':'] GivenSig +GivenSig ::= GivenImpl + | '(' ')' '=>' GivenImpl + | GivenConditional '=>' GivenSig +GivenImpl ::= GivenType ([‘=’ Expr] | TemplateBody) + | ConstrApps TemplateBody +GivenConditional ::= DefTypeParamClause + | DefTermParamClause + | '(' FunArgTypes ')' + | GivenType +GivenType ::= AnnotType1 {id [nl] AnnotType1} ``` -A given instance starts with the reserved word `given` and an optional _signature_. The signature -defines a name and/or parameters for the instance. It is followed by `:`. There are three kinds -of given instances: +A given instance starts with the reserved word `given`, which is followed by + + - An optional name and a colon + - An optional list of conditions. + - The implemented type(s) and their implementation, in two forms: alias givens and structural givens. + - An _alias given_ implements a single type with a right hand side following `=`. + - A _structural given_ implements one or more class constructors with a + list of member definitions in a template body. -- A _structural instance_ contains one or more types or constructor applications, - followed by `with` and a template body that contains member definitions of the instance. -- An _alias instance_ contains a type, followed by `=` and a right-hand side expression. -- An _abstract instance_ contains just the name and type, which is not followed by anything. +**Note** Parts of the given syntax have changed in Scala 3.6. The original syntax from Scala 3.0 on is described in a separate page [Previous Given Syntax](../previous-givens.md). The original syntax is still supported for now but will be deprecated and phased out over time. diff --git a/docs/_docs/reference/contextual/more-givens.md b/docs/_docs/reference/contextual/more-givens.md new file mode 100644 index 000000000000..3d0076543cd7 --- /dev/null +++ b/docs/_docs/reference/contextual/more-givens.md @@ -0,0 +1,204 @@ +--- +layout: doc-page +title: "Other Forms Of Givens" +nightlyOf: https://docs.scala-lang.org/scala3/reference/contextual/givens.html +--- + +The concept of given instances is quite general. This page covers forms of givens that were not treated before. + +## Simple Structural Givens + +Some givens simply instantiate a class without needing an alias or additional member declarations. Example: + +```scala +class IntOrd extends Ord[Int]: + def compare(x: Int, y: Int) = + if x < y then -1 else if x > y then +1 else 0 + +given IntOrd() +``` +In this case, the given clause consists of just a class creation expression, such as `IntOrd()` above. + +## Conditional Givens with Parameters + +Conditional givens can also be defined with parameters. Example: +```scala +given (config: Config) => Factory = MemoizingFactory(config) +``` +Here, `(config: Config)` describes a context parameter expressing a condition: We can synthesize a given `Factory` _provided_ we can synthesize a given `config` of type `Config`. + +Type parameters and context parameters can be combined. For instance the `listOrd` instance above could alternatively be expressed like this: +```scala +given listOrd: [T] => Ord[T] => Ord[List[T]]: + ... + def compare(x: List[T], y: List[T]) = ... +``` +As the example shows, each parameter section is followed by an `=>`. + +It is also possible to name context parameters: +```scala +given listOrd: [T] => (ord: Ord[T]) => Ord[List[T]]: + ... +``` + +## By Name Givens + +We sometimes find it necessary that a given alias is re-evaluated each time it is called. For instance, say we have a mutable variable `curCtx` and we want to define a given that returns the current value of that variable. A normal given alias will not do since by default given aliases are mapped to lazy vals. + +In general, we want to avoid re-evaluation of givens. But there are situations like the one above where we want to specify _by-name_ evaluation instead. This is achieved by writing a conditional given with an empty parameter list: +```scala + val curCtx: Context + given context: () => Context = curCtx +``` +With this definition, each time a `Context` is summoned we evaluate `context` function, which produces the current value of `curCtx`. + +## Given Macros + +Given aliases can have the `inline` and `transparent` modifiers. +Example: + +```scala +transparent inline given mkAnnotations: [A, T] => Annotations[A, T] = ${ + // code producing a value of a subtype of Annotations +} +``` + +Since `mkAnnotations` is `transparent`, the type of an application is the type of its right-hand side, which can be a proper subtype of the declared result type `Annotations[A, T]`. + +Structural givens can also have the `inline` modifier. But the `transparent` modifier is not allowed for them as their type is already known from the signature. + +Example: + +```scala +trait Show[T]: + inline def show(x: T): String + +inline given Show[Foo]: + inline def show(x: Foo): String = ${ ... } + +def app = + // inlines `show` method call and removes the call to `given Show[Foo]` + summon[Show[Foo]].show(foo) +``` +Note that inline methods within given instances may be `transparent`. + + + +## Pattern-Bound Given Instances + +Given instances can also appear in patterns. Example: + +```scala +for given Context <- applicationContexts do + +pair match + case (ctx @ given Context, y) => ... +``` + +In the first fragment above, anonymous given instances for class `Context` are established by enumerating over `applicationContexts`. In the second fragment, a given `Context` +instance named `ctx` is established by matching against the first half of the `pair` selector. + +In each case, a pattern-bound given instance consists of `given` and a type `T`. The pattern matches exactly the same selectors as the type ascription pattern `_: T`. + +## Negated Givens + + +We sometimes want to have an implicit search succeed if a given instance for some other type is _not_ available. There is a special class [`scala.util.NotGiven`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) that implements this kind of negation. + +For any query type `Q`, [`NotGiven[Q]`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) succeeds if and only if the implicit +search for `Q` fails, for example: + +```scala +import scala.util.NotGiven + +trait Tagged[A] + +case class Foo[A](value: Boolean) +object Foo: + given fooTagged: [A] => Tagged[A] => Foo[A] = Foo(true) + given fooNotTagged: [A] => NotGiven[Tagged[A]] => Foo[A] = Foo(false) + +@main def test(): Unit = + given Tagged[Int]() + assert(summon[Foo[Int]].value) // fooTagged is found + assert(!summon[Foo[String]].value) // fooNotTagged is found +``` + +## Summary + +Here is a summary of common forms of given clauses: + +```scala + // Simple typeclass + given Ord[Int]: + def compare(x: Int, y: Int) = ... + + // Parameterized typeclass with context bound + given [A: Ord] => Ord[List[A]]: + def compare(x: List[A], y: List[A]) = ... + + // Parameterized typeclass with context parameter + given [A] => Ord[A] => Ord[List[A]]: + def compare(x: List[A], y: List[A]) = ... + + // Parameterized typeclass with named context parameter + given [A] => (ord: Ord[A]) => Ord[List[A]]: + def compare(x: List[A], y: List[A]) = ... + + // Simple alias + given Ord[Int] = IntOrd() + + // Parameterized alias with context bound + given [A: Ord] => Ord[List[A]] = + ListOrd[A] + + // Parameterized alias with context parameter + given [A] => Ord[A] => Ord[List[A]] = + ListOrd[A] + + // Deferred given + given Context = deferred + + // By-name given + given () => Context = curCtx +``` + +All of these clauses also exist in named form: +```scala + // Simple typeclass + given intOrd: Ord[Int]: + def compare(x: Int, y: Int) = ... + + // Parameterized typeclass with context bound + given listOrd: [A: Ord] => Ord[List[A]]: + def compare(x: List[A], y: List[A]) = ... + + // Parameterized typeclass with context parameter + given listOrd: [A] => Ord[A] => Ord[List[A]]: + def compare(x: List[A], y: List[A]) = ... + + // Parameterized typeclass with named context parameter + given listOrd: [A] => (ord: Ord[A]) => Ord[List[A]]: + def compare(x: List[A], y: List[A]) = ... + + // Simple alias + given intOrd: Ord[Int] = IntOrd() + + // Parameterized alias with context bound + given listOrd: [A: Ord] => Ord[List[A]] = + ListOrd[A] + + // Parameterized alias with context parameter + given listOrd: [A] => Ord[A] => Ord[List[A]] = + ListOrd[A] + + // Abstract or deferred given + given context: Context = deferred + + // By-name given + given context: () => Context = curCtx +``` diff --git a/docs/_docs/reference/contextual/multiversal-equality.md b/docs/_docs/reference/contextual/multiversal-equality.md index 6258973c0cda..fb980853ea8e 100644 --- a/docs/_docs/reference/contextual/multiversal-equality.md +++ b/docs/_docs/reference/contextual/multiversal-equality.md @@ -109,7 +109,7 @@ By the usual rules of [type class derivation](./derivation.md), this generates the following `CanEqual` instance in the companion object of `Box`: ```scala -given [T, U](using CanEqual[T, U]): CanEqual[Box[T], Box[U]] = +given [T, U] => CanEqual[T, U] => CanEqual[Box[T], Box[U]] = CanEqual.derived ``` diff --git a/docs/_docs/reference/contextual/previous-givens.md b/docs/_docs/reference/contextual/previous-givens.md new file mode 100644 index 000000000000..dc88daaab691 --- /dev/null +++ b/docs/_docs/reference/contextual/previous-givens.md @@ -0,0 +1,233 @@ +--- +layout: doc-page +title: "Previous Given Syntax" +nightlyOf: https://docs.scala-lang.org/scala3/reference/contextual/previous-givens.html +--- + +Given instances (or, simply, "givens") define "canonical" values of certain types +that serve for synthesizing arguments to [context parameters](./using-clauses.md). Example: + +```scala +trait Ord[T]: + def compare(x: T, y: T): Int + extension (x: T) + def < (y: T) = compare(x, y) < 0 + def > (y: T) = compare(x, y) > 0 + +given intOrd: Ord[Int] with + def compare(x: Int, y: Int) = + if x < y then -1 else if x > y then +1 else 0 + +given listOrd[T](using ord: Ord[T]): Ord[List[T]] with + + def compare(xs: List[T], ys: List[T]): Int = (xs, ys) match + case (Nil, Nil) => 0 + case (Nil, _) => -1 + case (_, Nil) => +1 + case (x :: xs1, y :: ys1) => + val fst = ord.compare(x, y) + if fst != 0 then fst else compare(xs1, ys1) + +``` + +This code defines a trait `Ord` with two given instances. `intOrd` defines +a given for the type `Ord[Int]` whereas `listOrd[T]` defines givens +for `Ord[List[T]]` for all types `T` that come with a given instance for `Ord[T]` +themselves. The `using` clause in `listOrd` defines a condition: There must be a +given of type `Ord[T]` for a given of type `Ord[List[T]]` to exist. +Such conditions are expanded by the compiler to [context parameters](./using-clauses.md). + +## Anonymous Givens + +The name of a given can be left out. So the definitions +of the last section can also be expressed like this: + +```scala +given Ord[Int] with + ... +given [T](using Ord[T]): Ord[List[T]] with + ... +``` + +If the name of a given is missing, the compiler will synthesize a name from +the implemented type(s). + +**Note:** The name synthesized by the compiler is chosen to be readable and reasonably concise. For instance, the two instances above would get the names: + +```scala +given_Ord_Int +given_Ord_List +``` + +The precise rules for synthesizing names are found [here](./relationship-implicits.html#anonymous-given-instances). These rules do not guarantee absence of name conflicts between +given instances of types that are "too similar". To avoid conflicts one can +use named instances. + +**Note:** To ensure robust binary compatibility, publicly available libraries should prefer named instances. + +## Alias Givens + +An alias can be used to define a given instance that is equal to some expression. Example: + +```scala +given global: ExecutionContext = ForkJoinPool() +``` + +This creates a given `global` of type `ExecutionContext` that resolves to the right +hand side `ForkJoinPool()`. +The first time `global` is accessed, a new `ForkJoinPool` is created, which is then +returned for this and all subsequent accesses to `global`. This operation is thread-safe. + +Alias givens can be anonymous as well, e.g. + +```scala +given Position = enclosingTree.position +given (using config: Config): Factory = MemoizingFactory(config) +``` + +An alias given can have type parameters and context parameters just like any other given, +but it can only implement a single type. + +## Abstract Givens + +A given may be an abstract member, with the restriction that it must have an explicit name. + +```scala +trait HasOrd[T]: + given ord: Ord[T] +``` + +## More Structural Givens + +If an alias given instance is analogous to a lazy val, +and a structural given instance is analogous to an object, +albeit an object with an explicit type, +then a structural given may also be specified without an explicit type: + +```scala +class IntOrd extends Ord[Int]: + def compare(x: Int, y: Int) = + if x < y then -1 else if x > y then +1 else 0 + +given IntOrd() +``` + +Compare this syntax to: + +```scala +object intOrd extends IntOrd() +``` + +The empty parentheses are optional in the extends clause when defining a class, +but are required when defining a given. + +Further mixins are allowed as usual: + +```scala +given IntOrd() with OrdOps[Int] +``` + +## Given Macros + +Given aliases can have the `inline` and `transparent` modifiers. +Example: + +```scala +transparent inline given mkAnnotations[A, T]: Annotations[A, T] = ${ + // code producing a value of a subtype of Annotations +} +``` + +Since `mkAnnotations` is `transparent`, the type of an application is the type of its right-hand side, which can be a proper subtype of the declared result type `Annotations[A, T]`. + +Given instances can have the `inline` but not `transparent` modifiers as their type is already known from the signature. +Example: + +```scala +trait Show[T] { + inline def show(x: T): String +} + +inline given Show[Foo] with { + /*transparent*/ inline def show(x: Foo): String = ${ ... } +} + +def app = + // inlines `show` method call and removes the call to `given Show[Foo]` + summon[Show[Foo]].show(foo) +``` +Note that the inline methods within the given instances may be `transparent`. + +The inlining of given instances will not inline/duplicate the implementation of the given, it will just inline the instantiation of that instance. +This is used to help dead code elimination of the given instances that are not used after inlining. + + +## Pattern-Bound Given Instances + +Given instances can also appear in patterns. Example: + +```scala +for given Context <- applicationContexts do + +pair match + case (ctx @ given Context, y) => ... +``` + +In the first fragment above, anonymous given instances for class `Context` are established by enumerating over `applicationContexts`. In the second fragment, a given `Context` +instance named `ctx` is established by matching against the first half of the `pair` selector. + +In each case, a pattern-bound given instance consists of `given` and a type `T`. The pattern matches exactly the same selectors as the type ascription pattern `_: T`. + +## Negated Givens + +Scala 2's somewhat puzzling behavior with respect to ambiguity has been exploited to implement the analogue of a "negated" search in implicit resolution, +where a query Q1 fails if some other query Q2 succeeds and Q1 succeeds if Q2 fails. With the new cleaned up behavior these techniques no longer work. +But the new special type [`scala.util.NotGiven`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) now implements negation directly. + +For any query type `Q`, [`NotGiven[Q]`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) succeeds if and only if the implicit +search for `Q` fails, for example: + +```scala +import scala.util.NotGiven + +trait Tagged[A] + +case class Foo[A](value: Boolean) +object Foo: + given fooTagged[A](using Tagged[A]): Foo[A] = Foo(true) + given fooNotTagged[A](using NotGiven[Tagged[A]]): Foo[A] = Foo(false) + +@main def test(): Unit = + given Tagged[Int]() + assert(summon[Foo[Int]].value) // fooTagged is found + assert(!summon[Foo[String]].value) // fooNotTagged is found +``` + +## Given Instance Initialization + +A given instance without type or context parameters is initialized on-demand, the first +time it is accessed. If a given has type or context parameters, a fresh instance +is created for each reference. + +## Syntax + +Here is the syntax for given instances: + +```ebnf +TmplDef ::= ... + | ‘given’ GivenDef +GivenDef ::= [GivenSig] StructuralInstance + | [GivenSig] AnnotType ‘=’ Expr + | [GivenSig] AnnotType +GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ +StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ TemplateBody] +``` + +A given instance starts with the reserved word `given` and an optional _signature_. The signature +defines a name and/or parameters for the instance. It is followed by `:`. There are three kinds +of given instances: + +- A _structural instance_ contains one or more types or constructor applications, + followed by `with` and a template body that contains member definitions of the instance. +- An _alias instance_ contains a type, followed by `=` and a right-hand side expression. +- An _abstract instance_ contains just the name and type, which is not followed by anything. diff --git a/docs/_docs/reference/contextual/relationship-implicits.md b/docs/_docs/reference/contextual/relationship-implicits.md index fce07f51151a..4ff38f709200 100644 --- a/docs/_docs/reference/contextual/relationship-implicits.md +++ b/docs/_docs/reference/contextual/relationship-implicits.md @@ -15,7 +15,7 @@ Given instances can be mapped to combinations of implicit objects, classes and i 1. Given instances without parameters are mapped to implicit objects. For instance, ```scala - given intOrd: Ord[Int] with { ... } + given intOrd: Ord[Int] { ... } ``` maps to @@ -27,7 +27,7 @@ Given instances can be mapped to combinations of implicit objects, classes and i 2. Parameterized givens are mapped to combinations of classes and implicit methods. For instance, ```scala - given listOrd[T](using ord: Ord[T]): Ord[List[T]] with { ... } + given listOrd: [T] => (ord: Ord[T]) => Ord[List[T]] { ... } ``` maps to @@ -63,8 +63,8 @@ final implicit def given_Context = ctx Anonymous given instances get compiler synthesized names, which are generated in a reproducible way from the implemented type(s). For example, if the names of the `IntOrd` and `ListOrd` givens above were left out, the following names would be synthesized instead: ```scala -given given_Ord_Int: Ord[Int] with { ... } -given given_Ord_List[T](using ord: Ord[T]): Ord[List[T]] with { ... } +given given_Ord_Int: Ord[Int] { ... } +given given_Ord_List: [T] => (ord: Ord[T]) => Ord[List[T]] { ... } ``` The synthesized type names are formed from @@ -153,7 +153,7 @@ implicit def stringToToken(str: String): Token = new Keyword(str) one can write ```scala -given stringToToken: Conversion[String, Token] with +given stringToToken: Conversion[String, Token]: def apply(str: String): Token = KeyWord(str) ``` diff --git a/docs/_docs/reference/contextual/type-classes.md b/docs/_docs/reference/contextual/type-classes.md index 6a15ac3a83d4..0e1ccdf8d2c8 100644 --- a/docs/_docs/reference/contextual/type-classes.md +++ b/docs/_docs/reference/contextual/type-classes.md @@ -27,7 +27,7 @@ trait Monoid[T] extends SemiGroup[T]: An implementation of this `Monoid` type class for the type `String` can be the following: ```scala -given Monoid[String] with +given Monoid[String]: extension (x: String) def combine (y: String): String = x.concat(y) def unit: String = "" ``` @@ -35,7 +35,7 @@ given Monoid[String] with Whereas for the type `Int` one could write the following: ```scala -given Monoid[Int] with +given Monoid[Int]: extension (x: Int) def combine (y: Int): Int = x + y def unit: Int = 0 ``` @@ -43,22 +43,8 @@ given Monoid[Int] with This monoid can now be used as _context bound_ in the following `combineAll` method: ```scala -def combineAll[T: Monoid](xs: List[T]): T = - xs.foldLeft(summon[Monoid[T]].unit)(_.combine(_)) -``` - -To get rid of the `summon[...]` we can define a `Monoid` object as follows: - -```scala -object Monoid: - def apply[T](using m: Monoid[T]) = m -``` - -Which would allow to re-write the `combineAll` method this way: - -```scala -def combineAll[T: Monoid](xs: List[T]): T = - xs.foldLeft(Monoid[T].unit)(_.combine(_)) +def combineAll[T: Monoid as m](xs: List[T]): T = + xs.foldLeft(m.unit)(_.combine(_)) ``` ## Functors @@ -77,7 +63,7 @@ Which could read as follows: "A `Functor` for the type constructor `F[_]` repres This way, we could define an instance of `Functor` for the `List` type: ```scala -given Functor[List] with +given Functor[List]: def map[A, B](x: List[A], f: A => B): List[B] = x.map(f) // List already has a `map` method ``` @@ -109,7 +95,7 @@ trait Functor[F[_]]: The instance of `Functor` for `List` now becomes: ```scala -given Functor[List] with +given Functor[List]: extension [A](xs: List[A]) def map[B](f: A => B): List[B] = xs.map(f) // List already has a `map` method @@ -159,7 +145,7 @@ end Monad A `List` can be turned into a monad via this `given` instance: ```scala -given listMonad: Monad[List] with +given listMonad: Monad[List]: def pure[A](x: A): List[A] = List(x) extension [A](xs: List[A]) @@ -176,7 +162,7 @@ it explicitly. `Option` is an other type having the same kind of behaviour: ```scala -given optionMonad: Monad[Option] with +given optionMonad: Monad[Option]: def pure[A](x: A): Option[A] = Option(x) extension [A](xo: Option[A]) @@ -223,7 +209,7 @@ type ConfigDependent[Result] = Config => Result The monad instance will look like this: ```scala -given configDependentMonad: Monad[ConfigDependent] with +given configDependentMonad: Monad[ConfigDependent]: def pure[A](x: A): ConfigDependent[A] = config => x @@ -244,7 +230,7 @@ type ConfigDependent = [Result] =>> Config => Result Using this syntax would turn the previous `configDependentMonad` into: ```scala -given configDependentMonad: Monad[[Result] =>> Config => Result] with +given configDependentMonad: Monad[[Result] =>> Config => Result]: def pure[A](x: A): Config => A = config => x @@ -259,7 +245,7 @@ end configDependentMonad It is likely that we would like to use this pattern with other kinds of environments than our `Config` trait. The Reader monad allows us to abstract away `Config` as a type _parameter_, named `Ctx` in the following definition: ```scala -given readerMonad[Ctx]: Monad[[X] =>> Ctx => X] with +given readerMonad: [Ctx] => Monad[[X] =>> Ctx => X]: def pure[A](x: A): Ctx => A = ctx => x diff --git a/docs/_docs/reference/contextual/using-clauses.md b/docs/_docs/reference/contextual/using-clauses.md index 9177a2f47dc9..9d03a7d2cec5 100644 --- a/docs/_docs/reference/contextual/using-clauses.md +++ b/docs/_docs/reference/contextual/using-clauses.md @@ -115,7 +115,7 @@ Multiple `using` clauses are matched left-to-right in applications. Example: ```scala object global extends Universe { type Context = ... } -given ctx : global.Context with { type Symbol = ...; type Kind = ... } +given ctx : global.Context { type Symbol = ...; type Kind = ... } given sym : ctx.Symbol given kind: ctx.Kind diff --git a/docs/_docs/reference/enums/enums.md b/docs/_docs/reference/enums/enums.md index 8d4fca3268b0..4cad29cbd76a 100644 --- a/docs/_docs/reference/enums/enums.md +++ b/docs/_docs/reference/enums/enums.md @@ -147,16 +147,13 @@ We now want to deprecate the `Pluto` case. First we add the `scala.deprecated` a Outside the lexical scopes of `enum Planet` or `object Planet`, references to `Planet.Pluto` will produce a deprecation warning, but within those scopes we can still reference it to implement introspection over the deprecated cases: ```scala -trait Deprecations[T <: reflect.Enum] { +trait Deprecations[T <: reflect.Enum]: extension (t: T) def isDeprecatedCase: Boolean -} -object Planet { - given Deprecations[Planet] with { +object Planet: + given Deprecations[Planet]: extension (p: Planet) def isDeprecatedCase = p == Pluto - } -} ``` We could imagine that a library may use [type class derivation](../contextual/derivation.md) to automatically provide an instance for `Deprecations`. @@ -167,7 +164,8 @@ If you want to use the Scala-defined enums as [Java enums](https://docs.oracle.c the class `java.lang.Enum`, which is imported by default, as follows: ```scala -enum Color extends Enum[Color] { case Red, Green, Blue } +enum Color extends Enum[Color]: + case Red, Green, Blue ``` The type parameter comes from the Java enum [definition](https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Enum.html) and should be the same as the type of the enum. diff --git a/docs/_docs/reference/experimental/erased-defs-spec.md b/docs/_docs/reference/experimental/erased-defs-spec.md index 59dfed92da2a..1861b734bb47 100644 --- a/docs/_docs/reference/experimental/erased-defs-spec.md +++ b/docs/_docs/reference/experimental/erased-defs-spec.md @@ -34,9 +34,9 @@ TODO: complete 3. Functions * `(erased x1: T1, x2: T2, ..., xN: TN) => y : (erased T1, T2, ..., TN) => R` - * `(given x1: T1, erased x2: T2, ..., xN: TN) => y: (given T1, erased T2, ..., TN) => R` - * `(given erased T1) => R <:< erased T1 => R` - * `(given T1, erased T2) => R <:< (T1, erased T2) => R` + * `(using x1: T1, erased x2: T2, ..., xN: TN) => y: (using T1, erased T2, ..., TN) => R` + * `(using erased T1) => R <:< erased T1 => R` + * `(using T1, erased T2) => R <:< (T1, erased T2) => R` * ... Note that there is no subtype relation between `(erased T) => R` and `T => R` (or `(given erased T) => R` and `(given T) => R`). The `erased` parameters must match exactly in their respective positions. diff --git a/docs/_docs/reference/experimental/numeric-literals.md b/docs/_docs/reference/experimental/numeric-literals.md index 8b7aaa23f9e0..8317e9ff83c4 100644 --- a/docs/_docs/reference/experimental/numeric-literals.md +++ b/docs/_docs/reference/experimental/numeric-literals.md @@ -168,7 +168,7 @@ To accept `BigFloat` literals, all that's needed in addition is a `given` instan `FromDigits.Floating[BigFloat]`: ```scala - given FromDigits: FromDigits.Floating[BigFloat] with + given FromDigits: FromDigits.Floating[BigFloat]: def fromDigits(digits: String) = apply(digits) end BigFloat ``` @@ -205,7 +205,7 @@ object BigFloat: class FromDigits extends FromDigits.Floating[BigFloat]: def fromDigits(digits: String) = apply(digits) - given FromDigits with + given FromDigits: override inline def fromDigits(digits: String) = ${ fromDigitsImpl('digits) } diff --git a/docs/_docs/reference/experimental/typeclasses.md b/docs/_docs/reference/experimental/typeclasses.md index 08839ffe58eb..c366c40779b9 100644 --- a/docs/_docs/reference/experimental/typeclasses.md +++ b/docs/_docs/reference/experimental/typeclasses.md @@ -4,7 +4,7 @@ title: "Better Support for Type Classes" nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/typeclasses.html --- -Martin Odersky, 8.1.2024, edited 5.4.2024 +Martin Odersky, 8.1.2024, edited 5.4.2024 and 30.9.2024 A type class in Scala is a pattern where we define @@ -18,13 +18,14 @@ a bit cumbersome and limiting for standard generic programming patterns. Much ha This note shows that with some fairly small and reasonable tweaks to Scala's syntax and typing rules we can obtain a much better scheme for working with type classes, or do generic programming in general. The bulk of the suggested improvements has been implemented and is available -under source version `future` if the additional experimental language import `modularity` is present. For instance, using the following command: +in under source version `future` if the additional experimental language import `modularity` is present. For instance, using the following command: ``` scala compile -source:future -language:experimental.modularity ``` -It is intended to turn features described here into proposals under the Scala improvement process. A first installment is SIP 64, which covers some syntactic changes, names for context bounds, multiple context bounds and deferred givens. The order of exposition described in this note is different from the planned proposals of SIPs. This doc is not a guide on how to sequence details, but instead wants to present a vision of what is possible. For instance, we start here with a feature (Self types and `is` syntax) that has turned out to be controversial and that will probably be proposed only late in the sequence of SIPs. +It is intended to turn features described here into proposals under the Scala improvement process. A first installment is SIP 64, which covers some syntactic changes, names for context bounds, multiple context bounds and deferred givens. This SIP has been accepted for inclusion in the language and will be released in Scala 3.6. The remaining elements +that concern type classes are described in the following. There is also a separate [page on modularity improvements](../modularity.md) that describes proposed additions not directly related to type classes. ## Generalizing Context Bounds @@ -145,70 +146,6 @@ This makes writing instance definitions and using clauses quite pleasant. Exampl (more examples will follow below) - - -## Naming Context Bounds - -Context bounds are a convenient and legible abbreviation. A problem so far is that they are always anonymous, -one cannot name the using parameter to which a context bound expands. - -For instance, consider a `reduce` method over `Monoid`s defined like this: - -```scala -def reduce[A : Monoid](xs: List[A]): A = ??? -``` -Since we don't have a name for the `Monoid` instance of `A`, we need to resort to `summon` in the body of `reduce`: -```scala -def reduce[A : Monoid](xs: List[A]): A = - xs.foldLeft(summon Monoid[A])(_ `combine` _) -``` -That's generally considered too painful to write and read, hence people usually adopt one of two alternatives. Either, eschew context bounds and switch to using clauses: -```scala -def reduce[A](xs: List[A])(using m: Monoid[A]): A = - xs.foldLeft(m)(_ `combine` _) -``` -Or, plan ahead and define a "trampoline" method in `Monoid`'s companion object: -```scala - trait Monoid[A] extends SemiGroup[A]: - def unit: A - object Monoid: - def unit[A](using m: Monoid[A]): A = m.unit - ... - def reduce[A : Monoid](xs: List[A]): A = - xs.foldLeft(Monoid.unit)(_ `combine` _) -``` -This is all accidental complexity which can be avoided by the following proposal. - -**Proposal:** Allow to name a context bound, like this: -```scala - def reduce[A : Monoid as m](xs: List[A]): A = - xs.foldLeft(m.unit)(_ `combine` _) -``` - -We use `as x` after the type to bind the instance to `x`. This is analogous to import renaming, which also introduces a new name for something that comes before. - -**Benefits:** The new syntax is simple and clear. -It avoids the awkward choice between concise context bounds that can't be named and verbose using clauses that can. - -### New Syntax for Aggregate Context Bounds - -Aggregate context bounds like `A : X : Y` are not obvious to read, and it becomes worse when we add names, e.g. `A : X as x : Y as y`. - -**Proposal:** Allow to combine several context bounds inside `{...}`, analogous -to import clauses. Example: - -```scala - trait: - def showMax[X : {Ordering, Show}](x: X, y: X): String - class B extends A: - def showMax[X : {Ordering as ordering, Show as show}](x: X, y: X): String = - show.asString(ordering.max(x, y)) -``` - -The old syntax with multiple `:` should be phased out over time. - -**Benefits:** The new syntax is much clearer than the old one, in particular for newcomers that don't know context bounds well. - ### Better Default Names for Context Bounds So far, an unnamed context bound for a type parameter gets a synthesized fresh name. It would be much more useful if it got the name of the constrained type parameter instead, translated to be a term name. This means our `reduce` method over monoids would not even need an `as` binding. We could simply formulate it as follows: @@ -233,330 +170,7 @@ The default naming convention reduces the need for named context bounds. But nam - They give an explanation what a single unnamed context bound expands to. -### Expansion of Context Bounds - -Context bounds are currently translated to implicit parameters in the last parameter list of a method or class. This is a problem if a context bound is mentioned in one of the preceding parameter types. For example, consider a type class of parsers with associated type members `Input` and `Result` describing the input type on which the parsers operate and the type of results they produce: -```scala -trait Parser[P]: - type Input - type Result -``` -Here is a method `run` that runs a parser on an input of the required type: - -```scala -def run[P : Parser](in: P.Input): P.Result -``` -Or, making clearer what happens by using an explicit name for the context bound: -```scala -def run[P : Parser as p](in: p.Input): p.Result -``` -With the current translation this does not work since it would be expanded to: -```scala - def run[P](x: p.Input)(using p: Parser[P]): p.Result -``` -Note that the `p` in `p.Input` refers to the `p` introduced in the using clause, which comes later. So this is ill-formed. - -This problem would be fixed by changing the translation of context bounds so that they expand to using clauses immediately after the type parameter. But such a change is infeasible, for two reasons: - - 1. It would be a binary-incompatible change. - 2. Putting using clauses earlier can impair type inference. A type in - a using clause can be constrained by term arguments coming before that - clause. Moving the using clause first would miss those constraints, which could cause ambiguities in implicit search. - -But there is an alternative which is feasible: - -**Proposal:** Map the context bounds of a method or class as follows: - - 1. If one of the bounds is referred to by its term name in a subsequent parameter clause, the context bounds are mapped to a using clause immediately preceding the first such parameter clause. - 2. Otherwise, if the last parameter clause is a using (or implicit) clause, merge all parameters arising from context bounds in front of that clause, creating a single using clause. - 3. Otherwise, let the parameters arising from context bounds form a new using clause at the end. - -Rules (2) and (3) are the status quo, and match Scala 2's rules. Rule (1) is new but since context bounds so far could not be referred to, it does not apply to legacy code. Therefore, binary compatibility is maintained. - -**Discussion** More refined rules could be envisaged where context bounds are spread over different using clauses so that each comes as late as possible. But it would make matters more complicated and the gain in expressiveness is not clear to me. - -Named (either explicitly, or by default) context bounds in givens that produce classes are mapped to tracked val's of these classes (see #18958). This allows -references to these parameters to be precise, so that information about dependent type members is preserved. - - -## Context Bounds for Type Members - -It's not very orthogonal to allow subtype bounds for both type parameters and abstract type members, but context bounds only for type parameters. What's more, we don't even have the fallback of an explicit using clause for type members. The only alternative is to also introduce a set of abstract givens that get implemented in each subclass. This is extremely heavyweight and opaque to newcomers. - -**Proposal**: Allow context bounds for type members. Example: - -```scala - class Collection: - type Element : Ord -``` - -The question is how these bounds are expanded. Context bounds on type parameters -are expanded into using clauses. But for type members this does not work, since we cannot refer to a member type of a class in a parameter type of that class. What we are after is an equivalent of using parameter clauses but represented as class members. - -**Proposal:** Introduce a new way to implement a given definition in a trait like this: -```scala -given T = deferred -``` -`deferred` is a new method in the `scala.compiletime` package, which can appear only as the right hand side of a given defined in a trait. Any class implementing that trait will provide an implementation of this given. If a definition is not provided explicitly, it will be synthesized by searching for a given of type `T` in the scope of the inheriting class. Specifically, the scope in which this given will be searched is the environment of that class augmented by its parameters but not containing its members (since that would lead to recursive resolutions). If an implementation _is_ provided explicitly, it counts as an override of a concrete definition and needs an `override` modifier. - -Deferred givens allow a clean implementation of context bounds in traits, -as in the following example: -```scala -trait Sorted: - type Element : Ord - -class SortedSet[A : Ord] extends Sorted: - type Element = A -``` -The compiler expands this to the following implementation: -```scala -trait Sorted: - type Element - given Ord[Element] = compiletime.deferred - -class SortedSet[A](using A: Ord[A]) extends Sorted: - type Element = A - override given Ord[Element] = A // i.e. the A defined by the using clause -``` - -The using clause in class `SortedSet` provides an implementation for the deferred given in trait `Sorted`. - -**Benefits:** - - - Better orthogonality, type parameters and abstract type members now accept the same kinds of bounds. - - Better ergonomics, since deferred givens get naturally implemented in inheriting classes, no need for boilerplate to fill in definitions of abstract givens. - -**Alternative:** It was suggested that we use a modifier for a deferred given instead of a `= deferred`. Something like `deferred given C[T]`. But a modifier does not suggest the concept that a deferred given will be implemented automatically in subclasses unless an explicit definition is written. In a sense, we can see `= deferred` as the invocation of a magic macro that is provided by the compiler. So from a user's point of view a given with `deferred` right hand side is not abstract. -It is a concrete definition where the compiler will provide the correct implementation. - -### Abolish Abstract Givens - -With `deferred` givens there is no need anymore to also define abstract givens. The two mechanisms are very similar, but the user experience for -deferred givens is generally more ergonomic. Abstract givens also are uncomfortably close to concrete class instances. Their syntax clashes -with the quite common case where we want to establish a given without any nested definitions. For instance, consider a given that constructs a type tag: -```scala -class Tag[T] -``` -Then this works: -```scala -given Tag[String]() -given Tag[String] with {} -``` -But the following more natural syntax fails: -```scala -given Tag[String] -``` -The last line gives a rather cryptic error: -``` -1 |given Tag[String] - | ^ - | anonymous given cannot be abstract -``` -The underlying problem is that abstract givens are very rare (and should become completely unnecessary once deferred givens are introduced), yet occupy a syntax that looks very close to the more common case of concrete -typeclasses without nested definitions. - -**Proposal:** In the future, let the `= deferred` mechanism be the only way to deliver the functionality of abstract givens. Deprecate the current version of abstract givens, and remove them in a future Scala version. - -**Benefits:** - - - Simplification of the language since a feature is dropped - - Eliminate non-obvious and misleading syntax. - -The only downside is that deferred givens are restricted to be used in traits, whereas abstract givens are also allowed in abstract classes. But I would be surprised if actual code relied on that difference, and such code could in any case be easily rewritten to accommodate the restriction. - -## New Given Syntax - -A good language syntax is like a Bach fugue: A small set of motifs is combined in a multitude of harmonic ways. Dissonances and irregularities should be avoided. - -When designing Scala 3, I believe that, by and large, we achieved that goal, except in one area, which is the syntax of givens. There _are_ some glaring dissonances, as seen in this code for defining an ordering on lists: -```scala -given [A](using Ord[A]): Ord[List[A]] with - def compare(x: List[A], y: List[A]) = ... -``` -The `:` feels utterly foreign in this position. It's definitely not a type ascription, so what is its role? Just as bad is the trailing `with`. Everywhere else we use braces or trailing `:` to start a scope of nested definitions, so the need of `with` sticks out like a sore thumb. - -Sometimes unconventional syntax grows on you and becomes natural after a while. But here it was unfortunately the opposite. The longer I used given definitions in this style the more awkward they felt, in particular since the rest of the language seemed so much better put together by comparison. And I believe many others agree with me on this. Since the current syntax is unnatural and esoteric, this means it's difficult to discover and very foreign even after that. This makes it much harder to learn and apply givens than it need be. - -The previous conditional given syntax was inspired from method definitions. If we add the optional name to the previous example, we obtain something akin to an implicit method in Scala 2: -```scala -given listOrd[A](using Ord[A]): Ord[List[A]] with - def compare(x: List[A], y: List[A]) = ... -``` -The anonymous syntax was then obtained by simply dropping the name. -But without a name, the syntax looks weird and inconsistent. - -This is a problem since at least for typeclasses, anonymous givens should be the norm. -Givens are like extends clauses. We state a _fact_, that a -type implements a type class, or that a value can be used implicitly. We don't need a name for that fact. It's analogous to extends clauses, where we state that a class is a subclass of some other class or trait. We would not think it useful to name an extends clause, it's simply a fact that is stated. -It's also telling that every other language that defines type classes uses anonymous syntax. Somehow, nobody ever found it necessary to name these instances. - -A more intuitive and in my opinion cleaner alternative is to decree that a given should always look like it _implements a type_. Conditional givens should look like they implement function types. The `Ord` typeclass instances for `Int` and `List` would then look like this: -```scala -given Ord[String]: - def compare(x: String, y: String) = ... - -given [A : Ord] => Ord[List[A]]: - def compare(x: List[A], y: List[A]) = ... -``` -The second, conditional instance looks like it implements the function type -```scala -[A : Ord] => Ord[List[A]] -``` -Another way to see this is as an implication: -If `A` is a type that is `Ord`, then `List[A]` is `Ord` (and the rest of the given clause gives the implementation that makes it so). -Equivalently, `A` is `Ord` _implies_ `List[A]` is `Ord`, hence the `=>`. - -Yet another related meaning is that the given clause establishes a _context function_ of type `[A: Ord] ?=> Ord[List[A]]` that is automatically applied to evidence arguments of type `Ord[A]` and that yields instances of type `Ord[List[A]]`. Since givens are in any case applied automatically to all their arguments, we don't need to specify that separately with `?=>`, a simple `=>` arrow is sufficiently clear and is easier to read. - -All these viewpoints are equivalent, in a deep sense. This is exactly the Curry Howard isomorphism, which equates function types and implications. - -In the new syntax, a `given` clause consists of the following elements: - - - An optional name binding `id :` - - Zero or more _conditions_, which introduce type or value parameters. Each precondition ends in a `=>`. - - the implemented _type_, - - an implementation which consists of either an `=` and an expression, - or a template body. - -**Examples:** - -Here is an enumeration of common forms of given definitions in the new syntax. We show the following use cases: - - 1. A simple typeclass instance, such as `Ord[Int]`. - 2. A parameterized type class instance, such as `Ord` for lists. - 3. A type class instance with an explicit context parameter. - 4. A type class instance with a named eexplicit context parameter. - 4. A simple given alias. - 5. A parameterized given alias - 6. A given alias with an explicit context parameter. - 8. An abstract or deferred given - 9. A by-name given, e.g. if we have a given alias of a mutable variable, and we - want to make sure that it gets re-evaluated on each access. -```scala - // Simple typeclass - given Ord[Int]: - def compare(x: Int, y: Int) = ... - - // Parameterized typeclass with context bound - given [A: Ord] => Ord[List[A]]: - def compare(x: List[A], y: List[A]) = ... - - // Parameterized typeclass with context parameter - given [A] => Ord[A] => Ord[List[A]]: - def compare(x: List[A], y: List[A]) = ... - - // Parameterized typeclass with named context parameter - given [A] => (ord: Ord[A]) => Ord[List[A]]: - def compare(x: List[A], y: List[A]) = ... - - // Simple alias - given Ord[Int] = IntOrd() - - // Parameterized alias with context bound - given [A: Ord] => Ord[List[A]] = - ListOrd[A] - - // Parameterized alias with context parameter - given [A] => Ord[A] => Ord[List[A]] = - ListOrd[A] - - // Abstract or deferred given - given Context = deferred - - // By-name given - given () => Context = curCtx -``` -Here are the same examples, with optional names provided: -```scala - // Simple typeclass - given intOrd: Ord[Int]: - def compare(x: Int, y: Int) = ... - - // Parameterized typeclass with context bound - given listOrd: [A: Ord] => Ord[List[A]]: - def compare(x: List[A], y: List[A]) = ... - - // Parameterized typeclass with context parameter - given listOrd: [A] => Ord[A] => Ord[List[A]]: - def compare(x: List[A], y: List[A]) = ... - - // Parameterized typeclass with named context parameter - given listOrd: [A] => (ord: Ord[A]) => Ord[List[A]]: - def compare(x: List[A], y: List[A]) = ... - - // Simple alias - given intOrd: Ord[Int] = IntOrd() - - // Parameterized alias with context bound - given listOrd: [A: Ord] => Ord[List[A]] = - ListOrd[A] - - // Parameterized alias with context parameter - given listOrd: [A] => Ord[A] => Ord[List[A]] = - ListOrd[A] - - // Abstract or deferred given - given context: Context = deferred - - // By-name given - given context: () => Context = curCtx -``` - -**By Name Givens** - -We sometimes find it necessary that a given alias is re-evaluated each time it is called. For instance, say we have a mutable variable `curCtx` and we want to define a given that returns the current value of that variable. A normal given alias will not do since by default given aliases are mapped to -lazy vals. - -In general, we want to avoid re-evaluation of the given. But there are situations like the one above where we want to specify _by-name_ evaluation instead. The proposed new syntax for this is shown in the last clause above. This is arguably the a natural way to express by-name givens. We want to use a conditional given, since these map to methods, but the set of preconditions is empty, hence the `()` parameter. Equivalently, under the context function viewpoint, we are defining a context function of the form `() ?=> T`, and these are equivalent to by-name parameters. - -Compare with the current best way to do achieve this, which is to use a dummy type parameter. -```scala - given [DummySoThatItsByName]: Context = curCtx -``` -This has the same effect, but feels more like a hack than a clean solution. - -**Dropping `with`** - -In the new syntax, all typeclass instances introduce definitions like normal -class bodies, enclosed in braces `{...}` or following a `:`. The irregular -requirement to use `with` is dropped. In retrospect, the main reason to introduce `with` was since a definition like - -```scala -given [A](using Ord[A]): Ord[List[A]]: - def compare(x: List[A], y: List[A]) = ... -``` -was deemed to be too cryptic, with the double meaning of colons. But since that syntax is gone, we don't need `with` anymore. There's still a double meaning of colons, e.g. in -```scala -given intOrd: Ord[Int]: - ... -``` -but since now both uses of `:` are very familiar (type ascription _vs_ start of nested definitions), it's manageable. Besides, the problem occurs only for named typeclass instances, which should be the exceptional case anyway. - - -**Possible ambiguities** - -If one wants to define a given for an a actual function type (which is probably not advisable in practice), one needs to enclose the function type in parentheses, i.e. `given ([A] => F[A])`. This is true in the currently implemented syntax and stays true for all discussed change proposals. - -The double meaning of : with optional prefix names is resolved as usual. A : at the end of a line starts a nested definition block. If for some obscure reason one wants to define a named given on multiple lines, one has to format it as follows: -```scala - given intOrd - : Ord = ... -``` - -**Summary** - -This will be a fairly significant change to the given syntax. I believe there's still a possibility to do this. Not so much code has migrated to new style givens yet, and code that was written can be changed fairly easily. Specifically, there are about a 900K definitions of `implicit def`s -in Scala code on Github and about 10K definitions of `given ... with`. So about 1% of all code uses the Scala 3 syntax, which would have to be changed again. - -Changing something introduced just recently in Scala 3 is not fun, -but I believe these adjustments are preferable to let bad syntax -sit there and fester. The cost of changing should be amortized by improved developer experience over time, and better syntax would also help in migrating Scala 2 style implicits to Scala 3. But we should do it quickly before a lot more code -starts migrating. - -Migration to the new syntax is straightforward, and can be supported by automatic rewrites. For a transition period we can support both the old and the new syntax. It would be a good idea to backport the new given syntax to the LTS version of Scala so that code written in this version can already use it. The current LTS would then support old and new-style givens indefinitely, whereas new Scala 3.x versions would phase out the old syntax over time. - - -### Bonus: Fixing Singleton +## Fixing Singleton We know the current treatment of `Singleton` as a type bound is broken since `x.type | y.type <: Singleton` holds by the subtyping rules for union types, even though `x.type | y.type` is clearly not a singleton. @@ -578,7 +192,7 @@ def f[X: Singleton](x: X) = ... The context bound is treated specially by the compiler so that no using clause is generated at runtime (this is straightforward, using the erased definitions mechanism). -### Bonus: Precise Typing +##: Precise Typing This approach also presents a solution to the problem how to express precise type variables. We can introduce another special type class `Precise` and use it like this: @@ -588,28 +202,6 @@ def f[X: Precise](x: X) = ... Like a `Singleton` bound, a `Precise` bound disables automatic widening of singleton types or union types in inferred instances of type variable `X`. But there is no requirement that the type argument _must_ be a singleton. -## Summary of Syntax Changes - -Here is the complete context-free syntax for all proposed features. -Overall the syntax for givens becomes a lot simpler than what it was before. - -``` -TmplDef ::= 'given' GivenDef -GivenDef ::= [GivenConditional '=>'] GivenSig -GivenConditional ::= [DefTypeParamClause | UsingParamClause] {UsingParamClause} -GivenSig ::= GivenType ['as' id] ([‘=’ Expr] | TemplateBody) - | ConstrApps ['as' id] TemplateBody -GivenType ::= AnnotType {id [nl] AnnotType} - -TypeDef ::= id [TypeParamClause] TypeAndCtxBounds -TypeParamBounds ::= TypeAndCtxBounds -TypeAndCtxBounds ::= TypeBounds [‘:’ ContextBounds] -ContextBounds ::= ContextBound | '{' ContextBound {',' ContextBound} '}' -ContextBound ::= Type ['as' id] -``` - - - ## Examples @@ -880,17 +472,12 @@ Pattern2 ::= InfixPattern ['as' id] ## Summary -I have proposed some tweaks to Scala 3, which would greatly increase its usability for modular, type class based, generic programming. The proposed changes are: +I have proposed some tweaks to Scala 3, which would increase its usability for modular, type class based, generic programming. The proposed changes are: 1. Allow context bounds over classes that define a `Self` member type. - 1. Allow context bounds to be named with `as`. Use the bound parameter name as a default name for the generated context bound evidence. - 1. Add a new `{...}` syntax for multiple context bounds. - 1. Make context bounds also available for type members, which expand into a new form of deferred given. Phase out the previous abstract givens in favor of the new form. 1. Add a predefined type alias `is`. - 1. Introduce a new cleaner syntax of given clauses. - -It's interesting that givens, which are a very general concept in Scala, were "almost there" when it comes to full support of concepts and generic programming. We only needed to add a few usability tweaks to context bounds, -alongside two syntactic changes that supersede the previous forms of `given .. with` clauses and abstract givens. Also interesting is that the superseded syntax constructs were the two areas where we collectively felt that the previous solutions were a bit awkward, but we could not think of better ones at the time. It's very nice that more satisfactory solutions are now emerging. + 1. If a type parameter or member `T` has context bound `CB`, use `T` as the default name for the witness of `CB`. + 1. Cleanup `Singleton` and add a new trait `Precise` for non-widening instantiation of type variables., ## Conclusion diff --git a/docs/_docs/reference/metaprogramming/macros-spec.md b/docs/_docs/reference/metaprogramming/macros-spec.md index 27a0a2c1bdcb..261f9002e1e6 100644 --- a/docs/_docs/reference/metaprogramming/macros-spec.md +++ b/docs/_docs/reference/metaprogramming/macros-spec.md @@ -121,7 +121,7 @@ Finally, the object defines `valueOfConstant` (and `valueOfTuple`) which can tra ```scala object Type: - given of[T <: AnyKind](using Quotes): Type[T] = ... + given of: [T <: AnyKind] => Quotes => Type[T] = ... def show[T <: AnyKind](using Type[T])(using Quotes): String = ... def valueOfConstant[T](using Type[T])(using Quotes): Option[T] = ... def valueOfTuple[T <: Tuple](using Type[T])(using Quotes): Option[T] = ... diff --git a/docs/_docs/reference/metaprogramming/macros.md b/docs/_docs/reference/metaprogramming/macros.md index b63616185285..43eb5b733aeb 100644 --- a/docs/_docs/reference/metaprogramming/macros.md +++ b/docs/_docs/reference/metaprogramming/macros.md @@ -100,7 +100,7 @@ We can implement a `ToExpr` using a `given` definition that will add the definit In the following example we show how to implement a `ToExpr[Option[T]]` for any liftable type `T. ```scala -given OptionToExpr[T: Type: ToExpr]: ToExpr[Option[T]] with +given OptionToExpr: [T: {Type, ToExpr}] => ToExpr[Option[T]]: def apply(opt: Option[T])(using Quotes): Expr[Option[T]] = opt match case Some(x) => '{ Some[T]( ${Expr(x)} ) } @@ -420,7 +420,7 @@ These value extraction sub-patterns can be polymorphic using an instance of `Fro In the following example, we show the implementation of `OptionFromExpr` which internally uses the `FromExpr[T]` to extract the value using the `Expr(x)` pattern. ```scala -given OptionFromExpr[T](using Type[T], FromExpr[T]): FromExpr[Option[T]] with +given OptionFromExpr: [T: {Type, FromExpr}] => FromExpr[Option[T]]: def unapply(x: Expr[Option[T]])(using Quotes): Option[Option[T]] = x match case '{ Some( ${Expr(x)} ) } => Some(Some(x)) diff --git a/docs/sidebar.yml b/docs/sidebar.yml index 5048669ef664..9bea2d6c099d 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -34,7 +34,11 @@ subsection: - page: reference/contextual/givens.md - page: reference/contextual/using-clauses.md - page: reference/contextual/context-bounds.md + - page: reference/contextual/deferred-givens.md - page: reference/contextual/given-imports.md + - page: reference/contextual/more-givens.md + - page: reference/contextual/previous-givens.md + hidden: true - page: reference/contextual/extension-methods.md - page: reference/contextual/right-associative-extension-methods.md - page: reference/contextual/type-classes.md From 907d73a2cb946d6e054d9198cc3b35974e79f323 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 30 Sep 2024 17:51:43 +0200 Subject: [PATCH 7/9] Update most tests to new syntax I left some tests to use the old syntax, just so that we have early warnings for possible regressions. But most tests are now using the new syntax, so that we best reassurance that corner cases work. --- tests/init/crash/i6914.scala | 8 +++---- tests/init/crash/i7821.scala | 6 ++--- tests/neg-macros/BigFloat/BigFloat_1.scala | 4 ++-- tests/neg-macros/GenericNumLits/Even_1.scala | 2 +- tests/neg-macros/i11483/Test_2.scala | 2 +- tests/neg-macros/i17152/DFBits.scala | 4 ++-- tests/neg-macros/i19601/Macro.scala | 2 +- tests/neg-macros/i7919.scala | 6 ++--- .../GenericNumLits/Even_1.scala | 2 +- tests/neg/17579.check | 2 +- tests/neg/17579.scala | 2 +- tests/neg/19414.scala | 2 +- tests/neg/21538.scala | 2 +- tests/neg/abstract-givens.check | 2 +- tests/neg/abstract-givens.scala | 2 +- tests/neg/eql.scala | 2 +- tests/neg/exports.scala | 2 +- tests/neg/extmethod-overload.scala | 19 +++++++-------- .../neg/gadt-approximation-interaction.scala | 2 +- tests/neg/genericNumbers.scala | 6 ++--- tests/neg/given-loop-prevention.scala | 4 ++-- tests/neg/i10901.scala | 2 +- tests/neg/i11985.scala | 4 +--- tests/neg/i14177a.scala | 2 +- tests/neg/i15474b.scala | 2 +- tests/neg/i16453.scala | 2 +- tests/neg/i19328conversion.scala | 2 +- tests/neg/i5978.scala | 2 +- tests/neg/i6716.scala | 4 ++-- tests/neg/i7459.scala | 2 +- tests/neg/i8896-a.scala | 3 +-- tests/neg/i8896-b.scala | 3 +-- tests/neg/i9185.scala | 4 ++-- tests/neg/i9928.scala | 4 ++-- tests/neg/implicit-package-object.scala | 4 ++-- tests/neg/implied-for.scala | 4 ++-- tests/neg/import-given.scala | 2 +- tests/neg/missing-implicit6.check | 24 +++++++++---------- tests/neg/missing-implicit6.scala | 6 ++--- tests/neg/struct-given.scala | 2 +- tests/patmat/i6088.scala | 2 +- tests/pos-custom-args/captures/i16116.scala | 2 +- .../exprSummonWithTypeVar/Macro_1.scala | 4 ++-- tests/pos-macros/i13021/Width.scala | 2 +- tests/pos-macros/i18228.scala | 2 +- tests/pos-macros/macro-docs.scala | 6 ++--- tests/pos-macros/nil-liftable.scala | 2 +- tests/pos/20088.scala | 2 +- tests/pos/X.scala | 4 ++-- tests/pos/bson/bson.scala | 4 ++-- tests/pos/cbproxy-expansion.scala | 2 +- tests/pos/combine.scala | 2 +- tests/pos/end-given.scala | 2 +- tests/pos/erased-conforms.scala | 2 +- tests/pos/ext-override.scala | 2 +- tests/pos/givenFallback.scala | 6 ++--- tests/pos/hylolib-cb-extract.scala | 2 +- tests/pos/hylolib-cb/AnyCollection.scala | 8 ++----- tests/pos/hylolib-cb/AnyValue.scala | 2 +- tests/pos/hylolib-cb/BitArray.scala | 6 ++--- tests/pos/hylolib-cb/Integers.scala | 8 +++---- tests/pos/hylolib-cb/Slice.scala | 2 +- .../pos/hylolib-deferred-given-extract.scala | 4 ++-- .../AnyCollection.scala | 2 +- .../pos/hylolib-deferred-given/AnyValue.scala | 2 +- .../pos/hylolib-deferred-given/BitArray.scala | 6 ++--- .../pos/hylolib-deferred-given/HyArray.scala | 4 ++-- .../pos/hylolib-deferred-given/Integers.scala | 8 +++---- tests/pos/hylolib-deferred-given/Slice.scala | 2 +- tests/pos/i10259.scala | 2 +- tests/pos/i10929.scala | 4 ++-- tests/pos/i11174minimisation.scala | 2 +- tests/pos/i11175.scala | 4 ++-- tests/pos/i11243.scala | 8 +++---- tests/pos/i11538a.scala | 2 +- tests/pos/i11732.scala | 2 +- tests/pos/i11864.scala | 2 +- tests/pos/i12126.scala | 6 ++--- tests/pos/i12379b.scala | 2 +- tests/pos/i12591/Inner.scala | 2 +- tests/pos/i12910.scala | 4 ++-- tests/pos/i12945/A_1.scala | 2 +- tests/pos/i12949.scala | 6 ++--- tests/pos/i13001/Main_1.scala | 4 ++-- tests/pos/i13044.scala | 2 +- tests/pos/i13460.scala | 6 ++--- tests/pos/i13503.scala | 2 +- tests/pos/i13668.scala | 2 +- tests/pos/i13900.scala | 4 ++-- tests/pos/i14013.scala | 2 +- tests/pos/i14177b.scala | 10 ++++---- tests/pos/i14282.scala | 8 +++---- tests/pos/i14637.scala | 2 +- tests/pos/i15160.scala | 2 +- tests/pos/i15177.hylolib.scala | 2 +- tests/pos/i15183/decoder_1.scala | 6 ++--- tests/pos/i15264.scala | 6 ++--- tests/pos/i15331.scala | 2 +- tests/pos/i15664.scala | 2 +- tests/pos/i15670.scala | 4 ++-- tests/pos/i15867.scala | 2 +- tests/pos/i15867.specs2.scala | 2 +- tests/pos/i16104.scala | 2 +- tests/pos/i16596.more.scala | 2 +- tests/pos/i17002.scala | 2 +- tests/pos/i18062.scala | 2 +- tests/pos/i18175.scala | 4 ++-- tests/pos/i18211.scala | 2 +- tests/pos/i18253.orig.scala | 2 +- tests/pos/i18253.scala | 2 +- tests/pos/i18261.min/Main_0.scala | 2 +- tests/pos/i18261/DFBits_0.scala | 2 +- tests/pos/i18276a.scala | 2 +- tests/pos/i19404.scala | 2 +- tests/pos/i19407.scala | 2 +- tests/pos/i19623.scala | 2 +- tests/pos/i19724.scala | 2 +- tests/pos/i19749.scala | 2 +- tests/pos/i19857.scala | 2 +- tests/pos/i19942.1.scala | 4 ++-- tests/pos/i19955a.scala | 4 ++-- tests/pos/i19955b.scala | 4 ++-- tests/pos/i20053b.scala | 4 ++-- tests/pos/i20080.scala | 14 +++++------ tests/pos/i20344.scala | 2 +- tests/pos/i20377.scala | 2 +- tests/pos/i20572.scala | 4 ++-- tests/pos/i20858/defns_1.scala | 2 +- tests/pos/i21036.scala | 6 ++--- tests/pos/i21303/Test.scala | 4 ++-- tests/pos/i21303a/Test.scala | 6 ++--- tests/pos/i21320a.scala | 4 ++-- tests/pos/i21320b.scala | 4 ++-- tests/pos/i21352a/schema.scala | 2 +- tests/pos/i21352a/schemaDerivation.scala | 2 +- tests/pos/i21352b.scala | 4 ++-- tests/pos/i21352c.scala | 2 +- tests/pos/i21390.zio.scala | 2 +- tests/pos/i5915.scala | 4 ++-- tests/pos/i5978.scala | 8 +++---- tests/pos/i6716.scala | 2 +- tests/pos/i6900.scala | 2 +- tests/pos/i6914.scala | 4 ++-- tests/pos/i6938.scala | 6 ++--- tests/pos/i7056.scala | 2 +- tests/pos/i7375.scala | 4 ++-- tests/pos/i7413.scala | 2 +- tests/pos/i7586.scala | 11 +++++---- tests/pos/i7851.scala | 8 +++---- tests/pos/i7868.scala | 5 ++-- tests/pos/i7878.scala | 2 +- tests/pos/i8182.scala | 4 ++-- tests/pos/i8198.scala | 2 +- tests/pos/i8276.scala | 2 +- tests/pos/i8344-1.scala | 2 +- tests/pos/i8397.scala | 14 +++++------ tests/pos/i8623.scala | 2 +- tests/pos/i8825.scala | 2 +- tests/pos/i8927.scala | 2 +- tests/pos/i9342b.scala | 2 +- tests/pos/i9530.scala | 4 ++-- tests/pos/implicit-conversion.scala | 2 +- .../pos/implicit-prefix-disambiguation.scala | 2 +- tests/pos/interleaving-functor.scala | 2 +- tests/pos/mt-deskolemize.scala | 2 +- tests/pos/multi-given.scala | 2 ++ tests/pos/multiversal.scala | 2 +- tests/pos/not-looping-implicit.scala | 2 +- tests/pos/ord-over-tracked.scala | 2 +- tests/pos/parsercombinators-ctx-bounds.scala | 2 +- tests/pos/parsercombinators-givens-2.scala | 2 +- tests/pos/parsercombinators-givens.scala | 2 +- tests/pos/parsercombinators-this.scala | 2 +- tests/pos/phantom-Eq.scala | 2 +- tests/pos/phantom-Eq2/Phantom-Eq_1.scala | 2 +- tests/pos/phantom-Evidence.scala | 2 +- tests/pos/reference/delegates.scala | 18 +++++++------- tests/pos/reference/extension-methods.scala | 4 ++-- tests/pos/suspend-strawman/choices.scala | 2 +- tests/pos/suspend-strawman/generators.scala | 4 ++-- .../suspend-strawman/monadic-reflect.scala | 2 +- .../pos/suspend-strawman/simple-futures.scala | 2 +- tests/pos/the.scala | 2 +- .../pos/toplevel-opaque-xm/Logarithm_1.scala | 2 +- tests/pos/typeclass-aggregates.scala | 2 +- tests/pos/typeclasses-this.scala | 12 +++++----- tests/pos/typeclasses.scala | 10 ++++---- tests/run-macros/BigFloat/BigFloat_1.scala | 4 ++-- .../Derivation_1.scala | 2 +- tests/run/Signals.scala | 2 +- tests/run/Typeable.scala | 4 ++-- tests/run/abstract-givens.scala | 2 +- tests/run/cochis-example.scala | 2 +- tests/run/extension-specificity2.scala | 8 +++---- tests/run/extmethod-overload.scala | 2 +- tests/run/extmethods2.scala | 2 +- tests/run/fragables-extension.scala | 4 ++-- tests/run/genericNumLits.scala | 2 +- tests/run/given-eta.scala | 2 +- tests/run/i11050.scala | 6 ++--- tests/run/i11174.scala | 2 +- tests/run/i11174local.scala | 4 ++-- tests/run/i11542.scala | 2 +- tests/run/i11542a.scala | 2 +- tests/run/i11563.scala | 2 +- tests/run/i11583.scala | 4 ++-- tests/run/i11961.scala | 6 ++--- tests/run/i11966.scala | 4 ++-- tests/run/i12328.scala | 2 +- tests/run/i13146.scala | 6 ++--- tests/run/i13146a.scala | 4 ++-- tests/run/i13146poly.scala | 6 ++--- tests/run/i13304.scala | 4 ++-- tests/run/i13332shapeless.scala | 4 ++-- tests/run/i14150.scala | 2 +- tests/run/i17115.scala | 4 ++-- tests/run/i6716.scala | 2 +- tests/run/i7788.scala | 4 ++-- tests/run/i9011.scala | 4 ++-- tests/run/i9473.scala | 4 ++-- tests/run/i9530.scala | 2 +- tests/run/i9928.scala | 6 ++--- tests/run/ift-return.scala | 4 ++-- tests/run/implicit-alias.scala | 2 +- tests/run/implicit-specifity.scala | 12 +++++----- tests/run/implied-priority.scala | 6 ++--- tests/run/inline-numeric/Fractional.scala | 6 ++--- tests/run/inline-numeric/Integral.scala | 14 +++++------ tests/run/instances-anonymous.scala | 12 +++++----- tests/run/instances.scala | 10 ++++---- tests/run/poly-kinded-derives.scala | 14 +++++------ tests/run/publicInBinary/Lib_1.scala | 4 ++-- ...ng-context-implicits-with-conversion.scala | 2 +- tests/run/structural-contextual.scala | 2 +- tests/run/tagless.scala | 18 +++++++------- .../typeclass-derivation-doc-example.scala | 4 ++-- tests/run/tyql.scala | 2 +- tests/warn/implicit-conversions.scala | 6 ++--- 238 files changed, 451 insertions(+), 468 deletions(-) diff --git a/tests/init/crash/i6914.scala b/tests/init/crash/i6914.scala index 723b2ef94e0b..b5f848626772 100644 --- a/tests/init/crash/i6914.scala +++ b/tests/init/crash/i6914.scala @@ -5,7 +5,7 @@ object test1 { class ToExpr[T](using Liftable[T]) extends Conversion[T, Expr[T]] { def apply(x: T): Expr[T] = ??? } - given toExprFun[T](using Liftable[T]): ToExpr[T] with {} + given toExprFun: [T] => Liftable[T] => ToExpr[T]() given Liftable[Int] = ??? given Liftable[String] = ??? @@ -16,14 +16,12 @@ object test1 { def a: Expr[String] = "abc" } -object test2 { +object test2: - given autoToExpr[T](using Liftable[T]): Conversion[T, Expr[T]] with { + given autoToExpr: [T] => Liftable[T] => Conversion[T, Expr[T]]: def apply(x: T): Expr[T] = ??? - } given Liftable[Int] = ??? given Liftable[String] = ??? def a: Expr[String] = "abc" -} \ No newline at end of file diff --git a/tests/init/crash/i7821.scala b/tests/init/crash/i7821.scala index 1574801826bc..f99037573c75 100644 --- a/tests/init/crash/i7821.scala +++ b/tests/init/crash/i7821.scala @@ -3,9 +3,8 @@ object XObject { def anX: X = 5 - given ops: Object with { + given ops: Object: extension (x: X) def + (y: X): X = x + y - } } object MyXObject { @@ -13,9 +12,8 @@ object MyXObject { def anX: MyX = XObject.anX - given ops: Object with { + given ops: Object: extension (x: MyX) def + (y: MyX): MyX = x + y // error: warring: Infinite recursive call - } } object Main extends App { diff --git a/tests/neg-macros/BigFloat/BigFloat_1.scala b/tests/neg-macros/BigFloat/BigFloat_1.scala index 5bb5b49587bd..246e3dcd442d 100644 --- a/tests/neg-macros/BigFloat/BigFloat_1.scala +++ b/tests/neg-macros/BigFloat/BigFloat_1.scala @@ -35,7 +35,7 @@ object BigFloat extends App { def fromDigits(digits: String) = apply(digits) } - given BigFloatFromDigits with { + given BigFloatFromDigits { override inline def fromDigits(digits: String) = ${ BigFloatFromDigitsImpl('digits) } @@ -43,7 +43,7 @@ object BigFloat extends App { // Should be in StdLib: - given ToExpr[BigInt] with { + given ToExpr[BigInt] { def apply(x: BigInt)(using Quotes) = '{BigInt(${Expr(x.toString)})} } diff --git a/tests/neg-macros/GenericNumLits/Even_1.scala b/tests/neg-macros/GenericNumLits/Even_1.scala index 24bcf32cc7c0..5772d98d3808 100644 --- a/tests/neg-macros/GenericNumLits/Even_1.scala +++ b/tests/neg-macros/GenericNumLits/Even_1.scala @@ -16,7 +16,7 @@ object Even { def fromDigits(digits: String) = evenFromDigits(digits) } - given EvenFromDigits with { + given EvenFromDigits { override transparent inline def fromDigits(digits: String) = ${ EvenFromDigitsImpl('digits) } diff --git a/tests/neg-macros/i11483/Test_2.scala b/tests/neg-macros/i11483/Test_2.scala index 6fe975168684..e61716615d22 100644 --- a/tests/neg-macros/i11483/Test_2.scala +++ b/tests/neg-macros/i11483/Test_2.scala @@ -3,7 +3,7 @@ package x import scala.language.implicitConversions import scala.concurrent.Future -given FutureAsyncMonad: CpsMonad[Future] with +given FutureAsyncMonad: CpsMonad[Future]: def pure[T](t:T): Future[T] = ??? def impure[T](t:Future[T]): T = ??? def map[A,B](x:Future[A])(f: A=>B): Future[B] = ??? diff --git a/tests/neg-macros/i17152/DFBits.scala b/tests/neg-macros/i17152/DFBits.scala index dd0e8b88a962..a88485b56dc6 100644 --- a/tests/neg-macros/i17152/DFBits.scala +++ b/tests/neg-macros/i17152/DFBits.scala @@ -16,7 +16,7 @@ trait Baz trait Width[T]: type Out <: Int object Width: - given fromDFBoolOrBit[T <: DFBoolOrBit]: Width[T] with + given fromDFBoolOrBit: [T <: DFBoolOrBit] => Width[T]: type Out = 1 transparent inline given [T]: Width[T] = ${ getWidthMacro[T] } def getWidthMacro[T](using Quotes, Type[T]): Expr[Width[T]] = @@ -38,7 +38,7 @@ private object CompanionsDFBits: type OutW <: Int def apply(value: R): DFValOf[DFBits[OutW]] object Candidate: - given fromDFUInt[W <: Int, R <: DFValOf[DFDecimal]]: Candidate[R] with + given fromDFUInt: [W <: Int, R <: DFValOf[DFDecimal]] => Candidate[R]: type OutW = W def apply(value: R): DFValOf[DFBits[W]] = import DFVal.Ops.bits diff --git a/tests/neg-macros/i19601/Macro.scala b/tests/neg-macros/i19601/Macro.scala index 8d6d22005017..06260ab8c981 100644 --- a/tests/neg-macros/i19601/Macro.scala +++ b/tests/neg-macros/i19601/Macro.scala @@ -10,7 +10,7 @@ object Macros { '{ () } } - given [A](using Type[A]): FromExpr[Assertion[A]] with { + given [A] => Type[A] => FromExpr[Assertion[A]] { def unapply(assertion: Expr[Assertion[A]])(using Quotes): Option[Assertion[A]] = { import quotes.reflect.* diff --git a/tests/neg-macros/i7919.scala b/tests/neg-macros/i7919.scala index e68965fc614f..74863282e09a 100644 --- a/tests/neg-macros/i7919.scala +++ b/tests/neg-macros/i7919.scala @@ -3,16 +3,16 @@ import scala.quoted.* object Test { def staged[T](using Quotes) = { import quotes.reflect.* - given typeT: Type[T] with {} // error + given typeT: Type[T] {} // error val tt = TypeRepr.of[T] '{ "in staged" } } - given Expr[Int] with {} // error + given Expr[Int] {} // error new Expr[Int] // error class Expr2 extends Expr[Int] // error - given Type[Int] with {} // error + given Type[Int] {} // error new Type[Int] // error class Type2 extends Type[Int] // error diff --git a/tests/neg-with-compiler/GenericNumLits/Even_1.scala b/tests/neg-with-compiler/GenericNumLits/Even_1.scala index 0867150dd944..7f5824b30957 100644 --- a/tests/neg-with-compiler/GenericNumLits/Even_1.scala +++ b/tests/neg-with-compiler/GenericNumLits/Even_1.scala @@ -16,7 +16,7 @@ object Even { def fromDigits(digits: String) = evenFromDigits(digits) } - given EvenFromDigits with { + given EvenFromDigits { override inline def fromDigits(digits: String) = ${ EvenFromDigitsImpl('digits) } diff --git a/tests/neg/17579.check b/tests/neg/17579.check index 1149f9c0faa4..24b7d354dcb6 100644 --- a/tests/neg/17579.check +++ b/tests/neg/17579.check @@ -25,6 +25,6 @@ | | longer explanation available when compiling with `-explain` -- [E147] Syntax Warning: tests/neg/17579.scala:19:6 ------------------------------------------------------------------- -19 | final given Object with {} // warning: modifier `final` is redundant for this definition +19 | final given Object() // warning: modifier `final` is redundant for this definition | ^^^^^ | Modifier final is redundant for this definition diff --git a/tests/neg/17579.scala b/tests/neg/17579.scala index 268199e9006f..0ffd20d4b267 100644 --- a/tests/neg/17579.scala +++ b/tests/neg/17579.scala @@ -16,7 +16,7 @@ class C: { // No error in this case, because the `given` is translated to a class // definition, for which `final` is redundant but not illegal. - final given Object with {} // warning: modifier `final` is redundant for this definition + final given Object() // warning: modifier `final` is redundant for this definition } { diff --git a/tests/neg/19414.scala b/tests/neg/19414.scala index bb275ad943b7..8843441e81f2 100644 --- a/tests/neg/19414.scala +++ b/tests/neg/19414.scala @@ -9,7 +9,7 @@ class Printer given Writer[JsValue] = ??? given Writer[JsObject] = ??? -given [B: Writer](using printer: Printer = new Printer): BodySerializer[B] = ??? +given [B: Writer] => (printer: Printer = new Printer) => BodySerializer[B] = ??? def f: Unit = summon[BodySerializer[JsObject]] // error: Ambiguous given instances diff --git a/tests/neg/21538.scala b/tests/neg/21538.scala index 761e9cde678a..66500277159e 100644 --- a/tests/neg/21538.scala +++ b/tests/neg/21538.scala @@ -1,3 +1,3 @@ trait Bar[T] -given [T]: Bar[T] with {} +given [T] => Bar[T]() inline def foo[V](inline value: V)(using Bar[value.type]) : Unit = {} // error \ No newline at end of file diff --git a/tests/neg/abstract-givens.check b/tests/neg/abstract-givens.check index 022c454c31f1..1430c5b6e950 100644 --- a/tests/neg/abstract-givens.check +++ b/tests/neg/abstract-givens.check @@ -1,5 +1,5 @@ -- Error: tests/neg/abstract-givens.scala:11:8 ------------------------------------------------------------------------- -11 | given s[T](using T): Seq[T] with // error +11 | given s: [T] => T => Seq[T]: // error | ^ |instance cannot be created, since def iterator: Iterator[A] in trait IterableOnce in package scala.collection is not defined -- [E164] Declaration Error: tests/neg/abstract-givens.scala:8:8 ------------------------------------------------------- diff --git a/tests/neg/abstract-givens.scala b/tests/neg/abstract-givens.scala index 5aa5bdee88e3..dbd4a7a85927 100644 --- a/tests/neg/abstract-givens.scala +++ b/tests/neg/abstract-givens.scala @@ -8,7 +8,7 @@ object Test extends T: given y(using Int): String = summon[Int].toString * 22 // error given z[T](using T): Seq[T] = List(summon[T]) // error - given s[T](using T): Seq[T] with // error + given s: [T] => T => Seq[T]: // error def apply(x: Int) = ??? override def length = ??? diff --git a/tests/neg/eql.scala b/tests/neg/eql.scala index 58378800bbc5..40ec1fb5d9ed 100644 --- a/tests/neg/eql.scala +++ b/tests/neg/eql.scala @@ -1,7 +1,7 @@ object lst: opaque type Lst[+T] = Any object Lst: - given lstCanEqual[T, U]: CanEqual[Lst[T], Lst[U]] = CanEqual.derived + given lstCanEqual: [T, U] => CanEqual[Lst[T], Lst[U]] = CanEqual.derived val Empty: Lst[Nothing] = ??? end lst diff --git a/tests/neg/exports.scala b/tests/neg/exports.scala index c187582c940d..459a56e88c4f 100644 --- a/tests/neg/exports.scala +++ b/tests/neg/exports.scala @@ -5,7 +5,7 @@ type PrinterType def print(bits: BitMap): Unit = ??? def status: List[String] = ??? - given bitmap: BitMap with {} + given bitmap: BitMap() } class Scanner { diff --git a/tests/neg/extmethod-overload.scala b/tests/neg/extmethod-overload.scala index 8fa7c05222a1..ef927c0be6ce 100644 --- a/tests/neg/extmethod-overload.scala +++ b/tests/neg/extmethod-overload.scala @@ -1,16 +1,15 @@ -object Test { - given a: AnyRef with - extension (x: Int) { +object Test: + + given a: AnyRef: + extension (x: Int) def |+| (y: Int) = x + y - } - given b: AnyRef with - extension (x: Int) { + + given b: AnyRef: + extension (x: Int) def |+| (y: String) = x + y.length - } + assert((1 |+| 2) == 3) // error ambiguous - locally { + locally: import b.|+| assert((1 |+| "2") == 2) // OK - } -} \ No newline at end of file diff --git a/tests/neg/gadt-approximation-interaction.scala b/tests/neg/gadt-approximation-interaction.scala index 5f010e4b784d..a6bfe0d44007 100644 --- a/tests/neg/gadt-approximation-interaction.scala +++ b/tests/neg/gadt-approximation-interaction.scala @@ -28,7 +28,7 @@ object GivenLookup { class Tag[T] - given ti: Tag[Int] with {} + given ti: Tag[Int]() def foo[T](t: T, ev: T SUB Int) = ev match { case SUB.Refl() => diff --git a/tests/neg/genericNumbers.scala b/tests/neg/genericNumbers.scala index 0c5769f7ba12..7c08caeb4e9d 100644 --- a/tests/neg/genericNumbers.scala +++ b/tests/neg/genericNumbers.scala @@ -7,13 +7,11 @@ object Test extends App { case class Even(n: Int) - given FromDigits[Even] with { - def fromDigits(digits: String): Even = { + given FromDigits[Even]: + def fromDigits(digits: String): Even = val intValue = digits.toInt if (intValue % 2 == 0) Even(intValue) else throw FromDigits.MalformedNumber() - } - } val e: Even = 1234 // error diff --git a/tests/neg/given-loop-prevention.scala b/tests/neg/given-loop-prevention.scala index 9d404b8c6d8e..9ad2163a4bf8 100644 --- a/tests/neg/given-loop-prevention.scala +++ b/tests/neg/given-loop-prevention.scala @@ -2,11 +2,11 @@ class Foo object Bar { - given Foo with {} + given Foo() given List[Foo] = List(summon[Foo]) // ok } object Baz { given List[Foo] = List(summon[Foo]) // error - given Foo with {} + given Foo() } diff --git a/tests/neg/i10901.scala b/tests/neg/i10901.scala index dc1ea6e6eef6..996a0753c2e7 100644 --- a/tests/neg/i10901.scala +++ b/tests/neg/i10901.scala @@ -53,7 +53,7 @@ object BugExp4Point2D { class C object Container: - given C with {} + given C() object Test: extension (x: String)(using C) diff --git a/tests/neg/i11985.scala b/tests/neg/i11985.scala index fee056594974..52313ab09c99 100644 --- a/tests/neg/i11985.scala +++ b/tests/neg/i11985.scala @@ -11,10 +11,8 @@ object Test { def get(t: TT): C } - given [T <: Tuple, C, EV <: TupleTypeIndex[T, C]]: TupleExtractor[T, C] with { + given [T <: Tuple, C, EV <: TupleTypeIndex[T, C]] => TupleExtractor[T, C]: def get(t: T): C = t.toArray.apply(toIntC[TupleTypeIndex[T, C]]).asInstanceOf[C] // error - } - transparent inline def toIntC[N <: Int]: Int = inline constValue[N] match diff --git a/tests/neg/i14177a.scala b/tests/neg/i14177a.scala index 237eaacb3b66..91a63bdd6345 100644 --- a/tests/neg/i14177a.scala +++ b/tests/neg/i14177a.scala @@ -2,5 +2,5 @@ import scala.compiletime.* trait C[A] -inline given [Tup <: Tuple]: C[Tup] with +inline given [Tup <: Tuple] => C[Tup]: val cs = summonAll[Tuple.Map[Tup, C]] // error: Tuple element types must be known at compile time diff --git a/tests/neg/i15474b.scala b/tests/neg/i15474b.scala index 0c04b9880e1c..0a99056f8a6e 100644 --- a/tests/neg/i15474b.scala +++ b/tests/neg/i15474b.scala @@ -3,6 +3,6 @@ import scala.language.implicitConversions object Test1: - given c: Conversion[ String, Int ] with + given c: Conversion[ String, Int ]: def apply(from: String): Int = from.toInt // warn: infinite loop in function body // nopos-error: No warnings can be incurred under -Werror (or -Xfatal-warnings) diff --git a/tests/neg/i16453.scala b/tests/neg/i16453.scala index 00495c39e21a..b5767ac35417 100644 --- a/tests/neg/i16453.scala +++ b/tests/neg/i16453.scala @@ -12,7 +12,7 @@ def testScala3() = { given Conversion[Char, String] = ??? given Conversion[Char, Option[Int]] = ??? - given foo: Foo with + given foo: Foo: type T = Int given bar3: Int = 0 given baz3: Char = 'a' diff --git a/tests/neg/i19328conversion.scala b/tests/neg/i19328conversion.scala index 46dd1058b579..458bd5abb5b1 100644 --- a/tests/neg/i19328conversion.scala +++ b/tests/neg/i19328conversion.scala @@ -5,7 +5,7 @@ object i19328conversion: type Id[A] = A - given wrapId[A]: Conversion[A, Id[A]] with + given wrapId: [A] => Conversion[A, Id[A]]: def apply(x: A): Id[A] = x def bar(using bool: Boolean): Unit = () diff --git a/tests/neg/i5978.scala b/tests/neg/i5978.scala index 5dddfafb8726..b7e0344ec1c9 100644 --- a/tests/neg/i5978.scala +++ b/tests/neg/i5978.scala @@ -5,7 +5,7 @@ opaque type Position[Buffer] = Int trait TokenParser[Token, R] object TextParser { - given TP: TokenParser[Char, Position[CharSequence]] with {} + given TP: TokenParser[Char, Position[CharSequence]]() given FromCharToken(using T: TokenParser[Char, Position[CharSequence]]) : Conversion[Char, Position[CharSequence]] = ??? diff --git a/tests/neg/i6716.scala b/tests/neg/i6716.scala index eece8af9e560..a9826cb901c0 100644 --- a/tests/neg/i6716.scala +++ b/tests/neg/i6716.scala @@ -1,12 +1,12 @@ class Foo object Bar { - given Foo with {} + given Foo() given List[Foo] = List(summon[Foo]) // ok } object Baz { @annotation.nowarn given List[Foo] = List(summon[Foo]) // error - given Foo with {} + given Foo() } diff --git a/tests/neg/i7459.scala b/tests/neg/i7459.scala index a17f32b15afa..829132e5179d 100644 --- a/tests/neg/i7459.scala +++ b/tests/neg/i7459.scala @@ -22,7 +22,7 @@ trait Eq[T] { } object Eq { - given Eq[Int] with { + given Eq[Int] { def eqv(x: Int, y: Int) = x == y } diff --git a/tests/neg/i8896-a.scala b/tests/neg/i8896-a.scala index ae2cd6e88f6c..9f0953bfe939 100644 --- a/tests/neg/i8896-a.scala +++ b/tests/neg/i8896-a.scala @@ -4,8 +4,7 @@ trait Foo[A] object Example { - given Foo[Int] with { - } + given Foo[Int]() def foo0[A: Foo]: A => A = identity def foo1[A](implicit foo: Foo[A]): A => A = identity diff --git a/tests/neg/i8896-b.scala b/tests/neg/i8896-b.scala index a2559b00b3cc..f562d2d3b719 100644 --- a/tests/neg/i8896-b.scala +++ b/tests/neg/i8896-b.scala @@ -4,8 +4,7 @@ trait Foo[A] object Example { - given Foo[Int] with { - } + given Foo[Int]() def foo0[A: Foo]: A => A = identity def foo1[A](implicit foo: Foo[A]): A => A = identity diff --git a/tests/neg/i9185.scala b/tests/neg/i9185.scala index 34727eff1c46..8ec28135c1b9 100644 --- a/tests/neg/i9185.scala +++ b/tests/neg/i9185.scala @@ -1,8 +1,8 @@ trait M[F[_]] { def pure[A](x: A): F[A] } object M { extension [A, F[A]](x: A) def pure(using m: M[F]): F[A] = m.pure(x) - given listMonad: M[List] with { def pure[A](x: A): List[A] = List(x) } - given optionMonad: M[Option] with { def pure[A](x: A): Option[A] = Some(x) } + given listMonad: M[List] { def pure[A](x: A): List[A] = List(x) } + given optionMonad: M[Option] { def pure[A](x: A): Option[A] = Some(x) } val value1: List[String] = "ola".pure val value2 = "ola".pure // error val value3 = M.pure("ola") // error diff --git a/tests/neg/i9928.scala b/tests/neg/i9928.scala index a1034b1f20e9..cfe9cf663a85 100644 --- a/tests/neg/i9928.scala +++ b/tests/neg/i9928.scala @@ -2,7 +2,7 @@ trait Magic[F]: extension (x: Int) def read: F object Magic: - given Magic[String] with + given Magic[String]: extension(x: Int) def read: String = println("In string") s"$x" @@ -12,7 +12,7 @@ object Foo: import Magic.given def apply(s: String): Foo = s - given Magic[Foo] with + given Magic[Foo]: extension (x: Int) def read: Foo = println("In foo") Foo(s"$x") diff --git a/tests/neg/implicit-package-object.scala b/tests/neg/implicit-package-object.scala index 7b73d620b9b8..6d8c5d9ddff0 100644 --- a/tests/neg/implicit-package-object.scala +++ b/tests/neg/implicit-package-object.scala @@ -13,7 +13,7 @@ package A { given ToString[AB] = ab => println(ab) opaque type AC = String - given ToString[AC] with { + given ToString[AC] { def print(ac: AC): Unit = println(ac) } } @@ -31,7 +31,7 @@ package B { opaque type BC = String object BC { - given ToString[BC] with { + given ToString[BC] { def print(bc: BC): Unit = println(bc) } } diff --git a/tests/neg/implied-for.scala b/tests/neg/implied-for.scala index 87f762870400..cb43f799ee50 100644 --- a/tests/neg/implied-for.scala +++ b/tests/neg/implied-for.scala @@ -3,8 +3,8 @@ class B extends T class C extends T object A { - given b: B with {} - given c: C with {} + given b: B() + given c: C() } object Test extends App { diff --git a/tests/neg/import-given.scala b/tests/neg/import-given.scala index 080ed1e77ec5..1e5a9536c605 100644 --- a/tests/neg/import-given.scala +++ b/tests/neg/import-given.scala @@ -1,6 +1,6 @@ class TC object A { - given tc: TC with {} + given tc: TC() def foo(using TC) = () } object B { diff --git a/tests/neg/missing-implicit6.check b/tests/neg/missing-implicit6.check index 8c4cb331808b..7d6e16c0ec93 100644 --- a/tests/neg/missing-implicit6.check +++ b/tests/neg/missing-implicit6.check @@ -1,9 +1,9 @@ --- [E008] Not Found Error: tests/neg/missing-implicit6.scala:34:8 ------------------------------------------------------ -34 | "a".xxx // error, no suggested import +-- [E008] Not Found Error: tests/neg/missing-implicit6.scala:32:8 ------------------------------------------------------ +32 | "a".xxx // error, no suggested import | ^^^^^^^ | value xxx is not a member of String --- [E008] Not Found Error: tests/neg/missing-implicit6.scala:35:8 ------------------------------------------------------ -35 | 123.xxx // error, suggested import +-- [E008] Not Found Error: tests/neg/missing-implicit6.scala:33:8 ------------------------------------------------------ +33 | 123.xxx // error, suggested import | ^^^^^^^ | value xxx is not a member of Int, but could be made available as an extension method. | @@ -11,8 +11,8 @@ | | import Test.Ops.xxx | --- [E008] Not Found Error: tests/neg/missing-implicit6.scala:36:8 ------------------------------------------------------ -36 | 123.yyy // error, suggested import +-- [E008] Not Found Error: tests/neg/missing-implicit6.scala:34:8 ------------------------------------------------------ +34 | 123.yyy // error, suggested import | ^^^^^^^ | value yyy is not a member of Int, but could be made available as an extension method. | @@ -20,16 +20,16 @@ | | import Test.Ops.yyy | --- [E008] Not Found Error: tests/neg/missing-implicit6.scala:41:8 ------------------------------------------------------ -41 | 123.xxx // error, no suggested import +-- [E008] Not Found Error: tests/neg/missing-implicit6.scala:39:8 ------------------------------------------------------ +39 | 123.xxx // error, no suggested import | ^^^^^^^ | value xxx is not a member of Int --- [E008] Not Found Error: tests/neg/missing-implicit6.scala:42:8 ------------------------------------------------------ -42 | 123.yyy // error, no suggested import +-- [E008] Not Found Error: tests/neg/missing-implicit6.scala:40:8 ------------------------------------------------------ +40 | 123.yyy // error, no suggested import | ^^^^^^^ | value yyy is not a member of Int --- [E008] Not Found Error: tests/neg/missing-implicit6.scala:43:8 ------------------------------------------------------ -43 | 123.zzz // error, suggested import even though there's no instance of Bar in scope +-- [E008] Not Found Error: tests/neg/missing-implicit6.scala:41:8 ------------------------------------------------------ +41 | 123.zzz // error, suggested import even though there's no instance of Bar in scope | ^^^^^^^ | value zzz is not a member of Int, but could be made available as an extension method. | diff --git a/tests/neg/missing-implicit6.scala b/tests/neg/missing-implicit6.scala index ded6e5ba8fed..874ae77bb50f 100644 --- a/tests/neg/missing-implicit6.scala +++ b/tests/neg/missing-implicit6.scala @@ -7,13 +7,11 @@ trait Bar { } object instances { - given foo: Foo with { + given foo: Foo: type Out = Bar - } - given bar: Bar with { + given bar: Bar: type Out = Int - } } object Test { diff --git a/tests/neg/struct-given.scala b/tests/neg/struct-given.scala index 9bcd1630d448..13e0d98795fa 100644 --- a/tests/neg/struct-given.scala +++ b/tests/neg/struct-given.scala @@ -1,5 +1,5 @@ class C -given c[T]: C with +given c: [T] => C: def foo = 1 given d[T]: C = new C { def foo = 1 } diff --git a/tests/patmat/i6088.scala b/tests/patmat/i6088.scala index 8d8f676c0101..c88ae35a0c2f 100644 --- a/tests/patmat/i6088.scala +++ b/tests/patmat/i6088.scala @@ -17,7 +17,7 @@ enum ExprF[R[_],I] { /** Companion. */ object ExprF { - given hfunctor: HFunctor[ExprF] with { + given hfunctor: HFunctor[ExprF] { def hmap[A[_], B[_]](nt: A ~> B): ([x] =>> ExprF[A,x]) ~> ([x] =>> ExprF[B,x]) = { new ~>[[x] =>> ExprF[A,x], [x] =>> ExprF[B,x]] { def apply[I](fa: ExprF[A,I]): ExprF[B,I] = fa match { diff --git a/tests/pos-custom-args/captures/i16116.scala b/tests/pos-custom-args/captures/i16116.scala index 979bfdbe4328..fdc386ac40e1 100644 --- a/tests/pos-custom-args/captures/i16116.scala +++ b/tests/pos-custom-args/captures/i16116.scala @@ -9,7 +9,7 @@ trait CpsMonad[F[_]] { object CpsMonad { type Aux[F[_],C] = CpsMonad[F] { type Context = C } - given CpsMonad[Future] with {} + given CpsMonad[Future]() } @experimental diff --git a/tests/pos-macros/exprSummonWithTypeVar/Macro_1.scala b/tests/pos-macros/exprSummonWithTypeVar/Macro_1.scala index 72bcbe8b6515..2fac9b9a7f8d 100644 --- a/tests/pos-macros/exprSummonWithTypeVar/Macro_1.scala +++ b/tests/pos-macros/exprSummonWithTypeVar/Macro_1.scala @@ -2,7 +2,7 @@ import scala.compiletime.{erasedValue, summonFrom} import scala.quoted._ -inline given summonAfterTypeMatch[T]: Any = +inline given summonAfterTypeMatch: [T] => Any = ${ summonAfterTypeMatchExpr[T] } private def summonAfterTypeMatchExpr[T: Type](using Quotes): Expr[Any] = @@ -10,4 +10,4 @@ private def summonAfterTypeMatchExpr[T: Type](using Quotes): Expr[Any] = trait Foo[T] -given IntFoo[T <: Int]: Foo[T] = ??? +given IntFoo: [T <: Int] => Foo[T] = ??? diff --git a/tests/pos-macros/i13021/Width.scala b/tests/pos-macros/i13021/Width.scala index a163e1b5ebf1..60c1b47b99d8 100644 --- a/tests/pos-macros/i13021/Width.scala +++ b/tests/pos-macros/i13021/Width.scala @@ -3,7 +3,7 @@ import scala.quoted.* trait Width[T]: type Out <: Int object Width: - transparent inline given [T]: Width[T] = ${ getWidthMacro[T] } + transparent inline given [T] => Width[T] = ${ getWidthMacro[T] } def getWidthMacro[T](using Quotes, Type[T]): Expr[Width[T]] = '{ new Width[T] { diff --git a/tests/pos-macros/i18228.scala b/tests/pos-macros/i18228.scala index f0b8226fc135..2127ea7686f5 100644 --- a/tests/pos-macros/i18228.scala +++ b/tests/pos-macros/i18228.scala @@ -3,7 +3,7 @@ import scala.quoted.* case class QueryMeta[T](map: Map[String, String]) object QueryMeta: - given [T: Type]: FromExpr[QueryMeta[T]] = new FromExpr[QueryMeta[T]]: + given [T: Type] => FromExpr[QueryMeta[T]] = new FromExpr[QueryMeta[T]]: def unapply(expr: Expr[QueryMeta[T]])(using q: Quotes): Option[QueryMeta[T]] = import q.reflect.* expr match diff --git a/tests/pos-macros/macro-docs.scala b/tests/pos-macros/macro-docs.scala index f3cd6e3ef00a..820aae451486 100644 --- a/tests/pos-macros/macro-docs.scala +++ b/tests/pos-macros/macro-docs.scala @@ -2,12 +2,12 @@ import scala.quoted.* object MacrosMD_ToExpr { - given ToExpr[Boolean] with { + given ToExpr[Boolean] { def apply(b: Boolean)(using Quotes) = if (b) '{ true } else '{ false } } - given ToExpr[Int] with { + given ToExpr[Int] { def apply(n: Int)(using Quotes) = n match { case Int.MinValue => '{ Int.MinValue } case _ if n < 0 => '{ - ${ apply(-n) } } @@ -17,7 +17,7 @@ object MacrosMD_ToExpr { } } - given [T: ToExpr : Type]: ToExpr[List[T]] with { + given [T: ToExpr : Type] => ToExpr[List[T]] { def apply(xs: List[T])(using Quotes) = xs match { case head :: tail => '{ ${ Expr(head) } :: ${ apply(tail) } } case Nil => '{ Nil: List[T] } diff --git a/tests/pos-macros/nil-liftable.scala b/tests/pos-macros/nil-liftable.scala index a3277510d7bf..c95fc7698e5a 100644 --- a/tests/pos-macros/nil-liftable.scala +++ b/tests/pos-macros/nil-liftable.scala @@ -1,7 +1,7 @@ import scala.quoted.* class Test: - given NilToExpr: ToExpr[Nil.type] with { + given NilToExpr: ToExpr[Nil.type] { def apply(xs: Nil.type)(using Quotes): Expr[Nil.type] = '{ Nil } } diff --git a/tests/pos/20088.scala b/tests/pos/20088.scala index 308c5a0f0a91..30651ce9d39c 100644 --- a/tests/pos/20088.scala +++ b/tests/pos/20088.scala @@ -1,6 +1,6 @@ trait Foo trait Bar -given (using foo: Foo = new {}): Bar with {} +given (foo: Foo = new {}) => Bar() def Test = summon[Bar] diff --git a/tests/pos/X.scala b/tests/pos/X.scala index 04150b72beeb..72a14478b4cb 100644 --- a/tests/pos/X.scala +++ b/tests/pos/X.scala @@ -2,8 +2,8 @@ import scala.deriving.* trait FunctorK[F[_[_]]] object FunctorK { - given [C]: FunctorK[[F[_]] =>> C]() - given [T]: FunctorK[[F[_]] =>> Tuple1[F[T]]]() + given [C] => FunctorK[[F[_]] =>> C]() + given [T] => FunctorK[[F[_]] =>> Tuple1[F[T]]]() def derived[F[_[_]]](using m: Mirror { type MirroredType[X[_]] = F[X] ; type MirroredElemTypes[_[_]] }, r: FunctorK[m.MirroredElemTypes]): FunctorK[F] = new FunctorK[F] {} } diff --git a/tests/pos/bson/bson.scala b/tests/pos/bson/bson.scala index d901ee3e3a4f..2a1bc808fbc8 100644 --- a/tests/pos/bson/bson.scala +++ b/tests/pos/bson/bson.scala @@ -7,7 +7,7 @@ object BSONWriter extends BSONWriterInstances trait BSONHandler[T] extends BSONWriter[T] private[bson] trait BSONWriterInstances { - given mapWriter[V](using BSONWriter[V]): BSONDocumentWriter[Map[String, V]] = bson.mapWriter[V] + given mapWriter: [V] => BSONWriter[V] => BSONDocumentWriter[Map[String, V]] = bson.mapWriter[V] export bson.collectionWriter } @@ -21,7 +21,7 @@ object ¬ { private[bson] trait DefaultBSONHandlers extends LowPriorityHandlers private[bson] trait LowPriorityHandlers{ - given collectionWriter[T, Repr <: Iterable[T]](using BSONWriter[T], Repr ¬ Option[T]): BSONWriter[Repr] = ??? + given collectionWriter: [T, Repr <: Iterable[T]] => (BSONWriter[T], Repr ¬ Option[T]) => BSONWriter[Repr] = ??? private[bson] def mapWriter[V](implicit valueWriter: BSONWriter[V]): BSONDocumentWriter[Map[String, V]] = ??? } diff --git a/tests/pos/cbproxy-expansion.scala b/tests/pos/cbproxy-expansion.scala index ee145b62d4ed..bd7788ca0da0 100644 --- a/tests/pos/cbproxy-expansion.scala +++ b/tests/pos/cbproxy-expansion.scala @@ -6,7 +6,7 @@ def f1[S, T: TC[S] as tc](x: S, y: tc.Self) = () def f2[S, T: TC[S]](x: S, y: T.Self) = () def f3[S, T: TC[S]](x: S, y: Int) = () -given TC[String] with +given TC[String]: type Self = Int def unit = 42 diff --git a/tests/pos/combine.scala b/tests/pos/combine.scala index 930e5237e249..c9217e593dc8 100644 --- a/tests/pos/combine.scala +++ b/tests/pos/combine.scala @@ -2,7 +2,7 @@ trait Semigroup[A] { extension (x: A) def combine(y: A): A } given Semigroup[Int] = ??? -given [A, B](using Semigroup[A], Semigroup[B]): Semigroup[(A, B)] = ??? +given [A, B] => (Semigroup[A], Semigroup[B]) => Semigroup[(A, B)] = ??? object Test extends App { ((1, 1)) combine ((2, 2)) // doesn't compile ((1, 1): (Int, Int)) combine (2, 2) // compiles diff --git a/tests/pos/end-given.scala b/tests/pos/end-given.scala index 359d7d1b6a6b..0aacfb379c3c 100644 --- a/tests/pos/end-given.scala +++ b/tests/pos/end-given.scala @@ -1,3 +1,3 @@ -given Conversion[Int, String] with +given Conversion[Int, String]: def apply(x: Int) = "" end given diff --git a/tests/pos/erased-conforms.scala b/tests/pos/erased-conforms.scala index 1f366e0683c6..426490d5a53a 100644 --- a/tests/pos/erased-conforms.scala +++ b/tests/pos/erased-conforms.scala @@ -5,7 +5,7 @@ erased class <::<[-From, +To] extends ErasedTerm erased class =::=[From, To] extends (From <::< To) -erased given [X]: (X =::= X) = scala.compiletime.erasedValue +erased given [X] => (X =::= X) = scala.compiletime.erasedValue extension [From](x: From) inline def cast[To](using From <::< To): To = x.asInstanceOf[To] // Safe cast because we know `From <:< To` diff --git a/tests/pos/ext-override.scala b/tests/pos/ext-override.scala index d08439e13c9a..7c082695cbaa 100644 --- a/tests/pos/ext-override.scala +++ b/tests/pos/ext-override.scala @@ -7,6 +7,6 @@ trait Foo[T]: class Bla: def hi: String = "hi" object Bla: - given Foo[Bla] with + given Foo[Bla]: extension (x: Bla) def hi: String = x.hi diff --git a/tests/pos/givenFallback.scala b/tests/pos/givenFallback.scala index 760eb2b5aed2..12d667af05c1 100644 --- a/tests/pos/givenFallback.scala +++ b/tests/pos/givenFallback.scala @@ -1,13 +1,11 @@ trait TC[T] { def x: Int; def y: Int = 0 } -given [T]: TC[T] with { +given [T] => TC[T]: inline val x = 1 -} -given TC[Int] with { +given TC[Int]: inline val x = 2 inline override val y = 3 -} object Test extends App { val z: 2 = summon[TC[Int]].x diff --git a/tests/pos/hylolib-cb-extract.scala b/tests/pos/hylolib-cb-extract.scala index b80a88485a2b..0ea38d508093 100644 --- a/tests/pos/hylolib-cb-extract.scala +++ b/tests/pos/hylolib-cb-extract.scala @@ -14,5 +14,5 @@ class BitArray given Value[Boolean] {} -given Collection[BitArray] with +given Collection[BitArray]: type Element = Boolean diff --git a/tests/pos/hylolib-cb/AnyCollection.scala b/tests/pos/hylolib-cb/AnyCollection.scala index 50f4313e46ce..61300a7b2bfe 100644 --- a/tests/pos/hylolib-cb/AnyCollection.scala +++ b/tests/pos/hylolib-cb/AnyCollection.scala @@ -42,12 +42,12 @@ object AnyCollection { } -given anyCollectionIsCollection[T: Value]: Collection[AnyCollection[T]] with { +given anyCollectionIsCollection: [T: Value] => Collection[AnyCollection[T]]: type Element = T type Position = AnyValue - extension (self: AnyCollection[T]) { + extension (self: AnyCollection[T]) def startPosition = self._start() @@ -60,7 +60,3 @@ given anyCollectionIsCollection[T: Value]: Collection[AnyCollection[T]] with { def at(p: Position) = self._at(p) - - } - -} diff --git a/tests/pos/hylolib-cb/AnyValue.scala b/tests/pos/hylolib-cb/AnyValue.scala index b9d39869c09a..88709b7b4da2 100644 --- a/tests/pos/hylolib-cb/AnyValue.scala +++ b/tests/pos/hylolib-cb/AnyValue.scala @@ -58,7 +58,7 @@ object AnyValue { } -given anyValueIsValue: Value[AnyValue] with { +given anyValueIsValue: Value[AnyValue] { extension (self: AnyValue) { diff --git a/tests/pos/hylolib-cb/BitArray.scala b/tests/pos/hylolib-cb/BitArray.scala index 3a0b4658f747..0c8f98fb1ba4 100644 --- a/tests/pos/hylolib-cb/BitArray.scala +++ b/tests/pos/hylolib-cb/BitArray.scala @@ -318,7 +318,7 @@ object BitArray { } -given bitArrayPositionIsValue: Value[BitArray.Position] with { +given bitArrayPositionIsValue: Value[BitArray.Position] { extension (self: BitArray.Position) { @@ -335,7 +335,7 @@ given bitArrayPositionIsValue: Value[BitArray.Position] with { } -given bitArrayIsCollection: Collection[BitArray] with { +given bitArrayIsCollection: Collection[BitArray] { type Element = Boolean type Position = BitArray.Position @@ -361,7 +361,7 @@ given bitArrayIsCollection: Collection[BitArray] with { } -given bitArrayIsStringConvertible: StringConvertible[BitArray] with { +given bitArrayIsStringConvertible: StringConvertible[BitArray] { extension (self: BitArray) override def description: String = diff --git a/tests/pos/hylolib-cb/Integers.scala b/tests/pos/hylolib-cb/Integers.scala index b9bc203a88ea..02a0cd6df111 100644 --- a/tests/pos/hylolib-cb/Integers.scala +++ b/tests/pos/hylolib-cb/Integers.scala @@ -1,6 +1,6 @@ package hylo -given booleanIsValue: Value[Boolean] with { +given booleanIsValue: Value[Boolean] { extension (self: Boolean) { @@ -18,7 +18,7 @@ given booleanIsValue: Value[Boolean] with { } -given intIsValue: Value[Int] with { +given intIsValue: Value[Int] { extension (self: Int) { @@ -36,7 +36,7 @@ given intIsValue: Value[Int] with { } -given intIsComparable: Comparable[Int] with { +given intIsComparable: Comparable[Int] { extension (self: Int) { @@ -55,4 +55,4 @@ given intIsComparable: Comparable[Int] with { } -given intIsStringConvertible: StringConvertible[Int] with {} +given intIsStringConvertible: StringConvertible[Int] {} diff --git a/tests/pos/hylolib-cb/Slice.scala b/tests/pos/hylolib-cb/Slice.scala index b577ceeb3739..10d0ffd36fb0 100644 --- a/tests/pos/hylolib-cb/Slice.scala +++ b/tests/pos/hylolib-cb/Slice.scala @@ -24,7 +24,7 @@ final class Slice[Base: Collection as b]( } -given sliceIsCollection[T: Collection as c]: Collection[Slice[T]] with { +given sliceIsCollection: [T: Collection as c] => Collection[Slice[T]] { type Element = c.Element type Position = c.Position diff --git a/tests/pos/hylolib-deferred-given-extract.scala b/tests/pos/hylolib-deferred-given-extract.scala index 02d889dc9aac..220dad944198 100644 --- a/tests/pos/hylolib-deferred-given-extract.scala +++ b/tests/pos/hylolib-deferred-given-extract.scala @@ -13,7 +13,7 @@ trait Collection[Self]: class BitArray -given Value[Boolean] {} +given Value[Boolean]() -given Collection[BitArray] with +given Collection[BitArray]: type Element = Boolean diff --git a/tests/pos/hylolib-deferred-given/AnyCollection.scala b/tests/pos/hylolib-deferred-given/AnyCollection.scala index 55e453d6dc87..e2a946fca484 100644 --- a/tests/pos/hylolib-deferred-given/AnyCollection.scala +++ b/tests/pos/hylolib-deferred-given/AnyCollection.scala @@ -42,7 +42,7 @@ object AnyCollection { } -given anyCollectionIsCollection[T](using tIsValue: Value[T]): Collection[AnyCollection[T]] with { +given anyCollectionIsCollection: [T] => (tIsValue: Value[T]) => Collection[AnyCollection[T]] { type Element = T //given elementIsValue: Value[Element] = tIsValue diff --git a/tests/pos/hylolib-deferred-given/AnyValue.scala b/tests/pos/hylolib-deferred-given/AnyValue.scala index 21f2965e102e..5c1b68a52366 100644 --- a/tests/pos/hylolib-deferred-given/AnyValue.scala +++ b/tests/pos/hylolib-deferred-given/AnyValue.scala @@ -58,7 +58,7 @@ object AnyValue { } -given anyValueIsValue: Value[AnyValue] with { +given anyValueIsValue: Value[AnyValue] { extension (self: AnyValue) { diff --git a/tests/pos/hylolib-deferred-given/BitArray.scala b/tests/pos/hylolib-deferred-given/BitArray.scala index 485f30472847..d653f5e4d630 100644 --- a/tests/pos/hylolib-deferred-given/BitArray.scala +++ b/tests/pos/hylolib-deferred-given/BitArray.scala @@ -318,7 +318,7 @@ object BitArray { } -given bitArrayPositionIsValue: Value[BitArray.Position] with { +given bitArrayPositionIsValue: Value[BitArray.Position] { extension (self: BitArray.Position) { @@ -335,7 +335,7 @@ given bitArrayPositionIsValue: Value[BitArray.Position] with { } -given bitArrayIsCollection: Collection[BitArray] with { +given bitArrayIsCollection: Collection[BitArray] { type Element = Boolean //given elementIsValue: Value[Boolean] = booleanIsValue @@ -364,7 +364,7 @@ given bitArrayIsCollection: Collection[BitArray] with { } -given bitArrayIsStringConvertible: StringConvertible[BitArray] with { +given bitArrayIsStringConvertible: StringConvertible[BitArray] { extension (self: BitArray) override def description: String = diff --git a/tests/pos/hylolib-deferred-given/HyArray.scala b/tests/pos/hylolib-deferred-given/HyArray.scala index 98632dcb65bc..e82ce06d920b 100644 --- a/tests/pos/hylolib-deferred-given/HyArray.scala +++ b/tests/pos/hylolib-deferred-given/HyArray.scala @@ -162,7 +162,7 @@ object HyArray { } -given hyArrayIsValue[T](using tIsValue: Value[T]): Value[HyArray[T]] with { +given hyArrayIsValue: [T] => (tIsValue: Value[T]) => Value[HyArray[T]] { extension (self: HyArray[T]) { @@ -179,7 +179,7 @@ given hyArrayIsValue[T](using tIsValue: Value[T]): Value[HyArray[T]] with { } -given hyArrayIsCollection[T](using tIsValue: Value[T]): Collection[HyArray[T]] with { +given hyArrayIsCollection: [T] => (tIsValue: Value[T]) => Collection[HyArray[T]] { type Element = T //given elementIsValue: Value[T] = tIsValue diff --git a/tests/pos/hylolib-deferred-given/Integers.scala b/tests/pos/hylolib-deferred-given/Integers.scala index b9bc203a88ea..02a0cd6df111 100644 --- a/tests/pos/hylolib-deferred-given/Integers.scala +++ b/tests/pos/hylolib-deferred-given/Integers.scala @@ -1,6 +1,6 @@ package hylo -given booleanIsValue: Value[Boolean] with { +given booleanIsValue: Value[Boolean] { extension (self: Boolean) { @@ -18,7 +18,7 @@ given booleanIsValue: Value[Boolean] with { } -given intIsValue: Value[Int] with { +given intIsValue: Value[Int] { extension (self: Int) { @@ -36,7 +36,7 @@ given intIsValue: Value[Int] with { } -given intIsComparable: Comparable[Int] with { +given intIsComparable: Comparable[Int] { extension (self: Int) { @@ -55,4 +55,4 @@ given intIsComparable: Comparable[Int] with { } -given intIsStringConvertible: StringConvertible[Int] with {} +given intIsStringConvertible: StringConvertible[Int] {} diff --git a/tests/pos/hylolib-deferred-given/Slice.scala b/tests/pos/hylolib-deferred-given/Slice.scala index 57cdb38f6e53..234b16dfc428 100644 --- a/tests/pos/hylolib-deferred-given/Slice.scala +++ b/tests/pos/hylolib-deferred-given/Slice.scala @@ -26,7 +26,7 @@ final class Slice[Base](using } -given sliceIsCollection[T](using c: Collection[T]): Collection[Slice[T]] with { +given sliceIsCollection: [T] => (c: Collection[T]) => Collection[Slice[T]] { type Element = c.Element //given elementIsValue: Value[Element] = c.elementIsValue diff --git a/tests/pos/i10259.scala b/tests/pos/i10259.scala index 101a3d869a04..e8da9e6a7be7 100644 --- a/tests/pos/i10259.scala +++ b/tests/pos/i10259.scala @@ -4,7 +4,7 @@ trait S[T] extends (T => T): def apply(x: T) = ??? extension (x: T) def show: String -given S[Int] with +given S[Int]: extension (x: Int) def show = x.toString val x = 10.show diff --git a/tests/pos/i10929.scala b/tests/pos/i10929.scala index e916e4547e59..358de9ce30a8 100644 --- a/tests/pos/i10929.scala +++ b/tests/pos/i10929.scala @@ -5,11 +5,11 @@ infix abstract class TupleOf[T, +A]: object TupleOf: - given TupleOf[EmptyTuple, Nothing] with + given TupleOf[EmptyTuple, Nothing]: type Mapped[+A] = EmptyTuple def map[B](x: EmptyTuple)(f: Nothing => B): Mapped[B] = x - given [A, Rest <: Tuple](using tracked val tup: Rest TupleOf A): TupleOf[A *: Rest, A] with + given [A, Rest <: Tuple] => (tracked val tup: Rest TupleOf A) => TupleOf[A *: Rest, A]: type Mapped[+A] = A *: tup.Mapped[A] def map[B](x: A *: Rest)(f: A => B): Mapped[B] = (f(x.head) *: tup.map(x.tail)(f)) diff --git a/tests/pos/i11174minimisation.scala b/tests/pos/i11174minimisation.scala index c40c34552bb8..7e0aa42721bf 100644 --- a/tests/pos/i11174minimisation.scala +++ b/tests/pos/i11174minimisation.scala @@ -20,6 +20,6 @@ object EnumerateNames { class MainClass { enum Shape: case Point - inline given auto[T]: EnumerateNames[T] = EnumerateNames.derived[T] + inline given auto: [T] => EnumerateNames[T] = EnumerateNames.derived[T] def shapeNames: EnumerateNames[Shape] = EnumerateNames.derived[Shape] } \ No newline at end of file diff --git a/tests/pos/i11175.scala b/tests/pos/i11175.scala index bfefe84dde95..5a6f9fe852bb 100644 --- a/tests/pos/i11175.scala +++ b/tests/pos/i11175.scala @@ -10,10 +10,10 @@ object A object B -given Printer[A.type] with +given Printer[A.type]: def print(a:A.type):String = "a" -given Printer[B.type] with +given Printer[B.type]: def print(b:B.type):String = "b" diff --git a/tests/pos/i11243.scala b/tests/pos/i11243.scala index 7966df0c8243..42294ed5bf76 100644 --- a/tests/pos/i11243.scala +++ b/tests/pos/i11243.scala @@ -54,7 +54,7 @@ object WriterTest extends App { end Monad - given eitherMonad[Err]: Monad[[X] =>> Either[Err,X]] with + given eitherMonad: [Err] => Monad[[X] =>> Either[Err,X]]: def pure[A](a: A): Either[Err, A] = Right(a) extension [A,B](x: Either[Err,A]) def flatMap(f: A => Either[Err, B]) = { x match { @@ -63,7 +63,7 @@ object WriterTest extends App { } } - given optionMonad: Monad[Option] with + given optionMonad: Monad[Option]: def pure[A](a: A) = Some(a) extension[A,B](fa: Option[A]) def flatMap(f: A => Option[B]) = { @@ -75,7 +75,7 @@ object WriterTest extends App { } } - given listMonad: Monad[List] with + given listMonad: Monad[List]: def pure[A](a: A): List[A] = List(a) extension[A,B](x: List[A]) @@ -88,7 +88,7 @@ object WriterTest extends App { case class Transformer[F[_]: Monad,A](val wrapped: F[A]) - given transformerMonad[F[_]: Monad]: Monad[[X] =>> Transformer[F,X]] with { + given transformerMonad: [F[_]: Monad] => Monad[[X] =>> Transformer[F,X]] { def pure[A](a: A): Transformer[F,A] = Transformer(summon[Monad[F]].pure(a)) diff --git a/tests/pos/i11538a.scala b/tests/pos/i11538a.scala index 243900c43b44..51ecdb227ab9 100644 --- a/tests/pos/i11538a.scala +++ b/tests/pos/i11538a.scala @@ -3,7 +3,7 @@ package a: trait Printer[A]: def print(a: A): Unit - given Printer[String] with + given Printer[String]: def print(s: String) = println(s) package b: diff --git a/tests/pos/i11732.scala b/tests/pos/i11732.scala index a1138a94fcd7..c8c74eccc51b 100644 --- a/tests/pos/i11732.scala +++ b/tests/pos/i11732.scala @@ -6,7 +6,7 @@ trait TupleConversion[A, B] { } object TupleConversion { - inline given autoTupleConversion[Prod <: Product](using m: Mirror.ProductOf[Prod]): TupleConversion[Prod, m.MirroredElemTypes] = + inline given autoTupleConversion: [Prod <: Product] => (m: Mirror.ProductOf[Prod]) => TupleConversion[Prod, m.MirroredElemTypes] = new TupleConversion[Prod, m.MirroredElemTypes] { def to(a: Prod): m.MirroredElemTypes = Tuple.fromProductTyped(a) def from(b: m.MirroredElemTypes): Prod = m.fromProduct(b) diff --git a/tests/pos/i11864.scala b/tests/pos/i11864.scala index 4f7735f1c8c5..ba43336e13ca 100644 --- a/tests/pos/i11864.scala +++ b/tests/pos/i11864.scala @@ -40,7 +40,7 @@ final class CallbackTo[+A] { object CallbackTo { type MapGuard[A] = { type Out = A } - erased given MapGuard[A]: MapGuard[A] = compiletime.erasedValue + erased given MapGuard: [A] => MapGuard[A] = compiletime.erasedValue def traverse[A, B](ta: List[A]): CallbackTo[List[B]] = val x: CallbackTo[List[A] => List[B]] = ??? diff --git a/tests/pos/i12126.scala b/tests/pos/i12126.scala index cffa7fbcbbca..aac2f39d4d95 100644 --- a/tests/pos/i12126.scala +++ b/tests/pos/i12126.scala @@ -22,12 +22,12 @@ object Structures: def map2[B, C](fb: F[B], f: (A, B) => C): F[C] = flatMap(a => fb.map(b => f(a, b))) - given Monad[List] with + given Monad[List]: def pure[A](a: A) = List(a) extension[A](fa: List[A]) def flatMap[B](f: A => List[B]) = fa.flatMap(f) - given Monad[Option] with + given Monad[Option]: def pure[A](a: A) = Some(a) extension[A](fa: Option[A]) def flatMap[B](f: A => Option[B]) = fa.flatMap(f) @@ -41,7 +41,7 @@ object Structures: object Kleisli: def apply[F[_], A, B](f: A => F[B]): Kleisli[F, A, B] = f - given [F[_], A](using F: Monad[F]): Monad[[B] =>> Kleisli[F, A, B]] with + given [F[_], A] => (F: Monad[F]) => Monad[[B] =>> Kleisli[F, A, B]]: def pure[B](b: B) = Kleisli(_ => F.pure(b)) extension[B](k: Kleisli[F, A, B]) def flatMap[C](f: B => Kleisli[F, A, C]) = diff --git a/tests/pos/i12379b.scala b/tests/pos/i12379b.scala index 2a83f69bae3d..6586f7b85a42 100644 --- a/tests/pos/i12379b.scala +++ b/tests/pos/i12379b.scala @@ -4,7 +4,7 @@ inline def convFail[Of, From](inline from : From) : Unit = inline def convOK[Of, From](inline from : From)(using c : Conversion[From, Of]) : Unit = {} class Bar[T](value : T) -given [T <: Int] : Conversion[T, Bar[T]] = Bar(_) +given [T <: Int] => Conversion[T, Bar[T]] = Bar(_) @main def main : Unit = { convOK[Bar[1],1](1) diff --git a/tests/pos/i12591/Inner.scala b/tests/pos/i12591/Inner.scala index 2f8018c4d824..a0b3e2f6410d 100644 --- a/tests/pos/i12591/Inner.scala +++ b/tests/pos/i12591/Inner.scala @@ -4,7 +4,7 @@ package inner sealed trait Foo object Foo: trait TC[T] - given ofFoo[T <: Foo]: TC[T] = ??? + given ofFoo: [T <: Foo] => TC[T] = ??? trait Bar extends Foo import Foo.TC diff --git a/tests/pos/i12910.scala b/tests/pos/i12910.scala index e78408aa5e5f..4c0d4ac369e1 100644 --- a/tests/pos/i12910.scala +++ b/tests/pos/i12910.scala @@ -3,7 +3,7 @@ trait Type[T]: type varchar -given Type[varchar] with +given Type[varchar]: type Out = String class Placeholder[T, U] @@ -17,7 +17,7 @@ trait Encoder[P, X]: object Encoder: def apply[P, X](placeholder: P)(using e: Encoder[P, X]): X => String = e.encode - given [T, X]: Encoder[Placeholder[T, X], X] with + given [T, X] => Encoder[Placeholder[T, X], X]: def encode(x: X): String = ??? def Test = diff --git a/tests/pos/i12945/A_1.scala b/tests/pos/i12945/A_1.scala index 890171a63051..62519fde262b 100644 --- a/tests/pos/i12945/A_1.scala +++ b/tests/pos/i12945/A_1.scala @@ -3,7 +3,7 @@ object Lie: trait TC[-T]: type Out object TC: - given [W <: Int]: TC[Lie[W]] with + given [W <: Int] => TC[Lie[W]]: type Out = W val x = summon[Lie.TC[Lie[7]]] diff --git a/tests/pos/i12949.scala b/tests/pos/i12949.scala index 5a886aa894b3..71a8ce67d032 100644 --- a/tests/pos/i12949.scala +++ b/tests/pos/i12949.scala @@ -6,11 +6,11 @@ object Catch22: object Hodor: object TC: import Catch22.TC - given fromString[V <: String]: TC[V] = ??? - transparent inline given fromDouble[V <: Double]: TC[V] = + given fromString: [V <: String] => TC[V] = ??? + transparent inline given fromDouble: [V <: Double] => TC[V] = new TC[V]: type Out = Double - given fromInt[V <: Int]: TC[V] with + given fromInt: [V <: Int] => TC[V]: type Out = Int object Test: diff --git a/tests/pos/i13001/Main_1.scala b/tests/pos/i13001/Main_1.scala index ad46df9f2fe1..9cdce20ef3bf 100644 --- a/tests/pos/i13001/Main_1.scala +++ b/tests/pos/i13001/Main_1.scala @@ -4,13 +4,13 @@ trait Arbitrary[T] trait Gen[+T] object ArbitraryDerivation: - given deriveArb[A](using gen: DerivedGen[A]): Arbitrary[A] = ??? + given deriveArb: [A] => (gen: DerivedGen[A]) => Arbitrary[A] = ??? opaque type DerivedGen[A] = Gen[A] object DerivedGen extends DerivedGenInstances sealed abstract class DerivedGenInstances: - inline given derived[A](using gen: K0.Generic[A]): DerivedGen[A] = + inline given derived: [A] => (gen: K0.Generic[A]) => DerivedGen[A] = val dummy: DerivedGen[A] = ??? gen.derive(dummy, dummy) diff --git a/tests/pos/i13044.scala b/tests/pos/i13044.scala index 36299d9e8366..ce483b4a403c 100644 --- a/tests/pos/i13044.scala +++ b/tests/pos/i13044.scala @@ -36,7 +36,7 @@ trait SchemaDerivation { } } - inline given gen[A]: Schema[A] = derived + inline given gen: [A] => Schema[A] = derived } case class H(i: Int) diff --git a/tests/pos/i13460.scala b/tests/pos/i13460.scala index fd57cd9b8521..90b2a9aff1fe 100644 --- a/tests/pos/i13460.scala +++ b/tests/pos/i13460.scala @@ -5,7 +5,7 @@ class Lazy[A](obj: => A) { lazy val value: A = obj } object Lazy { - given [A](using obj: => A ): Lazy[A] = new Lazy(obj) + given [A] => (obj: => A) => Lazy[A] = new Lazy(obj) } trait MyTypeClass[A] { @@ -13,10 +13,10 @@ trait MyTypeClass[A] { } object MyTypeClass { - given IntTypeClass: MyTypeClass[Int] with + given IntTypeClass: MyTypeClass[Int]: def makeString(a: Int): String = a.toString - inline given derived[A](using m: Mirror.Of[A]): MyTypeClass[A] = + inline given derived: [A] => (m: Mirror.Of[A]) => MyTypeClass[A] = inline m match case p: Mirror.ProductOf[A] => productConverter(p) diff --git a/tests/pos/i13503.scala b/tests/pos/i13503.scala index c60b0e05862c..020ba437e141 100644 --- a/tests/pos/i13503.scala +++ b/tests/pos/i13503.scala @@ -1,5 +1,5 @@ trait First {type Out} -given First with {type Out = 123} +given First {type Out = 123} trait Second {type Out} transparent inline given (using f: First): Second = new Second {type Out = f.Out} diff --git a/tests/pos/i13668.scala b/tests/pos/i13668.scala index 2199e0eb82c5..aebdd0478407 100644 --- a/tests/pos/i13668.scala +++ b/tests/pos/i13668.scala @@ -1,6 +1,6 @@ class MyType() trait Candidate[R] -given Candidate[MyType] with {} +given Candidate[MyType]() class Fuzzy[W]() class Fuzzy1() class Bear() diff --git a/tests/pos/i13900.scala b/tests/pos/i13900.scala index e6197d7f3f33..8b23fc2bdc20 100644 --- a/tests/pos/i13900.scala +++ b/tests/pos/i13900.scala @@ -3,10 +3,10 @@ import scala.annotation.targetName opaque type Inlined[T] = T object Inlined: extension [T](inlined: Inlined[T]) def value: T = inlined - inline given fromValue[T <: Singleton]: Conversion[T, Inlined[T]] = + inline given fromValue: [T <: Singleton] => Conversion[T, Inlined[T]] = value => value @targetName("fromValueWide") - given fromValue[Wide]: Conversion[Wide, Inlined[Wide]] = value => value + given fromValue: [Wide] => Conversion[Wide, Inlined[Wide]] = value => value def forced[T](value: Any): Inlined[T] = value.asInstanceOf[T] extension [T <: Int](lhs: Inlined[T]) diff --git a/tests/pos/i14013.scala b/tests/pos/i14013.scala index d20112392002..e1a586af9d45 100644 --- a/tests/pos/i14013.scala +++ b/tests/pos/i14013.scala @@ -47,7 +47,7 @@ object App2 extends App { object Foo2 { case class Bar(i: Int) - private given BarOps: AnyRef with { + private given BarOps: AnyRef { extension (bar: Bar) def twice: Bar = Bar(bar.i * 2) } diff --git a/tests/pos/i14177b.scala b/tests/pos/i14177b.scala index 6da9a72ae551..4d3810116617 100644 --- a/tests/pos/i14177b.scala +++ b/tests/pos/i14177b.scala @@ -1,15 +1,15 @@ class T -inline given fail1: T with +inline given fail1: T: val cs = scala.compiletime.summonAll[EmptyTuple] -inline given fail2[X]: T with +inline given fail2: [X] => T: val cs = scala.compiletime.summonAll[EmptyTuple] -inline given fail3(using DummyImplicit): T with +inline given fail3: () => T: val cs = scala.compiletime.summonAll[EmptyTuple] inline given ok1: T = new T: val cs = scala.compiletime.summonAll[EmptyTuple] -inline given ok2[X]: T = new T: +inline given ok2: [X] => T = new T: val cs = scala.compiletime.summonAll[EmptyTuple] -inline given ok3(using DummyImplicit): T = new T: +inline given ok3: () => T = new T: val cs = scala.compiletime.summonAll[EmptyTuple] diff --git a/tests/pos/i14282.scala b/tests/pos/i14282.scala index 2cc3ff1226e2..2dd768183124 100644 --- a/tests/pos/i14282.scala +++ b/tests/pos/i14282.scala @@ -2,12 +2,12 @@ trait Foo[A] { inline def foo(): Unit } -inline given FooA[A]: Foo[A] with { +inline given FooA: [A] => Foo[A]: inline def foo(): Unit = println() -} + def test1 = FooA.foo() -inline given FooInt: Foo[Int] with { +inline given FooInt: Foo[Int]: inline def foo(): Unit = println() -} + def test2 = FooInt.foo() diff --git a/tests/pos/i14637.scala b/tests/pos/i14637.scala index 5ae3b5e7a881..512471f7b19a 100644 --- a/tests/pos/i14637.scala +++ b/tests/pos/i14637.scala @@ -3,6 +3,6 @@ class C object Givens: - given cOrdering: Ordering[C] with + given cOrdering: Ordering[C]: override def compare(c0: C, c1: C) = 0 val greeting = "we love Givens" \ No newline at end of file diff --git a/tests/pos/i15160.scala b/tests/pos/i15160.scala index cc55e0f5fb19..bef59f3c9d80 100644 --- a/tests/pos/i15160.scala +++ b/tests/pos/i15160.scala @@ -2,7 +2,7 @@ trait Eq[A] { def eqv(a1: A, a2: A): Boolean } -given stringEq: Eq[String] with { +given stringEq: Eq[String] { def eqv(a1: String, a2: String) = a1 == a2 } diff --git a/tests/pos/i15177.hylolib.scala b/tests/pos/i15177.hylolib.scala index 96cf87680a1c..be2f5900094b 100644 --- a/tests/pos/i15177.hylolib.scala +++ b/tests/pos/i15177.hylolib.scala @@ -6,6 +6,6 @@ trait Coll[Self]: extension (self: Self) def pos: Pos extension [Self: Coll](self: Self) def trigger = self.pos class Slice[Base] -given SliceIsColl[T: Coll as c]: Coll[Slice[T]] with +given SliceIsColl: [T: Coll as c] => Coll[Slice[T]]: type Pos = c.Pos extension (self: Slice[T]) def pos: Pos = ??? diff --git a/tests/pos/i15183/decoder_1.scala b/tests/pos/i15183/decoder_1.scala index 532fd7246c3a..fd8f21deffed 100644 --- a/tests/pos/i15183/decoder_1.scala +++ b/tests/pos/i15183/decoder_1.scala @@ -4,11 +4,11 @@ sealed trait Decoder[T] object Decoder { given Decoder[Double] = ??? - inline given summonEmptyTuple[H]: Tuple.Map[EmptyTuple.type, Decoder] = + inline given summonEmptyTuple: [H] => Tuple.Map[EmptyTuple.type, Decoder] = EmptyTuple - inline given summonTuple[H, T <: Tuple](using hd: Decoder[H], td: Tuple.Map[T, Decoder]): Tuple.Map[H *: T, Decoder] = + inline given summonTuple: [H, T <: Tuple] => (hd: Decoder[H], td: Tuple.Map[T, Decoder]) => Tuple.Map[H *: T, Decoder] = hd *: td - inline given derived[T](using m: Mirror.Of[T], d: Tuple.Map[m.MirroredElemTypes, Decoder]): Decoder[T] = ??? + inline given derived: [T] => (m: Mirror.Of[T], d: Tuple.Map[m.MirroredElemTypes, Decoder]) => Decoder[T] = ??? } diff --git a/tests/pos/i15264.scala b/tests/pos/i15264.scala index 18ca92df6cb1..57036393b90a 100644 --- a/tests/pos/i15264.scala +++ b/tests/pos/i15264.scala @@ -36,9 +36,9 @@ object repro: given gc: C[Int] = new C[Int] // these seem like they should work but don't - given gcq[V](using p0: priority.Prio0)(using c: C[V]): C[Q[V]] = new C[Q[V]] - given gbq[V](using p1: priority.Prio1)(using b: B[V]): B[Q[V]] = new B[Q[V]] - given gaq[V](using p2: priority.Prio2)(using a: A[V]): A[Q[V]] = new A[Q[V]] + given gcq: [V] => priority.Prio0 => C[V] => C[Q[V]] = new C[Q[V]] + given gbq: [V] => priority.Prio1 => B[V] => B[Q[V]] = new B[Q[V]] + given gaq: [V] => priority.Prio2 => A[V] => A[Q[V]] = new A[Q[V]] object test1: import repro.* diff --git a/tests/pos/i15331.scala b/tests/pos/i15331.scala index faf9992cb4f2..337493e73f05 100644 --- a/tests/pos/i15331.scala +++ b/tests/pos/i15331.scala @@ -4,7 +4,7 @@ object Test: trait Arrow {type Dom; type Codom} - given composeArrows[A, Arr1 <: Arrow, Arr2 <: Arrow]: Composable[Arr1 {type Dom = A}, Arr2 {type Codom = A}] with + given composeArrows: [A, Arr1 <: Arrow, Arr2 <: Arrow] => Composable[Arr1 {type Dom = A}, Arr2 {type Codom = A}]: def compose(a: Arr1 {type Dom = A}, b: Arr2 {type Codom = A}): Arrow {type Dom = b.Dom; type Codom = a.Codom} = ??? object arr1 extends Arrow { type Dom = Int; type Codom = Int} diff --git a/tests/pos/i15664.scala b/tests/pos/i15664.scala index 7db8fe8cf23f..7b00e9ec7e85 100644 --- a/tests/pos/i15664.scala +++ b/tests/pos/i15664.scala @@ -11,7 +11,7 @@ sealed abstract class ZManaged[-R, +E, +A] type RManaged[-R, +A] = ZManaged[R, Throwable, A] type ForZManaged[R, E] = [X] =>> ZManaged[R, E, X] -given zManagedCpsMonad[R, E]: CpsMonadInstanceContext[ForZManaged[R, E]] = ??? +given zManagedCpsMonad: [R, E] => CpsMonadInstanceContext[ForZManaged[R, E]] = ??? // Usage def failing[R, E](using diff --git a/tests/pos/i15670.scala b/tests/pos/i15670.scala index b46b3708fe4e..c07290321b20 100644 --- a/tests/pos/i15670.scala +++ b/tests/pos/i15670.scala @@ -5,8 +5,8 @@ trait Read[T] trait Codec[T] extends Read[T] trait CodecTypeProjection[C[_]] object JsonTransform { - given SetCodec[T, C[_]: CodecTypeProjection]: scala.Conversion[C[T], C[Set[T]]] = ??? - given SetCodecExp[T, C[_]: CodecTypeProjection](using codec: C[T]): C[Set[T]] = codec + given SetCodec: [T, C[_]: CodecTypeProjection] => scala.Conversion[C[T], C[Set[T]]] = ??? + given SetCodecExp: [T, C[_]: CodecTypeProjection] => (codec: C[T]) => C[Set[T]] = codec given Codec[String] = ??? given CodecTypeProjection[Read] = ??? } diff --git a/tests/pos/i15867.scala b/tests/pos/i15867.scala index 2e62177ba590..b4f552c6b8c5 100644 --- a/tests/pos/i15867.scala +++ b/tests/pos/i15867.scala @@ -4,7 +4,7 @@ enum SUB[-A, +B]: class Pow(self: Int): def **(other: Int): Int = math.pow(self, other).toInt -given fromList[T]: Conversion[List[T], Pow] = ??? +given fromList: [T] => Conversion[List[T], Pow] = ??? given fromInt: Conversion[Int, Pow] = Pow(_) diff --git a/tests/pos/i15867.specs2.scala b/tests/pos/i15867.specs2.scala index da89b2cba9f0..1e519169d868 100644 --- a/tests/pos/i15867.specs2.scala +++ b/tests/pos/i15867.specs2.scala @@ -1,5 +1,5 @@ class Foo: - given Conversion[String, Data] with + given Conversion[String, Data]: def apply(str: String): Data = new Data(str) class Data(str: String): diff --git a/tests/pos/i16104.scala b/tests/pos/i16104.scala index 7624d5c68a4a..16f935d0e641 100644 --- a/tests/pos/i16104.scala +++ b/tests/pos/i16104.scala @@ -8,7 +8,7 @@ def Case2 = { object WriteOf: final inline def tuple[T <: Tuple]: Write[T] = ??? - given EntryToJson[T]: scala.Conversion[T, JsonStructureEntry[T]] = ??? + given EntryToJson: [T] => scala.Conversion[T, JsonStructureEntry[T]] = ??? class JsonStructureEntry[T](t: T): def writeAs[X >: T](using Write[X]): util.Try[JsonVal] = ??? diff --git a/tests/pos/i16596.more.scala b/tests/pos/i16596.more.scala index 2470eb9eb3c2..c3cb0800be61 100644 --- a/tests/pos/i16596.more.scala +++ b/tests/pos/i16596.more.scala @@ -7,7 +7,7 @@ object NatExample { case class Succ[N <: Nat](prev: N) extends Nat given zero: Zero.type = Zero - given buildSucc[N <: Nat](using n: N): Succ[N] = Succ(n) + given buildSucc: [N <: Nat] => (n: N) => Succ[N] = Succ(n) def value[N <: Nat](using n: N): N = n diff --git a/tests/pos/i17002.scala b/tests/pos/i17002.scala index d33c1bd386d9..f0382f72b7eb 100644 --- a/tests/pos/i17002.scala +++ b/tests/pos/i17002.scala @@ -7,4 +7,4 @@ class Test object Test: @methOnly - given test2[T]: Test with {} + given test2: [T] => Test() diff --git a/tests/pos/i18062.scala b/tests/pos/i18062.scala index 48863c4349c7..d638f7449972 100644 --- a/tests/pos/i18062.scala +++ b/tests/pos/i18062.scala @@ -7,7 +7,7 @@ object WrapperConvert: implicit def id[F[_]]: WrapperConvert[F, F] = new WrapperConvert[F, F]: def conv[X](fx: F[X]): F[X] = fx -transparent inline given convertX[F[_], X](using wc: WrapperConvert[F, CB]): Conversion[F[X], X] = +transparent inline given convertX: [F[_], X] => (wc: WrapperConvert[F, CB]) => Conversion[F[X], X] = new Conversion[F[X], X]: def apply(fx: F[X]) = wc.conv(fx).get diff --git a/tests/pos/i18175.scala b/tests/pos/i18175.scala index 2480ddccc320..76879c10fb39 100644 --- a/tests/pos/i18175.scala +++ b/tests/pos/i18175.scala @@ -10,8 +10,8 @@ object Regex: abstract class Sanitizer[T] object Sanitizer: given Sanitizer[EmptyTuple] = ??? - given stringcase[T <: Tuple: Sanitizer]: Sanitizer[String *: T] = ??? - given optioncase[T <: Tuple: Sanitizer]: Sanitizer[Option[String] *: T] = ??? + given stringcase: [T <: Tuple: Sanitizer] => Sanitizer[String *: T] = ??? + given optioncase: [T <: Tuple: Sanitizer] => Sanitizer[Option[String] *: T] = ??? given Sanitizer[String] = ??? given Sanitizer[Option[String]] = ??? diff --git a/tests/pos/i18211.scala b/tests/pos/i18211.scala index c5ec30ba5d61..45a51932adce 100644 --- a/tests/pos/i18211.scala +++ b/tests/pos/i18211.scala @@ -21,7 +21,7 @@ object Indexes { next: Indexes[A, Tuple.Drop[T, S[IndexOf[A, T]]]] ): Indexes[A, T] = ??? - given empty[A, T <: Tuple](using IndexOf[A, T] =:= -1): Indexes[A, T] = ??? + given empty: [A, T <: Tuple] => (IndexOf[A, T] =:= -1) => Indexes[A, T] = ??? } class GetAll[A]: diff --git a/tests/pos/i18253.orig.scala b/tests/pos/i18253.orig.scala index 9efe1224ebfd..0eaf93ed9ac4 100644 --- a/tests/pos/i18253.orig.scala +++ b/tests/pos/i18253.orig.scala @@ -4,7 +4,7 @@ trait DFSInt[W <: Int] trait Candidate[R]: type OutW <: Int object Candidate: - given [W <: Int, R <: DFSInt[W]]: Candidate[R] with + given [W <: Int, R <: DFSInt[W]] => Candidate[R]: type OutW = W def foo[R](rhs: R)(using icR: Candidate[R]): DFSInt[Max[8, icR.OutW]] = ??? diff --git a/tests/pos/i18253.scala b/tests/pos/i18253.scala index 8f395ee8e943..c9d043a8804d 100644 --- a/tests/pos/i18253.scala +++ b/tests/pos/i18253.scala @@ -4,7 +4,7 @@ trait Foo[A] trait Bar[B]: type Out <: Int object Bar: - given inst[C <: Int]: Bar[C] with + given [C <: Int] => Bar[C]: type Out = C class Test: diff --git a/tests/pos/i18261.min/Main_0.scala b/tests/pos/i18261.min/Main_0.scala index 23d7cbe28198..4d8f79ca241c 100644 --- a/tests/pos/i18261.min/Main_0.scala +++ b/tests/pos/i18261.min/Main_0.scala @@ -2,4 +2,4 @@ type Id[T] = Any match { case Any => T } class Foo[A] object Foo: - given inst[X, Y <: Id[X]]: Foo[Y] = new Foo[Y] + given inst: [X, Y <: Id[X]] => Foo[Y] = new Foo[Y] diff --git a/tests/pos/i18261/DFBits_0.scala b/tests/pos/i18261/DFBits_0.scala index 63b5abb495ef..bbdf871fefb4 100644 --- a/tests/pos/i18261/DFBits_0.scala +++ b/tests/pos/i18261/DFBits_0.scala @@ -3,5 +3,5 @@ trait DFBits[W <: Int] trait Candidate[R]: type OutW <: Int object Candidate: - given [W <: Int, R <: Foo[DFBits[W]]]: Candidate[R] with + given [W <: Int, R <: Foo[DFBits[W]]] => Candidate[R]: type OutW = W diff --git a/tests/pos/i18276a.scala b/tests/pos/i18276a.scala index 46c2722fd8be..eb92066715ef 100644 --- a/tests/pos/i18276a.scala +++ b/tests/pos/i18276a.scala @@ -11,5 +11,5 @@ class ParsersBase { abstract class Parser[+T]: def map[U](f: T => U): Parser[U] = ??? - given [A, B, X]: Conversion[(A, B) => X, (A ~ B) => X] = ??? + given [A, B, X] => Conversion[(A, B) => X, (A ~ B) => X] = ??? } diff --git a/tests/pos/i19404.scala b/tests/pos/i19404.scala index 8d6d4406ebb2..d57027bc46e0 100644 --- a/tests/pos/i19404.scala +++ b/tests/pos/i19404.scala @@ -1,4 +1,4 @@ -given ipEncoder[IP <: IpAddress]: Encoder[IP] = Encoder[String].contramap(_.toString) +given ipEncoder: [IP <: IpAddress] => Encoder[IP] = Encoder[String].contramap(_.toString) class Encoder[A] { final def contramap[B](f: B => A): Encoder[B] = new Encoder[B] diff --git a/tests/pos/i19407.scala b/tests/pos/i19407.scala index b7440a53540d..11c8e746ac43 100644 --- a/tests/pos/i19407.scala +++ b/tests/pos/i19407.scala @@ -6,6 +6,6 @@ object Decoder: object GeneratedEnumDecoder: - given [A <: GeneratedEnum]: Decoder[A] = + given [A <: GeneratedEnum] => Decoder[A] = summon[Decoder[Int]] ??? \ No newline at end of file diff --git a/tests/pos/i19623.scala b/tests/pos/i19623.scala index 8ab8cde159a9..ca3e6b0806e2 100644 --- a/tests/pos/i19623.scala +++ b/tests/pos/i19623.scala @@ -22,7 +22,7 @@ trait RecordLike[R] { val r: %{ val name: String; } = ??? // originally derived in macro, use dummy instance instead - transparent inline given outputRecordLike[R <: %]: RecordLike[R] = null.asInstanceOf[ + transparent inline given outputRecordLike: [R <: %] => RecordLike[R] = null.asInstanceOf[ RecordLike[R] { type ElemTypes = String *: EmptyTuple } diff --git a/tests/pos/i19724.scala b/tests/pos/i19724.scala index 776cf9167890..3054a2541850 100644 --- a/tests/pos/i19724.scala +++ b/tests/pos/i19724.scala @@ -1,5 +1,5 @@ object repro: abstract class Mapper[A, B] extends (A => B) - given Mapper[Int, Double] with + given Mapper[Int, Double]: inline def apply(v: Int): Double = v.toDouble diff --git a/tests/pos/i19749.scala b/tests/pos/i19749.scala index 367c5f61bdce..bbffe3a94961 100644 --- a/tests/pos/i19749.scala +++ b/tests/pos/i19749.scala @@ -5,7 +5,7 @@ case class A(x: Int, y: String) trait SomeTrait[T] object SomeTrait: - given [T]: SomeTrait[T] with {} + given [T] => SomeTrait[T]() def f1[T](using p: Mirror.ProductOf[T]): Tuple.Elem[p.MirroredElemTypes, 0] = ??? diff --git a/tests/pos/i19857.scala b/tests/pos/i19857.scala index aeb6e49111c6..9414290fc369 100644 --- a/tests/pos/i19857.scala +++ b/tests/pos/i19857.scala @@ -18,6 +18,6 @@ type FromProduct[T <: Product] <: DFTypeAny = T match trait Width2[T] object Width2: - inline given [T]: Width2[T] = new Width2[T] {} + inline given [T] => Width2[T] = new Width2[T] {} val x = summon[Width2[Of[(DFBit, DFBit)]]] diff --git a/tests/pos/i19942.1.scala b/tests/pos/i19942.1.scala index 20f923886089..b4ae15bd2b2e 100644 --- a/tests/pos/i19942.1.scala +++ b/tests/pos/i19942.1.scala @@ -13,11 +13,11 @@ object DerivedAlternative: inline def apply[F[_]]: Alternative[F] = import DerivedAlternative.given summonInline[DerivedAlternative[F]].instance - given nested[F[_], G[_]]: DerivedAlternative[F <<< G] = ??? + given nested: [F[_], G[_]] => DerivedAlternative[F <<< G] = ??? object auto: object alternative: - transparent inline given [F[_]]: Alternative[F] = DerivedAlternative[F] + transparent inline given [F[_]] => Alternative[F] = DerivedAlternative[F] trait Test: import Test.* diff --git a/tests/pos/i19955a.scala b/tests/pos/i19955a.scala index b8ea95d41d24..4c89aa615511 100644 --- a/tests/pos/i19955a.scala +++ b/tests/pos/i19955a.scala @@ -2,7 +2,7 @@ trait Summon[R, T <: R]: type Out object Summon: - given [R, T <: R]: Summon[R, T] with + given [R, T <: R] => Summon[R, T]: type Out = R trait DFTypeAny @@ -14,7 +14,7 @@ trait Candidate[R]: type OutW <: Int object Candidate: type Aux[R, O <: Int] = Candidate[R] { type OutW = O } - given [W <: Int, R <: DFValOf[DFBits[W]]]: Candidate[R] with + given [W <: Int, R <: DFValOf[DFBits[W]]] => Candidate[R]: type OutW = W extension [L](lhs: L) def foo(using es: Summon[L, lhs.type]): Unit = ??? diff --git a/tests/pos/i19955b.scala b/tests/pos/i19955b.scala index 99e101b312b1..845b6df9d91f 100644 --- a/tests/pos/i19955b.scala +++ b/tests/pos/i19955b.scala @@ -3,11 +3,11 @@ trait Wrap[W] trait IsWrapOfInt[R]: type Out <: Int -given [W <: Int, R <: Wrap[W]]: IsWrapOfInt[R] with +given [W <: Int, R <: Wrap[W]] => IsWrapOfInt[R]: type Out = Int trait IsInt[U <: Int] -given [U <: Int]: IsInt[U] = ??? +given [U <: Int] => IsInt[U] = ??? extension [L](lhs: L) def get(using ev: IsWrapOfInt[L]): ev.Out = ??? extension (lhs: Int) def isInt(using IsInt[lhs.type]): Unit = ??? diff --git a/tests/pos/i20053b.scala b/tests/pos/i20053b.scala index 25180d56bbae..aedd4e88019c 100644 --- a/tests/pos/i20053b.scala +++ b/tests/pos/i20053b.scala @@ -1,10 +1,10 @@ trait Sub[R, T >: R] -given [R, T >: R]: Sub[R, T] with {} +given [R, T >: R] => Sub[R, T]() trait Candidate[-R]: type OutP -given [P]: Candidate[Option[P]] with +given [P] => Candidate[Option[P]]: type OutP = P extension [L](lhs: L) diff --git a/tests/pos/i20080.scala b/tests/pos/i20080.scala index dbf6843fcbc4..cd8dc15c8add 100644 --- a/tests/pos/i20080.scala +++ b/tests/pos/i20080.scala @@ -4,11 +4,11 @@ trait Zippable[-A, -B]: def zip(left: A, right: B): Out object Zippable extends ZippableLowPrio: - given append[A <: Tuple, B]: (Zippable[A, B] { type Out = Tuple.Append[A, B] }) = + given append: [A <: Tuple, B] => (Zippable[A, B] { type Out = Tuple.Append[A, B] }) = (left, right) => left :* right trait ZippableLowPrio: - given pair[A, B]: (Zippable[A, B] { type Out = (A, B) }) = + given pair: [A, B] => (Zippable[A, B] { type Out = (A, B) }) = (left, right) => (left, right) @@ -17,16 +17,16 @@ object Minimization: trait Fun1: type Out def apply(x: Any): Out - + type M[X] = X match case String => X - + def test[A] = - + val _: Fun1 { type Out = M[A] } = new Fun1: type Out = M[A] def apply(x: Any): Out = ??? - + val _: Fun1 { type Out = M[A] } = x => ??? - + val _: Fun1 { type Out = A match {case String => A} } = x => ??? diff --git a/tests/pos/i20344.scala b/tests/pos/i20344.scala index d3b2a060d6e2..0e8a3d8baabc 100644 --- a/tests/pos/i20344.scala +++ b/tests/pos/i20344.scala @@ -19,7 +19,7 @@ type Beta[R] = [F[_]] =>> GenBeta[R, R, R][F] object Beta: trait Params[+A, +B] trait BetaInstances: - given schrodingerRandomBetaForDouble[F[_]: Monad]: Beta[Double][F] = ??? + given schrodingerRandomBetaForDouble: [F[_]: Monad] => Beta[Double][F] = ??? object all extends BetaInstances diff --git a/tests/pos/i20377.scala b/tests/pos/i20377.scala index 7a4c0fccfd7e..661fa7adfca9 100644 --- a/tests/pos/i20377.scala +++ b/tests/pos/i20377.scala @@ -6,7 +6,7 @@ class ClassToMap[A]() abstract class ClassToFind[Rows <: AnyNamedTuple]: def mapped: NamedTuple.Map[Rows, ClassToMap] -given TDB: ClassToFind[(t1: Int, t2: String)] with +given TDB: ClassToFind[(t1: Int, t2: String)]: override def mapped = ( t1 = ClassToMap[Int](), t2 = ClassToMap[String]() diff --git a/tests/pos/i20572.scala b/tests/pos/i20572.scala index 4ee4490c839c..b1c1d549936e 100644 --- a/tests/pos/i20572.scala +++ b/tests/pos/i20572.scala @@ -1,7 +1,7 @@ //> using options -Werror trait Writes[T] trait Format[T] extends Writes[T] -given [T: List]: Writes[T] = null -given [T]: Format[T] = null +given [T: List] => Writes[T] = null +given [T] => Format[T] = null val _ = summon[Writes[Int]] diff --git a/tests/pos/i20858/defns_1.scala b/tests/pos/i20858/defns_1.scala index 7b4b84745b58..0479f30af22b 100644 --- a/tests/pos/i20858/defns_1.scala +++ b/tests/pos/i20858/defns_1.scala @@ -16,7 +16,7 @@ trait AutoLayer[A]: ): ZLayer[IAnyType[p.MirroredElemTypes], Nothing, A] object AutoLayer: - inline given derived[A](using p: Mirror.ProductOf[A]): AutoLayer[A] = { + inline given derived: [A] => (p: Mirror.ProductOf[A]) => AutoLayer[A] = { val a: ZIO[IAnyType[p.MirroredElemTypes], Nothing, A] = ??? new AutoLayer[A]: override def zlayer(using diff --git a/tests/pos/i21036.scala b/tests/pos/i21036.scala index 1c98346e4ef3..c80889a976eb 100644 --- a/tests/pos/i21036.scala +++ b/tests/pos/i21036.scala @@ -7,10 +7,10 @@ opaque type Id = String object Id: given SameRuntime[Id, String] = ??? -given BSONHandler[String] = ??? -given [T: BSONHandler]: BSONHandler[List[T]] = ??? +given BSONHandler[String] = ??? +given [T: BSONHandler] => BSONHandler[List[T]] = ??? -given opaqueWriter[T, A](using rs: SameRuntime[T, A], writer: BSONWriter[A]): BSONWriter[T] = ??? +given opaqueWriter: [T, A] => (rs: SameRuntime[T, A], writer: BSONWriter[A]) => BSONWriter[T] = ??? val x = summon[BSONHandler[List[Id]]] // this doesn't emit warning val y = summon[BSONWriter[List[Id]]] // this did emit warning diff --git a/tests/pos/i21303/Test.scala b/tests/pos/i21303/Test.scala index fe3efa6e38f3..be6d0df22850 100644 --- a/tests/pos/i21303/Test.scala +++ b/tests/pos/i21303/Test.scala @@ -11,11 +11,11 @@ trait TSNamedType[T] extends TSType[T] trait DefaultTSTypes extends JavaTSTypes trait JavaTSTypes { - given javaEnumTSType[E <: java.lang.Enum[E]: ClassTag]: TSType[E] = ??? + given javaEnumTSType: [E <: java.lang.Enum[E]: ClassTag] => TSType[E] = ??? } object DefaultTSTypes extends DefaultTSTypes trait TSTypeMacros { - inline given [T: Mirror.Of]: TSType[T] = derived[T] + inline given [T: Mirror.Of] => TSType[T] = derived[T] inline def derived[T](using m: Mirror.Of[T]): TSType[T] = { val elemInstances = summonAll[m.MirroredElemTypes] ??? diff --git a/tests/pos/i21303a/Test.scala b/tests/pos/i21303a/Test.scala index 83a598b5f17f..af1471fe3c12 100644 --- a/tests/pos/i21303a/Test.scala +++ b/tests/pos/i21303a/Test.scala @@ -11,12 +11,12 @@ trait TSNamedType[T] extends TSType[T] trait DefaultTSTypes extends JavaTSTypes trait JavaTSTypes { - given javaEnumTSType[E <: java.lang.Enum[E]: ClassTag]: TSType[E] = ??? - given javaEnumTSNamedType[E <: java.lang.Enum[E]: ClassTag]: TSNamedType[E] = ??? + given javaEnumTSType: [E <: java.lang.Enum[E]: ClassTag] => TSType[E] = ??? + given javaEnumTSNamedType: [E <: java.lang.Enum[E]: ClassTag] => TSNamedType[E] = ??? } object DefaultTSTypes extends DefaultTSTypes trait TSTypeMacros { - inline given [T: Mirror.Of]: TSType[T] = derived[T] + inline given [T: Mirror.Of] => TSType[T] = derived[T] inline def derived[T](using m: Mirror.Of[T]): TSType[T] = { val elemInstances = summonAll[m.MirroredElemTypes] ??? diff --git a/tests/pos/i21320a.scala b/tests/pos/i21320a.scala index 0a7e0d1941d1..03930f0b90c9 100644 --- a/tests/pos/i21320a.scala +++ b/tests/pos/i21320a.scala @@ -6,7 +6,7 @@ trait ConfigMonoid[T]: def orElse(main: T, defaults: T): T object ConfigMonoid: - given option[T]: ConfigMonoid[Option[T]] = ??? + given option: [T] => ConfigMonoid[Option[T]] = ??? inline def zeroTuple[C <: Tuple]: Tuple = inline erasedValue[C] match @@ -25,7 +25,7 @@ object ConfigMonoid: defaults ) - inline given derive[T](using m: Mirror.ProductOf[T]): ConfigMonoid[T] = + inline given derive: [T] => (m: Mirror.ProductOf[T]) => ConfigMonoid[T] = new ConfigMonoid[T]: def zero: T = m.fromProduct(zeroTuple[m.MirroredElemTypes]) def orElse(main: T, defaults: T): T = m.fromProduct(valueTuple[m.MirroredElemTypes, T](0, main, defaults)) diff --git a/tests/pos/i21320b.scala b/tests/pos/i21320b.scala index 6711d3d9d952..2c4963ec2f03 100644 --- a/tests/pos/i21320b.scala +++ b/tests/pos/i21320b.scala @@ -6,7 +6,7 @@ trait ConfigMonoid[T]: def orElse(main: T, defaults: T): T object ConfigMonoid: - given option[T]: ConfigMonoid[Option[T]] = ??? + given option: [T] => ConfigMonoid[Option[T]] = ??? inline def zeroTuple[C <: Tuple]: Tuple = inline erasedValue[C] match @@ -25,7 +25,7 @@ object ConfigMonoid: defaults ) - inline given derive[T](using m: Mirror.ProductOf[T]): ConfigMonoid[T] = + inline given derive: [T] => (m: Mirror.ProductOf[T]) => ConfigMonoid[T] = new ConfigMonoid[T]: def zero: T = m.fromProduct(zeroTuple[m.MirroredElemTypes]) def orElse(main: T, defaults: T): T = m.fromProduct(valueTuple[m.MirroredElemTypes, T](0, main, defaults)) diff --git a/tests/pos/i21352a/schema.scala b/tests/pos/i21352a/schema.scala index 486e1bb1ea34..c8b5dd3c2398 100644 --- a/tests/pos/i21352a/schema.scala +++ b/tests/pos/i21352a/schema.scala @@ -11,7 +11,7 @@ object Schema extends SchemaCompanionMacros: ??? trait SchemaCompanionMacros extends SchemaDerivation: - given derivedStringBasedUnionEnumeration[S](using IsUnionOf[String, S]): Schema[S] = + given derivedStringBasedUnionEnumeration: [S] => IsUnionOf[String, S] => Schema[S] = val x: Schema[S] = ??? x.name(None) diff --git a/tests/pos/i21352a/schemaDerivation.scala b/tests/pos/i21352a/schemaDerivation.scala index d34a59c51a61..9a64167ac98d 100644 --- a/tests/pos/i21352a/schemaDerivation.scala +++ b/tests/pos/i21352a/schemaDerivation.scala @@ -15,7 +15,7 @@ object CaseClass: sealed trait IsUnionOf[T, A] object IsUnionOf: - transparent inline given derived[T, A]: IsUnionOf[T, A] = ${ deriveImpl[T, A] } + transparent inline given derived: [T, A] => IsUnionOf[T, A] = ${ deriveImpl[T, A] } private def deriveImpl[T, A](using quotes: Quotes): Expr[IsUnionOf[T, A]] = ??? trait SchemaDerivation: diff --git a/tests/pos/i21352b.scala b/tests/pos/i21352b.scala index 6e1dfbd18e3c..ddf268000969 100644 --- a/tests/pos/i21352b.scala +++ b/tests/pos/i21352b.scala @@ -6,7 +6,7 @@ object serializer: implicit val UnitReader: Reader[Unit] = ??? implicit val StringReader: Reader[String] = ??? // A way to derive instances needs to be available - inline given superTypeReader[T: scala.reflect.ClassTag]: Reader[T] = ??? + inline given superTypeReader: [T: scala.reflect.ClassTag] => Reader[T] = ??? import serializer.Reader trait Codec[T] @@ -25,7 +25,7 @@ trait Communicate[F[_]]: def notification[X <: LSPNotification](notif: X, in: notif.In): F[Unit] object Communicate: - given codec[T: Reader]: Codec[T] = ??? + given codec: [T: Reader] => Codec[T] = ??? def channel[F[_]: Monadic](channel: Channel[F]) = new Communicate[F]: diff --git a/tests/pos/i21352c.scala b/tests/pos/i21352c.scala index 22169f3560a8..a06fd64b1fd8 100644 --- a/tests/pos/i21352c.scala +++ b/tests/pos/i21352c.scala @@ -7,7 +7,7 @@ trait ReadImplicits: import scala.deriving.* given roe: Read[Option[EmptyTuple]] = ??? given rou: Read[Option[Unit]] = ??? - given cons1[H, T <: Tuple](using Read[Option[H]], Read[Option[T]]): Read[Option[H *: T]] = ??? + given cons1: [H, T <: Tuple] => (Read[Option[H]], Read[Option[T]]) => Read[Option[H *: T]] = ??? trait Fragment: def query[B: Read]: String = ??? diff --git a/tests/pos/i21390.zio.scala b/tests/pos/i21390.zio.scala index 3aece69632b3..c04d99b64b27 100644 --- a/tests/pos/i21390.zio.scala +++ b/tests/pos/i21390.zio.scala @@ -5,7 +5,7 @@ class Has[A] object Has: class Union[B, C] object Union: - given HasHasUnion[B0 <: Has[?], C0 <: Has[?]]: Union[B0, C0] = ??? + given HasHasUnion: [B0 <: Has[?], C0 <: Has[?]] => Union[B0, C0] = ??? class Lay[+D]: def and1[B1 >: D, C1](that: Lay[C1])(using Has.Union[B1, C1]): Lay[B1 & C1] = ??? diff --git a/tests/pos/i5915.scala b/tests/pos/i5915.scala index acccbf64a684..c6df5eaebe53 100644 --- a/tests/pos/i5915.scala +++ b/tests/pos/i5915.scala @@ -2,8 +2,8 @@ trait RunDSL val rdsl = new RunDSL {} -given RunNNFExpr[B]: RunDSL = rdsl +given RunNNFExpr: [B] => RunDSL = rdsl -given RunNNFImpl[B]: RunDSL with { +given RunNNFImpl: [B] => RunDSL { //override def runDSL(b: NNF[B]): B = b.terminal } \ No newline at end of file diff --git a/tests/pos/i5978.scala b/tests/pos/i5978.scala index f1954b8c8275..d254d78e93aa 100644 --- a/tests/pos/i5978.scala +++ b/tests/pos/i5978.scala @@ -8,7 +8,7 @@ trait TokenParser[Token, R] package p1 { object TextParser { - given TP: TokenParser[Char, Position[CharSequence]] with {} + given TP: TokenParser[Char, Position[CharSequence]]() def f (using TokenParser[Char, Position[CharSequence]]) = ??? @@ -85,9 +85,9 @@ package p3 { package p4 { class TC - given A: TC with {} + given A: TC() - given B[X[_], Y]: TC with {} + given B: [X[_], Y] => TC() - given C(using TC): TC with {} + given C: TC => TC() } \ No newline at end of file diff --git a/tests/pos/i6716.scala b/tests/pos/i6716.scala index 617adc3c09f0..721a9eb9a794 100644 --- a/tests/pos/i6716.scala +++ b/tests/pos/i6716.scala @@ -2,7 +2,7 @@ trait Monad[T]: def id: String class Foo object Foo { - given Monad[Foo] with { def id = "Foo" } + given Monad[Foo] { def id = "Foo" } } opaque type Bar = Foo diff --git a/tests/pos/i6900.scala b/tests/pos/i6900.scala index 55587a18b4ba..1aa04b1ee177 100644 --- a/tests/pos/i6900.scala +++ b/tests/pos/i6900.scala @@ -8,7 +8,7 @@ object Test1 { // But not with newstyle /* - given [A]: Conversion[A, Foo[A]] with + given [A]: Conversion[A, Foo[A]]: def apply(a: A) = new Foo[A]: def foo[C]: C => A = _ => a */ diff --git a/tests/pos/i6914.scala b/tests/pos/i6914.scala index 2d8cf164f422..c4d840f7bbdc 100644 --- a/tests/pos/i6914.scala +++ b/tests/pos/i6914.scala @@ -5,7 +5,7 @@ object test1 { class ToExpr[T](using Liftable[T]) extends Conversion[T, Expr[T]] { def apply(x: T): Expr[T] = ??? } - given toExpr[T](using Liftable[T]): ToExpr[T] with {} + given toExpr: [T] => Liftable[T] => ToExpr[T]() given Liftable[Int] = ??? given Liftable[String] = ??? @@ -18,7 +18,7 @@ object test1 { object test2 { - given autoToExpr[T](using Liftable[T]): Conversion[T, Expr[T]] with { + given autoToExpr: [T] => Liftable[T] => Conversion[T, Expr[T]] { def apply(x: T): Expr[T] = ??? } diff --git a/tests/pos/i6938.scala b/tests/pos/i6938.scala index e58ab2829cf9..8127fc133f72 100644 --- a/tests/pos/i6938.scala +++ b/tests/pos/i6938.scala @@ -1,5 +1,5 @@ trait Foo[T] object Foo: - given [T]: Foo[Tuple1[T]] with {} - given [T, U]: Foo[(T, U)] with {} - given [T, U, V]: Foo[(T, U, V)] with {} \ No newline at end of file + given [T] => Foo[Tuple1[T]]() + given [T, U] => Foo[(T, U)]() + given [T, U, V] => Foo[(T, U, V)]() \ No newline at end of file diff --git a/tests/pos/i7056.scala b/tests/pos/i7056.scala index a347dfe7b519..fa3c132b58b3 100644 --- a/tests/pos/i7056.scala +++ b/tests/pos/i7056.scala @@ -9,7 +9,7 @@ trait T1[T] { extension (t1: T) def idnt1: Any } -given [T <: A](using PartialId[T]): T1[T] = new T1[T] { +given [T <: A] => PartialId[T] => T1[T] = new T1[T] { extension (t1: T) def idnt1: Any = ??? } diff --git a/tests/pos/i7375.scala b/tests/pos/i7375.scala index 9da548f99ce7..0320696b0c5d 100644 --- a/tests/pos/i7375.scala +++ b/tests/pos/i7375.scala @@ -5,7 +5,7 @@ trait Entity[M, T, P]: class GreetingPerson(private val name: String) object GreetingPerson: - given GreetingPersonEntity: Entity[GreetingPerson, GreetedPerson, String] with + given GreetingPersonEntity: Entity[GreetingPerson, GreetedPerson, String]: extension (me: GreetingPerson) def receive(sender: GreetedPerson)(msg: String)(using Entity[GreetedPerson, GreetingPerson, String]): Unit = println(f"Thanks for saying $msg, ${sender.name()}") @@ -15,7 +15,7 @@ object GreetingPerson: class GreetedPerson(private val name: String) object GreetedPerson: - given GreetedPersonEntity: Entity[GreetedPerson, GreetingPerson, String] with + given GreetedPersonEntity: Entity[GreetedPerson, GreetingPerson, String]: extension (me: GreetedPerson) def receive(sender: GreetingPerson)(msg: String)(using Entity[GreetingPerson, GreetedPerson, String]): Unit = println(f"Thanks for saying $msg, ${sender.name()}") diff --git a/tests/pos/i7413.scala b/tests/pos/i7413.scala index ebc0c5b2777a..2aaf87a1e82a 100644 --- a/tests/pos/i7413.scala +++ b/tests/pos/i7413.scala @@ -11,7 +11,7 @@ trait Greeter: case class MyFixture(name: String, greeter: Greeter) object Test1: - given conv: Conversion[0, Greeter] with + given conv: Conversion[0, Greeter]: def apply(x: 0): Greeter = ??? val g: Greeter = 0 diff --git a/tests/pos/i7586.scala b/tests/pos/i7586.scala index 364c99478337..b0ecd84e5aff 100644 --- a/tests/pos/i7586.scala +++ b/tests/pos/i7586.scala @@ -5,14 +5,15 @@ case class S[N <: Nat](pred: N) extends Nat type Z = Z.type given zero: Z = Z -given succ[N <: Nat](using n: N): S[N] = S(n) +given succ: [N <: Nat] => (n: N) => S[N] = S(n) case class Sum[N <: Nat, M <: Nat, R <: Nat](result: R) -given sumZ[N <: Nat](using n: N): Sum[Z, N, N] = Sum(n) -given sumS[N <: Nat, M <: Nat, R <: Nat]( - using sum: Sum[N, M, R] -): Sum[S[N], M, S[R]] = Sum(S(sum.result)) +given sumZ: [N <: Nat] => (n: N) => Sum[Z, N, N] = Sum(n) +given sumS: [N <: Nat, M <: Nat, R <: Nat] + => (sum: Sum[N, M, R]) + => Sum[S[N], M, S[R]] + = Sum(S(sum.result)) def add[N <: Nat, M <: Nat, R <: Nat](n: N, m: M)( using sum: Sum[N, M, R] diff --git a/tests/pos/i7851.scala b/tests/pos/i7851.scala index 16d28ad353f9..612a6abeb873 100644 --- a/tests/pos/i7851.scala +++ b/tests/pos/i7851.scala @@ -1,18 +1,18 @@ //> using options -experimental trait Wrappable[T] { } -given Wrappable[Float] with { } +given Wrappable[Float]() case class Wrapped[T: Wrappable](value: T) trait Wrapper[T] { type WrappedT } object Wrapper { type Aux[T <: Tuple, WrappedT0 <: Tuple] = Wrapper[T] { type WrappedT = WrappedT0 } } -given Wrapper[EmptyTuple] with { type WrappedT = EmptyTuple } +given Wrapper[EmptyTuple] { type WrappedT = EmptyTuple } -given [T: Wrappable]: Wrapper[T] with { type WrappedT = Wrapped[T] } +given [T: Wrappable] => Wrapper[T] { type WrappedT = Wrapped[T] } -given [H: Wrappable, T <: Tuple, WrappedT0 <: Tuple](using Wrapper.Aux[T, WrappedT0]): Wrapper[H *: T] with { +given [H: Wrappable, T <: Tuple, WrappedT0 <: Tuple] => Wrapper.Aux[T, WrappedT0] => Wrapper[H *: T] { type WrappedT = Wrapped[H] *: WrappedT0 } diff --git a/tests/pos/i7868.scala b/tests/pos/i7868.scala index f4d7da6acb5b..fa31bd131b0c 100644 --- a/tests/pos/i7868.scala +++ b/tests/pos/i7868.scala @@ -15,16 +15,15 @@ object Coproduct { object At { - given atHead[Head, Tail]: At[Head +: Tail, Head, 0] with { + given atHead: [Head, Tail] => At[Head +: Tail, Head, 0]: def cast: Head <:< Head +: Tail = summon[Head <:< Head +: Tail] - } given atTail[Head, Tail, Value, NextIndex <: Int] (using atNext: At[Tail, Value, NextIndex]) : At[Head +: Tail, Value, S[NextIndex]] with val cast: Value <:< Head +: Tail = atNext.cast - given [A](using A): (() => A) = { () => summon[A]} + given [A] => A => (() => A) = { () => summon[A] } } def upCast[A, B](a: A)(using erased evidence: (A <:< B) ): B = a.asInstanceOf[B] diff --git a/tests/pos/i7878.scala b/tests/pos/i7878.scala index 05a1b6093e6a..68815c35eb96 100644 --- a/tests/pos/i7878.scala +++ b/tests/pos/i7878.scala @@ -4,7 +4,7 @@ object Boom { import scala.compiletime.* trait Fail[A <: Int, B <: Int] - transparent inline given fail[X <: Int, Y <: Int]: Fail[X, Y] = { + transparent inline given fail: [X <: Int, Y <: Int] => Fail[X, Y] = { scala.compiletime.summonFrom { case t: Fail[X, y] if constValue[y] < constValue[Y] => ??? } diff --git a/tests/pos/i8182.scala b/tests/pos/i8182.scala index 9acf2941c570..08b40cb570ab 100644 --- a/tests/pos/i8182.scala +++ b/tests/pos/i8182.scala @@ -3,8 +3,8 @@ package example trait Show[-A]: extension (a: A) def show: String -given (using rec: Show[String]): Show[String] = ??? // must be Show[String] as the argument +given Show[String] => Show[String] = ??? // must be Show[String] as the argument -given (using rec: => Show[String]): Show[Option[String]] = ??? // must be byname argument +given (rec: => Show[String]) => Show[Option[String]] = ??? // must be byname argument def test = Option("").show diff --git a/tests/pos/i8198.scala b/tests/pos/i8198.scala index 5e4efa82924a..7ea8f67d25de 100644 --- a/tests/pos/i8198.scala +++ b/tests/pos/i8198.scala @@ -6,6 +6,6 @@ trait Eq[A] { case class Id[T](id: T) -given idEq[A](using eqA: Eq[A]): Eq[Id[A]] = new { +given idEq: [A] => (eqA: Eq[A]) => Eq[Id[A]] = new { extension (i1: Id[A]) def === (i2: Id[A]) = !(i1.id /== i2.id) } diff --git a/tests/pos/i8276.scala b/tests/pos/i8276.scala index e68cf009bc33..3e2ad15bd8f4 100644 --- a/tests/pos/i8276.scala +++ b/tests/pos/i8276.scala @@ -1,6 +1,6 @@ object NOTHING -inline given [A]: Conversion[NOTHING.type, Option[A]] = _ => None +inline given [A] => Conversion[NOTHING.type, Option[A]] = _ => None def apply[A](p: Vector[A], o: Option[A] = NOTHING): Unit = ??? diff --git a/tests/pos/i8344-1.scala b/tests/pos/i8344-1.scala index 92b393da2497..2707507f39f5 100644 --- a/tests/pos/i8344-1.scala +++ b/tests/pos/i8344-1.scala @@ -5,7 +5,7 @@ enum Datatype[T] { } object Datatype { - given [H, T <: STuple](using ht: Datatype[H], tt: Datatype[T]): Datatype[H *: T] = tt match { + given [H, T <: STuple] => (ht: Datatype[H], tt: Datatype[T]) => Datatype[H *: T] = tt match { case Datatype.Tuple(elems) => Datatype.Tuple(ht *: elems) } } diff --git a/tests/pos/i8397.scala b/tests/pos/i8397.scala index d0b97f84129d..707d8c1f1942 100644 --- a/tests/pos/i8397.scala +++ b/tests/pos/i8397.scala @@ -1,4 +1,4 @@ -given foo(using x: Int): AnyRef with +given foo: (x: Int) => AnyRef: type T = x.type // #7859 @@ -6,17 +6,17 @@ given foo(using x: Int): AnyRef with trait Lub2[A, B]: type Output -given [A <: C, B <: C, C]: Lub2[A, B] with +given [A <: C, B <: C, C] => Lub2[A, B]: type Output = C trait Lub[Union]: type Output -given [A]: Lub[A] with +given [A] => Lub[A]: type Output = A -given [Left, Right]( - using lubLeft: Lub[Right], lubRight: Lub[Right])( - using lub2: Lub2[lubLeft.Output, lubRight.Output]) - : Lub[Left | Right] with +given [Left, Right] + => (lubLeft: Lub[Right], lubRight: Lub[Right]) + => (lub2: Lub2[lubLeft.Output, lubRight.Output]) + => Lub[Left | Right]: type Output = lub2.Output diff --git a/tests/pos/i8623.scala b/tests/pos/i8623.scala index e0df48811e1c..69664bfd5148 100644 --- a/tests/pos/i8623.scala +++ b/tests/pos/i8623.scala @@ -11,7 +11,7 @@ def test1 = unseal.pos def test2 = - given QC with {} + given QC() def unseal(using qctx: QC): qctx.tasty.Tree = ??? unseal.pos diff --git a/tests/pos/i8825.scala b/tests/pos/i8825.scala index d7115babfdc4..a9c487b5404a 100644 --- a/tests/pos/i8825.scala +++ b/tests/pos/i8825.scala @@ -17,7 +17,7 @@ object Length { def instance[L <: HList, Out0 <: Nat]: Aux[L, Out0] = new Length[L] { type Out = Out0 } given hnilLength: Aux[HNil, Zero] = instance - given hconsLength[H, T <: HList] (using length: Length[T]): Aux[HCons[H, T], Succ[length.Out]] = instance // (*) + given hconsLength: [H, T <: HList] => (length: Length[T]) => Aux[HCons[H, T], Succ[length.Out]] = instance // (*) //given hconsLength[H, T <: HList, N <: Nat] (using length: Aux[T, N]): Aux[HCons[H, T], Succ[N]] = instance // (**) } diff --git a/tests/pos/i8927.scala b/tests/pos/i8927.scala index 2dfb419abab3..ab1e850ff8e6 100644 --- a/tests/pos/i8927.scala +++ b/tests/pos/i8927.scala @@ -17,7 +17,7 @@ sealed trait DPair[k <: AnyKind, K[_ <: k], +V[_ <: k]]: case _ => None object DPair: - given pair [k, K[_ <: k], V[_ <: k], C <: k]: Conversion[(K[C], V[C]), DPair[k, K, V]] = tup => + given pair: [k, K[_ <: k], V[_ <: k], C <: k] => Conversion[(K[C], V[C]), DPair[k, K, V]] = tup => case class dpair(key: K[C], value: V[C]) extends DPair[k, K, V]: type A = C dpair(tup._1, tup._2) diff --git a/tests/pos/i9342b.scala b/tests/pos/i9342b.scala index e317391f9bb8..36093876e989 100644 --- a/tests/pos/i9342b.scala +++ b/tests/pos/i9342b.scala @@ -1,7 +1,7 @@ trait Label[A]: def apply(v: A): String -given [A]: Label[A] = _.toString +given [A] => Label[A] = _.toString extension [A](x: A) inline def label(using inline l: Label[A]): String = l(x) diff --git a/tests/pos/i9530.scala b/tests/pos/i9530.scala index 32b2f26dbd6c..ab481bd64d1b 100644 --- a/tests/pos/i9530.scala +++ b/tests/pos/i9530.scala @@ -15,12 +15,12 @@ extension [A <: Animal](animal: A)(using diet: Diet[A]) def food4 = diet.food trait Monkey extends Animal -given Diet[Monkey] with +given Diet[Monkey]: type F = Banana def food: Seq[Banana] = Seq(new Banana("yellow"), Banana("green")) trait FoodOps -given FoodOps with +given FoodOps: extension [A <: Animal](using diet: Diet[A])(animal: A) def food5 = diet.food extension [A <: Animal](animal: A)(using diet: Diet[A]) def food6 = diet.food diff --git a/tests/pos/implicit-conversion.scala b/tests/pos/implicit-conversion.scala index a2d12b8ab709..9154b24681c9 100644 --- a/tests/pos/implicit-conversion.scala +++ b/tests/pos/implicit-conversion.scala @@ -1,6 +1,6 @@ object Test { // a problematic implicit conversion, should we flag it? - given Conversion[String, Int] with { + given Conversion[String, Int] { def apply(x: String): Int = Integer.parseInt(toString) } } \ No newline at end of file diff --git a/tests/pos/implicit-prefix-disambiguation.scala b/tests/pos/implicit-prefix-disambiguation.scala index f7843e7f5831..cd1906fe5043 100644 --- a/tests/pos/implicit-prefix-disambiguation.scala +++ b/tests/pos/implicit-prefix-disambiguation.scala @@ -4,7 +4,7 @@ class J[X] trait A: given I[B] = ??? - given (using I[B]): J[B] = ??? + given I[B] => J[B] = ??? object A extends A trait B extends A diff --git a/tests/pos/interleaving-functor.scala b/tests/pos/interleaving-functor.scala index b588e35f60a2..e4a3804ef928 100644 --- a/tests/pos/interleaving-functor.scala +++ b/tests/pos/interleaving-functor.scala @@ -7,7 +7,7 @@ object functorInterleaving: def map[A](x: F[A])[B](f: A => B): F[B] - given Functor[List] with + given Functor[List]: def map[A](x: List[A])[B](f: A => B): List[B] = x.map(f) diff --git a/tests/pos/mt-deskolemize.scala b/tests/pos/mt-deskolemize.scala index 34f38289b24d..df408e67d767 100644 --- a/tests/pos/mt-deskolemize.scala +++ b/tests/pos/mt-deskolemize.scala @@ -37,7 +37,7 @@ class MyExpr3 extends ProdExprAlt[(Prim, VecExpr[Prim], Prim)] trait Constable[E <: Expr]: def lit(v: ExtractValue[E]): E object Constable: - given [E <: Expr]: Constable[E] = ??? + given [E <: Expr] => Constable[E] = ??? object Test: def fromLiteral[E <: Expr : Constable](v: ExtractValue[E]): E = diff --git a/tests/pos/multi-given.scala b/tests/pos/multi-given.scala index 5553df36f1c9..2b404672e9cb 100644 --- a/tests/pos/multi-given.scala +++ b/tests/pos/multi-given.scala @@ -8,3 +8,5 @@ def foo(implicit a: A, b: B, c: C) = "foo" given A() with B given ops: A() with B() + +given ops2: A(), B diff --git a/tests/pos/multiversal.scala b/tests/pos/multiversal.scala index f7fa14264a3c..d6fd267555f5 100644 --- a/tests/pos/multiversal.scala +++ b/tests/pos/multiversal.scala @@ -1,7 +1,7 @@ object Test { import scala.CanEqual - given [X, Y](using CanEqual[X, Y]): CanEqual[List[X], List[Y]] = CanEqual.derived + given [X, Y] => CanEqual[X, Y] => CanEqual[List[X], List[Y]] = CanEqual.derived val b: Byte = 1 val c: Char = 2 diff --git a/tests/pos/not-looping-implicit.scala b/tests/pos/not-looping-implicit.scala index ebaf25e760f2..d99da915fbf4 100644 --- a/tests/pos/not-looping-implicit.scala +++ b/tests/pos/not-looping-implicit.scala @@ -30,7 +30,7 @@ object Schema { ??? } - inline given gen[A]: Schema[A] = derived[A] + inline given gen: [A] => Schema[A] = derived[A] } sealed trait InputValue diff --git a/tests/pos/ord-over-tracked.scala b/tests/pos/ord-over-tracked.scala index a9b4aba556e1..4016a575a838 100644 --- a/tests/pos/ord-over-tracked.scala +++ b/tests/pos/ord-over-tracked.scala @@ -6,7 +6,7 @@ trait Ord[T]: given Ord[Int] = ??? case class D(tracked val x: Int) -given [T <: D]: Ord[T] = (a, b) => a.x < b.x +given [T <: D] => Ord[T] = (a, b) => a.x < b.x def mySort[T: Ord](x: Array[T]): Array[T] = ??? diff --git a/tests/pos/parsercombinators-ctx-bounds.scala b/tests/pos/parsercombinators-ctx-bounds.scala index d77abea5e539..50338dbc2fa5 100644 --- a/tests/pos/parsercombinators-ctx-bounds.scala +++ b/tests/pos/parsercombinators-ctx-bounds.scala @@ -17,7 +17,7 @@ end Combinator final case class Apply[C, E](action: C => Option[E]) final case class Combine[A, B](first: A, second: B) -given apply[C, E]: Combinator[Apply[C, E]] with { +given apply: [C, E] => Combinator[Apply[C, E]] { type Context = C type Element = E extension(self: Apply[C, E]) { diff --git a/tests/pos/parsercombinators-givens-2.scala b/tests/pos/parsercombinators-givens-2.scala index 8349d69a30af..4b00c3801716 100644 --- a/tests/pos/parsercombinators-givens-2.scala +++ b/tests/pos/parsercombinators-givens-2.scala @@ -18,7 +18,7 @@ end Combinator final case class Apply[C, E](action: C => Option[E]) final case class Combine[A, B](first: A, second: B) -given apply[C, E]: Combinator[Apply[C, E]] with { +given apply: [C, E] => Combinator[Apply[C, E]] { type Context = C type Element = E extension(self: Apply[C, E]) { diff --git a/tests/pos/parsercombinators-givens.scala b/tests/pos/parsercombinators-givens.scala index 5b5588c93840..1fa8080b0688 100644 --- a/tests/pos/parsercombinators-givens.scala +++ b/tests/pos/parsercombinators-givens.scala @@ -18,7 +18,7 @@ end Combinator final case class Apply[C, E](action: C => Option[E]) final case class Combine[A, B](first: A, second: B) -given apply[C, E]: Combinator[Apply[C, E]] with { +given apply: [C, E] => Combinator[Apply[C, E]] { type Context = C type Element = E extension(self: Apply[C, E]) { diff --git a/tests/pos/parsercombinators-this.scala b/tests/pos/parsercombinators-this.scala index 70b423985400..19ac878c888f 100644 --- a/tests/pos/parsercombinators-this.scala +++ b/tests/pos/parsercombinators-this.scala @@ -19,7 +19,7 @@ end Combinator final case class Apply[C, E](action: C => Option[E]) final case class Combine[A, B](first: A, second: B) -given apply[C, E]: Combinator with { +given apply: [C, E] => Combinator { type Self = Apply[C, E] type Context = C type Element = E diff --git a/tests/pos/phantom-Eq.scala b/tests/pos/phantom-Eq.scala index 9f892d353b41..d844c4b110c6 100644 --- a/tests/pos/phantom-Eq.scala +++ b/tests/pos/phantom-Eq.scala @@ -29,5 +29,5 @@ object EqUtil { erased given eqByteNum: PhantomEq[Byte, Number] = compiletime.erasedValue erased given eqNumByte: PhantomEq[Number, Byte] = compiletime.erasedValue - erased given eqSeq[T, U](using erased PhantomEq[T, U]): PhantomEq[Seq[T], Seq[U]] = compiletime.erasedValue + erased given eqSeq: [T, U] => (erased PhantomEq[T, U]) => PhantomEq[Seq[T], Seq[U]] = compiletime.erasedValue } diff --git a/tests/pos/phantom-Eq2/Phantom-Eq_1.scala b/tests/pos/phantom-Eq2/Phantom-Eq_1.scala index 120c68174898..b041a4a87efe 100644 --- a/tests/pos/phantom-Eq2/Phantom-Eq_1.scala +++ b/tests/pos/phantom-Eq2/Phantom-Eq_1.scala @@ -14,6 +14,6 @@ object EqUtil { erased given eqDouble: PhantomEqEq[Double] = new PhantomEq[Double, Double] erased given eqByteNum: PhantomEq[Byte, Number] = new PhantomEq[Byte, Number] erased given eqNumByte: PhantomEq[Number, Byte] = new PhantomEq[Number, Byte] - erased given eqSeq[T, U] (using erased eq: PhantomEq[T, U]): PhantomEq[Seq[T], Seq[U]] = + erased given eqSeq: [T, U] => (erased eq: PhantomEq[T, U]) => PhantomEq[Seq[T], Seq[U]] = new PhantomEq[Seq[T], Seq[U]] } diff --git a/tests/pos/phantom-Evidence.scala b/tests/pos/phantom-Evidence.scala index ecdd84cbc481..f56ce3b798ee 100644 --- a/tests/pos/phantom-Evidence.scala +++ b/tests/pos/phantom-Evidence.scala @@ -26,5 +26,5 @@ object WithNormalState { object Utils { type =::=[From, To] - erased given tpEquals[A]: (A =::= A) = compiletime.erasedValue + erased given tpEquals: [A] => (A =::= A) = compiletime.erasedValue } diff --git a/tests/pos/reference/delegates.scala b/tests/pos/reference/delegates.scala index 1cc7a29eee7d..95b9856b687b 100644 --- a/tests/pos/reference/delegates.scala +++ b/tests/pos/reference/delegates.scala @@ -26,11 +26,11 @@ end Common object Instances extends Common: - given intOrd: Ord[Int] with + given intOrd: Ord[Int]: extension (x: Int) def compareTo(y: Int) = if (x < y) -1 else if (x > y) +1 else 0 - given listOrd[T](using Ord[T]): Ord[List[T]] with + given listOrd: [T] => Ord[T] => Ord[List[T]]: extension (xs: List[T]) def compareTo(ys: List[T]): Int = (xs, ys) match case (Nil, Nil) => 0 case (Nil, _) => -1 @@ -49,13 +49,13 @@ object Instances extends Common: def second = xs.tail.head def third = xs.tail.tail.head - given listMonad: Monad[List] with + given listMonad: Monad[List]: extension [A](xs: List[A]) def flatMap[B](f: A => List[B]): List[B] = xs.flatMap(f) def pure[A](x: A): List[A] = List(x) - given readerMonad[Ctx]: Monad[[X] =>> Ctx => X] with + given readerMonad: [Ctx] => Monad[[X] =>> Ctx => X]: extension [A](r: Ctx => A) def flatMap[B](f: A => Ctx => B): Ctx => B = ctx => f(r(ctx))(ctx) def pure[A](x: A): Ctx => A = @@ -93,7 +93,7 @@ object Instances extends Common: object TastyImpl extends TastyAPI: type Symbol = String - given symDeco: SymDeco with + given symDeco: SymDeco: extension (sym: Symbol) def name = sym class D[T] @@ -122,7 +122,7 @@ object Instances extends Common: class Token(str: String) object Token: - given StringToToken: Conversion[String, Token] with + given StringToToken: Conversion[String, Token]: def apply(str: String): Token = new Token(str) val x: Token = "if" @@ -140,11 +140,11 @@ object PostConditions: end PostConditions object AnonymousInstances extends Common: - given Ord[Int] with + given Ord[Int]: extension (x: Int) def compareTo(y: Int) = if (x < y) -1 else if (x > y) +1 else 0 - given [T: Ord]: Ord[List[T]] with + given [T: Ord] => Ord[List[T]]: extension (xs: List[T]) def compareTo(ys: List[T]): Int = (xs, ys).match case (Nil, Nil) => 0 case (Nil, _) => -1 @@ -165,7 +165,7 @@ object AnonymousInstances extends Common: : Convertible[List[From], List[To]] with extension (x: List[From]) def convert: List[To] = x.map(c.convert) - given Monoid[String] with + given Monoid[String]: extension (x: String) def combine(y: String): String = x.concat(y) def unit: String = "" diff --git a/tests/pos/reference/extension-methods.scala b/tests/pos/reference/extension-methods.scala index 64fd23322c1b..54310d6f6dd9 100644 --- a/tests/pos/reference/extension-methods.scala +++ b/tests/pos/reference/extension-methods.scala @@ -81,7 +81,7 @@ object ExtMethods: trait Ord[T]: extension (x: T) def less (y: T): Boolean object Ord: - given Ord[Int] with + given Ord[Int]: extension (x: Int) def less (y: Int): Boolean = x < y end Ord @@ -90,7 +90,7 @@ object ExtMethods: extension [T](xs: Lst[Lst[T]]) def flatten: Lst[T] = xs.foldLeft(Lst())(_ ++ _) - given ord[T: Ord]: Ord[Lst[T]] with + given ord: [T: Ord] => Ord[Lst[T]]: extension (xs: Lst[T]) def less (ys: Lst[T]): Boolean = ??? end Lst diff --git a/tests/pos/suspend-strawman/choices.scala b/tests/pos/suspend-strawman/choices.scala index 968c223d9c0b..e15626c6ecc7 100644 --- a/tests/pos/suspend-strawman/choices.scala +++ b/tests/pos/suspend-strawman/choices.scala @@ -7,7 +7,7 @@ trait Choice: // the handler def choices[T](body: Choice ?=> T): Seq[T] = boundary[Seq[T]]: - given Choice with + given Choice: def choose[A](choices: A*): A = suspend[A, Seq[T]](s => choices.flatMap(s.resume)) Seq(body) diff --git a/tests/pos/suspend-strawman/generators.scala b/tests/pos/suspend-strawman/generators.scala index a890196e6215..a5c73fe41ffe 100644 --- a/tests/pos/suspend-strawman/generators.scala +++ b/tests/pos/suspend-strawman/generators.scala @@ -15,7 +15,7 @@ object generate: var step: () => Unit = () => boundary[Unit]: - given CanProduce[T] with + given CanProduce[T]: def produce(x: T): Unit = nextElem = Some(x) suspend[Unit, Unit]: k => @@ -55,7 +55,7 @@ object Variant2: var step: () => Option[T] = () => boundary: - given CanProduce[T] with + given CanProduce[T]: def produce(x: T): Unit = suspend[Unit, Option[T]]: k => step = () => k.resume(()) diff --git a/tests/pos/suspend-strawman/monadic-reflect.scala b/tests/pos/suspend-strawman/monadic-reflect.scala index 84c5255c2a96..19bb3a283c8a 100644 --- a/tests/pos/suspend-strawman/monadic-reflect.scala +++ b/tests/pos/suspend-strawman/monadic-reflect.scala @@ -48,7 +48,7 @@ trait Monadic[M[_]: Monad]: */ def reify[R](prog: CanReflect[M] ?=> R): M[R] = boundary [M[R]]: - given CanReflect[M] with + given CanReflect[M]: def reflect[R2](mr: M[R2]): R2 = suspend [R2, M[R]] (k => mr.flatMap(k.resume)) pure(prog) diff --git a/tests/pos/suspend-strawman/simple-futures.scala b/tests/pos/suspend-strawman/simple-futures.scala index 0a80a74d49dc..8e75b0d4870a 100644 --- a/tests/pos/suspend-strawman/simple-futures.scala +++ b/tests/pos/suspend-strawman/simple-futures.scala @@ -32,7 +32,7 @@ object Future: // a handler for Async def async(body: Async ?=> Unit): Unit = boundary [Unit]: - given Async with + given Async: def await[T](f: Future[T]): T = f.result match case Some(x) => x case None => suspend[T, Unit](s => f.addWaiting(s.resume)) diff --git a/tests/pos/the.scala b/tests/pos/the.scala index 52c6e364fd92..90c56573c7cc 100644 --- a/tests/pos/the.scala +++ b/tests/pos/the.scala @@ -2,7 +2,7 @@ object Test { trait Foo { type T; val x: T } - given intFoo: Foo with { + given intFoo: Foo { type T = Int val x = 3 } diff --git a/tests/pos/toplevel-opaque-xm/Logarithm_1.scala b/tests/pos/toplevel-opaque-xm/Logarithm_1.scala index f2744aaae5af..436097fee478 100644 --- a/tests/pos/toplevel-opaque-xm/Logarithm_1.scala +++ b/tests/pos/toplevel-opaque-xm/Logarithm_1.scala @@ -14,7 +14,7 @@ object Logarithm { def exponent(l: Logarithm): Double = l - given AnyRef with { + given AnyRef { // This is the second way to unlift the logarithm type extension (x: Logarithm) def toDouble: Double = math.exp(x) extension (x: Logarithm) def + (y: Logarithm) = Logarithm(math.exp(x) + math.exp(y)) diff --git a/tests/pos/typeclass-aggregates.scala b/tests/pos/typeclass-aggregates.scala index 5e4551b226b7..bf1a59247170 100644 --- a/tests/pos/typeclass-aggregates.scala +++ b/tests/pos/typeclass-aggregates.scala @@ -42,6 +42,6 @@ val y: Int = ??? : x.Self // given [A, B](using ord: A is Ord, monoid: A is Monoid) => A is Ord & Monoid = // new ord.OrdProxy with monoid.MonoidProxy {} -given [A](using ord: Ord { type Self = A }, monoid: Monoid { type Self = A}): ((Ord & Monoid) { type Self = A}) = +given [A] => (ord: Ord { type Self = A }, monoid: Monoid { type Self = A}) => ((Ord & Monoid) { type Self = A}) = new ord.OrdProxy with monoid.MonoidProxy {} diff --git a/tests/pos/typeclasses-this.scala b/tests/pos/typeclasses-this.scala index 33ccb8d9d653..ebe0dc348a06 100644 --- a/tests/pos/typeclasses-this.scala +++ b/tests/pos/typeclasses-this.scala @@ -36,7 +36,7 @@ end Common object Instances extends Common: - given intOrd: (Int is Ord) with + given intOrd: (Int is Ord): extension (x: Int) def compareTo(y: Int) = if x < y then -1 @@ -44,7 +44,7 @@ object Instances extends Common: else 0 // given [T](using tracked val ev: Ord { type Self = T}): Ord { type Self = List[T] } with - given [T: Ord]: (List[T] is Ord) with + given [T: Ord] => (List[T] is Ord): extension (xs: List[T]) def compareTo(ys: List[T]): Int = (xs, ys) match case (Nil, Nil) => 0 case (Nil, _) => -1 @@ -53,7 +53,7 @@ object Instances extends Common: val fst = x.compareTo(y) if (fst != 0) fst else xs1.compareTo(ys1) - given listMonad: (List is Monad) with + given listMonad: (List is Monad): extension [A](xs: List[A]) def flatMap[B](f: A => List[B]): List[B] = xs.flatMap(f) def pure[A](x: A): List[A] = @@ -61,7 +61,7 @@ object Instances extends Common: type Reader[Ctx] = [X] =>> Ctx => X - given readerMonad[Ctx]: (Reader[Ctx] is Monad) with + given readerMonad: [Ctx] => Reader[Ctx] is Monad: extension [A](r: Ctx => A) def flatMap[B](f: A => Ctx => B): Ctx => B = ctx => f(r(ctx))(ctx) def pure[A](x: A): Ctx => A = @@ -83,7 +83,7 @@ object Instances extends Common: def maximum[T: Ord](xs: List[T]): T = xs.reduce(_ `max` _) - given descending[T: Ord]: (T is Ord) with + given descending: [T: Ord] => T is Ord: extension (x: T) def compareTo(y: T) = T.compareTo(y)(x) def minimum[T: Ord](xs: List[T]) = @@ -123,7 +123,7 @@ class Sheep(val name: String): println(s"$name gets a haircut!") isNaked = true -given Sheep is Animal with +given Sheep is Animal: def apply(name: String) = Sheep(name) extension (self: Self) def name: String = self.name diff --git a/tests/pos/typeclasses.scala b/tests/pos/typeclasses.scala index d0315a318310..40f992cbcb57 100644 --- a/tests/pos/typeclasses.scala +++ b/tests/pos/typeclasses.scala @@ -31,7 +31,7 @@ end Common object Instances extends Common: - given intOrd: (Int is Ord) with + given intOrd: Int is Ord: type Self = Int extension (x: Int) def compareTo(y: Int) = @@ -39,7 +39,7 @@ object Instances extends Common: else if x > y then +1 else 0 - given listOrd[T](using ord: T is Ord): (List[T] is Ord) with + given listOrd: [T] => (ord: T is Ord) => List[T] is Ord: extension (xs: List[T]) def compareTo(ys: List[T]): Int = (xs, ys) match case (Nil, Nil) => 0 case (Nil, _) => -1 @@ -49,7 +49,7 @@ object Instances extends Common: if (fst != 0) fst else xs1.compareTo(ys1) end listOrd - given listMonad: (List is Monad) with + given listMonad: List is Monad: extension [A](xs: List[A]) def flatMap[B](f: A => List[B]): List[B] = xs.flatMap(f) def pure[A](x: A): List[A] = @@ -60,7 +60,7 @@ object Instances extends Common: //given [Ctx] => Reader[Ctx] is Monad as readerMonad: - given readerMonad[Ctx]: (Reader[Ctx] is Monad) with + given readerMonad: [Ctx] => Reader[Ctx] is Monad: extension [A](r: Ctx => A) def flatMap[B](f: A => Ctx => B): Ctx => B = ctx => f(r(ctx))(ctx) def pure[A](x: A): Ctx => A = @@ -132,7 +132,7 @@ instance Sheep: Animal with */ // Implement the `Animal` trait for `Sheep`. -given (Sheep is Animal) with +given Sheep is Animal: def apply(name: String) = Sheep(name) extension (self: Self) def name: String = self.name diff --git a/tests/run-macros/BigFloat/BigFloat_1.scala b/tests/run-macros/BigFloat/BigFloat_1.scala index 5bb5b49587bd..246e3dcd442d 100644 --- a/tests/run-macros/BigFloat/BigFloat_1.scala +++ b/tests/run-macros/BigFloat/BigFloat_1.scala @@ -35,7 +35,7 @@ object BigFloat extends App { def fromDigits(digits: String) = apply(digits) } - given BigFloatFromDigits with { + given BigFloatFromDigits { override inline def fromDigits(digits: String) = ${ BigFloatFromDigitsImpl('digits) } @@ -43,7 +43,7 @@ object BigFloat extends App { // Should be in StdLib: - given ToExpr[BigInt] with { + given ToExpr[BigInt] { def apply(x: BigInt)(using Quotes) = '{BigInt(${Expr(x.toString)})} } diff --git a/tests/run-macros/quoted-liftable-derivation-macro-2/Derivation_1.scala b/tests/run-macros/quoted-liftable-derivation-macro-2/Derivation_1.scala index 1b45835006c0..1212866a3df0 100644 --- a/tests/run-macros/quoted-liftable-derivation-macro-2/Derivation_1.scala +++ b/tests/run-macros/quoted-liftable-derivation-macro-2/Derivation_1.scala @@ -9,7 +9,7 @@ object Lft { given Lft[Int] with def toExpr(x: Int)(using Quotes) = Expr(x) - inline given derived[T](using inline m: Mirror.Of[T]): Lft[T] = ${ derivedExpr('m) } + inline given derived: [T] => (inline m: Mirror.Of[T]) => Lft[T] = ${ derivedExpr('m) } private def derivedExpr[T](mirrorExpr: Expr[Mirror.Of[T]])(using Quotes, Type[T]): Expr[Lft[T]] = { val tpe = summonExprOrError[Type[T]] diff --git a/tests/run/Signals.scala b/tests/run/Signals.scala index bf5232bcd2d4..f6c67eb3df9f 100644 --- a/tests/run/Signals.scala +++ b/tests/run/Signals.scala @@ -29,7 +29,7 @@ package frp: object Signal: type Caller = Signal[?] - given noCaller: Caller(???) with + given noCaller: Caller(???): override def computeValue() = () end Signal diff --git a/tests/run/Typeable.scala b/tests/run/Typeable.scala index 18bf9a4deb6a..58a9838db9a1 100644 --- a/tests/run/Typeable.scala +++ b/tests/run/Typeable.scala @@ -27,13 +27,13 @@ object Typeable: class instanceOf[T: Typeable]: def unapply(x: Any): Option[T] = Typeable[T].cast(x) - given int: Typeable[Int] with + given int: Typeable[Int]: def cast(x: Any): Option[Int] = x match case x: Int => Some(x) case _ => None def describe = "Int" - given list[T: Typeable]: Typeable[List[T]] with + given list: [T: Typeable] => Typeable[List[T]]: def cast(x: Any): Option[List[T]] = x match case x: List[_] if x.forall(Typeable[T].cast(_).isDefined) => Some(x.asInstanceOf[List[T]]) case _ => None diff --git a/tests/run/abstract-givens.scala b/tests/run/abstract-givens.scala index 6ff966411dde..addbf524ba47 100644 --- a/tests/run/abstract-givens.scala +++ b/tests/run/abstract-givens.scala @@ -6,7 +6,7 @@ trait T: object Test extends T, App: given x: Int = 22 override given y(using Int): String = summon[Int].toString - given z[T](using T): Seq[T] with + given z: [T] => T => Seq[T]: override def apply(x: Int) = ??? override def length = ??? override def iterator = ??? diff --git a/tests/run/cochis-example.scala b/tests/run/cochis-example.scala index 93ce9323d2f7..652d58ef0d81 100644 --- a/tests/run/cochis-example.scala +++ b/tests/run/cochis-example.scala @@ -1,7 +1,7 @@ import Predef.{assert, $conforms as _} trait A { - given id[X]: (X => X) = x => x + given id: [X] => (X => X) = x => x def trans[X](x: X)(using f: X => X) = f(x) // (2) } object Test extends A with App{ diff --git a/tests/run/extension-specificity2.scala b/tests/run/extension-specificity2.scala index eeaad80a3687..aa1aef299163 100644 --- a/tests/run/extension-specificity2.scala +++ b/tests/run/extension-specificity2.scala @@ -4,11 +4,11 @@ trait Foo[F[_]]: def test1 = // Simplified from https://github.com/typelevel/spotted-leopards/issues/2 - given listFoo: Foo[List] with + given listFoo: Foo[List]: extension [A](fa: List[A]) def foo[B](fb: List[B]): Int = 1 - given functionFoo[T]: Foo[[A] =>> T => A] with + given functionFoo: [T] => Foo[[A] =>> T => A]: extension [A](fa: T => A) def foo[B](fb: T => B): Int = 2 @@ -23,9 +23,9 @@ def test2 = trait Bar2: extension (x: Int => 1) def bar(y: Int): Int - given bla1[T]: Bar1[T] with + given bla1: [T] => Bar1[T]: extension (x: T => T) def bar(y: T): Int = 1 - given bla2: Bar2 with + given bla2: Bar2: extension (x: Int => 1) def bar(y: Int): Int = 2 val f: Int => 1 = x => 1 diff --git a/tests/run/extmethod-overload.scala b/tests/run/extmethod-overload.scala index 4a9fe125a8a9..46239ed3290b 100644 --- a/tests/run/extmethod-overload.scala +++ b/tests/run/extmethod-overload.scala @@ -97,7 +97,7 @@ object Test extends App { extension (x: Int) def yy(y: Int) = x + y } - given AnyRef with + given AnyRef: extension (x: Int) { def yy (y: Int) = x - y } diff --git a/tests/run/extmethods2.scala b/tests/run/extmethods2.scala index f876b00a9974..a65082dc9e11 100644 --- a/tests/run/extmethods2.scala +++ b/tests/run/extmethods2.scala @@ -2,7 +2,7 @@ object Test extends App { class TC - given stringListOps(using TC): Object with { + given stringListOps: TC => Object { type T = List[String] extension (x: T) def foo(y: T) = (x ++ y, summon[TC]) extension (x: T) def bar(y: Int) = (x(0)(y), summon[TC]) diff --git a/tests/run/fragables-extension.scala b/tests/run/fragables-extension.scala index 417a612a3f04..1fc738af25d8 100644 --- a/tests/run/fragables-extension.scala +++ b/tests/run/fragables-extension.scala @@ -11,11 +11,11 @@ given Fragable[Int] = x => List(IntFrag(x)) given Fragable[String] = x => List(StringFrag(x)) -given [A: Fragable]: Fragable[List[A]] = +given [A: Fragable] => Fragable[List[A]] = x => x.flatMap(_.toFrags) given Fragable[EmptyTuple] = x => Nil -given [A: Fragable, B <: Tuple: Fragable]: Fragable[A *: B] = +given [A: Fragable, B <: Tuple: Fragable] => Fragable[A *: B] = x => x.head.toFrags ++ x.tail.toFrags def f[T: Fragable](x: T) = diff --git a/tests/run/genericNumLits.scala b/tests/run/genericNumLits.scala index 7f91ab0b3ef5..7d1737903d21 100644 --- a/tests/run/genericNumLits.scala +++ b/tests/run/genericNumLits.scala @@ -10,7 +10,7 @@ object Test extends App { case class Even(n: Int) - given FromDigits[Even] with { + given FromDigits[Even] { def fromDigits(digits: String): Even = { val intValue = digits.toInt if (intValue % 2 == 0) Even(intValue) diff --git a/tests/run/given-eta.scala b/tests/run/given-eta.scala index a01f1c441018..571125f2b4c5 100644 --- a/tests/run/given-eta.scala +++ b/tests/run/given-eta.scala @@ -12,7 +12,7 @@ def g(x: Int)(using d: D) (y: d.T): d.T = d.trans(y) val x = f assert(x(2)(3) == 6) - given D with + given D: type T = Int def trans(other: T) = 2 * other val y = g diff --git a/tests/run/i11050.scala b/tests/run/i11050.scala index 027812c013c4..34613fdaf5fd 100644 --- a/tests/run/i11050.scala +++ b/tests/run/i11050.scala @@ -107,9 +107,9 @@ trait Show[-T]: def show(x: T): String object Show: - given Show[Int] with { def show(x: Int) = s"$x" } - given Show[Char] with { def show(x: Char) = s"'$x'" } - given Show[String] with { def show(x: String) = s"$"$x$"" } + given Show[Int] { def show(x: Int) = s"$x" } + given Show[Char] { def show(x: Char) = s"'$x'" } + given Show[String] { def show(x: String) = s"$"$x$"" } inline def show[T](x: T): String = summonInline[Show[T]].show(x) diff --git a/tests/run/i11174.scala b/tests/run/i11174.scala index 644d3144d8d8..89759d37b076 100644 --- a/tests/run/i11174.scala +++ b/tests/run/i11174.scala @@ -38,7 +38,7 @@ class MainClass { case Square(width: Int, height: Int) extends Shape case Circle(radius: Int) extends Shape - given EnumerateNames[Int] with { + given EnumerateNames[Int] { def apply: String = "int" } inline given auto[T]:EnumerateNames[T] = EnumerateNames.derived diff --git a/tests/run/i11174local.scala b/tests/run/i11174local.scala index a0c9b8e253b9..1f18c67680d9 100644 --- a/tests/run/i11174local.scala +++ b/tests/run/i11174local.scala @@ -34,10 +34,10 @@ trait EnumerateNames[T] { } class MainClass { - given EnumerateNames[Int] with { + given EnumerateNames[Int] { def apply: String = "int" } - inline given auto[T]: EnumerateNames[T] = EnumerateNames.derived + inline given auto: [T] => EnumerateNames[T] = EnumerateNames.derived def deriveEnumerateNames[T](using en: EnumerateNames[T]) = en.apply def run = { diff --git a/tests/run/i11542.scala b/tests/run/i11542.scala index 32e940e745d0..2d799f4233f9 100644 --- a/tests/run/i11542.scala +++ b/tests/run/i11542.scala @@ -14,7 +14,7 @@ object demo { childReaders: List[Reader[_]] ) extends Reader[A] - inline given rdr[A <: Tuple](using m: deriving.Mirror.ProductOf[A]): Reader[A] = { + inline given rdr: [A <: Tuple] => (m: deriving.Mirror.ProductOf[A]) => Reader[A] = { new CombinedReader(m, summonReader[m.MirroredElemTypes]) } diff --git a/tests/run/i11542a.scala b/tests/run/i11542a.scala index db4142fb1a86..37a0c816d1f2 100644 --- a/tests/run/i11542a.scala +++ b/tests/run/i11542a.scala @@ -1,6 +1,6 @@ type Foo = Tuple2[Int, Int] // case class Foo(x: Int, y: Int) // works class Reader(m: deriving.Mirror.ProductOf[Foo]) -given reader1(using m: deriving.Mirror.ProductOf[Foo]): Reader = new Reader(m) +given reader1: (m: deriving.Mirror.ProductOf[Foo]) => Reader = new Reader(m) inline def summonReader(): Reader = compiletime.summonInline[Reader] @main def Test() = summonReader() diff --git a/tests/run/i11563.scala b/tests/run/i11563.scala index 97f60140e402..182bcc11927e 100644 --- a/tests/run/i11563.scala +++ b/tests/run/i11563.scala @@ -4,7 +4,7 @@ import scala.deriving.Mirror trait Printer[T]: def format: String -given Printer[String] with +given Printer[String]: def format: String = "String" inline given[T](using mirror: Mirror.ProductOf[T]): Printer[T] = Printer.derived[T] diff --git a/tests/run/i11583.scala b/tests/run/i11583.scala index fd4d63faa084..bbb00671e528 100644 --- a/tests/run/i11583.scala +++ b/tests/run/i11583.scala @@ -20,11 +20,11 @@ extension [A](a: A) @main def Test = - given Context with + given Context: type Type = String type Term = Boolean - given Env with + given Env: type Extra = Int val t1: (String, Boolean, Int) = true.:#:("hello")(23) diff --git a/tests/run/i11961.scala b/tests/run/i11961.scala index f289f6b415b6..1ecb205b2ba5 100644 --- a/tests/run/i11961.scala +++ b/tests/run/i11961.scala @@ -17,10 +17,10 @@ trait Printable[T]: object Printable: - given Printable[String] with + given Printable[String]: def print: Unit = println("STRING") - given Printable[Boolean] with + given Printable[Boolean]: def print: Unit = println("BOOLEAN") def printProduct[T](p: Mirror.ProductOf[T], elems: => List[Printable[_]]): Printable[T] = @@ -28,7 +28,7 @@ object Printable: def print: Unit = elems.foreach(_.print) - inline given derived[T](using m: Mirror.Of[T]): Printable[T] = + inline given derived: [T] => (m: Mirror.Of[T]) => Printable[T] = val elemInstances = summonAllPrintable[m.MirroredElemTypes] inline m match case p: Mirror.ProductOf[T] => printProduct(p, elemInstances) diff --git a/tests/run/i11966.scala b/tests/run/i11966.scala index 184e68f7599c..57956b9d7274 100644 --- a/tests/run/i11966.scala +++ b/tests/run/i11966.scala @@ -6,11 +6,11 @@ trait B[T: A]: trait C[T: A] extends B[T] -given a1: A[Int] with +given a1: A[Int]: def f = 1 class D extends C[Int]: - given a2: A[Int] with + given a2: A[Int]: def f = 2 @main def Test = D() diff --git a/tests/run/i12328.scala b/tests/run/i12328.scala index 0f9f00ca19aa..04e97c618e10 100644 --- a/tests/run/i12328.scala +++ b/tests/run/i12328.scala @@ -20,7 +20,7 @@ object Schema { new Schema[T] { } } - inline given gen[T]: Schema[T] = derived + inline given gen: [T] => Schema[T] = derived } @main def Test: Unit = { diff --git a/tests/run/i13146.scala b/tests/run/i13146.scala index cbaee29a5ec0..6d77e6ddc209 100644 --- a/tests/run/i13146.scala +++ b/tests/run/i13146.scala @@ -10,7 +10,7 @@ trait Eq[-T]: def eqv(x: T, y: T): Boolean object Eq: - given Eq[Int] with + given Eq[Int]: def eqv(x: Int, y: Int) = x == y def check(elem: Eq[_])(x: Any, y: Any): Boolean = @@ -31,7 +31,7 @@ object Eq: case ((x, y), elem) => check(elem)(x, y) } - inline given derived[T](using m: Mirror.Of[T]): Eq[T] = + inline given derived: [T] => (m: Mirror.Of[T]) => Eq[T] = lazy val elemInstances = summonAll[m.MirroredElemTypes] inline m match case s: Mirror.SumOf[T] => eqSum(s, elemInstances) @@ -43,7 +43,7 @@ enum Opt[+T]: case Nn object Opt: - given derivedEq[T]: Eq[Opt[T]] = Eq.derived + given derivedEq: [T] => Eq[Opt[T]] = Eq.derived @main def Test(): Unit = import Opt.* diff --git a/tests/run/i13146a.scala b/tests/run/i13146a.scala index 37e135ac9f76..f9df675510e3 100644 --- a/tests/run/i13146a.scala +++ b/tests/run/i13146a.scala @@ -26,7 +26,7 @@ trait Eq[-T]: object Eq: - given Eq[Int] with + given Eq[Int]: def eqv(x: Int, y: Int) = x == y def check(elem: Eq[_])(x: Any, y: Any): Boolean = @@ -47,7 +47,7 @@ object Eq: case ((x, y), elem) => check(elem)(x, y) } - inline given derived[T](using m: Mirror.Of[T]): Eq[T] = + inline given derived: [T] => (m: Mirror.Of[T]) => Eq[T] = lazy val elemInstances = summonAll[T, m.MirroredElemTypes] inline m match case s: Mirror.SumOf[T] => eqSum(s, elemInstances) diff --git a/tests/run/i13146poly.scala b/tests/run/i13146poly.scala index 849f4dc7eb52..1d011221b931 100644 --- a/tests/run/i13146poly.scala +++ b/tests/run/i13146poly.scala @@ -3,10 +3,10 @@ import scala.deriving.* trait Functor[F[_]] object Functor: - given [C]: Functor[[T] =>> C]() + given [C] => Functor[[T] =>> C]() given Functor[[T] =>> Tuple1[T]]() - given t2 [T]: Functor[[U] =>> (T, U)]() - given t3 [T, U]: Functor[[V] =>> (T, U, V)]() + given t2: [T] => Functor[[U] =>> (T, U)]() + given t3: [T, U] => Functor[[V] =>> (T, U, V)]() def derived[F[_]](using m: Mirror { type MirroredType[X] = F[X] ; type MirroredElemTypes[_] }, r: Functor[m.MirroredElemTypes]): Functor[F] = new Functor[F] {} diff --git a/tests/run/i13304.scala b/tests/run/i13304.scala index f60359b82d47..f8e50f004848 100644 --- a/tests/run/i13304.scala +++ b/tests/run/i13304.scala @@ -1,10 +1,10 @@ trait Zero[F[_]]: def zero[A]: F[A] -given Zero[List] with +given Zero[List]: def zero[A] = List.empty[A] -given Zero[Option] with +given Zero[Option]: def zero[A] = Option.empty[A] diff --git a/tests/run/i13332shapeless.scala b/tests/run/i13332shapeless.scala index 204980d8fe62..fe63a9ba6855 100644 --- a/tests/run/i13332shapeless.scala +++ b/tests/run/i13332shapeless.scala @@ -119,7 +119,7 @@ package GenericTestsAux2 { class Bar[A] object Bar { - given gen[A](using Generic[A]): Bar[A] = Bar() + given gen: [A: Generic] => Bar[A] = Bar() } class Outer1 { @@ -362,7 +362,7 @@ package shapeless { case Mirror.Sum { type MirroredType = T } => CListRefl[Elems] case Mirror.Product { type MirroredType = T } => Elems - transparent inline given [T](using m: Mirror.Of[T]): Generic[T] = apply[T] + transparent inline given [T: Mirror.Of] => Generic[T] = apply[T] transparent inline def apply[T](using m: Mirror.Of[T]) = new Generic[T] { type Repr = Generic.Repr[T, m.type, m.MirroredElemTypes] diff --git a/tests/run/i14150.scala b/tests/run/i14150.scala index 9ddfaf342bb9..89060333105b 100644 --- a/tests/run/i14150.scala +++ b/tests/run/i14150.scala @@ -22,7 +22,7 @@ object GetConstValue { } } - given empty : GetConstValue[EmptyTuple] with { + given empty : GetConstValue[EmptyTuple] { type Out = EmptyTuple def get : Out = EmptyTuple } diff --git a/tests/run/i17115.scala b/tests/run/i17115.scala index 5a7cac5d0dc1..5c82cf13a8ad 100644 --- a/tests/run/i17115.scala +++ b/tests/run/i17115.scala @@ -1,6 +1,6 @@ trait A[T <: Tuple] { val x: Int } -given empty: A[EmptyTuple] with { val x = 1 } -given inductive[Tup <: NonEmptyTuple](using A[Tuple.Tail[Tup]]): A[Tup] with { val x = summon[A[Tuple.Tail[Tup]]].x + 1 } +given empty: A[EmptyTuple] { val x = 1 } +given inductive: [Tup <: NonEmptyTuple] => A[Tuple.Tail[Tup]] => A[Tup] { val x = summon[A[Tuple.Tail[Tup]]].x + 1 } object Test: def main(args: Array[String]): Unit = diff --git a/tests/run/i6716.scala b/tests/run/i6716.scala index e793381cce1c..c0678c51fb30 100644 --- a/tests/run/i6716.scala +++ b/tests/run/i6716.scala @@ -4,7 +4,7 @@ trait Monad[T]: def id: String class Foo object Foo { - given Monad[Foo] with { def id = "Foo" } + given Monad[Foo] { def id = "Foo" } } opaque type Bar = Foo diff --git a/tests/run/i7788.scala b/tests/run/i7788.scala index 99d16ba1521c..3dc4d247ad94 100644 --- a/tests/run/i7788.scala +++ b/tests/run/i7788.scala @@ -4,9 +4,9 @@ trait Show[-A]: given Show[String] = x => x given Show[Int] = _.toString -given showEither[A,B](using sA: Show[A])(using Show[B]): Show[Either[A,B]] = +given showEither: [A,B] => (sA: Show[A]) => Show[B] => Show[Either[A,B]] = _.fold(a => s"Left(${summon[Show[A]].show(a)})", b => s"Right(${summon[Show[B]].show(b)})") -given [A,B](using sA: Show[A])(using sB: Show[B]): Show[(A,B)] = (a,b) => s"(${sA.show(a)}), ${sB.show(b)})" +given [A,B] => (sA: Show[A]) => (sB: Show[B]) => Show[(A,B)] = (a,b) => s"(${sA.show(a)}), ${sB.show(b)})" @main def Test = diff --git a/tests/run/i9011.scala b/tests/run/i9011.scala index 22ab9bc1e1a6..13afbf1a4297 100644 --- a/tests/run/i9011.scala +++ b/tests/run/i9011.scala @@ -10,7 +10,7 @@ trait Eq[T] { } object Eq { - given Eq[Int] with { + given Eq[Int] { def eqv(x: Int, y: Int) = x == y } @@ -40,7 +40,7 @@ object Eq { } } - inline given derived[T](using m: Mirror.Of[T]): Eq[T] = { + inline given derived: [T] => (m: Mirror.Of[T]) => Eq[T] = { val elemInstances = summonAll[m.MirroredElemTypes] inline m match { case s: Mirror.SumOf[T] => eqSum(s, elemInstances) diff --git a/tests/run/i9473.scala b/tests/run/i9473.scala index 384870ea42af..4b4e8d4c1d07 100644 --- a/tests/run/i9473.scala +++ b/tests/run/i9473.scala @@ -11,7 +11,7 @@ trait Eq[T] { } object Eq { - given Eq[Int] with { + given Eq[Int] { def eqv(x: Int, y: Int) = x == y } @@ -36,7 +36,7 @@ object Eq { } } - inline given derived[T](using m: Mirror.Of[T]): Eq[T] = { + inline given derived: [T] => (m: Mirror.Of[T]) => Eq[T] = { lazy val elemInstances = summonAll[m.MirroredElemTypes] inline m match { case s: Mirror.SumOf[T] => eqSum(s, elemInstances) diff --git a/tests/run/i9530.scala b/tests/run/i9530.scala index e0262764039f..0c003a4bf475 100644 --- a/tests/run/i9530.scala +++ b/tests/run/i9530.scala @@ -13,7 +13,7 @@ extension (using s: Scope)(expr: s.Expr) def f(using s: Scope)(x: s.Expr): (String, s.Value) = (x.show, x.eval) -given scope: Scope with +given scope: Scope: case class Expr(str: String) type Value = Int def expr(x: String) = Expr(x) diff --git a/tests/run/i9928.scala b/tests/run/i9928.scala index 3a3f818b17d3..6e4149ef6538 100644 --- a/tests/run/i9928.scala +++ b/tests/run/i9928.scala @@ -2,7 +2,7 @@ trait Magic[F]: extension (x: Int) def read: F trait LowPrio: - given Magic[String] with + given Magic[String]: extension(x: Int) def read: String = println("In string") s"$x" @@ -15,7 +15,7 @@ object test1: import Magic.given def apply(s: String): Foo = s - given Magic[Foo] with + given Magic[Foo]: extension (x: Int) def read: Foo = println("In foo") Foo(s"$x") @@ -25,7 +25,7 @@ object test1: object test2: object Magic extends LowPrio: - given Magic[Foo] with + given Magic[Foo]: extension (x: Int) def read: Foo = println("In foo") Foo(s"$x") diff --git a/tests/run/ift-return.scala b/tests/run/ift-return.scala index 021c73173051..b49f4c647ee0 100644 --- a/tests/run/ift-return.scala +++ b/tests/run/ift-return.scala @@ -11,9 +11,9 @@ def f(x: Boolean): A ?=> (c: Ctx) ?=> (Int, c.T) = (summon[A].x, summon[Ctx].y) @main def Test = - given A with + given A: val x = 22 - given Ctx with + given Ctx: type T = String val x = "abc" val y = "def" diff --git a/tests/run/implicit-alias.scala b/tests/run/implicit-alias.scala index 64117c3fc977..b376e1635496 100644 --- a/tests/run/implicit-alias.scala +++ b/tests/run/implicit-alias.scala @@ -60,7 +60,7 @@ object Test extends App { locally { println("with type params") - given t[X]: TC = new TC + given t: [X] => TC = new TC summon[TC] summon[TC] } diff --git a/tests/run/implicit-specifity.scala b/tests/run/implicit-specifity.scala index 9e59cf5f1869..b12fe5b2788f 100644 --- a/tests/run/implicit-specifity.scala +++ b/tests/run/implicit-specifity.scala @@ -5,19 +5,19 @@ object Show { def apply[T](implicit st: Show[T]): Int = st.i given showInt: Show[Int] = new Show[Int](0) - given fallback[T]: Show[T] = new Show[T](1) + given fallback: [T] => Show[T] = new Show[T](1) } class Generic object Generic { given gen: Generic = new Generic - given showGen[T](using Generic): Show[T] = new Show[T](2) + given showGen: [T] => Generic => Show[T] = new Show[T](2) } class Generic2 object Generic2 { opaque type HiPriority = AnyRef - given showGen[T]: (Show[T] & HiPriority) = new Show[T](2).asInstanceOf + given showGen: [T] => Show[T] & HiPriority = new Show[T](2).asInstanceOf } class SubGen extends Generic @@ -29,11 +29,11 @@ object Contextual { given ctx: Context() - given showGen[T](using Generic): Show[T] = new Show[T](2) + given showGen: [T] => Generic => Show[T] = new Show[T](2) - given showGen[T](using Generic, Context): Show[T] = new Show[T](3) + given showGen: [T] => (Generic, Context) => Show[T] = new Show[T](3) - given showGen[T](using SubGen): Show[T] = new Show[T](4) + given showGen: [T] => SubGen => Show[T] = new Show[T](4) } object Test extends App { diff --git a/tests/run/implied-priority.scala b/tests/run/implied-priority.scala index a9380e117875..52eb07f1679d 100644 --- a/tests/run/implied-priority.scala +++ b/tests/run/implied-priority.scala @@ -77,12 +77,12 @@ def test2a = { */ object Impl3 { trait LowPriority // A marker trait to indicate a lower priority - given t1[T]: E[T]("low") with LowPriority + given t1: [T] => E[T]("low"), LowPriority } object Override { - given over[T]: E[T]("hi") with {} + given over: [T] => E[T]("hi") } def test3 = { @@ -135,7 +135,7 @@ object HigherPriority { } object fallback5 { - given [T](using ev: E[T] = new E[T]("fallback")): (E[T] & HigherPriority.Type) = HigherPriority.inject(ev) + given [T] => (ev: E[T] = new E[T]("fallback")) => E[T] & HigherPriority.Type = HigherPriority.inject(ev) } def test5 = { diff --git a/tests/run/inline-numeric/Fractional.scala b/tests/run/inline-numeric/Fractional.scala index f1bc81246a43..e88442e42c9d 100644 --- a/tests/run/inline-numeric/Fractional.scala +++ b/tests/run/inline-numeric/Fractional.scala @@ -17,13 +17,13 @@ trait Fractional[T] extends Numeric[T]: transparent inline def /(inline y: T) = div(x, y) object Fractional: - given BigDecimalIsFractional: BigDecimalIsConflicted with Fractional[BigDecimal] with + given BigDecimalIsFractional: BigDecimalIsConflicted, Fractional[BigDecimal]: transparent inline def div(inline x: BigDecimal, inline y: BigDecimal): BigDecimal = x / y protected transparent inline def isNaN(inline x: BigDecimal): Boolean = false protected transparent inline def isNegZero(inline x: BigDecimal): Boolean = false - given DoubleIsFractional: Fractional[Double] with Ordering.DoubleIeeeOrdering with + given DoubleIsFractional: Fractional[Double], Ordering.DoubleIeeeOrdering: transparent inline def plus(inline x: Double, inline y: Double): Double = x + y transparent inline def minus(inline x: Double, inline y: Double): Double = x - y transparent inline def times(inline x: Double, inline y: Double): Double = x * y @@ -42,7 +42,7 @@ object Fractional: transparent inline def toFloat: Float = x.toFloat transparent inline def toDouble: Double = x - given FloatIsFractional: Fractional[Float] with Ordering.FloatIeeeOrdering with + given FloatIsFractional: Fractional[Float], Ordering.FloatIeeeOrdering: transparent inline def plus(inline x: Float, inline y: Float): Float = x + y transparent inline def minus(inline x: Float, inline y: Float): Float = x - y transparent inline def times(inline x: Float, inline y: Float): Float = x * y diff --git a/tests/run/inline-numeric/Integral.scala b/tests/run/inline-numeric/Integral.scala index 1a740a3e1d99..3b199aad6b11 100644 --- a/tests/run/inline-numeric/Integral.scala +++ b/tests/run/inline-numeric/Integral.scala @@ -19,11 +19,11 @@ trait Integral[T] extends Numeric[T]: transparent inline def /%(inline y: T) = (quot(x, y), rem(x, y)) object Integral: - given BigDecimalAsIfIntegral: Integral[BigDecimal] with BigDecimalIsConflicted with + given BigDecimalAsIfIntegral: Integral[BigDecimal], BigDecimalIsConflicted: transparent inline def quot(inline x: BigDecimal, inline y: BigDecimal): BigDecimal = x quot y transparent inline def rem(inline x: BigDecimal, inline y: BigDecimal): BigDecimal = x remainder y - given BigIntIsIntegral: Integral[BigInt] with Ordering.BigIntOrdering with + given BigIntIsIntegral: Integral[BigInt], Ordering.BigIntOrdering: transparent inline def plus(inline x: BigInt, inline y: BigInt): BigInt = x + y transparent inline def minus(inline x: BigInt, inline y: BigInt): BigInt = x - y transparent inline def times(inline x: BigInt, inline y: BigInt): BigInt = x * y @@ -41,7 +41,7 @@ object Integral: transparent inline def quot(inline x: BigInt, inline y: BigInt): BigInt = x / y transparent inline def rem(inline x: BigInt, inline y: BigInt): BigInt = x % y - given ByteIsIntegral: Integral[Byte] with Ordering.ByteOrdering with + given ByteIsIntegral: Integral[Byte], Ordering.ByteOrdering: transparent inline def plus(inline x: Byte, inline y: Byte): Byte = (x + y).toByte transparent inline def minus(inline x: Byte, inline y: Byte): Byte = (x - y).toByte transparent inline def times(inline x: Byte, inline y: Byte): Byte = (x * y).toByte @@ -59,7 +59,7 @@ object Integral: transparent inline def toFloat: Float = x.toFloat transparent inline def toDouble: Double = x.toDouble - given CharIsIntegral: Integral[Char] with Ordering.CharOrdering with + given CharIsIntegral: Integral[Char], Ordering.CharOrdering: transparent inline def plus(inline x: Char, inline y: Char): Char = (x + y).toChar transparent inline def minus(inline x: Char, inline y: Char): Char = (x - y).toChar transparent inline def times(inline x: Char, inline y: Char): Char = (x * y).toChar @@ -77,7 +77,7 @@ object Integral: transparent inline def toFloat: Float = x.toFloat transparent inline def toDouble: Double = x.toDouble - given IntIsIntegral: Integral[Int] with Ordering.IntOrdering with + given IntIsIntegral: Integral[Int], Ordering.IntOrdering: transparent inline def plus(inline x: Int, inline y: Int): Int = x + y transparent inline def minus(inline x: Int, inline y: Int): Int = x - y transparent inline def times(inline x: Int, inline y: Int): Int = x * y @@ -95,7 +95,7 @@ object Integral: transparent inline def toFloat: Float = x.toFloat transparent inline def toDouble: Double = x.toDouble - given LongIsIntegral: Integral[Long] with Ordering.LongOrdering with + given LongIsIntegral: Integral[Long], Ordering.LongOrdering: transparent inline def plus(inline x: Long, inline y: Long): Long = x + y transparent inline def minus(inline x: Long, inline y: Long): Long = x - y transparent inline def times(inline x: Long, inline y: Long): Long = x * y @@ -113,7 +113,7 @@ object Integral: transparent inline def toFloat: Float = x.toFloat transparent inline def toDouble: Double = x.toDouble - given ShortIsIntegral: Integral[Short] with Ordering.ShortOrdering with + given ShortIsIntegral: Integral[Short], Ordering.ShortOrdering: transparent inline def plus(inline x: Short, inline y: Short): Short = (x + y).toShort transparent inline def minus(inline x: Short, inline y: Short): Short = (x - y).toShort transparent inline def times(inline x: Short, inline y: Short): Short = (x * y).toShort diff --git a/tests/run/instances-anonymous.scala b/tests/run/instances-anonymous.scala index 7a42496504ee..7fc0f69ee736 100644 --- a/tests/run/instances-anonymous.scala +++ b/tests/run/instances-anonymous.scala @@ -16,7 +16,7 @@ object Test extends App { println(circle.circumference) - given AnyRef with { + given AnyRef { extension (xs: Seq[String]) def longestStrings: Seq[String] = { val maxLength = xs.map(_.length).max xs.filter(_.length == maxLength) @@ -45,7 +45,7 @@ object Test extends App { def unit: T } - given Monoid[String] with { + given Monoid[String] { extension (x: String) def combine(y: String): String = x.concat(y) def unit: String = "" } @@ -63,13 +63,13 @@ object Test extends App { val minimum: T } - given Ord[Int] with { + given Ord[Int] { extension (x: Int) def compareTo(y: Int) = if (x < y) -1 else if (x > y) +1 else 0 val minimum = Int.MinValue } - given [T: Ord]: Ord[List[T]] with { + given [T: Ord] => Ord[List[T]] { extension (xs: List[T]) def compareTo(ys: List[T]): Int = (xs, ys).match { case (Nil, Nil) => 0 case (Nil, _) => -1 @@ -101,14 +101,14 @@ object Test extends App { def pure[A](x: A): F[A] } - given Monad[List] with { + given Monad[List] { extension [A](xs: List[A]) def flatMap[B](f: A => List[B]): List[B] = xs.flatMap(f) def pure[A](x: A): List[A] = List(x) } - given [Ctx]: Monad[[X] =>> Ctx => X] with { + given [Ctx] => Monad[[X] =>> Ctx => X] { extension [A](r: Ctx => A) def flatMap[B](f: A => Ctx => B): Ctx => B = ctx => f(r(ctx))(ctx) def pure[A](x: A): Ctx => A = diff --git a/tests/run/instances.scala b/tests/run/instances.scala index 128ea0700e02..1e1d908cbddf 100644 --- a/tests/run/instances.scala +++ b/tests/run/instances.scala @@ -46,7 +46,7 @@ object Test extends App { trait Monoid[T] extends SemiGroup[T]: def unit: T - given StringMonoid: Monoid[String] with + given StringMonoid: Monoid[String]: extension (x: String) def combine(y: String): String = x.concat(y) def unit: String = "" @@ -63,12 +63,12 @@ object Test extends App { val minimum: T end Ord - given Ord[Int] with + given Ord[Int]: extension (x: Int) def compareTo(y: Int) = if (x < y) -1 else if (x > y) +1 else 0 val minimum = Int.MinValue - given listOrd[T: Ord]: Ord[List[T]] with + given listOrd: [T: Ord] => Ord[List[T]]: extension (xs: List[T]) def compareTo(ys: List[T]): Int = (xs, ys).match case (Nil, Nil) => 0 case (Nil, _) => -1 @@ -99,13 +99,13 @@ object Test extends App { def pure[A](x: A): F[A] end Monad - given listMonad: Monad[List] with + given listMonad: Monad[List]: extension [A](xs: List[A]) def flatMap[B](f: A => List[B]): List[B] = xs.flatMap(f) def pure[A](x: A): List[A] = List(x) - given readerMonad[Ctx]: Monad[[X] =>> Ctx => X] with + given readerMonad: [Ctx] => Monad[[X] =>> Ctx => X]: extension [A](r: Ctx => A) def flatMap[B](f: A => Ctx => B): Ctx => B = ctx => f(r(ctx))(ctx) def pure[A](x: A): Ctx => A = diff --git a/tests/run/poly-kinded-derives.scala b/tests/run/poly-kinded-derives.scala index 0d3c7e9f8ffd..627d2780a802 100644 --- a/tests/run/poly-kinded-derives.scala +++ b/tests/run/poly-kinded-derives.scala @@ -22,10 +22,10 @@ object Test extends App { { trait Functor[F[_]] object Functor { - given [C]: Functor[[T] =>> C]() + given [C] => Functor[[T] =>> C]() given Functor[[T] =>> Tuple1[T]]() - given t2 [T]: Functor[[U] =>> (T, U)]() - given t3 [T, U]: Functor[[V] =>> (T, U, V)]() + given t2: [T] => Functor[[U] =>> (T, U)]() + given t3: [T, U] => Functor[[V] =>> (T, U, V)]() def derived[F[_]](using m: Mirror { type MirroredType[X] = F[X] ; type MirroredElemTypes[_] }, r: Functor[m.MirroredElemTypes]): Functor[F] = new Functor[F] {} } @@ -40,8 +40,8 @@ object Test extends App { { trait FunctorK[F[_[_]]] object FunctorK { - given [C]: FunctorK[[F[_]] =>> C]() - given [T]: FunctorK[[F[_]] =>> Tuple1[F[T]]]() + given [C] => FunctorK[[F[_]] =>> C]() + given [T] => FunctorK[[F[_]] =>> Tuple1[F[T]]]() def derived[F[_[_]]](using m: Mirror { type MirroredType[X[_]] = F[X] ; type MirroredElemTypes[_[_]] }, r: FunctorK[m.MirroredElemTypes]): FunctorK[F] = new FunctorK[F] {} } @@ -56,10 +56,10 @@ object Test extends App { { trait Bifunctor[F[_, _]] object Bifunctor { - given [C]: Bifunctor[[T, U] =>> C]() + given [C] => Bifunctor[[T, U] =>> C]() given Bifunctor[[T, U] =>> Tuple1[U]]() given t2: Bifunctor[[T, U] =>> (T, U)]() - given t3 [T]: Bifunctor[[U, V] =>> (T, U, V)]() + given t3: [T] => Bifunctor[[U, V] =>> (T, U, V)]() def derived[F[_, _]](using m: Mirror { type MirroredType[X, Y] = F[X, Y] ; type MirroredElemTypes[_, _] }, r: Bifunctor[m.MirroredElemTypes]): Bifunctor[F] = ??? } diff --git a/tests/run/publicInBinary/Lib_1.scala b/tests/run/publicInBinary/Lib_1.scala index d9936670a458..e7b5a0780d1c 100644 --- a/tests/run/publicInBinary/Lib_1.scala +++ b/tests/run/publicInBinary/Lib_1.scala @@ -47,9 +47,9 @@ class Qux() extends Foo(5, 5): trait A[T]: def f: T -@publicInBinary given A[Int] with +@publicInBinary given A[Int]: def f: Int = 1 -@publicInBinary given (using Double): A[Int] with +@publicInBinary given Double => A[Int]: def f: Int = 1 package inlines { diff --git a/tests/run/string-context-implicits-with-conversion.scala b/tests/run/string-context-implicits-with-conversion.scala index adcbae38830c..7173155e5bf9 100644 --- a/tests/run/string-context-implicits-with-conversion.scala +++ b/tests/run/string-context-implicits-with-conversion.scala @@ -4,7 +4,7 @@ object Lib { opaque type Showed = String - given [T](using show: Show[T]): Conversion[T, Showed] = x => show(x) + given [T] => (show: Show[T]) => Conversion[T, Showed] = x => show(x) trait Show[T] { def apply(x: T): String diff --git a/tests/run/structural-contextual.scala b/tests/run/structural-contextual.scala index e1d0890b73cd..43872856e4ed 100644 --- a/tests/run/structural-contextual.scala +++ b/tests/run/structural-contextual.scala @@ -15,7 +15,7 @@ type Person = ResolvingSelectable { @main def Test = - given Resolver with + given Resolver: def resolve(label: String) = label match case "name" => "Emma" case "age" => 8 diff --git a/tests/run/tagless.scala b/tests/run/tagless.scala index 5abc32d84578..7c1ffd3b433c 100644 --- a/tests/run/tagless.scala +++ b/tests/run/tagless.scala @@ -40,12 +40,12 @@ object Test extends App { add(lit(8), neg(add(lit(1), lit(2)))) // Base operations as type classes - given Exp[Int] with + given Exp[Int]: def lit(i: Int): Int = i def neg(t: Int): Int = -t def add(l: Int, r: Int): Int = l + r - given Exp[String] with + given Exp[String]: def lit(i: Int): String = i.toString def neg(t: String): String = s"(-$t)" def add(l: String, r: String): String = s"($l + $r)" @@ -65,10 +65,10 @@ object Test extends App { def tfm1[T: Exp : Mult] = add(lit(7), neg(mul(lit(1), lit(2)))) def tfm2[T: Exp : Mult] = mul(lit(7), tf1) - given Mult[Int] with + given Mult[Int]: def mul(l: Int, r: Int): Int = l * r - given Mult[String] with + given Mult[String]: def mul(l: String, r: String): String = s"$l * $r" println(tfm1[Int]) @@ -83,7 +83,7 @@ object Test extends App { } import Tree.* - given Exp[Tree] with Mult[Tree] with + given Exp[Tree], Mult[Tree]: def lit(i: Int): Tree = Node("Lit", Leaf(i.toString)) def neg(t: Tree): Tree = Node("Neg", t) def add(l: Tree, r: Tree): Tree = Node("Add", l , r) @@ -148,7 +148,7 @@ object Test extends App { def value[T](using Exp[T]): T } - given Exp[Wrapped] with + given Exp[Wrapped]: def lit(i: Int) = new Wrapped { def value[T](using e: Exp[T]): T = e.lit(i) } @@ -190,7 +190,7 @@ object Test extends App { // Added operation: negation pushdown enum NCtx { case Pos, Neg } - given [T](using e: Exp[T]): Exp[NCtx => T] with + given [T] => (e: Exp[T]) => Exp[NCtx => T]: import NCtx.* def lit(i: Int) = { case Pos => e.lit(i) @@ -209,7 +209,7 @@ object Test extends App { println(pushNeg(tf1[NCtx => String])) println(pushNeg(pushNeg(pushNeg(tf1))): String) - given [T](using e: Mult[T]): Mult[NCtx => T] with + given [T] => (e: Mult[T]) => Mult[NCtx => T]: import NCtx.* def mul(l: NCtx => T, r: NCtx => T): NCtx => T = { case Pos => e.mul(l(Pos), r(Pos)) @@ -222,7 +222,7 @@ object Test extends App { import IExp.* // Going from type class encoding to ADT encoding - given initialize: Exp[IExp] with + given initialize: Exp[IExp]: def lit(i: Int): IExp = Lit(i) def neg(t: IExp): IExp = Neg(t) def add(l: IExp, r: IExp): IExp = Add(l, r) diff --git a/tests/run/typeclass-derivation-doc-example.scala b/tests/run/typeclass-derivation-doc-example.scala index bc00311478bd..71c811608f5a 100644 --- a/tests/run/typeclass-derivation-doc-example.scala +++ b/tests/run/typeclass-derivation-doc-example.scala @@ -11,7 +11,7 @@ trait Eq[T] { } object Eq { - given Eq[Int] with { + given Eq[Int] { def eqv(x: Int, y: Int) = x == y } @@ -36,7 +36,7 @@ object Eq { } } - inline given derived[T](using m: Mirror.Of[T]): Eq[T] = { + inline given derived: [T] => (m: Mirror.Of[T]) => Eq[T] = { val elemInstances = summonAll[m.MirroredElemTypes] inline m match { case s: Mirror.SumOf[T] => eqSum(s, elemInstances) diff --git a/tests/run/tyql.scala b/tests/run/tyql.scala index 35777e9a4c13..8fe253b559ac 100644 --- a/tests/run/tyql.scala +++ b/tests/run/tyql.scala @@ -94,7 +94,7 @@ object Expr: extension [A <: AnyNamedTuple](x: A) def toRow: Join[A] = Join(x) /** Same as _.toRow, as an implicit conversion */ - given [A <: AnyNamedTuple]: Conversion[A, Expr.Join[A]] = Expr.Join(_) + given [A <: AnyNamedTuple] => Conversion[A, Expr.Join[A]] = Expr.Join(_) end Expr diff --git a/tests/warn/implicit-conversions.scala b/tests/warn/implicit-conversions.scala index 946d0c96fd5a..2896d7dc4447 100644 --- a/tests/warn/implicit-conversions.scala +++ b/tests/warn/implicit-conversions.scala @@ -5,11 +5,11 @@ class B object A { - given Conversion[A, B] with { + given Conversion[A, B] { def apply(x: A): B = ??? } - given Conversion[B, A] with { + given Conversion[B, A] { def apply(x: B): A = ??? } } @@ -17,7 +17,7 @@ object A { class C object D { - given Conversion[A, C] with { + given Conversion[A, C] { def apply(x: A): C = ??? } } From c76dc8087d34076dcb7b91fa3ba18da07f08d9c6 Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 4 Oct 2024 19:07:15 +0200 Subject: [PATCH 8/9] Address some points in code review. --- docs/_docs/internals/syntax.md | 2 +- docs/_docs/reference/contextual/context-bounds.md | 9 ++++++--- docs/_docs/reference/syntax.md | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/_docs/internals/syntax.md b/docs/_docs/internals/syntax.md index 0cde7bc127aa..d0074bb503c2 100644 --- a/docs/_docs/internals/syntax.md +++ b/docs/_docs/internals/syntax.md @@ -486,7 +486,7 @@ GivenConditional ::= DefTypeParamClause GivenType ::= AnnotType1 {id [nl] AnnotType1} OldGivenDef ::= [OldGivenSig] (AnnotType [‘=’ Expr] | StructuralInstance) -- syntax up to Scala 3.5, to be deprecated in the future -OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present +OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody] Extension ::= ‘extension’ [DefTypeParamClause] {UsingParamClause} diff --git a/docs/_docs/reference/contextual/context-bounds.md b/docs/_docs/reference/contextual/context-bounds.md index ef32dc7b08c2..a06cb2d79181 100644 --- a/docs/_docs/reference/contextual/context-bounds.md +++ b/docs/_docs/reference/contextual/context-bounds.md @@ -71,7 +71,7 @@ The witness context parameter(s) generated from context bounds are added as foll 1. If one of the bounds is referred to by its name in a subsequent parameter clause, the context bounds are mapped to a using clause immediately preceding the first such parameter clause. 2. Otherwise, if the last parameter clause is a using (or implicit) clause, merge all parameters arising from context bounds in front of that clause, creating a single using clause. - 3. Otherwise, let the parameters arising from context bounds form a new using clause at the end. + 3. Otherwise, the parameters arising from context bounds form a new using clause at the end. Rules (2) and (3) match Scala 2's rules. Rule (1) is new but since context bounds so far could not be referred to, it does not apply to legacy code. Therefore, binary compatibility with Scala 2 and earlier Scala 3 versions is maintained. @@ -151,11 +151,14 @@ val less: Comparer = [X] => (x: X, y: X) => (ord: Ord[X]) ?=> The expansion of using clauses does look inside alias types. For instance, here is a variation of the previous example that uses a parameterized type alias: ```scala -type Cmp[X] = (x: X, y: X) => Ord[X] ?=> Boolean +type Cmp[X] = (x: X, y: X) => Boolean type Comparer2 = [X: Ord] => Cmp[X] ``` The expansion of the right hand side of `Comparer2` expands the `Cmp[X]` alias -and then inserts the context function at the same place as what's done for `Comparer`. +and then inserts the context function at the same place as what's done for `Comparer`: +```scala + [X] => (x: X, y: X) => Ord[X] ?=> Boolean +``` ### Context Bounds for Type Members diff --git a/docs/_docs/reference/syntax.md b/docs/_docs/reference/syntax.md index adf25c9342fa..3e71718d0752 100644 --- a/docs/_docs/reference/syntax.md +++ b/docs/_docs/reference/syntax.md @@ -461,7 +461,7 @@ GivenConditional ::= DefTypeParamClause GivenType ::= AnnotType1 {id [nl] AnnotType1} OldGivenDef ::= [OldGivenSig] (AnnotType [‘=’ Expr] | StructuralInstance) -- syntax up to Scala 3.5, to be deprecated in the future -OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present +OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody] Extension ::= ‘extension’ [DefTypeParamClause] {UsingParamClause} From df75afc7a53e4f3bbd43483813719182d391021f Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 4 Oct 2024 19:11:51 +0200 Subject: [PATCH 9/9] Apply suggestions from code review Co-authored-by: Dimi Racordon --- docs/_docs/reference/contextual/context-bounds.md | 6 +++--- docs/_docs/reference/contextual/deferred-givens.md | 4 ++-- docs/_docs/reference/contextual/givens.md | 6 +++--- docs/_docs/reference/contextual/more-givens.md | 6 ++---- docs/_docs/reference/contextual/previous-givens.md | 7 +++---- docs/_docs/reference/experimental/typeclasses.md | 2 +- docs/_docs/reference/syntax.md | 6 +++--- 7 files changed, 17 insertions(+), 20 deletions(-) diff --git a/docs/_docs/reference/contextual/context-bounds.md b/docs/_docs/reference/contextual/context-bounds.md index a06cb2d79181..60357b3f098d 100644 --- a/docs/_docs/reference/contextual/context-bounds.md +++ b/docs/_docs/reference/contextual/context-bounds.md @@ -199,10 +199,10 @@ The syntax of function types and function literals is generalized as follows to allow context bounds for generic type parameters. ```ebnf -FunType ::= FunTypeArgs (‘=>’ | ‘?=>’) Type +FunType ::= FunTypeArgs ('=>' | '?=>') Type | DefTypeParamClause '=>' Type -FunExpr ::= FunParams (‘=>’ | ‘?=>’) Expr - | DefTypeParamClause ‘=>’ Expr +FunExpr ::= FunParams ('=>' | '?=>') Expr + | DefTypeParamClause '=>' Expr ``` The syntax for abstract type members is generalized as follows to allow context bounds: diff --git a/docs/_docs/reference/contextual/deferred-givens.md b/docs/_docs/reference/contextual/deferred-givens.md index 232c15afda35..e63e26858d29 100644 --- a/docs/_docs/reference/contextual/deferred-givens.md +++ b/docs/_docs/reference/contextual/deferred-givens.md @@ -40,7 +40,7 @@ class SortedString[A] extends Sorted: override given Ord[String] = ... ``` -Note that the implementing given needs an `override` modifier since the `deferred` given in class `Sorted` counts as a concrete (i.e. not abstract) definition. In a sense, the `deferred` right hand side in `Sorted` is like a (magic, compiler-supported) macro, with the peculiarity that the macro's implementation also affects subclasses. +Note that the implementing given needs an `override` modifier since the `deferred` given in class `Sorted` counts as a concrete (i.e. not abstract) definition. In a sense, `deferred` on the right-hand side in `Sorted` is like a (magic, compiler-supported) macro, with the peculiarity that the macro's implementation also affects subclasses. ## Abstract Givens @@ -52,6 +52,6 @@ trait HasOrd[T]: ``` An abstract given has the form `given name: Type` without a right-hand side or arguments to the type. -Since Scala 3.6, abstract givens are made redundant by deferred givens. Deferred givens can replace abstract givens. They have better ergonomics, since deferred givens get naturally implemented in inheriting classes, so there is no longer any need for boilerplate to fill in definitions of abstract givens. +Since Scala 3.6, abstract givens are made redundant by deferred givens. Deferred givens have better ergonomics, since they get naturally implemented in inheriting classes, so there is no longer any need for boilerplate to fill in definitions of abstract givens. It is therefore recommended that software architectures relying on abstract givens be migrated to use deferred givens instead. Abstract givens are still supported in Scala 3.6, but will likely be deprecated and phased out over time. diff --git a/docs/_docs/reference/contextual/givens.md b/docs/_docs/reference/contextual/givens.md index b7be460c9a34..088ded2e8db4 100644 --- a/docs/_docs/reference/contextual/givens.md +++ b/docs/_docs/reference/contextual/givens.md @@ -83,11 +83,11 @@ given Position = enclosingTree.position ## Given Instance Initialization An unconditional given instance without parameters is initialized on-demand, the first -time it is accessed. If the given is a simple alias to some immutable value, the given is implemented as a simple forwarder, without incurring the cost of a field to hold a cached value. If a given is conditional, a fresh instance is created for each reference. +time it is accessed. If the given is a mere alias to some immutable value, the given is implemented as a simple forwarder, without incurring the cost of a field to hold a cached value. If a given is conditional, a fresh instance is created for each reference. ## Syntax -Here is the full syntax for given instances. Some of these forms of givens are explained on a separate page on [Other Forms of Givens](../more-givens.md). +Here is the full syntax for given instances. Some of these forms of givens are explained in a separate page: [Other Forms of Givens](../more-givens.md). ```ebnf Here is the complete context-free syntax for all proposed features. @@ -106,7 +106,7 @@ GivenConditional ::= DefTypeParamClause GivenType ::= AnnotType1 {id [nl] AnnotType1} ``` -A given instance starts with the reserved word `given`, which is followed by +A given instance starts with the reserved keyword `given`, which is followed by - An optional name and a colon - An optional list of conditions. diff --git a/docs/_docs/reference/contextual/more-givens.md b/docs/_docs/reference/contextual/more-givens.md index 3d0076543cd7..2f6dd63f7eab 100644 --- a/docs/_docs/reference/contextual/more-givens.md +++ b/docs/_docs/reference/contextual/more-givens.md @@ -43,14 +43,12 @@ given listOrd: [T] => (ord: Ord[T]) => Ord[List[T]]: ## By Name Givens -We sometimes find it necessary that a given alias is re-evaluated each time it is called. For instance, say we have a mutable variable `curCtx` and we want to define a given that returns the current value of that variable. A normal given alias will not do since by default given aliases are mapped to lazy vals. - -In general, we want to avoid re-evaluation of givens. But there are situations like the one above where we want to specify _by-name_ evaluation instead. This is achieved by writing a conditional given with an empty parameter list: +Though in general we want to avoid re-evaluating a given, there are situations where such a re-evaluation may be necessary. For instance, say we have a mutable variable `curCtx` and we want to define a given that returns the current value of that variable. A normal given alias will not do since by default given aliases are mapped to lazy vals. In this case, we can specify a _by-name_ evaluation insteadby writing a conditional given with an empty parameter list: ```scala val curCtx: Context given context: () => Context = curCtx ``` -With this definition, each time a `Context` is summoned we evaluate `context` function, which produces the current value of `curCtx`. +With this definition, each time a `Context` is summoned we evaluate the `context` function, which produces the current value of `curCtx`. ## Given Macros diff --git a/docs/_docs/reference/contextual/previous-givens.md b/docs/_docs/reference/contextual/previous-givens.md index dc88daaab691..a78d8a3751ea 100644 --- a/docs/_docs/reference/contextual/previous-givens.md +++ b/docs/_docs/reference/contextual/previous-givens.md @@ -161,7 +161,6 @@ Note that the inline methods within the given instances may be `transparent`. The inlining of given instances will not inline/duplicate the implementation of the given, it will just inline the instantiation of that instance. This is used to help dead code elimination of the given instances that are not used after inlining. - ## Pattern-Bound Given Instances Given instances can also appear in patterns. Example: @@ -215,12 +214,12 @@ Here is the syntax for given instances: ```ebnf TmplDef ::= ... - | ‘given’ GivenDef + | 'given' GivenDef GivenDef ::= [GivenSig] StructuralInstance | [GivenSig] AnnotType ‘=’ Expr | [GivenSig] AnnotType -GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ TemplateBody] +GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ':' +StructuralInstance ::= ConstrApp {'with' ConstrApp} [‘with’ TemplateBody] ``` A given instance starts with the reserved word `given` and an optional _signature_. The signature diff --git a/docs/_docs/reference/experimental/typeclasses.md b/docs/_docs/reference/experimental/typeclasses.md index c366c40779b9..add5853e10ba 100644 --- a/docs/_docs/reference/experimental/typeclasses.md +++ b/docs/_docs/reference/experimental/typeclasses.md @@ -18,7 +18,7 @@ a bit cumbersome and limiting for standard generic programming patterns. Much ha This note shows that with some fairly small and reasonable tweaks to Scala's syntax and typing rules we can obtain a much better scheme for working with type classes, or do generic programming in general. The bulk of the suggested improvements has been implemented and is available -in under source version `future` if the additional experimental language import `modularity` is present. For instance, using the following command: +in source version `future` if the additional experimental language import `modularity` is present. For instance, using the following command: ``` scala compile -source:future -language:experimental.modularity diff --git a/docs/_docs/reference/syntax.md b/docs/_docs/reference/syntax.md index 3e71718d0752..0f78ff03583e 100644 --- a/docs/_docs/reference/syntax.md +++ b/docs/_docs/reference/syntax.md @@ -214,9 +214,9 @@ ParamValueType ::= Type [‘*’] TypeArgs ::= ‘[’ Types ‘]’ Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>> TypeBounds ::= [‘>:’ Type] [‘<:’ Type] -TypeAndCtxBounds ::= TypeBounds [‘:’ ContextBounds] +TypeAndCtxBounds ::= TypeBounds [':' ContextBounds] ContextBounds ::= ContextBound - | ContextBound `:` ContextBounds -- to be deprecated + | ContextBound ':' ContextBounds -- to be deprecated | '{' ContextBound {',' ContextBound} '}' ContextBound ::= Type ['as' id] Types ::= Type {‘,’ Type} @@ -441,7 +441,7 @@ TypeDef ::= id [HkTypeParamClause] {FunParamClause}TypeBounds TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef | [‘case’] ‘object’ ObjectDef | ‘enum’ EnumDef - | ‘given’ (GivenDef | OldGivenDef) + | 'given' (GivenDef | OldGivenDef) ClassDef ::= id ClassConstr [Template] ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses ConstrMods ::= {Annotation} [AccessModifier]