Annotations are applied to definitions, declarations, types, or expressions.

Declaration annotations 

Annotations are applied to declarations using withAnnots(annot, ...). This takes vararg of AnnotationInfo, which is created using ANNOT(typ|"C", arg, ...).

    withAnnots(ANNOT(SerializableAttr)) := BLOCK(
  DEF("get", IntClass) := LIT(0)

This prints as:

@serializable class C {
  def get: Int = 0

Type annotations 

Type annotations are written by calling withAnnots(annot, ...) on TYPEVAR(...).

val annot = ANNOT(SpecializedClass, REF(IntClass))

    withTypeParams(TYPEVAR("T") withAnnots(annot)) := BLOCK(
  DEF("apply", "T")

This prints as:

trait Function0[@specialized(Int) T] {
  def apply: T

Annotated expressions 

Annotated expressions are written as tree withAnnots(annot, ...):

REF("e") withAnnots(ANNOT(UncheckedClass))

This prints as:

(e: @unchecked)