diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index d7a4241d8a44..e6e2fe3e409a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1900,11 +1900,24 @@ trait Namers extends MethodSynthesis { annotations filterNot (_ eq null) map { ann => val ctx = typer.context // need to be lazy, #1782. enteringTyper to allow inferView in annotation args, scala/bug#5892. - AnnotationInfo lazily { - enteringTyper { - val annotSig = newTyper(ctx.makeNonSilent(ann)).typedAnnotation(ann, Some(annotee)) - if (pred(annotSig)) annotSig else UnmappableAnnotation // UnmappableAnnotation will be dropped in typedValDef and typedDefDef - } + def computeInfo: AnnotationInfo = enteringTyper { + val annotSig = newTyper(ctx.makeNonSilent(ann)).typedAnnotation(ann, Some(annotee)) + if (pred(annotSig)) annotSig else UnmappableAnnotation // UnmappableAnnotation will be dropped in typedValDef and typedDefDef + } + ann match { + case treeInfo.Applied(fun, _, _) => + def computeSymbol = enteringTyper { + val fun1 = newTyper(ctx.makeNonSilent(fun.duplicate)).typed(fun, context.defaultModeForTyped.forFunMode, WildcardType) + fun1.tpe.finalResultType.typeSymbol + } + AnnotationInfo.lazily(computeSymbol, computeInfo) + case _ => + AnnotationInfo lazily { + enteringTyper { + val annotSig = newTyper(ctx.makeNonSilent(ann)).typedAnnotation(ann, Some(annotee)) + if (pred(annotSig)) annotSig else UnmappableAnnotation // UnmappableAnnotation will be dropped in typedValDef and typedDefDef + } + } } } diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 37e54a23e519..5cc5111bf322 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -110,6 +110,9 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => def lazily(lazyInfo: => AnnotationInfo) = new LazyAnnotationInfo(lazyInfo) + def lazily(lazySymbol: => Symbol, lazyInfo: => AnnotationInfo) = + new ExtraLazyAnnotationInfo(lazySymbol, lazyInfo) + def apply(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]): AnnotationInfo = new CompleteAnnotationInfo(atp, args, assocs) @@ -154,7 +157,7 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => /** Symbol annotations parsed in `Namer` (typeCompleter of * definitions) have to be lazy (#1782) */ - final class LazyAnnotationInfo(lazyInfo: => AnnotationInfo) extends AnnotationInfo { + class LazyAnnotationInfo(lazyInfo: => AnnotationInfo) extends AnnotationInfo { private[this] var forced = false private lazy val forcedInfo = try lazyInfo finally forced = true @@ -172,6 +175,11 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => override def completeInfo(): Unit = forcedInfo } + final class ExtraLazyAnnotationInfo(sym: => Symbol, lazyInfo: => AnnotationInfo) extends LazyAnnotationInfo(lazyInfo) { + private[this] lazy val typeSymbol = sym + override def symbol: Symbol = typeSymbol + } + /** Typed information about an annotation. It can be attached to either * a symbol or an annotated type. * diff --git a/test/files/pos/unchecked-stable-cyclic-error.scala b/test/files/pos/unchecked-stable-cyclic-error.scala new file mode 100644 index 000000000000..db320c3c6d56 --- /dev/null +++ b/test/files/pos/unchecked-stable-cyclic-error.scala @@ -0,0 +1,8 @@ +import scala.annotation.StaticAnnotation + +class anno(a: Any) extends StaticAnnotation + +object Test { + def foo = attr + @anno(foo) def attr: Int = foo +}