From d4c26fc6072e69d3f58685e6bfec4609eb9af13c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 21 Oct 2016 15:08:35 +0200 Subject: Roll normalizedTree into main PostTyper transform Since we now transform all type trees, no need to have a separate traversal for checking. --- src/dotty/tools/dotc/transform/PostTyper.scala | 43 +++++-------- src/dotty/tools/dotc/typer/Checking.scala | 87 +++++++++++--------------- 2 files changed, 50 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala index b72785dce..6b9fc084e 100644 --- a/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/src/dotty/tools/dotc/transform/PostTyper.scala @@ -76,13 +76,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran // TODO fill in } - /** Check bounds of AppliedTypeTrees. - */ - private def normalizeTree(tree: Tree)(implicit ctx: Context): Tree = { - if (tree.isType) Checking.typeCheck(tree) - tree - } - /** If the type of `tree` is a TermRefWithSignature with an underdefined * signature, narrow the type by re-computing the signature (which should * be fully-defined by now). @@ -171,14 +164,19 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran } override def transform(tree: Tree)(implicit ctx: Context): Tree = - try normalizeTree(tree) match { + try tree match { case tree: Ident if !tree.isType => tree.tpe match { case tpe: ThisType => This(tpe.cls).withPos(tree.pos) case _ => paramFwd.adaptRef(fixSignature(tree)) } - case tree: Select if !tree.isType => - transformSelect(paramFwd.adaptRef(fixSignature(tree)), Nil) + case tree @ Select(qual, name) => + if (name.isTypeName) { + Checking.checkRealizable(qual.tpe, qual.pos.focus) + super.transform(tree) + } + else + transformSelect(paramFwd.adaptRef(fixSignature(tree)), Nil) case tree: Super => if (ctx.owner.enclosingMethod.isInlineMethod) ctx.error(em"super not allowed in inline ${ctx.owner}", tree.pos) @@ -241,7 +239,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran tree } else { - Checking.typeChecker.traverse(tree.rhs) + //Checking.typeChecker.traverse(tree.rhs) cpy.TypeDef(tree)(rhs = TypeTree(tree.symbol.info)) } super.transform(tree1) @@ -253,25 +251,12 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran super.transform(tree) case tree @ Annotated(annotated, annot) => cpy.Annotated(tree)(transform(annotated), transformAnnot(annot)) - case AppliedTypeTree(tycon, args) => - // If `args` is a list of named arguments, return corresponding type parameters, - // otherwise return type parameters unchanged - val tparams = tycon.tpe.typeParams - def argNamed(tparam: TypeParamInfo) = args.find { - case NamedArg(name, _) => name == tparam.paramName - case _ => false - }.getOrElse(TypeTree(tparam.paramRef)) - val orderedArgs = if (hasNamedArg(args)) tparams.map(argNamed) else args - val bounds = tparams.map(_.paramBoundsAsSeenFrom(tycon.tpe)) - def instantiate(bound: Type, args: List[Type]) = - bound.LambdaAbstract(tparams).appliedTo(args) - Checking.checkBounds(orderedArgs, bounds, instantiate) - - def checkValidIfHKApply(implicit ctx: Context): Unit = - Checking.checkWildcardHKApply(tycon.tpe.appliedTo(args.map(_.tpe)), tree.pos) - checkValidIfHKApply(ctx.addMode(Mode.AllowLambdaWildcardApply)) + case tree: AppliedTypeTree => + Checking.checkAppliedType(tree) + super.transform(tree) + case SingletonTypeTree(ref) => + Checking.checkRealizable(ref.tpe, ref.pos.focus) super.transform(tree) - case tree: TypeTree => tree.withType( tree.tpe match { diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index b6c9e0047..753475d84 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -55,60 +55,45 @@ object Checking { def checkBounds(args: List[tpd.Tree], poly: PolyType)(implicit ctx: Context): Unit = checkBounds(args, poly.paramBounds, _.substParams(poly, _)) - /** If type is a higher-kinded application with wildcard arguments, - * check that it or one of its supertypes can be reduced to a normal application. - * Unreducible applications correspond to general existentials, and we - * cannot handle those. + /** Check applied type trees for well-formedness. This means + * - all arguments are within their corresponding bounds + * - if type is a higher-kinded application with wildcard arguments, + * check that it or one of its supertypes can be reduced to a normal application. + * Unreducible applications correspond to general existentials, and we + * cannot handle those. */ - def checkWildcardHKApply(tp: Type, pos: Position)(implicit ctx: Context): Unit = tp match { - case tp @ HKApply(tycon, args) if args.exists(_.isInstanceOf[TypeBounds]) => - tycon match { - case tycon: PolyType => - ctx.errorOrMigrationWarning( - ex"unreducible application of higher-kinded type $tycon to wildcard arguments", - pos) - case _ => - checkWildcardHKApply(tp.superType, pos) - } - case _ => - } - - /** Traverse type tree, performing the following checks: - * 1. All arguments of applied type trees must conform to their bounds. - * 2. Prefixes of type selections and singleton types must be realizable. - */ - val typeChecker = new TreeTraverser { - def traverse(tree: Tree)(implicit ctx: Context) = { - typeCheck(tree) - traverseChildren(tree) - } + def checkAppliedType(tree: AppliedTypeTree)(implicit ctx: Context) = { + val AppliedTypeTree(tycon, args) = tree + // If `args` is a list of named arguments, return corresponding type parameters, + // otherwise return type parameters unchanged + val tparams = tycon.tpe.typeParams + def argNamed(tparam: TypeParamInfo) = args.find { + case NamedArg(name, _) => name == tparam.paramName + case _ => false + }.getOrElse(TypeTree(tparam.paramRef)) + val orderedArgs = if (hasNamedArg(args)) tparams.map(argNamed) else args + val bounds = tparams.map(_.paramBoundsAsSeenFrom(tycon.tpe)) + def instantiate(bound: Type, args: List[Type]) = + bound.LambdaAbstract(tparams).appliedTo(args) + checkBounds(orderedArgs, bounds, instantiate) + + def checkWildcardHKApply(tp: Type, pos: Position): Unit = tp match { + case tp @ HKApply(tycon, args) if args.exists(_.isInstanceOf[TypeBounds]) => + tycon match { + case tycon: PolyType => + ctx.errorOrMigrationWarning( + ex"unreducible application of higher-kinded type $tycon to wildcard arguments", + pos) + case _ => + checkWildcardHKApply(tp.superType, pos) + } + case _ => + } + def checkValidIfHKApply(implicit ctx: Context): Unit = + checkWildcardHKApply(tycon.tpe.appliedTo(args.map(_.tpe)), tree.pos) + checkValidIfHKApply(ctx.addMode(Mode.AllowLambdaWildcardApply)) } - def typeCheck(tree: Tree)(implicit ctx: Context) = tree match { - case AppliedTypeTree(tycon, args) => - // If `args` is a list of named arguments, return corresponding type parameters, - // otherwise return type parameters unchanged - val tparams = tycon.tpe.typeParams - def argNamed(tparam: TypeParamInfo) = args.find { - case NamedArg(name, _) => name == tparam.paramName - case _ => false - }.getOrElse(TypeTree(tparam.paramRef)) - val orderedArgs = if (hasNamedArg(args)) tparams.map(argNamed) else args - val bounds = tparams.map(_.paramBoundsAsSeenFrom(tycon.tpe)) - def instantiate(bound: Type, args: List[Type]) = - bound.LambdaAbstract(tparams).appliedTo(args) - checkBounds(orderedArgs, bounds, instantiate) - - def checkValidIfHKApply(implicit ctx: Context): Unit = - checkWildcardHKApply(tycon.tpe.appliedTo(args.map(_.tpe)), tree.pos) - checkValidIfHKApply(ctx.addMode(Mode.AllowLambdaWildcardApply)) - case Select(qual, name) if name.isTypeName => - checkRealizable(qual.tpe, qual.pos.focus) - case SingletonTypeTree(ref) => - checkRealizable(ref.tpe, ref.pos.focus) - case _ => - } - /** Check that `tp` refers to a nonAbstract class * and that the instance conforms to the self type of the created class. */ -- cgit v1.2.3