Open sandboxFocusImprove this doc

LAMA0292: The scope of a member doesn't match the scope of its type

Severity Error
Reported by Metalama.Framework
Message Execution scope mismatch: the member '<Member>' is <MemberScope>, but the declaring type '<DeclaringType>' is <DeclaringTypeScope>. Change the scope of the declaring type, for example with the [CompileTime] or [RunTimeOrCompileTime] attribute, or move the member to a type of a compatible scope.

Cause

Metalama assigns a scope to every declaration: run-time, compile-time, or run-time-or-compile-time. A type and its members are compiled into the same assemblies, so the scope of a member must be compatible with the scope of its type. For instance, a compile-time member can't live in a run-time type, because the run-time type doesn't exist in the compile-time assembly.

Metalama reports LAMA0292 when it finds one of the following combinations. Templates are exempt, because they're legitimately run-time members of compile-time types.

  • A compile-time member, typically a member marked with [CompileTime], in a run-time type.
  • A run-time-or-compile-time member, for instance a member marked with [RunTimeOrCompileTime], in a run-time type.
  • A run-time member in a compile-time type.
  • A method of a run-time type that isn't marked with a scope attribute but has a parameter of a compile-time-only type, like IMethod. The message then says compile-time (inferred from parameter types).

In the message, <Member> and <MemberScope> are the member and its scope, and <DeclaringType> and <DeclaringTypeScope> are the declaring type and its scope.

In the following example, the Format method of the LogFormatter helper class is marked [CompileTime], but the class itself isn't, so it's run-time.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0292.Error;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        Console.WriteLine( $"Entering {LogFormatter.Format( meta.Target.Type.Name, meta.Target.Method.Name )}." );
11
12        return meta.Proceed();
13    }
14}
15
16// This type is not marked [CompileTime], so it is run-time.
17internal static class LogFormatter
18{
19    // Error: a compile-time method cannot be declared in a run-time type.
20    [CompileTime]
    Error LAMA0292: Execution scope mismatch: the member 'LogFormatter.Format(string, string)' is compile-time, but the declaring type 'LogFormatter' is run-time. Change the scope of the declaring type, for example with the [CompileTime] or [RunTimeOrCompileTime] attribute, or move the member to a type of a compatible scope.

21    public static string Format( string typeName, string methodName ) => $"{typeName}::{methodName}";
22}
23
1namespace Doc.LAMA0292.Error;
2
3internal class Calculator
4{
5    [Log]
6    public int Add( int a, int b ) => a + b;
7}
8

Resolution

Make the scope of the type and of its members consistent:

  • When the whole type is meant to run at compile time, move the scope attribute from the member to the declaring type, as in the following example.
  • When the type must keep its current scope, move the member to another type that has the same scope as the member.
  • For a method that has compile-time parameters in a run-time type, mark the type with [CompileTime], or move the method to a compile-time type.

1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0292.Fixed;
5
6public class LogAttribute : OverrideMethodAspect
7{
8    public override dynamic? OverrideMethod()
9    {
10        Console.WriteLine( $"Entering {LogFormatter.Format( meta.Target.Type.Name, meta.Target.Method.Name )}." );
11
12        return meta.Proceed();
13    }
14}
15
16// Fixed: the [CompileTime] attribute is on the type, so the whole type is compile-time.
17[CompileTime]
18internal static class LogFormatter
19{
20    public static string Format( string typeName, string methodName ) => $"{typeName}::{methodName}";
21}
22
Source Code
1namespace Doc.LAMA0292.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.LAMA0292.Fixed;
4
5internal class Calculator
6{
7    [Log]
8    public int Add(int a, int b)
9    {
10        Console.WriteLine("Entering Calculator::Add.");
11        return a + b;
12    }
13}
14

See also