postsharp / Metalama

Metalama is a Roslyn-based meta-programming framework. Use this repo to report bugs or ask questions.
181 stars 6 forks source link

Modifying accessor on struct causes unexpected exception #29

Closed eddycurrently closed 2 years ago

eddycurrently commented 2 years ago

I was trying out Metalama today and encountered an issue trying add some code to extend the setter on a property in struct. A minimal example to reproduce the problem is below:

using Metalama.Framework.Aspects;
using Metalama.Framework.Code;

var trackedInstance = new TrackedClass();

trackedInstance.i = 4;

public class TrackedObjectAttribute : TypeAspect
{
    public override void BuildAspect( IAspectBuilder<INamedType> builder )
    {
        foreach (var fieldOrProperty in builder.Target.FieldsAndProperties)
        {
            builder.Advice.OverrideAccessors(fieldOrProperty, null, nameof(this.OverrideSetter));
        }
    }

    [Template]
    private dynamic OverrideSetter( dynamic value )
    {
        meta.Proceed();
        return value;
    }
}

[TrackedObject]
public struct TrackedClass
{
    public int i { get; set; }
}

Trying to build this in the latest version(0.5.32-preview) on .NET6.0 gives the following error: error LAMA0001: Unexpected exception occurred in Metalama: AssertionFailedException while processing the StructDeclaration with code `[TrackedObject]`

