8000 Remove logic to check if a named arg could be an assignment · scala/scala@b984e99 · GitHub
[go: up one dir, main page]

Skip to content

Commit b984e99

Browse files
committed
Remove logic to check if a named arg could be an assignment
An `x = e` expression in parameter position is now a named argument, syntactically, unconditionally. Fixes scala/scala-dev#426
1 parent 03884f6 commit b984e99

File tree

3 files changed

+8
-119
lines changed

3 files changed

+8
-119
lines changed

src/compiler/scala/tools/nsc/settings/ScalaSettings.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ trait ScalaSettings extends AbsScalaSettings
8989
def isScala212: Boolean = source.value >= version 8000 212
9090
private[this] val version213 = ScalaVersion("2.13.0")
9191
def isScala213: Boolean = source.value >= version213
92+
private[this] val version214 = ScalaVersion("2.14.0")
93+
def isScala214: Boolean = source.value >= version214
9294

9395
/**
9496
* -X "Advanced" settings

src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,6 @@ trait ContextErrors {
4545
case class NormalTypeError(underlyingTree: Tree, errMsg: String)
4646
extends TreeTypeError
4747

48-
/**
49-
* Marks a TypeError that was constructed from a CyclicReference (under silent).
50-
* This is used for named arguments, where we need to know if an assignment expression
51-
* failed with a cyclic reference or some other type error.
52-
*/
53-
class NormalTypeErrorFromCyclicReference(underlyingTree: Tree, errMsg: String)
54-
extends NormalTypeError(underlyingTree, errMsg)
55-
5648
case class AccessTypeError(underlyingTree: Tree, errMsg: String)
5749
extends TreeTypeError
5850

@@ -1128,9 +1120,8 @@ trait ContextErrors {
11281120
// hence we (together with reportTypeError in TypeDiagnostics) make sure that this CyclicReference
11291121
// evades all the handlers on its way and successfully reaches `isCyclicOrErroneous` in Implicits
11301122
throw ex
1131-
case c @ CyclicReference(sym, info: TypeCompleter) =>
1132-
val error = new NormalTypeErrorFromCyclicReference(tree, typer.cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage)
1133-
issueTypeError(error)
1123+
case CyclicReference(sym, info: TypeCompleter) =>
1124+
issueNormalTypeError(tree, typer.cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage)
11341125
case _ =>
11351126
contextNamerErrorGen.issue(TypeErrorWithUnderlyingTree(tree, ex))
11361127
}
@@ -1322,24 +1313,9 @@ trait ContextErrors {
13221313
issueSymbolTypeError(sym, errMsg)
13231314
}
13241315

