| 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
1namespace Doc.LAMA0292.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.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