Open sandboxFocusImprove this doc

LA0190: Aspect Target Uses a Ref Struct

Severity Error
Reported by PostSharp
Message Cannot apply the aspect "<Aspect>" to target "<Target>": the target is or uses the ref struct "<RefStruct>", which aspects do not support. Set the UnsupportedTargetAction property of the aspect to Ignore to skip such targets.

Cause

A ref struct, such as Span<T> or ReadOnlySpan<T>, can only live on the stack: it cannot be boxed, stored in a field of a class, or passed to the objects, such as MethodExecutionArgs, that the code of an aspect receives. PostSharp does not apply aspects to declarations that use a ref struct, and reports LA0190 when:

  • the target is a member of a ref struct;
  • the target is a method whose return type or a parameter type is a ref struct;
  • the target is a property or a field of a ref struct type;
  • the target is an event whose delegate has a ref struct parameter or return type.

<RefStruct> is the ref struct that PostSharp found: the declaring type, or the type of the return value, parameter or location.

Multicasting often causes this message: an aspect applied to a class reaches every method of the class, including the methods that take a span. In the following example, the [Log] aspect applied to TextParser also reaches the overload of CountWords that takes a ReadOnlySpan<T>.

using System;
using PostSharp.Aspects;
using PostSharp.Serialization;

namespace Errors.LA0190_Error;

[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"Entering {args.Method.Name}" );
    }
}

[Log]
public class TextParser
{
    public int CountWords( string text ) => this.CountWords( text.AsSpan() );

    // The aspect cannot be applied to a method that has a ref struct parameter.
    public int CountWords( ReadOnlySpan<char> text )
    {
        int count = 0;
        bool inWord = false;

        foreach ( char c in text )
        {
            if ( char.IsWhiteSpace( c ) )
            {
                inWord = false;
            }
            else if ( !inWord )
            {
                inWord = true;
                count++;
            }
        }

        return count;
    }
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine( new TextParser().CountWords( "The quick brown fox" ) );
    }
}
error LA0190: LA0190_Error.cs(22,16): Cannot apply the aspect "Errors.LA0190_Error.LogAttribute" to target "Errors.LA0190_Error.TextParser.CountWords(System.ReadOnlySpan<System.Char>)": the target is or uses the ref struct "System.ReadOnlySpan`1<char>", which aspects do not support. Set the UnsupportedTargetAction property of the aspect to Ignore to skip such targets.

Resolution

  • Set the UnsupportedTargetAction property of the aspect to Ignore, so that the aspect skips the declarations that use a ref struct without an error. You can set it where you apply the aspect, or in the constructor of the aspect class.
  • Exclude the declaration from the multicast, for example with the AttributeExclude property on a second instance of the aspect applied to the declaration.
  • Apply the aspect to a member that does not use the ref struct, such as an overload that takes a string.

In the following example, the aspect skips the overload that takes a span, and still applies to the constructor and to the other overload.

using System;
using PostSharp.Aspects;
using PostSharp.Serialization;

namespace Errors.LA0190_Fixed;

[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"Entering {args.Method.Name}" );
    }
}

// The aspect skips the members that it does not support.
[Log( UnsupportedTargetAction = UnsupportedTargetAction.Ignore )]
public class TextParser
{
    public int CountWords( string text ) => this.CountWords( text.AsSpan() );

    public int CountWords( ReadOnlySpan<char> text )
    {
        int count = 0;
        bool inWord = false;

        foreach ( char c in text )
        {
            if ( char.IsWhiteSpace( c ) )
            {
                inWord = false;
            }
            else if ( !inWord )
            {
                inWord = true;
                count++;
            }
        }

        return count;
    }
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine( new TextParser().CountWords( "The quick brown fox" ) );
    }
}
Entering .ctor
Entering CountWords
4

See Also

Reference

UnsupportedTargetAction
UnsupportedTargetAction

Other Resources

Semantic Advising of Iterator and Async Methods