aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Types.scala10
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala12
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala44
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala14
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala41
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala46
-rw-r--r--test/dotc/tests.scala4
-rw-r--r--tests/pos/bigint.scala7
-rw-r--r--tests/pos/t1693.scala (renamed from tests/pending/pos/t1693.scala)0
-rw-r--r--tests/pos/t1832.scala (renamed from tests/pending/pos/t1832.scala)0
-rwxr-xr-xtests/pos/t2060.scala (renamed from tests/pending/pos/t2060.scala)0
11 files changed, 117 insertions, 61 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 088a2e3af..36b546230 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -756,6 +756,11 @@ object Types {
def typeParamNamed(name: TypeName)(implicit ctx: Context): Symbol =
classSymbol.decls.lookup(name) orElse member(name).symbol
+ /** If this is a prototype with some ignored component, reveal one more
+ * layer of it. Otherwise the type itself.
+ */
+ def deepenProto(implicit ctx: Context): Type = this
+
// ----- Substitutions -----------------------------------------------------
/** Substitute all types that refer in their symbol attribute to
@@ -1057,12 +1062,13 @@ object Types {
if (owner.isTerm) d else d.asSeenFrom(prefix)
}
- private def checkSymAssign(sym: Symbol) =
+ private def checkSymAssign(sym: Symbol)(implicit ctx: Context) =
assert(
(lastSymbol eq sym) ||
(lastSymbol eq null) ||
(lastSymbol.defRunId != sym.defRunId) ||
- (lastSymbol.defRunId == NoRunId),
+ (lastSymbol.defRunId == NoRunId) ||
+ (lastSymbol.infoOrCompleter == ErrorType),
s"data race? overwriting symbol of $this / ${this.getClass} / ${lastSymbol.id} / ${sym.id}")
protected def sig: Signature = Signature.NotAMethod
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index dd8f04d92..c20598bb3 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -7,7 +7,7 @@ import Contexts.Context, Scopes.Scope, Denotations._, Annotations.Annotation
import StdNames.nme
import ast.{Trees, untpd}
import typer.Namer
-import typer.ProtoTypes.{SelectionProto, ViewProto, FunProto}
+import typer.ProtoTypes.{SelectionProto, ViewProto, FunProto, IgnoredProto}
import Trees._
import scala.annotation.switch
@@ -108,10 +108,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close
}
- case tp: SelectionProto =>
- return toText(RefinedType(WildcardType, tp.name, tp.memberProto))
- case tp: ViewProto =>
- return toText(tp.argType) ~ " ?=>? " ~ toText(tp.resultType)
case tp: TypeRef =>
if ((tp.symbol is TypeParam | TypeArgument) && !ctx.phase.erasedTypes) {
return tp.info match {
@@ -121,8 +117,14 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
case ExprType(result) =>
return "=> " ~ toText(result)
+ case tp: SelectionProto =>
+ return toText(RefinedType(WildcardType, tp.name, tp.memberProto))
+ case tp: ViewProto =>
+ return toText(tp.argType) ~ " ?=>? " ~ toText(tp.resultType)
case FunProto(args, resultType, _) =>
return "funproto(" ~ toTextGlobal(args, ", ") ~ "):" ~ toText(resultType)
+ case tp: IgnoredProto =>
+ return "?"
case _ =>
}
super.toText(tp)
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 0f47336fc..92acb7939 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -434,7 +434,7 @@ trait Applications extends Compatibility { self: Typer =>
def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
def realApply(implicit ctx: Context): Tree = track("realApply") {
- var proto = new FunProto(tree.args, pt, this)
+ var proto = new FunProto(tree.args, ignoreIfProto(pt), this)
val fun1 = typedExpr(tree.fun, proto)
// Warning: The following line is dirty and fragile. We record that auto-tupling was demanded as
@@ -453,30 +453,13 @@ trait Applications extends Compatibility { self: Typer =>
else new ApplyToUntyped(tree, fun1, funRef, proto, pt)
val result = app.result
ConstFold(result)
- } { (failedVal, failedState) => fun1 match {
- case Select(qual, name) =>
- // try with prototype `[].name(args)`, this might succeed by inserting an
- // implicit conversion around []. (an example is Int + BigInt).
- tryEither { implicit ctx =>
- val simpleFunProto = new FunProto(tree.args, WildcardType, this) // drop result type, because views are disabled
- val selProto = SelectionProto(name, simpleFunProto, NoViewsAllowed)
- val qual1 = adaptInterpolated(qual, selProto)
- if (qual eq qual1) ctx.error("no progress")
- if (ctx.reporter.hasErrors) qual1
- else
- typedApply(
- cpy.Apply(tree,
- cpy.Select(fun1, untpd.TypedSplice(qual1), name),
- proto.typedArgs map untpd.TypedSplice),
- pt)
- } { (_, _) =>
- failedState.commit()
- failedVal
- }
- case _ =>
- failedState.commit()
- failedVal
- }
+ } { (failedVal, failedState) =>
+ val fun2 = tryInsertImplicit(fun1, proto)
+ if (fun1 eq fun2) {
+ failedState.commit()
+ failedVal
+ } else typedApply(
+ cpy.Apply(tree, untpd.TypedSplice(fun2), proto.typedArgs map untpd.TypedSplice), pt)
}
case _ =>
fun1.tpe match {
@@ -771,7 +754,7 @@ trait Applications extends Compatibility { self: Typer =>
def isAsSpecific(alt1: TermRef, tp1: Type, alt2: TermRef, tp2: Type): Boolean = ctx.traceIndented(i"isAsSpecific $tp1 $tp2", overload) { tp1 match {
case tp1: PolyType =>
def bounds(tparamRefs: List[TypeRef]) = tp1.paramBounds map (_.substParams(tp1, tparamRefs))
- val tparams = ctx.newTypeParams(alt1.symbol.owner, tp1.paramNames, EmptyFlags, bounds)
+ val tparams = ctx.newTypeParams(alt1.symbol, tp1.paramNames, EmptyFlags, bounds)
isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2)
case tp1: MethodType =>
def repeatedToSingle(tp: Type) = if (tp.isRepeatedParam) tp.argTypesHi.head else tp
@@ -927,7 +910,14 @@ trait Applications extends Compatibility { self: Typer =>
alts filter (normalizedCompatible(_, pt))
}
if (isDetermined(candidates)) candidates
- else narrowMostSpecific(candidates)
+ else narrowMostSpecific(candidates) match {
+ case result @ (alt1 :: alt2 :: _) =>
+ val deepPt = pt.deepenProto
+ if (deepPt ne pt) resolveOverloaded(alts, deepPt, targs)
+ else result
+ case result =>
+ result
+ }
}
}
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index a32f552ed..d2a94e287 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -368,7 +368,10 @@ trait Implicits { self: Typer =>
return defn.isValueSubClass(from.symbol, to.symbol)
case _ =>
}
+ case from: ValueType =>
+ ;
case _ =>
+ return false
}
inferView(dummyTreeOfType(from), to)(ctx.fresh.setExploreTyperState).isInstanceOf[SearchSuccess]
}
@@ -410,12 +413,15 @@ trait Implicits { self: Typer =>
else new ImplicitSearch(pt, argument, pos)
val result = isearch.bestImplicit
result match {
- case success: SearchSuccess =>
- // println(s"committing to ${success.tstate.show}")
- success.tstate.commit()
+ case result: SearchSuccess =>
+ result.tstate.commit()
+ result
+ case result: AmbiguousImplicits =>
+ val deepPt = pt.deepenProto
+ if (deepPt ne pt) inferImplicit(deepPt, argument, pos) else result
case _ =>
+ result
}
- result
}
}
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index fab652849..1438f9e16 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -71,6 +71,23 @@ object ProtoTypes {
override def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean = false
}
+ /** A trait for prototypes that match all types */
+ trait MatchAlways extends ProtoType {
+ def isMatchedBy(tp1: Type)(implicit ctx: Context) = true
+ def map(tm: TypeMap)(implicit ctx: Context): ProtoType = this
+ def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T = x
+ }
+
+ /** A class marking ignored prototypes that can be reviealed by `deepenProto` */
+ case class IgnoredProto(proto: ProtoType) extends UncachedGroundType with MatchAlways {
+ override def deepenProto(implicit ctx: Context): Type = proto
+ }
+
+ def ignoreIfProto(tp: Type): Type = tp match {
+ case proto: ProtoType => IgnoredProto(proto)
+ case _ => tp
+ }
+
/** A prototype for expressions [] that are part of a selection operation:
*
* [ ].name: proto
@@ -107,6 +124,8 @@ object ProtoTypes {
def map(tm: TypeMap)(implicit ctx: Context) = derivedSelectionProto(name, tm(memberProto), compat)
def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context) = ta(x, memberProto)
+ override def deepenProto(implicit ctx: Context) = derivedSelectionProto(name, memberProto.deepenProto, compat)
+
override def computeHash = addDelta(doHash(name, memberProto), if (compat eq NoViewsAllowed) 1 else 0)
}
@@ -126,8 +145,7 @@ object ProtoTypes {
if (name.isConstructorName) WildcardType
else tp match {
case tp: UnapplyFunProto => new UnapplySelectionProto(name)
- case tp: ProtoType => SelectionProto(name, WildcardType, typer)
- case _ => SelectionProto(name, tp, typer)
+ case tp => SelectionProto(name, ignoreIfProto(tp), typer)
}
/** A prototype for expressions [] that are in some unspecified selection operation
@@ -208,7 +226,10 @@ object ProtoTypes {
def map(tm: TypeMap)(implicit ctx: Context): FunProto =
derivedFunProto(args, tm(resultType), typer)
- def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T = ta(x, resultType)
+ def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T =
+ ta(ta.foldOver(x, typedArgs.tpes), resultType)
+
+ override def deepenProto(implicit ctx: Context) = derivedFunProto(args, resultType.deepenProto, typer)
}
/** A prototype for implicitly inferred views:
@@ -226,10 +247,10 @@ object ProtoTypes {
def map(tm: TypeMap)(implicit ctx: Context): ViewProto = derivedViewProto(tm(argType), tm(resultType))
- def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T = ta(ta(x, argType), resultType)
+ def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T =
+ ta(ta(x, argType), resultType)
- override def namedPartsWith(p: NamedType => Boolean)(implicit ctx: Context): collection.Set[NamedType] =
- AndType.unchecked(argType, resultType).namedPartsWith(p) // this is more efficient than oring two namedParts sets
+ override def deepenProto(implicit ctx: Context) = derivedViewProto(argType, resultType.deepenProto)
}
class CachedViewProto(argType: Type, resultType: Type)(implicit ctx: Context) extends ViewProto(argType, resultType) {
@@ -266,17 +287,15 @@ object ProtoTypes {
def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T =
ta(ta.foldOver(x, targs), resultType)
+
+ override def deepenProto(implicit ctx: Context) = derivedPolyProto(targs, resultType.deepenProto)
}
/** A prototype for expressions [] that are known to be functions:
*
* [] _
*/
- object AnyFunctionProto extends UncachedGroundType with ProtoType {
- def isMatchedBy(tp: Type)(implicit ctx: Context) = true
- def map(tm: TypeMap)(implicit ctx: Context) = this
- def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context) = x
- }
+ object AnyFunctionProto extends UncachedGroundType with MatchAlways
/** Add all parameters in given polytype `pt` to the constraint's domain.
* If the constraint contains already some of these parameters in its domain,
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 944b44510..5d477193c 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -1009,15 +1009,41 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}
- def tryInsertApply(tree: Tree, pt: Type)(fallBack: (Tree, TyperState) => Tree)(implicit ctx: Context): Tree =
- tryEither {
- implicit ctx =>
- val sel = typedSelect(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt)
- if (sel.tpe.isError) sel else adapt(sel, pt)
- } {
- fallBack
+ /** Try to insert `.apply` so that the result conforms to prototype `pt`.
+ * If that fails try to insert an implicit conversion around the qualifier
+ * part of `tree`. If either result conforms to `pt`, adapt it, else
+ * continue with `fallBack`.
+ */
+ def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType)(fallBack: (Tree, TyperState) => Tree)(implicit ctx: Context): Tree =
+ tryEither { implicit ctx =>
+ val sel = typedSelect(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt)
+ if (sel.tpe.isError) sel else adapt(sel, pt)
+ } { (failedTree, failedState) =>
+ val tree1 = tryInsertImplicit(tree, pt)
+ if (tree1 eq tree) fallBack(failedTree, failedState)
+ else adapt(tree1, pt)
}
+ /** If this tree is a select node `qual.name`, try to insert an implicit conversion
+ * `c` around `qual` so that `c(qual).name` conforms to `pt`. If that fails
+ * return `tree` itself.
+ */
+ def tryInsertImplicit(tree: Tree, pt: ProtoType)(implicit ctx: Context): Tree = ctx.traceIndented(i"try ins impl $tree $pt") { tree match {
+ case Select(qual, name) =>
+ val normalizedProto = pt match {
+ case pt: FunProto => pt.derivedFunProto(pt.args, WildcardType, pt.typer) // drop result type, because views are disabled
+ case _ => pt
+ }
+ val qualProto = SelectionProto(name, normalizedProto, NoViewsAllowed)
+ tryEither { implicit ctx =>
+ val qual1 = adaptInterpolated(qual, qualProto)
+ if ((qual eq qual1) || ctx.reporter.hasErrors) tree
+ else typedSelect(cpy.Select(tree, untpd.TypedSplice(qual1), name), pt)
+ } { (_, _) => tree
+ }
+ case _ => tree
+ }}
+
def adapt(tree: Tree, pt: Type)(implicit ctx: Context) = /*>|>*/ track("adapt") /*<|<*/ {
/*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ {
interpolateUndetVars(tree)
@@ -1087,7 +1113,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def hasEmptyParams(denot: SingleDenotation) = denot.info.paramTypess == ListOfNil
pt match {
case pt: FunProto =>
- tryInsertApply(tree, pt)((_, _) => noMatches)
+ tryInsertApplyOrImplicit(tree, pt)((_, _) => noMatches)
case _ =>
if (altDenots exists (_.info.paramTypess == ListOfNil))
typed(untpd.Apply(untpd.TypedSplice(tree), Nil), pt)
@@ -1113,7 +1139,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
adaptToArgs(wtp, pt.tupled)
else
tree
- case _ => tryInsertApply(tree, pt) {
+ case _ => tryInsertApplyOrImplicit(tree, pt) {
val more = tree match {
case Apply(_, _) => " more"
case _ => ""
@@ -1216,7 +1242,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case pt: FunProto =>
adaptToArgs(wtp, pt)
case pt: PolyProto =>
- tryInsertApply(tree, pt) {
+ tryInsertApplyOrImplicit(tree, pt) {
(_, _) => tree // error will be reported in typedTypeApply
}
case _ =>
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 9a173a5ce..4acf8374e 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -64,8 +64,8 @@ class tests extends CompilerTest {
@Test def neg_privates() = compileFile(negDir, "privates", xerrors = 2)
@Test def neg_rootImports = compileFile(negDir, "rootImplicits", xerrors = 2)
@Test def neg_templateParents() = compileFile(negDir, "templateParents", xerrors = 3)
- @Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", "-language:noAutoTupling" :: Nil, xerrors = 3)
- @Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 3)
+ @Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", "-language:noAutoTupling" :: Nil, xerrors = 4)
+ @Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 4)
@Test def neg_companions = compileFile(negDir, "companions", xerrors = 1)
@Test def neg_i39 = compileFile(negDir, "i39", xerrors = 1)
@Test def neg_i50_volatile = compileFile(negDir, "i50-volatile", xerrors = 4)
diff --git a/tests/pos/bigint.scala b/tests/pos/bigint.scala
new file mode 100644
index 000000000..e1aaaf96e
--- /dev/null
+++ b/tests/pos/bigint.scala
@@ -0,0 +1,7 @@
+import scala.math.BigInt
+//import BigInt._
+object test {
+
+ 1 * BigInt(0)
+
+}
diff --git a/tests/pending/pos/t1693.scala b/tests/pos/t1693.scala
index 881bf89a0..881bf89a0 100644
--- a/tests/pending/pos/t1693.scala
+++ b/tests/pos/t1693.scala
diff --git a/tests/pending/pos/t1832.scala b/tests/pos/t1832.scala
index 9ad9703c2..9ad9703c2 100644
--- a/tests/pending/pos/t1832.scala
+++ b/tests/pos/t1832.scala
diff --git a/tests/pending/pos/t2060.scala b/tests/pos/t2060.scala
index 0b9079062..0b9079062 100755
--- a/tests/pending/pos/t2060.scala
+++ b/tests/pos/t2060.scala