From b268dc3b797b3c744f21e053a1b3748967742285 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 15 May 2015 12:09:20 +0200 Subject: [PATCH 1/3] Allow AnnotatedType in operands of `with`. Brings in line with Scala 2 spec. --- docs/SyntaxSummary.txt | 13 ++++++------ src/dotty/tools/dotc/parsing/Parsers.scala | 24 +++++++++++++--------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/docs/SyntaxSummary.txt b/docs/SyntaxSummary.txt index e40b3fd6c594..dadf15bed94d 100644 --- a/docs/SyntaxSummary.txt +++ b/docs/SyntaxSummary.txt @@ -99,8 +99,9 @@ grammar. FunArgTypes ::= InfixType | `(' [ FunArgType {`,' FunArgType } ] `)' InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2) - RefinedType ::= WithType {Annotation | [nl] Refinement} Annotated(t, annot), RefinedTypeTree(t, ds) - WithType ::= SimpleType {`with' SimpleType} (deprecated) + RefinedType ::= WithType {[nl] Refinement} RefinedTypeTree(t, ds) + WithType ::= AnnotType {`with' AnnotType} (deprecated) + AnnotType ::= SimpleType {Annotation} Annotated(t, annot) SimpleType ::= SimpleType TypeArgs AppliedTypeTree(t, args) | SimpleType `#' id SelectFromTypeTree(t, name) | StableId @@ -121,9 +122,9 @@ grammar. Expr ::= FunParams `=>' Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr) | Expr1 - FunParams ::= Bindings - | [`implicit'] id - | `_' + FunParams ::= Bindings + | [`implicit'] id + | `_' ExprInParens ::= PostfixExpr `:' Type | Expr BlockResult ::= (FunParams | [`implicit'] id `:' InfixType) => Block @@ -301,7 +302,7 @@ grammar. TemplateOpt ::= [`extends' Template | [nl] TemplateBody] Template ::= ConstrApps [TemplateBody] | TemplateBody Template(constr, parents, self, stats) ConstrApps ::= ConstrApp {`with' ConstrApp} - ConstrApp ::= SimpleType {ArgumentExprs} Apply(tp, args) + ConstrApp ::= AnnotType {ArgumentExprs} Apply(tp, args) ConstrExpr ::= SelfInvocation | ConstrBlock diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index dd2c9bcaa43b..dbf57c22e4bc 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -679,25 +679,29 @@ object Parsers { def refinedTypeRest(t: Tree): Tree = { newLineOptWhenFollowedBy(LBRACE) - in.token match { - case AT => refinedTypeRest(atPos(t.pos.start) { Annotated(annot(), t) }) - case LBRACE => refinedTypeRest(atPos(t.pos.start) { RefinedTypeTree(t, refinement()) }) - case _ => t - } + if (in.token == LBRACE) refinedTypeRest(atPos(t.pos.start) { RefinedTypeTree(t, refinement()) }) + else t } - /** WithType ::= SimpleType {`with' SimpleType} (deprecated) + /** WithType ::= AnnotType {`with' AnnotType} (deprecated) */ - def withType(): Tree = withTypeRest(simpleType()) + def withType(): Tree = withTypeRest(annotType()) - def withTypeRest(t: Tree): Tree = { + def withTypeRest(t: Tree): Tree = if (in.token == WITH) { deprecationWarning("`with' as a type operator has been deprecated; use `&' instead") in.nextToken() AndTypeTree(t, withType()) } else t - } + + /** AnnotType ::= SimpleType {Annotation} + */ + def annotType(): Tree = annotTypeRest(simpleType()) + + def annotTypeRest(t: Tree): Tree = + if (in.token == AT) annotTypeRest(atPos(t.pos.start) { Annotated(annot(), t) }) + else t /** SimpleType ::= SimpleType TypeArgs * | SimpleType `#' Id @@ -1834,7 +1838,7 @@ object Parsers { /** ConstrApp ::= SimpleType {ParArgumentExprs} */ val constrApp = () => { - val t = simpleType() + val t = annotType() if (in.token == LPAREN) parArgumentExprss(wrapNew(t)) else t } From 2085d316032bda70cc9300458b9c6ce22ad343fb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 15 May 2015 12:17:29 +0200 Subject: [PATCH 2/3] Disallow {...} arguments for annotations This mimics scalac's behavior (but not the official syntax; in fact the official syntax seems to be ambiguous. --- docs/SyntaxSummary.txt | 2 +- src/dotty/tools/dotc/parsing/Parsers.scala | 4 ++-- tests/pos/annot.scala | 13 +++++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/SyntaxSummary.txt b/docs/SyntaxSummary.txt index dadf15bed94d..1bbdc84d7635 100644 --- a/docs/SyntaxSummary.txt +++ b/docs/SyntaxSummary.txt @@ -249,7 +249,7 @@ grammar. AccessModifier ::= (`private' | `protected') [AccessQualifier] AccessQualifier ::= `[' (id | `this') `]' - Annotation ::= `@' SimpleType {ArgumentExprs} Apply(tpe, args) + Annotation ::= `@' SimpleType {ParArgumentExprs} Apply(tpe, args) TemplateBody ::= [nl] `{' [SelfType] TemplateStat {semi TemplateStat} `} (self, stats) TemplateStat ::= Import diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index dbf57c22e4bc..b790772455a6 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1429,10 +1429,10 @@ object Parsers { else tree1 } - /** Annotation ::= `@' SimpleType {ArgumentExprs} + /** Annotation ::= `@' SimpleType {ParArgumentExprs} */ def annot() = - adjustStart(accept(AT)) { ensureApplied(argumentExprss(wrapNew(simpleType()))) } + adjustStart(accept(AT)) { ensureApplied(parArgumentExprss(wrapNew(simpleType()))) } def annotations(skipNewLines: Boolean = false): List[Tree] = { if (skipNewLines) newLineOptWhenFollowedBy(AT) diff --git a/tests/pos/annot.scala b/tests/pos/annot.scala index c3a17ff1dc6f..106057258b7f 100644 --- a/tests/pos/annot.scala +++ b/tests/pos/annot.scala @@ -1,7 +1,10 @@ import java.beans.Transient +import annotation.unchecked.uncheckedVariance class Test { +// testing combinations of annotation syntax + @SuppressWarnings(Array("hi")) def foo() = ??? // evalutation of annotation on type cannot be deferred as requires implicit resolution(only generic Array$.apply applies here) @SuppressWarnings(Array("hi", "foo")) def foo2() = ??? //can be deferred as there is a non-generic method @@ -11,5 +14,15 @@ class Test { @Transient(false) def bar = ??? @Transient() def baz = ??? + +// testing annotations in types + + class A + trait B + + val x: A @uncheckedVariance with B @uncheckedVariance = ??? + + //class C extends A @uncheckedVariance () with B @uncheckedVariance { val x = 10 } + } From bd05533b42a5f123747b1ce500f1fba2b1516757 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 15 May 2015 13:56:12 +0200 Subject: [PATCH 3/3] Make normalizeToRef survive annotated types Did not handle this case before. --- src/dotty/tools/backend/jvm/GenBCode.scala | 2 +- src/dotty/tools/dotc/core/TypeOps.scala | 9 +++++---- tests/pos/annot.scala | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/dotty/tools/backend/jvm/GenBCode.scala b/src/dotty/tools/backend/jvm/GenBCode.scala index d7557acecb10..eabf1b660ec9 100644 --- a/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/src/dotty/tools/backend/jvm/GenBCode.scala @@ -38,7 +38,7 @@ class GenBCode extends Phase { def run(implicit ctx: Context): Unit = { - new GenBCodePipeline(entryPoints.toList, new DottyBackendInterface()(ctx))(ctx).run(ctx.compilationUnit.tpdTree) + new GenBCodePipeline(entryPoints.toList, new DottyBackendInterface()(ctx))(ctx).run(ctx.compilationUnit.tpdTree) entryPoints.clear() } } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 1adabbd2d54e..acbd5b6f0b19 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -302,18 +302,19 @@ trait TypeOps { this: Context => // TODO: Make standalone object. // println(s"normalizing $parents of $cls in ${cls.owner}") // !!! DEBUG var refinements: SimpleMap[TypeName, Type] = SimpleMap.Empty var formals: SimpleMap[TypeName, Symbol] = SimpleMap.Empty - def normalizeToRef(tp: Type): TypeRef = tp match { + def normalizeToRef(tp: Type): TypeRef = tp.dealias match { + case tp: TypeRef => + tp case tp @ RefinedType(tp1, name: TypeName) => val prevInfo = refinements(name) refinements = refinements.updated(name, if (prevInfo == null) tp.refinedInfo else prevInfo & tp.refinedInfo) formals = formals.updated(name, tp1.typeParamNamed(name)) normalizeToRef(tp1) - case tp: TypeRef => - if (tp.symbol.info.isAlias) normalizeToRef(tp.info.bounds.hi) - else tp case ErrorType => defn.AnyClass.typeRef + case AnnotatedType(_, tpe) => + normalizeToRef(tpe) case _ => throw new TypeError(s"unexpected parent type: $tp") } diff --git a/tests/pos/annot.scala b/tests/pos/annot.scala index 106057258b7f..e6e4f8051ba9 100644 --- a/tests/pos/annot.scala +++ b/tests/pos/annot.scala @@ -22,7 +22,7 @@ class Test { val x: A @uncheckedVariance with B @uncheckedVariance = ??? - //class C extends A @uncheckedVariance () with B @uncheckedVariance { val x = 10 } + class C extends A @uncheckedVariance () with B @uncheckedVariance { val x = 10 } }