| Severity | Error |
| Reported by | Metalama.Framework |
| Message | Cannot reference '<ReferencedSymbol>' in '<DeclaringSymbol>' because '<ReferencedSymbol>' is compile-time-only but '<DeclaringSymbol>' is <DeclaringScope>. Consider adding [CompileTime] to '<DeclaringSymbol>', or do not use '<ReferencedSymbol>' in '<DeclaringSymbol>'. |
Cause
Metalama assigns a scope to every declaration. Compile-time-only declarations, like the code model (IMethod, IDeclaration), meta, and types marked with [CompileTime], exist only while Metalama compiles your project. Run-time declarations are part of the compiled program. Members of aspect classes that are neither templates nor marked with [CompileTime] are run-time-or-compile-time: they're compiled into both the compile-time assembly and the run-time assembly.
Code that runs at run time can't use compile-time-only declarations, because they don't exist at run time. Metalama reports LAMA0117 when a declaration whose scope is run-time or run-time-or-compile-time references a compile-time-only declaration outside of a template, typeof, or nameof. In the message, <DeclaringSymbol> is the declaration containing the reference, <ReferencedSymbol> is the compile-time-only declaration, and <DeclaringScope> is the scope of <DeclaringSymbol>.
In the following example, the helper method IsMethod of the Log aspect isn't marked [CompileTime], so it's run-time-or-compile-time, but it uses the compile-time-only interface IMethod.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0117.Error;
6
7public class LogAttribute : OverrideMethodAspect
8{
9 public override dynamic? OverrideMethod()
10 {
11 Console.WriteLine( $"Executing {meta.Target.Method}." );
12
13 return meta.Proceed();
14 }
15
16 // This helper is neither a template nor marked [CompileTime], so it is run-time-or-compile-time.
17 public static bool IsMethod( object declaration )
18 {
19 // Error: IMethod is compile-time-only.
Error LAMA0117: Cannot reference 'IMethod' in 'LogAttribute.IsMethod(object)' because 'IMethod' is compile-time-only but 'LogAttribute.IsMethod(object)' is run-time-or-compile-time. Consider adding [CompileTime] to 'LogAttribute.IsMethod(object)', or do not use 'IMethod' in 'LogAttribute.IsMethod(object)'.
20 return declaration is IMethod;
21 }
22}
23
1namespace Doc.LAMA0117.Error;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
Resolution
Depending on your intent, do one of the following:
- If the code is meant to run at compile time, add [CompileTime] to the declaration or to its containing type. The following example adds
[CompileTime]to the helper method. - If the code is meant to run at run time, remove the reference to the compile-time-only declaration. To generate run-time code from compile-time information, use a template instead.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0117.Fixed;
6
7public class LogAttribute : OverrideMethodAspect
8{
9 public override dynamic? OverrideMethod()
10 {
11 Console.WriteLine( $"Executing {meta.Target.Method}." );
12
13 return meta.Proceed();
14 }
15
16 // Fixed: the helper is marked [CompileTime], so it can use compile-time-only types.
17 [CompileTime]
18 public static bool IsMethod( object declaration )
19 {
20 return declaration is IMethod;
21 }
22}
23
1namespace Doc.LAMA0117.Fixed;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
1using System;
2
3namespace Doc.LAMA0117.Fixed;
4
5internal class Calculator
6{
7 [Log]
8 public int Add(int a, int b)
9 {
10 Console.WriteLine("Executing Calculator.Add(int, int).");
11 return a + b;
12 }
13}
14