Open sandboxFocusImprove this doc

LAMA0104: The expression has the wrong scope

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


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

See also