From cd8bf2d69cf1463fa16a69badb2a839f540bb2fa Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 6 May 2016 12:30:55 +0200 Subject: Hooks to check that comparisons with == / != make sense Also, check that pattern matching against idents/selects/literals makes sense. The hooks perform an implicit search for an instance of `Eq[L, R]`, where `L`, `R` are the argument types. So far this always succeeeds because Eq.eqAny matches all such types. A separate commit will check the returned search term for validity. --- src/dotty/tools/dotc/typer/Typer.scala | 56 +++++++--------------------------- 1 file changed, 11 insertions(+), 45 deletions(-) (limited to 'src/dotty/tools/dotc/typer/Typer.scala') diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index f7fa318cd..b26ff4509 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1540,26 +1540,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit tree.withType(wtp.resultType) } val args = (wtp.paramNames, wtp.paramTypes).zipped map { (pname, formal) => - def where = d"parameter $pname of $methodStr" - inferImplicit(formal, EmptyTree, tree.pos.endPos) match { - case SearchSuccess(arg, _, _) => - arg - case ambi: AmbiguousImplicits => - implicitArgError(s"ambiguous implicits: ${ambi.explanation} of $where") - case failure: SearchFailure => - val arg = synthesizedClassTag(formal) - if (!arg.isEmpty) arg - else { - var msg = d"no implicit argument of type $formal found for $where" + failure.postscript - for (notFound <- formal.typeSymbol.getAnnotation(defn.ImplicitNotFoundAnnot); - Literal(Constant(raw: String)) <- notFound.argument(0)) - msg = err.implicitNotFoundString( - raw, - formal.typeSymbol.typeParams.map(_.name.unexpandedName.toString), - formal.argInfos) - implicitArgError(msg) - } - } + def implicitArgError(msg: String => String) = + errors += (() => msg(d"parameter $pname of $methodStr")) + inferImplicitArg(formal, implicitArgError, tree.pos.endPos) } if (errors.nonEmpty) { // If there are several arguments, some arguments might already @@ -1609,8 +1592,14 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit else missingArgs case _ => - if (tree.tpe <:< pt) tree - else if (ctx.mode is Mode.Pattern) tree // no subtype check for pattern + if (ctx.mode is Mode.Pattern) { + tree match { + case _: RefTree | _: Literal if !isVarPattern(tree) => checkCanEqual(pt, wtp, tree.pos) + case _ => + } + tree + } + else if (tree.tpe <:< pt) tree else if (wtp.isInstanceOf[MethodType]) missingArgs else { typr.println(i"adapt to subtype ${tree.tpe} !<:< $pt") @@ -1618,29 +1607,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit adaptToSubType(wtp) } } - - /** If `formal` is of the form ClassTag[T], where `T` is a class type, - * synthesize a class tag for `T`. - */ - def synthesizedClassTag(formal: Type): Tree = { - if (formal.isRef(defn.ClassTagClass)) - formal.argTypes match { - case arg :: Nil => - val tp = fullyDefinedType(arg, "ClassTag argument", tree.pos) - tp.underlyingClassRef(refinementOK = false) match { - case tref: TypeRef => - return ref(defn.ClassTagModule) - .select(nme.apply) - .appliedToType(tp) - .appliedTo(clsOf(tref)) - .withPos(tree.pos.endPos) - case _ => - } - case _ => - } - EmptyTree - } - /** Adapt an expression of constant type to a different constant type `tpe`. */ def adaptConstant(tree: Tree, tpe: ConstantType): Tree = { def lit = Literal(tpe.value).withPos(tree.pos) -- cgit v1.2.3