1325-
def AmbiguousReferenceInNamesDefaultError(arg: Tree, name: Name)(implicit context: Context) = {
1326-
if (!arg.isErroneous) { // check if name clash wasn't reported already
1327-
issueNormalTypeError(arg,
1328-
"reference to "+ name +" is ambiguous; it is both a method parameter "+
1329-
"and a variable in scope.")
1330-
setError(arg)
1331-
} else arg
1332-
}
1333-
1334-
def WarnAfterNonSilentRecursiveInference(param: Symbol, arg: Tree)(implicit context: Context) = {
1335-
val note = "failed to determine if '"+ param.name + " = ...' is a named argument or an assignment expression.\n"+
1336-
"an explicit type is required for the definition mentioned in the error message above."
1337-
context.warning(arg.pos, note)
1338-
}
1339-
1340-
def UnknownParameterNameNamesDefaultError(arg: Tree, name: Name, isVariableInScope: Boolean)(implicit context: Context) = {
1316+
def UnknownParameterNameNamesDefaultError(arg: Tree, name: Name, warnVariableInScope: Boolean)(implicit context: Context) = {
13411317
val suffix =
1342-
if (isVariableInScope)
1318+
if (warnVariableInScope)
13431319
s"\nNote that assignments in argument position are no longer allowed since Scala 2.13.\nTo express the assignment expression, wrap it in brackets, e.g., `{ $name = ... }`."
13441320
else ""
13451321
issueNormalTypeError(arg, s"unknown parameter name: $name$suffix")

src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala

Lines changed: 2 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -486,82 +486,6 @@ trait NamesDefaults { self: Analyzer =>
486486
} else NoSymbol
487487
}
488488

489-
def isVariableInScope(context: Context, name: Name): Boolean = {
490-
context.lookupSymbol(name, _.isVariable).isSuccess
491-
}
492-
493-
/** A full type check is very expensive; let's make sure there's a name
494-
* somewhere which could potentially be ambiguous before we go that route.
495-
*/
496-
private def isAmbiguousAssignment(typer: Typer, param: Symbol, arg: Tree) = {
497-
import typer.context
498-
(context isNameInScope param.name) && {
499-
// for named arguments, check whether the assignment expression would
500-
// typecheck. if it does, report an ambiguous error.
501-
val paramtpe = param.tpe.cloneInfo(param)
502-
// replace type parameters by wildcard. in the below example we need to
503-
// typecheck (x = 1) with wildcard (not T) so that it succeeds.
504-
// def f[T](x: T) = x
505-
// var x = 0
506-
// f(x = 1) << "x = 1" typechecks with expected type WildcardType
507-
val udp = context.undetparams
508-
context.savingUndeterminedTypeParams(reportAmbiguous = false) {
509-
val subst = new SubstTypeMap(udp, udp map (_ => WildcardType)) {
510-
override def apply(tp: Type): Type = super.apply(dropByName(tp))
511-
}
512-
// This throws an exception which is caught in `tryTypedApply` (as it
513-
// uses `silent`) - unfortunately, tryTypedApply recovers from the
514-
// exception if you use errorTree(arg, ...) and conforms is allowed as
515-
// a view (see tryImplicit in Implicits) because it tries to produce a
516-
// new qualifier (if the old one was P, the new one will be
517-
// conforms.apply(P)), and if that works, it pretends nothing happened.
518-
//
519-
// To make sure tryTypedApply fails, we would like to pass EmptyTree
520-
// instead of arg, but can't do that because eventually setType(ErrorType)
521-
// is called, and EmptyTree can only be typed NoType. Thus we need to
522-
// disable conforms as a view...
523-
val errsBefore = reporter.ERROR.count
524-
try typer.silent { tpr =>
525-
val res = tpr.typed(arg.duplicate, subst(paramtpe))
526-
// better warning for scala/bug#5044: if `silent` was not actually silent give a hint to the user
527-
// [H]: the reason why `silent` is not silent is because the cyclic reference exception is
528-
// thrown in a context completely different from `context` here. The exception happens while
529-
// completing the type, and TypeCompleter is created/run with a non-silent Namer `context`
530-
// and there is at the moment no way to connect the two unless we go through some global state.
531-
if (errsBefore < reporter.ERROR.count)
532-
WarnAfterNonSilentRecursiveInference(param, arg)(context)
533-
res
534-
} match {
535-
case SilentResultValue(t) =>
536-
!t.isErroneous // #4041
537-
case SilentTypeError(e: NormalTypeErrorFromCyclicReference) =>
538-
// If we end up here, the CyclicReference was reported in a silent context. This can
539-
// happen for local definitions, when the completer for a definition is created during
540-
// type checking in silent mode. ContextErrors.TypeSigError catches that cyclic reference
541-
// and transforms it into a NormalTypeErrorFromCyclicReference.
542-
// The cycle needs to be reported, because the program cannot be typed: we don't know
543-
// if we have an assignment or a named arg.
544-
context.issue(e)
545-
// 'err = true' is required because we're in a silent context
546-
WarnAfterNonSilentRecursiveInference(param, arg)(context)
547-
false
548-
case _ =>
549-
// We got a type error, so it cannot be an assignment (it doesn't type check as one).
550-
false
551-
}
552-
catch {
553-
// `silent` only catches and returns TypeErrors which are not
554-
// CyclicReferences. Fix for #3685
555-
case cr @ CyclicReference(sym, _) =>
556-
(sym.name == param.name) && sym.accessedOrSelf.isVariable && {
557-
NameClashError(sym, arg)(context)
558-
true
559-
}
560-
}
561-
}
562-
}
563-
}
564-
565489
/** Removes name assignments from args. Additionally, returns an array mapping
566490
* argument indices from call-site-order to definition-site-order.
567491
*
@@ -597,28 +521,15 @@ trait NamesDefaults { self: Analyzer =>
597521
def stripNamedArg(arg: NamedArg, argIndex: Int): Tree = {
598522
val NamedArg(Ident(name), rhs) = arg
599523
params indexWhere (p => matchesName(p, name, argIndex)) match {
600-
case -1 if positionalAllowed && !settings.isScala213 =>
601-
if (isVariableInScope(context0, name)) {
602-
// only issue the deprecation warning if `name` is in scope, this avoids the warning when mis-spelling a parameter name.
603-
context0.deprecationWarning(
604-
arg.pos,
605-
context0.owner,
606-
s"assignments in argument position are deprecated in favor of named arguments. Wrap the assignment in brackets, e.g., `{ $name = ... }`.",
607-
"2.12.4")
608-
}
609-
// prevent isNamed from being true when calling doTypedApply recursively,
610-
// treat the arg as an assignment of type Unit
611-
Assign(arg.lhs, rhs) setPos arg.pos
612524
case -1 =>
613-
UnknownParameterNameNamesDefaultError(arg, name, isVariableInScope(context0, name))
525+
val warnVariableInScope = !settings.isScala214 && context0.lookupSymbol(name, _.isVariable).isSuccess
526+
UnknownParameterNameNamesDefaultError(arg, name, warnVariableInScope)
614527
case paramPos if argPos contains paramPos =>
615528
val existingArgIndex = argPos.indexWhere(_ == paramPos)
616529
val otherName = Some(args(paramPos)) collect {
617530
case NamedArg(Ident(oName), _) if oName != name => oName
618531
}
619532
DoubleParamNamesDefaultError(arg, name, existingArgIndex+1, otherName)
620-
case paramPos if !settings.isScala213 && isAmbiguousAssignment(typer, params(paramPos), arg) =>
621-
AmbiguousReferenceInNamesDefaultError(arg, name)
622533
case paramPos if paramPos != argIndex =>
623534
positionalAllowed = false // named arg is not in original parameter order: require names after this
624535
argPos(argIndex) = paramPos // fix up the arg position

0 commit comments

Comments
 (0)
0