I tried some older versions and 0.5.26-preview and older seemed to work, but anything newer did not. I did also get an error log from 0.5.27-preview on the same code, and (while I am not sure it's related or helpful) I have copied the log below:

Metalama Version: 0.5.27-preview
Runtime: .NET Framework 4.8.4510.0
Processor Architecture: X64
OS Description: Microsoft Windows 10.0.22000 
OS Architecture: X64
Exception type: System.AggregateException
Exception message: One or more errors occurred.
-------
System.AggregateException: One or more errors occurred. ---> Metalama.Framework.Engine.AssertionFailedException: Exception of type 'Metalama.Framework.Engine.AssertionFailedException' was thrown.
   at Obfuscated.^RB4kYY0pN6FB.^CpidEr45.^n8ZCMKr_[??0](??0 _0, Func`3 _1)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 36
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 168
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SyntaxList`1 list) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 145
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitCompilationUnit(CompilationUnitSyntax node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\CSharpSyntaxGenerator\CSharpSyntaxGenerator.SourceGenerator\Syntax.xml.Main.Generated.cs:line 1882
   at Obfuscated.^RB4kYY0pN6FB.^CpidEr45.VisitCompilationUnit(CompilationUnitSyntax _0)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 36
   at Obfuscated.^RB4kYY0pN6FB.^46Z9(^_XL_Cszqd2Vh _0)
   at Obfuscated.^XvFgQf6vvYK8.^28tIpU9F()
   at Obfuscated.^gzIzh9UP0pDC.^4Vg2G3mY(AspectPipelineConfiguration _0, AspectPipelineResult _1, ^mCAaZZ8k632t _2, CancellationToken _3)
   at Obfuscated.^mjGX9Ib2unuR.^_w6byyh5(AspectPipelineConfiguration _0, AspectPipelineResult _1, IDiagnosticAdder _2, CancellationToken _3, AspectPipelineResult& _4)
   at Metalama.Framework.Engine.Pipeline.AspectPipeline.^_w6byyh5(PartialCompilation _0, CompilationModel _1, IDiagnosticAdder _2, AspectPipelineConfiguration _3, CancellationToken _4, AspectPipelineResult& _5)
   at Metalama.Framework.Engine.Pipeline.CompileTime.CompileTimeAspectPipeline.^UcvoxiWP.^0NTn5_wx()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Metalama.Framework.Engine.Pipeline.CompileTime.CompileTimeAspectPipeline.^4m1nNkaa.^0NTn5_wx()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Metalama.Framework.Engine.Pipeline.SourceTransformer.Execute(TransformerContext context)
---> (Inner Exception #0) Metalama.Framework.Engine.AssertionFailedException: Exception of type 'Metalama.Framework.Engine.AssertionFailedException' was thrown.
   at Obfuscated.^RB4kYY0pN6FB.^CpidEr45.^n8ZCMKr_[??0](??0 _0, Func`3 _1)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 36
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 168
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SyntaxList`1 list) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 145
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitCompilationUnit(CompilationUnitSyntax node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\CSharpSyntaxGenerator\CSharpSyntaxGenerator.SourceGenerator\Syntax.xml.Main.Generated.cs:line 1882
   at Obfuscated.^RB4kYY0pN6FB.^CpidEr45.VisitCompilationUnit(CompilationUnitSyntax _0)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 36
   at Obfuscated.^RB4kYY0pN6FB.^46Z9(^_XL_Cszqd2Vh _0)
   at Obfuscated.^XvFgQf6vvYK8.^28tIpU9F()
   at Obfuscated.^gzIzh9UP0pDC.^4Vg2G3mY(AspectPipelineConfiguration _0, AspectPipelineResult _1, ^mCAaZZ8k632t _2, CancellationToken _3)
   at Obfuscated.^mjGX9Ib2unuR.^_w6byyh5(AspectPipelineConfiguration _0, AspectPipelineResult _1, IDiagnosticAdder _2, CancellationToken _3, AspectPipelineResult& _4)
   at Metalama.Framework.Engine.Pipeline.AspectPipeline.^_w6byyh5(PartialCompilation _0, CompilationModel _1, IDiagnosticAdder _2, AspectPipelineConfiguration _3, CancellationToken _4, AspectPipelineResult& _5)
   at Metalama.Framework.Engine.Pipeline.CompileTime.CompileTimeAspectPipeline.^UcvoxiWP.^0NTn5_wx()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Metalama.Framework.Engine.Pipeline.CompileTime.CompileTimeAspectPipeline.^4m1nNkaa.^0NTn5_wx()<---
gfraiteur commented 2 years ago

Could you please update the Metalama package to the latest version? We've improved error reporting and it should report information about the offending code.

eddycurrently commented 2 years ago

Ah, managed to find the log, the latest version didn't point me to the location like previous version as far as I could tell.

Metalama Version: 0.5.32-preview
Runtime: .NET Framework 4.8.4510.0
Processor Architecture: X64
OS Description: Microsoft Windows 10.0.22000 
OS Architecture: X64
Exception type: Metalama.Framework.Engine.Utilities.Roslyn.SyntaxProcessingException
Exception message: AssertionFailedException while processing the StructDeclaration with code `[TrackedObject]
public struct Tracke...` at 'CompilationUnit/StructDeclaration[TrackedClass]' in 'C:\Users\removed.username\source\repos\DefaultImplementationExperiments\DefaultImplementationExperiments\Program.cs' (26,1-30,2): Exception of type 'Metalama.Framework.Engine.AssertionFailedException' was thrown.
===== Exception ===== 
Metalama.Framework.Engine.Utilities.Roslyn.SyntaxProcessingException: AssertionFailedException while processing the StructDeclaration with code `[TrackedObject]
public struct Tracke...` at 'CompilationUnit/StructDeclaration[TrackedClass]' in 'C:\Users\removed.username\source\repos\DefaultImplementationExperiments\DefaultImplementationExperiments\Program.cs' (26,1-30,2): Exception of type 'Metalama.Framework.Engine.AssertionFailedException' was thrown. ---> Metalama.Framework.Engine.AssertionFailedException: Exception of type 'Metalama.Framework.Engine.AssertionFailedException' was thrown.
   at Obfuscated.^RB4kYY0pN6FB.^CpidEr45.^n8ZCMKr_[??0](??0 _0, Func`3 _1)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 36
   at Metalama.Framework.Engine.Utilities.Roslyn.SafeSyntaxRewriter.Visit(SyntaxNode node)
   --- End of inner exception stack trace ---
   at Metalama.Framework.Engine.Utilities.Roslyn.SafeSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 168
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SyntaxList`1 list) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 145
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitCompilationUnit(CompilationUnitSyntax node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\CSharpSyntaxGenerator\CSharpSyntaxGenerator.SourceGenerator\Syntax.xml.Main.Generated.cs:line 1882
   at Obfuscated.^RB4kYY0pN6FB.^CpidEr45.VisitCompilationUnit(CompilationUnitSyntax _0)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node) in C:\buildAgent\work\4fbb2b97781db749\src\Compilers\CSharp\Portable\Syntax\CSharpSyntaxRewriter.cs:line 36
   at Metalama.Framework.Engine.Utilities.Roslyn.SafeSyntaxRewriter.Visit(SyntaxNode node)
   at Obfuscated.^RB4kYY0pN6FB.^46Z9(^_XL_Cszqd2Vh _0)
   at Obfuscated.^XvFgQf6vvYK8.^28tIpU9F()
   at Obfuscated.^gzIzh9UP0pDC.^4Vg2G3mY(AspectPipelineConfiguration _0, AspectPipelineResult _1, ^mCAaZZ8k632t _2, CancellationToken _3)
   at Obfuscated.^mjGX9Ib2unuR.^_w6byyh5(AspectPipelineConfiguration _0, AspectPipelineResult _1, IDiagnosticAdder _2, CancellationToken _3, AspectPipelineResult& _4)
   at Metalama.Framework.Engine.Pipeline.AspectPipeline.^_w6byyh5(PartialCompilation _0, CompilationModel _1, IDiagnosticAdder _2, AspectPipelineConfiguration _3, CancellationToken _4, AspectPipelineResult& _5)
   at Metalama.Framework.Engine.Pipeline.CompileTime.CompileTimeAspectPipeline.^UcvoxiWP.^0NTn5_wx()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Metalama.Framework.Engine.Pipeline.CompileTime.CompileTimeAspectPipeline.^4m1nNkaa.^0NTn5_wx()
===== Syntax Tree ===== 
using Metalama.Framework.Aspects;
using Metalama.Framework.Code;

var trackedInstance = new TrackedClass();

trackedInstance.i = 4;

public class TrackedObjectAttribute : TypeAspect
{
    public override void BuildAspect( IAspectBuilder<INamedType> builder )
    {
        foreach (var fieldOrProperty in builder.Target.FieldsAndProperties)
        {
            builder.Advice.OverrideAccessors(fieldOrProperty, null, nameof(this.OverrideSetter));
        }
    }

    [Template]
    private dynamic OverrideSetter( dynamic value )
    {
        meta.Proceed();
        return value;
    }
}

[TrackedObject]
public struct TrackedClass
{
    public int i { get; set; }
}
gfraiteur commented 2 years ago

Thank you. Transferring to @addabis because he's responsible for this component.

addabis commented 2 years ago

Thanks again for reporting this, we are in process of fixing this bug.

addabis commented 2 years ago

Hello @eddycurrently, we have recently fixed this bug in our newest released version of Metalama 0.5.36-preview.