Skip to content

Commit bff4268

Browse files
committed
fixed several problems with implicits.
Changed ways inner types of modules print: Module.this.Type => Module.type
1 parent 9e8c022 commit bff4268

File tree

18 files changed

+96
-53
lines changed

18 files changed

+96
-53
lines changed

src/compiler/scala/tools/nsc/symtab/Flags.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ object Flags extends Enumeration {
4141
// constructor.
4242
final val ABSOVERRIDE = 0x00040000 // combination of abstract & override
4343
final val LOCAL = 0x00080000 // symbol is local to current class.
44-
// pre: PRIVATE is also set
44+
// pre: PRIVATE or PROTECTED are also set
4545
final val JAVA = 0x00100000 // symbol was defined by a Java class
4646
final val SYNTHETIC = 0x00200000 // symbol is compiler-generated
4747
final val STABLE = 0x00400000 // functions that are assumed to be stable

src/compiler/scala/tools/nsc/symtab/Symbols.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,12 @@ trait Symbols {
378378

379379
def ownerChain: List[Symbol] = this :: owner.ownerChain
380380

381+
def hasTransOwner(sym: Symbol) = {
382+
var o = this
383+
while ((o ne sym) && (o ne NoSymbol)) o = o.owner
384+
o eq sym
385+
}
386+
381387
def name: Name = rawname
382388

383389
final def name_=(name: Name) {

src/compiler/scala/tools/nsc/symtab/Types.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -627,17 +627,21 @@ trait Types {
627627
checkMalformedSwitch = false
628628
while (continue) {
629629
continue = false
630-
var bcs = baseClasses
630+
val bcs0 = baseClasses
631+
var bcs = bcs0
631632
while (!bcs.isEmpty) {
632633
val decls = bcs.head.info.decls
633-
bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
634634
var entry =
635635
if (name == nme.ANYNAME) decls.elems else decls lookupEntry name
636636
while (entry ne null) {
637637
val sym = entry.sym
638638
if (sym.getFlag(requiredFlags) == requiredFlags) {
639639
val excl = sym.getFlag(excluded)
640-
if (excl == 0) {
640+
if (excl == 0 &&
641+
(// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
642+
(bcs eq bcs0) ||
643+
sym.getFlag(PRIVATE | LOCAL) != (PRIVATE | LOCAL) ||
644+
(bcs0.head.hasTransOwner(bcs.head)))) {
641645
if (name.isTypeName || stableOnly) {
642646
checkMalformedSwitch = savedCheckMalformedSwitch
643647
if (util.Statistics.enabled)
@@ -677,6 +681,7 @@ trait Types {
677681
entry = if (name == nme.ANYNAME) entry.next else decls lookupNextEntry entry
678682
} // while (entry ne null)
679683
// excluded = excluded | LOCAL
684+
bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
680685
} // while (!bcs.isEmpty)
681686
excluded = excludedFlags
682687
} // while (continue)
@@ -833,7 +838,7 @@ trait Types {
833838
if (settings.debug.value) sym.nameString + ".this."
834839
else if (sym.isRoot || sym.isEmptyPackageClass || sym.isInterpreterWrapper || sym.isScalaPackageClass) ""
835840
else if (sym.isAnonymousClass || sym.isRefinementClass) "this."
836-
else if (sym.isPackageClass) sym.fullNameString + "."
841+
else if (sym.isModuleClass) sym.fullNameString + "."
837842
else sym.nameString + ".this."
838843
override def toString: String =
839844
if (sym.isRoot) "<root>"

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,17 @@ trait EtaExpansion { self: Analyzer =>
4343
if (pos == util.NoPosition) {
4444
if (inIDE) newTermName( ("eta$" + symbolHash + (cnt - 1)))
4545
else newTermName(unit.fresh.newName("eta$" + symbolHash + (cnt - 1)))
46+
/*
4647
} else if (n == 0) {
47-
newTermName(unit.fresh.newName(pos, "eta$" + symbolHash))
48+
newTermName(unit.fresh.newName(pos, "etaC$" + symbolHash))
49+
*/
4850
} else {
49-
newTermName(unit.fresh.newName(pos, "eta$" + symbolHash + n + "$"))
51+
newTermName(unit.fresh.newName(pos, "eta$" + symbolHash + (cnt - 1) + "$"))
52+
// Martin to Sean: I removed the
53+
// else if (n == 0) branch and changed `n' in the line above to `(cnt - 1)'
54+
// this was necessary because otherwise curried eta-expansions would get the same
55+
// symbol. An example which failes test/files/run/Course-2002-02.scala
56+
// todo: review and get rid of the `n' argument (which is unused right now).
5057
}
5158
}
5259
// { cnt = cnt + 1; newTermName("eta$" + cnt) }

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ trait Infer {
327327
def isPlausiblyCompatible(tp: Type, pt: Type): Boolean = tp match {
328328
case PolyType(_, restpe) =>
329329
isPlausiblyCompatible(restpe, pt)
330+
case mt: ImplicitMethodType =>
331+
isPlausiblyCompatible(mt.resultType, pt)
330332
case MethodType(formals, _) =>
331333
pt.normalize match {
332334
case TypeRef(pre, sym, args) =>
@@ -1081,7 +1083,11 @@ trait Infer {
10811083
def inferExprAlternative(tree: Tree, pt: Type): Unit = tree.tpe match {
10821084
case OverloadedType(pre, alts) => tryTwice {
10831085
var alts1 = alts filter (alt => isCompatible(pre.memberType(alt), pt))
1084-
if (alts1.isEmpty) alts1 = alts
1086+
var secondTry = false
1087+
if (alts1.isEmpty) {
1088+
alts1 = alts
1089+
secondTry = true
1090+
}
10851091
def improves(sym1: Symbol, sym2: Symbol): Boolean =
10861092
sym2 == NoSymbol ||
10871093
{ val tp1 = pre.memberType(sym1)
@@ -1105,11 +1111,13 @@ trait Infer {
11051111
}
11061112
typeErrorTree(tree, tree.symbol.tpe, pt)
11071113
} else if (!competing.isEmpty) {
1108-
if (!pt.isErroneous)
1109-
context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt)
1110-
setError(tree)
1111-
()
1112-
1114+
if (secondTry) {
1115+
typeErrorTree(tree, tree.symbol.tpe, pt)
1116+
} else {
1117+
if (!pt.isErroneous)
1118+
context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt)
1119+
setError(tree)
1120+
}
11131121
} else {
11141122
val applicable = alts1 filter (alt =>
11151123
global.typer.infer.isCompatible(pre.memberType(alt), pt))

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ abstract class RefChecks extends InfoTransform {
169169
val mb = member.accessBoundary(member.owner)
170170
val ob = other.accessBoundary(member.owner)
171171
if (mb != RootClass && mb != NoSymbol && // todo: change
172-
(ob == RootClass || ob == NoSymbol ||
173-
mb != ob && !(ob.ownerChain contains mb) ||
172+
(ob == RootClass || ob == NoSymbol || !ob.hasTransOwner(mb) ||
174173
(other hasFlag PROTECTED) && !(member hasFlag PROTECTED))) {
175174
overrideAccessError()
176175
} else if (other hasFlag FINAL) { // (1.2)

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

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,12 @@ trait Typers { self: Analyzer =>
165165
case OverloadedType(_, _) => EmptyTree
166166
case PolyType(_, _) => EmptyTree
167167
case _ =>
168-
val result = inferImplicit(pos, functionType(List(from), to), true, reportAmbiguous)
168+
val result = inferImplicit(pos, MethodType(List(from), to), reportAmbiguous)
169169
if (result != EmptyTree) result
170170
else inferImplicit(
171171
pos,
172-
functionType(List(appliedType(ByNameParamClass.typeConstructor, List(from))), to),
173-
true, reportAmbiguous)
172+
MethodType(List(appliedType(ByNameParamClass.typeConstructor, List(from))), to),
173+
reportAmbiguous)
174174
}
175175
}
176176

@@ -379,7 +379,7 @@ trait Typers { self: Analyzer =>
379379
var o = owner
380380
while (o != NoSymbol && o != sym.owner &&
381381
!o.isLocal && !o.hasFlag(PRIVATE) &&
382-
!o.privateWithin.ownerChain.contains(sym.owner))
382+
!o.privateWithin.hasTransOwner(sym.owner))
383383
o = o.owner
384384
if (o == sym.owner) addHidden(sym)
385385
} else if (sym.owner.isTerm && !sym.isTypeParameterOrSkolem) {
@@ -548,7 +548,7 @@ trait Typers { self: Analyzer =>
548548

549549
/** The member with given name of given qualifier tree */
550550
def member(qual: Tree, name: Name) = qual.tpe match {
551-
case ThisType(clazz) if (context.enclClass.owner.ownerChain contains clazz) =>
551+
case ThisType(clazz) if (context.enclClass.owner.hasTransOwner(clazz)) =>
552552
qual.tpe.member(name)
553553
case _ =>
554554
if (phase.next.erasedTypes) qual.tpe.member(name)
@@ -1248,7 +1248,7 @@ trait Typers { self: Analyzer =>
12481248

12491249
private def checkStructuralCondition(refinement: Symbol, vparam: ValDef) {
12501250
val tp = vparam.symbol.tpe
1251-
if (tp.typeSymbol.isAbstractType && !(tp.typeSymbol.ownerChain contains refinement))
1251+
if (tp.typeSymbol.isAbstractType && !(tp.typeSymbol.hasTransOwner(refinement)))
12521252
error(vparam.tpt.pos,"Parameter type in structural refinement may not refer to abstract type defined outside that same refinement")
12531253
}
12541254

@@ -3148,29 +3148,45 @@ trait Typers { self: Analyzer =>
31483148
* to <code>pt</code>, EmptyTree otherwise.
31493149
* @pre <code>info.tpe</code> does not contain an error
31503150
*/
3151-
private def typedImplicit(pos: Position, info: ImplicitInfo, pt: Type, isLocal: Boolean): Tree = {
3151+
private def typedImplicit(pos: Position, info: ImplicitInfo, pt0: Type, pt: Type, isLocal: Boolean): Tree = {
31523152
def isStable(tp: Type): Boolean = tp match {
31533153
case TypeRef(pre, sym, _) => sym.isPackageClass || sym.isModuleClass && isStable(pre)
31543154
case _ => tp.isStable
31553155
}
3156+
// println("typed impl for "+pt+"? "+info.name+":"+info.tpe+(isPlausiblyCompatible(info.tpe, pt))+isCompatible(depoly(info.tpe), pt)+isStable(info.pre))
31563157
if (isPlausiblyCompatible(info.tpe, pt) && isCompatible(depoly(info.tpe), pt) && isStable(info.pre)) {
31573158
val tree = atPos(pos) {
31583159
if (info.pre == NoPrefix/*isLocal*/) Ident(info.name)
31593160
else Select(gen.mkAttributedQualifier(info.pre), info.name)
31603161
}
3162+
// println("typed impl?? "+info.name+":"+info.tpe+" ==> "+tree+" with "+pt)
31613163
def fail(reason: String, sym1: Symbol, sym2: Symbol): Tree = {
31623164
if (settings.debug.value)
3163-
log(tree+" is not a valid implicit value because:\n"+reason + sym1+" "+sym2)
3165+
println(tree+" is not a valid implicit value because:\n"+reason + sym1+" "+sym2)
31643166
EmptyTree
31653167
}
31663168
try {
3167-
// if (!isLocal) tree setSymbol info.sym
3168-
val tree1 = typed1(tree, EXPRmode, pt)
3169-
//if (settings.debug.value) log("typed implicit "+tree1+":"+tree1.tpe+", pt = "+pt)
3170-
val tree2 = adapt(tree1, EXPRmode, pt)
3171-
//if (settings.debug.value) log("adapted implicit "+tree1.symbol+":"+tree2.tpe+" to "+pt)
3169+
// if (!isLocal) tree setSymbol info.sym
3170+
val isView = (pt0 ne pt)
3171+
val tree1 =
3172+
if (isView)
3173+
typed1(Apply(tree, List(Ident("<argument>") setType pt0.paramTypes.head)), EXPRmode, pt0.resultType)
3174+
else
3175+
typed1(tree, EXPRmode, pt)
3176+
//if (settings.debug.value) println("typed implicit "+tree1+":"+tree1.tpe+", pt = "+pt)
3177+
val tree2 = if (isView) (tree1: @unchecked) match { case Apply(fun, _) => fun }
3178+
else adapt(tree1, EXPRmode, pt)
3179+
//if (settings.debug.value) println("adapted implicit "+tree1.symbol+":"+tree2.tpe+" to "+pt)("adapted implicit "+tree1.symbol+":"+tree2.tpe+" to "+pt)
3180+
def hasMatchingSymbol(tree: Tree): Boolean = (tree.symbol == info.sym) || {
3181+
tree match {
3182+
case Apply(fun, _) => hasMatchingSymbol(fun)
3183+
case TypeApply(fun, _) => hasMatchingSymbol(fun)
3184+
case Select(pre, name) => name == nme.apply && pre.symbol == info.sym
3185+
case _ => false
3186+
}
3187+
}
31723188
if (tree2.tpe.isError) EmptyTree
3173-
else if (info.sym == tree1.symbol) tree2
3189+
else if (hasMatchingSymbol(tree1)) tree2
31743190
else fail("syms differ: ", tree1.symbol, info.sym)
31753191
} catch {
31763192
case ex: TypeError => fail(ex.getMessage(), NoSymbol, NoSymbol)
@@ -3181,15 +3197,17 @@ trait Typers { self: Analyzer =>
31813197
/** Infer implicit argument or view.
31823198
*
31833199
* @param pos position for error reporting
3184-
* @param pt the expected type of the implicit
3200+
* @param pt0 the expected type of the implicit
31853201
* @param isView are we searching for a view? (this affects the error message)
31863202
* @param reportAmbiguous should ambiguous errors be reported?
31873203
* False iff we search for a view to find out
31883204
* whether one type is coercible to another
31893205
* @return ...
31903206
* @see <code>isCoercible</code>
31913207
*/
3192-
private def inferImplicit(pos: Position, pt: Type, isView: Boolean, reportAmbiguous: Boolean): Tree = {
3208+
private def inferImplicit(pos: Position, pt0: Type, reportAmbiguous: Boolean): Tree = {
3209+
val pt = normalize(pt0)
3210+
val isView = pt0.isInstanceOf[MethodType]
31933211

31943212
if (util.Statistics.enabled) implcnt = implcnt + 1
31953213
val startTime = if (util.Statistics.enabled) currentTime else 0l
@@ -3239,7 +3257,7 @@ trait Typers { self: Analyzer =>
32393257
!containsError(info.tpe) &&
32403258
!(isLocal && shadowed.contains(info.name)) &&
32413259
(!isView || info.sym != Predef_identity) &&
3242-
tc.typedImplicit(pos, info, pt, isLocal) != EmptyTree
3260+
tc.typedImplicit(pos, info, pt0, pt, isLocal) != EmptyTree
32433261
def applicableInfos(is: List[ImplicitInfo]) = {
32443262
val result = is filter isApplicable
32453263
if (isLocal)
@@ -3259,7 +3277,7 @@ trait Typers { self: Analyzer =>
32593277
"yet alternative definition ",
32603278
"is defined in a subclass.\n Both definitions ")
32613279
}
3262-
tc.typedImplicit(pos, best, pt, isLocal)
3280+
tc.typedImplicit(pos, best, pt0, pt, isLocal)
32633281
}
32643282
}
32653283

@@ -3305,7 +3323,7 @@ trait Typers { self: Analyzer =>
33053323
def applyImplicitArgs(tree: Tree): Tree = tree.tpe match {
33063324
case MethodType(formals, _) =>
33073325
def implicitArg(pt: Type) = {
3308-
val arg = inferImplicit(tree.pos, pt, false, true)
3326+
val arg = inferImplicit(tree.pos, pt, true)
33093327
if (arg != EmptyTree) arg
33103328
else errorTree(tree, "no implicit argument matching parameter type "+pt+" was found.")
33113329
}

test/files/neg/bug1275.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
bug1275.scala:13: error: The kind of type MyType does not conform to the expected kind of type MyType[+t] <: TestCovariance.this.Seq[t] in trait Seq.
1+
bug1275.scala:13: error: The kind of type MyType does not conform to the expected kind of type MyType[+t] <: TestCovariance.Seq[t] in trait Seq.
22
def span[a, s <: Seq[a] { type MyType <: s } ](xs: s): s = xs f
33
^
44
one error found

test/files/neg/bug452.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
bug452.scala:3: error: type mismatch;
22
found : Test.type (with underlying type object Test)
3-
required: Test.this.Foo
3+
required: Test.Foo
44
def this() = this(this);
55
^
66
one error found

test/files/neg/bug515.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
bug515.scala:7: error: type mismatch;
22
found : java.lang.String
3-
required: Test.this.Truc
3+
required: Test.Truc
44
val parent: Truc = file.getMachin
55
^
66
one error found

0 commit comments

Comments
 (0)