| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The expression '<Expression>' is <ActualScope>, but it is expected to be <ExpectedScope> because the expression appears in <Context>. |
Cause
In a T# template, every expression is either compile-time, evaluated while Metalama compiles the target project, or run-time, emitted into the target code and evaluated when the program runs. Metalama infers the scope of each expression and reports LAMA0104 when an expression appears in a context that requires the other scope. The last part of the message describes this context.
The most common case is a run-time expression used where only a compile-time value makes sense, for instance as the index of a compile-time collection like meta.Target.Parameters. In the following example, the local variable index is initialized with a literal, so Metalama treats it as a run-time variable.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0104.Error;
5
6public class LogFirstParameterAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // Error: 'index' is a run-time variable, but it is used to index a compile-time collection.
11 var index = 0;
Error LAMA0104: The expression 'index' is run-time, but it is expected to be compile-time because the expression appears in element of the compile-time collection 'meta.Target.Parameters'.
12 Console.WriteLine( $"First parameter: {meta.Target.Parameters[index].Name}" );
13
14 return meta.Proceed();
15 }
16}
17
1namespace Doc.LAMA0104.Error;
2
3internal class Calculator
4{
5 [LogFirstParameter]
6 public int Add( int a, int b ) => a + b;
7}
8
Resolution
Make both sides of the expression agree on the scope:
- To make a local variable compile-time, initialize it with meta.CompileTime(...), as in the following example, or with an expression that's already compile-time.
- To use a compile-time value in run-time code, convert it with meta.RunTime(...).
- If you need run-time data, such as the value of a parameter, use the run-time members of the code model, like IParameter.Value, instead of indexing a compile-time collection at run time.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0104.Fixed;
5
6public class LogFirstParameterAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 // Fixed: meta.CompileTime makes 'index' a compile-time variable.
11 var index = meta.CompileTime( 0 );
12 Console.WriteLine( $"First parameter: {meta.Target.Parameters[index].Name}" );
13
14 return meta.Proceed();
15 }
16}
17
1namespace Doc.LAMA0104.Fixed;
2
3internal class Calculator
4{
5 [LogFirstParameter]
6 public int Add( int a, int b ) => a + b;
7}
8
1using System;
2
3namespace Doc.LAMA0104.Fixed;
4
5internal class Calculator
6{
7 [LogFirstParameter]
8 public int Add(int a, int b)
9 {
10 Console.WriteLine("First parameter: a");
11 return a + b;
12 }
13}
14