Open sandboxFocusImprove this doc

LAMA0117: Code that isn't compile-time references a compile-time-only declaration

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
Source Code
1namespace Doc.LAMA0117.Fixed;
2


3internal class Calculator
4{
5    [Log]
6    public int Add( int a, int b ) => a + b;
7}
8
Transformed Code
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

See also