summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala35
3 files changed, 36 insertions, 12 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index e67d6814f1..3ac5d388d3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -373,6 +373,7 @@ trait MethodSynthesis {
// spot that brand of them. In other words it's an artifact of the implementation.
val tpt = derivedSym.tpe.finalResultType match {
case ExistentialType(_, _) => TypeTree()
+ case _ if mods.isDeferred => TypeTree()
case tp => TypeTree(tp)
}
tpt setPos derivedSym.pos.focus
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index 76ff341d3f..c5245c4e9e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -414,7 +414,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// (the prefix of the argument passed to the unapply must equal the prefix of the type of the binder)
val treeMaker = TypeTestTreeMaker(patBinder, patBinder, extractor.paramType, extractor.paramType)(pos, extractorArgTypeTest = true)
(List(treeMaker), treeMaker.nextBinder)
- } else (Nil, patBinder)
+ } else {
+ // no type test needed, but the tree maker relies on `patBinderOrCasted` having type `extractor.paramType` (and not just some type compatible with it)
+ // SI-6624 shows this is necessary because apparently patBinder may have an unfortunate type (.decls don't have the case field accessors)
+ // TODO: get to the bottom of this -- I assume it happens when type checking infers a weird type for an unapply call
+ // by going back to the parameterType for the extractor call we get a saner type, so let's just do that for now
+ /* TODO: uncomment when `settings.developer` and `devWarning` become available
+ if (settings.developer.value && !(patBinder.info =:= extractor.paramType))
+ devWarning(s"resetting info of $patBinder: ${patBinder.info} to ${extractor.paramType}")
+ */
+ (Nil, patBinder setInfo extractor.paramType)
+ }
withSubPats(typeTestTreeMaker :+ extractor.treeMaker(patBinderOrCasted, pos), extractor.subBindersAndPatterns: _*)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 1cfc8c909b..42c7d4a6b8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1058,6 +1058,10 @@ trait Typers extends Modes with Adaptations with Tags {
instantiateToMethodType(mt)
case _ =>
+ def shouldInsertApply(tree: Tree) = inAllModes(mode, EXPRmode | FUNmode) && (tree.tpe match {
+ case _: MethodType | _: OverloadedType | _: PolyType => false
+ case _ => applyPossible
+ })
def applyPossible = {
def applyMeth = member(adaptToName(tree, nme.apply), nme.apply)
dyna.acceptsApplyDynamic(tree.tpe) || (
@@ -1071,14 +1075,12 @@ trait Typers extends Modes with Adaptations with Tags {
adaptType()
else if (
inExprModeButNot(mode, FUNmode) && !tree.isDef && // typechecking application
- tree.symbol != null && tree.symbol.isTermMacro) // of a macro
+ tree.symbol != null && tree.symbol.isTermMacro && // of a macro
+ !tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined)
macroExpand(this, tree, mode, pt)
else if (inAllModes(mode, PATTERNmode | FUNmode))
adaptConstrPattern()
- else if (inAllModes(mode, EXPRmode | FUNmode) &&
- !tree.tpe.isInstanceOf[MethodType] &&
- !tree.tpe.isInstanceOf[OverloadedType] &&
- applyPossible)
+ else if (shouldInsertApply(tree))
insertApply()
else if (!context.undetparams.isEmpty && !inPolyMode(mode)) { // (9)
assert(!inHKMode(mode), modeString(mode)) //@M
@@ -3772,9 +3774,14 @@ trait Typers extends Modes with Adaptations with Tags {
case t: ValOrDefDef => t.rhs
case t => t
}
- val (outer, explicitTargs) = cxTree1 match {
+ val cxTree2 = cxTree1 match {
+ case Typed(t, tpe) => t // ignore outer type annotation
+ case t => t
+ }
+ val (outer, explicitTargs) = cxTree2 match {
case TypeApply(fun, targs) => (fun, targs)
case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs)
+ case Select(TypeApply(fun, targs), nme) => (Select(fun, nme), targs)
case t => (t, Nil)
}
def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty
@@ -4855,9 +4862,9 @@ trait Typers extends Modes with Adaptations with Tags {
// find out whether the programmer is trying to eta-expand a macro def
// to do that we need to typecheck the tree first (we need a symbol of the eta-expandee)
// that typecheck must not trigger macro expansions, so we explicitly prohibit them
- // Q: "but, " - you may ask - ", `typed1` doesn't call adapt, which does macro expansion, so why explicit check?"
- // A: solely for robustness reasons. this mechanism might change in the future, which might break unprotected code
- val exprTyped = context.withMacrosDisabled(typed1(expr, mode, pt))
+ // however we cannot do `context.withMacrosDisabled`
+ // because `expr` might contain nested macro calls (see SI-6673)
+ val exprTyped = typed1(expr updateAttachment SuppressMacroExpansionAttachment, mode, pt)
exprTyped match {
case macroDef if macroDef.symbol != null && macroDef.symbol.isTermMacro && !macroDef.symbol.isErroneous =>
MacroEtaError(exprTyped)
@@ -5001,8 +5008,14 @@ trait Typers extends Modes with Adaptations with Tags {
}
def typedTypeTree(tree: TypeTree) = {
- if (tree.original != null)
- tree setType typedType(tree.original, mode).tpe
+ if (tree.original != null) {
+ val newTpt = typedType(tree.original, mode)
+ tree setType newTpt.tpe
+ newTpt match {
+ case tt @ TypeTree() => tree setOriginal tt.original
+ case _ => tree
+ }
+ }
else
// we should get here only when something before failed
// and we try again (@see tryTypedApply). In that case we can assign