summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala22
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala19
4 files changed, 32 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 7b45b3efe5..bba5fd4e5e 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -693,7 +693,7 @@ abstract class Erasure extends AddInterfaces
adaptToType(unbox(tree, pt), pt)
else if (isPrimitiveValueType(tree.tpe) && !isPrimitiveValueType(pt)) {
adaptToType(box(tree, pt.toString), pt)
- } else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.params.isEmpty) {
+ } else if (isMethodTypeWithEmptyParams(tree.tpe)) {
// [H] this assert fails when trying to typecheck tree !(SomeClass.this.bitmap) for single lazy val
//assert(tree.symbol.isStable, "adapt "+tree+":"+tree.tpe+" to "+pt)
adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt)
@@ -783,16 +783,21 @@ abstract class Erasure extends AddInterfaces
else if (!isPrimitiveValueType(qual1.tpe) && isPrimitiveValueMember(tree.symbol))
qual1 = unbox(qual1, tree.symbol.owner.tpe)
- if (isPrimitiveValueMember(tree.symbol) && !isPrimitiveValueType(qual1.tpe))
+ def selectFrom(qual: Tree) = treeCopy.Select(tree, qual, name)
+
+ if (isPrimitiveValueMember(tree.symbol) && !isPrimitiveValueType(qual1.tpe)) {
tree.symbol = NoSymbol
- else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.params.isEmpty) {
+ selectFrom(qual1)
+ } else if (isMethodTypeWithEmptyParams(qual1.tpe)) {
assert(qual1.symbol.isStable, qual1.symbol);
- qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType
+ val applied = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType
+ adaptMember(selectFrom(applied))
} else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) {
assert(tree.symbol.owner != ArrayClass)
- qual1 = cast(qual1, tree.symbol.owner.tpe)
+ selectFrom(cast(qual1, tree.symbol.owner.tpe))
+ } else {
+ selectFrom(qual1)
}
- treeCopy.Select(tree, qual1, name)
}
case SelectFromArray(qual, name, erasure) =>
var qual1 = typedQualifier(qual)
@@ -870,6 +875,11 @@ abstract class Erasure extends AddInterfaces
tree1
}
}
+
+ private def isMethodTypeWithEmptyParams(tpe: Type) = tpe match {
+ case MethodType(Nil, _) => true
+ case _ => false
+ }
}
/** The erasure transformer */
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index e8a2c9f43c..acc4f7ff67 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -426,6 +426,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/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index f5d4df14fe..36edd46f25 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1289,7 +1289,8 @@ trait Namers extends MethodSynthesis {
if (clazz.isDerivedValueClass) {
log("Ensuring companion for derived value class " + name + " at " + cdef.pos.show)
clazz setFlag FINAL
- enclosingNamerWithScope(clazz.owner.info.decls).ensureCompanionObject(cdef)
+ // Don't force the owner's info lest we create cycles as in SI-6357.
+ enclosingNamerWithScope(clazz.owner.rawInfo.decls).ensureCompanionObject(cdef)
}
result
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index f2d7adc628..a2aca45e8f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1117,7 +1117,8 @@ 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 ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode))
adaptConstrPattern()
@@ -5221,9 +5222,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)
@@ -5367,8 +5368,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