diff options
author | Paul Phillips <paulp@improving.org> | 2012-05-03 23:11:05 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-05-04 01:22:23 -0700 |
commit | 01f6ed8e22d02811fe62b9183d9f84bdda5ede4b (patch) | |
tree | 6cc9b5a4847ba7940ddd8313a1a906b06024b5bf /src | |
parent | aad6deae7204a7fc95b59ede61b188bb62f51188 (diff) | |
download | scala-01f6ed8e22d02811fe62b9183d9f84bdda5ede4b.tar.gz scala-01f6ed8e22d02811fe62b9183d9f84bdda5ede4b.tar.bz2 scala-01f6ed8e22d02811fe62b9183d9f84bdda5ede4b.zip |
Fix for one of the oldest open soundness bugs.
Closes SI-963, since it was one of my random 30 it won the prize.
The trick after adding the stability check (which has been sitting
there commented out for 3+ years) was that implicit search depended
on the wrongness, because memberWildcardType would create scopes
with members of the form
?{ val name: tp }
And since a def shouldn't match that, fixing it broke everything
until I flipped it around: memberWildcardType should be seeking
?{ def name: tp }
It could also search for a mutable value: the relevant quality
is that it not be stable so it doesn't have a tighter type than
the members it hopes to match.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/reflect/internal/Types.scala | 17 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 4 |
2 files changed, 11 insertions, 10 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 66657c4412..09e7303b90 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -5719,14 +5719,15 @@ trait Types extends api.Types { self: SymbolTable => val info1 = tp1.memberInfo(sym1) val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1) //System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG - sym2.isTerm && (info1 <:< info2) /*&& (!sym2.isStable || sym1.isStable) */ || - sym2.isAbstractType && { - val memberTp1 = tp1.memberType(sym1) - // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner))) - info2.bounds.containsType(memberTp1) && - kindsConform(List(sym2), List(memberTp1), tp1, sym1.owner) - } || - sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.typeSymbol, tp1) =:= tp1.memberType(sym1) //@MAT ok + ( sym2.isTerm && (info1 <:< info2) && (!sym2.isStable || sym1.isStable) + || sym2.isAbstractType && { + val memberTp1 = tp1.memberType(sym1) + // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner))) + info2.bounds.containsType(memberTp1) && + kindsConform(List(sym2), List(memberTp1), tp1, sym1.owner) + } + || sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.typeSymbol, tp1) =:= tp1.memberType(sym1) //@MAT ok + ) } /** A function implementing `tp1` matches `tp2`. */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 0d7ef71193..787d7af136 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -214,13 +214,13 @@ trait Implicits { override def hashCode = 1 } - /** A constructor for types ?{ name: tp }, used in infer view to member + /** A constructor for types ?{ def/type name: tp }, used in infer view to member * searches. */ def memberWildcardType(name: Name, tp: Type) = { val result = refinedType(List(WildcardType), NoSymbol) name match { - case x: TermName => result.typeSymbol.newValue(x) setInfoAndEnter tp + case x: TermName => result.typeSymbol.newMethod(x) setInfoAndEnter tp case x: TypeName => result.typeSymbol.newAbstractType(x) setInfoAndEnter tp } result |