Skip to content

Commit

Permalink
Switch mapping of context bounds to using clauses in 3.6 (#21257)
Browse files Browse the repository at this point in the history
Was future before.

We can roll this out now, since we already made it an error in 3.5 to
pass a normal argument to a using clause. It would be good to roll this
out now since otherwise context bounds would represent an exception to
the implicit priority inversion in #19300.

See discussion at the end of #19300 for details.
  • Loading branch information
odersky authored Jul 25, 2024
2 parents f0b3a2b + 81b4250 commit ad22fa6
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 32 deletions.
2 changes: 1 addition & 1 deletion community-build/community-projects/spire
16 changes: 14 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,12 @@ object desugar {
// implicit resolution in Scala 3.

val paramssNoContextBounds =
val iflag = if Feature.sourceVersion.isAtLeast(`future`) then Given else Implicit
val iflag = paramss.lastOption.flatMap(_.headOption) match
case Some(param) if param.mods.isOneOf(GivenOrImplicit) =>
param.mods.flags & GivenOrImplicit
case _ =>
if Feature.sourceVersion.isAtLeast(`3.6`) then Given
else Implicit
val flags = if isPrimaryConstructor then iflag | LocalParamAccessor else iflag | Param
mapParamss(paramss) {
tparam => desugarContextBounds(tparam, evidenceParamBuf, flags, freshName, paramss)
Expand Down Expand Up @@ -472,7 +477,14 @@ object desugar {
case ValDefs(mparams) :: _ if mparams.exists(referencesBoundName) =>
params :: mparamss
case ValDefs(mparams @ (mparam :: _)) :: Nil if mparam.mods.isOneOf(GivenOrImplicit) =>
(params ++ mparams) :: Nil
val normParams =
if params.head.mods.flags.is(Given) != mparam.mods.flags.is(Given) then
params.map: param =>
val normFlags = param.mods.flags &~ GivenOrImplicit | (mparam.mods.flags & (GivenOrImplicit))
param.withMods(param.mods.withFlags(normFlags))
.showing(i"ADAPTED PARAM $result ${result.mods.flags} for ${meth.name}")
else params
(normParams ++ mparams) :: Nil
case mparams :: mparamss1 =>
mparams :: recur(mparamss1)
case Nil =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/util/Signatures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ object Signatures {

def isSyntheticEvidence(name: String) =
name.startsWith(NameKinds.ContextBoundParamName.separator)
&& symbol.paramSymss.flatten.find(_.name.show == name).exists(_.flags.is(Flags.Implicit))
&& symbol.paramSymss.flatten.find(_.name.show == name).exists(_.flags.isOneOf(Flags.GivenOrImplicit))

def toTypeParam(tpe: PolyType): List[Param] =
val evidenceParams = (tpe.paramNamess.flatten zip tpe.paramInfoss.flatten).flatMap:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ class ShortenedTypePrinter(
val (methodParams, extParams) = splitExtensionParamss(gsym)
val paramss = methodParams ++ extParams
lazy val implicitParams: List[Symbol] =
paramss.flatMap(params => params.filter(p => p.is(Flags.Implicit)))
paramss.flatMap(params => params.filter(p => p.isOneOf(Flags.GivenOrImplicit)))

lazy val implicitEvidenceParams: Set[Symbol] =
implicitParams
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,8 @@ trait ClassLikeSupport:
// `def foo[A: ClassTag] = 1`.
// Scala spec states that `$` should not be used in names and behaviour may be undefiend in such case.
// Documenting method slightly different then its definition is withing the 'undefiend behaviour'.
symbol.paramSymss.flatten.find(_.name == name).exists(_.flags.is(Flags.Implicit))
symbol.paramSymss.flatten.find(_.name == name).exists(p =>
p.flags.is(Flags.Given) || p.flags.is(Flags.Implicit))

def handlePolyType(memberInfo: MemberInfo, polyType: PolyType): MemberInfo =
val typeParamList = MemberInfo.TypeParameterList(polyType.paramNames.zip(polyType.paramBounds).toMap)
Expand Down
2 changes: 1 addition & 1 deletion staging/test-resources/repl-staging/i6263
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ scala> import quoted.staging.{Compiler => StagingCompiler, _}
scala> implicit def compiler: StagingCompiler = StagingCompiler.make(getClass.getClassLoader)
def compiler: scala.quoted.staging.Compiler
scala> def fn[T : Type](v : T) = println("ok")
def fn[T](v: T)(implicit evidence$1: scala.quoted.Type[T]): Unit
def fn[T](v: T)(using evidence$1: scala.quoted.Type[T]): Unit
scala> withQuotes { fn("foo") }
ok
scala> withQuotes { fn((1,2)) }
Expand Down
13 changes: 13 additions & 0 deletions tests/neg/ctx-bounds-priority-migration.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//> using options -source 3.5
trait Eq[A]
trait Order[A] extends Eq[A]:
def toOrdering: Ordering[A]

def f[Element: Eq: Order] = summon[Eq[Element]].toOrdering // ok

def Test() =
val eq: Eq[Int] = ???
val ord: Order[Int] = ???
f(eq, ord) // error
f(using eq, ord) // ok

6 changes: 6 additions & 0 deletions tests/neg/ctx-bounds-priority.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//> using options -source 3.6
trait Eq[A]
trait Order[A] extends Eq[A]:
def toOrdering: Ordering[A]

def Test[Element: Eq: Order] = summon[Eq[Element]].toOrdering // error
38 changes: 19 additions & 19 deletions tests/neg/i10901.check
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
-- [E008] Not Found Error: tests/neg/i10901.scala:45:38 ----------------------------------------------------------------
45 | val pos1: Point2D[Int,Double] = x º y // error
| ^^^
| value º is not a member of object BugExp4Point2D.IntT.
| An extension method was tried, but could not be fully constructed:
|
| º(x)
|
| failed with:
|
| Ambiguous overload. The overloaded alternatives of method º in object dsl with types
| [T1, T2]
| (x: BugExp4Point2D.ColumnType[T1])
| (y: BugExp4Point2D.ColumnType[T2])
| (implicit evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| [T1, T2]
| (x: T1)
| (y: BugExp4Point2D.ColumnType[T2])
| (implicit evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| both match arguments ((x : BugExp4Point2D.IntT.type))((y : BugExp4Point2D.DoubleT.type))
| value º is not a member of object BugExp4Point2D.IntT.
| An extension method was tried, but could not be fully constructed:
|
| º(x)
|
| failed with:
|
| Ambiguous overload. The overloaded alternatives of method º in object dsl with types
| [T1, T2]
| (x: BugExp4Point2D.ColumnType[T1])
| (y: BugExp4Point2D.ColumnType[T2])
| (using evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| [T1, T2]
| (x: T1)
| (y: BugExp4Point2D.ColumnType[T2])
| (using evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| both match arguments ((x : BugExp4Point2D.IntT.type))((y : BugExp4Point2D.DoubleT.type))
-- [E008] Not Found Error: tests/neg/i10901.scala:48:38 ----------------------------------------------------------------
48 | val pos4: Point2D[Int,Double] = x º 201.1 // error
| ^^^
Expand All @@ -31,8 +31,8 @@
| Ambiguous overload. The overloaded alternatives of method º in object dsl with types
| [T1, T2]
| (x: BugExp4Point2D.ColumnType[T1])
| (y: T2)(implicit evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| [T1, T2](x: T1)(y: T2)(implicit evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| (y: T2)(using evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| [T1, T2](x: T1)(y: T2)(using evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| both match arguments ((x : BugExp4Point2D.IntT.type))((201.1d : Double))
-- [E008] Not Found Error: tests/neg/i10901.scala:62:16 ----------------------------------------------------------------
62 | val y = "abc".foo // error
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/i20901/Foo.tastycheck
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Trees (98 bytes, starting from <elided base index>):
61: SHAREDtype 6
63: IDENTtpt 16 [T]
65: TYPEREFdirect 39
67: IMPLICIT
67: GIVEN
68: IDENTtpt 17 [Nothing]
70: TYPEREF 17 [Nothing]
72: TERMREFpkg 2 [scala]
Expand Down
10 changes: 5 additions & 5 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -2621,9 +2621,9 @@ example/Methods#m6(+1). => method m6 (param x: List[T]): Nothing
example/Methods#m6(+1).(x) => param x: List[T]
example/Methods#m6(+2). => method m6 (param x: List[T]): Nothing
example/Methods#m6(+2).(x) => param x: List[T]
example/Methods#m7(). => method m7 [typeparam U ](param c: Methods[T], param l: List[U])(implicit param evidence$1: Ordering[U]): Nothing
example/Methods#m7(). => method m7 [typeparam U ](param c: Methods[T], param l: List[U])(implicit given param evidence$1: Ordering[U]): Nothing
example/Methods#m7().(c) => param c: Methods[T]
example/Methods#m7().(evidence$1) => implicit param evidence$1: Ordering[U]
example/Methods#m7().(evidence$1) => implicit given param evidence$1: Ordering[U]
example/Methods#m7().(l) => param l: List[U]
example/Methods#m7().[U] => typeparam U
example/Methods#m9(). => method m9 (param x: m9().): Nothing
Expand Down Expand Up @@ -3553,10 +3553,10 @@ example/Synthetic#F# => class F extends Object { self: F => +1 decls }
example/Synthetic#F#`<init>`(). => primary ctor <init> (): F
example/Synthetic#J# => class J [typeparam T ] extends Object { self: J[T] => +4 decls }
example/Synthetic#J#[T] => typeparam T
example/Synthetic#J#`<init>`(). => primary ctor <init> [typeparam T ]()(implicit param evidence$1: Manifest[T]): J[T]
example/Synthetic#J#`<init>`().(evidence$1) => implicit param evidence$1: Manifest[T]
example/Synthetic#J#`<init>`(). => primary ctor <init> [typeparam T ](implicit given param evidence$1: Manifest[T])(): J[T]
example/Synthetic#J#`<init>`().(evidence$1) => implicit given param evidence$1: Manifest[T]
example/Synthetic#J#arr. => val method arr Array[T]
example/Synthetic#J#evidence$1. => private[this] implicit val method evidence$1 Manifest[T]
example/Synthetic#J#evidence$1. => private[this] implicit val given method evidence$1 Manifest[T]
example/Synthetic#Name. => val method Name Regex
example/Synthetic#`<init>`(). => primary ctor <init> (): Synthetic
example/Synthetic#a1. => val method a1 Int
Expand Down

0 comments on commit ad22fa6

Please sign in to comment.