Skip to content

Fix/annotated types #573

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions docs/SyntaxSummary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -248,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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/backend/jvm/GenBCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down
28 changes: 16 additions & 12 deletions src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1425,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)
Expand Down Expand Up @@ -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
}
Expand Down
13 changes: 13 additions & 0 deletions tests/pos/annot.scala
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 }

}