mapperly icon indicating copy to clipboard operation
mapperly copied to clipboard

UseDeepCloning generate Dictionary<string?, xxx> when mapping from nullable disable class file

Open latop2604 opened this issue 1 year ago • 0 comments

  • [x] I have read the documentation, including the FAQ
  • [x] I can reproduce the bug using the latest prerelease version
  • [x] I have searched existing discussion and issue to avoid duplicates

Describe the bug The source generator does not respect generic type parameter constraint notnull on Dictionary TKey when mapping a class with #nullable disable

Instead of Dictionary<string?, xxx>, it should generate Dictionary<string, int>

Declaration code

#nullable enable
using Riok.Mapperly.Abstractions;

DataMapper.MapData(new Data());


[Mapper(UseDeepCloning = true)]
public static partial class DataMapper
{
    public static partial Data MapData(Data data);
}


#nullable disable
public class Data
{
    public int Id { get; set; }
    public Dictionary<string, int> Attributes { get; set; }
}

Actual relevant generated code

// <auto-generated />
#nullable enable
public static partial class DataMapper
{
   //...

    [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.1.1.0")]
    private static global::System.Collections.Generic.Dictionary<string?, int> MapToDictionaryOfStringAndInt32(global::System.Collections.Generic.IReadOnlyDictionary<string?, int> source)
    {
        var target = new global::System.Collections.Generic.Dictionary<string?, int>(source.Count);
        foreach (var item in source)
        {
            target[item.Key == null ? default : item.Key] = item.Value;
        }
        return target;
    }
}

Expected relevant generated code

// <auto-generated />
#nullable enable
public static partial class DataMapper
{
    // ...

    [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.1.1.0")]
    private static global::System.Collections.Generic.Dictionary<string, int> MapToDictionaryOfStringAndInt32(global::System.Collections.Generic.IReadOnlyDictionary<string, int> source)
    {
        var target = new global::System.Collections.Generic.Dictionary<string, int>(source.Count);
        foreach (var item in source)
        {
            target[item.Key == null ? default : item.Key] = item.Value;
        }
        return target;
    }
}

Reported relevant diagnostics

  • Argument of type 'Dictionary<string, int>' cannot be used for parameter 'source' of type 'IReadOnlyDictionary<string?, int>' in 'Dictionary<string?, int> DataMapper.MapToDictionaryOfStringAndInt32(IReadOnlyDictionary<string?, int> source)' due to differences in the nullability of reference types.
  • The type 'string?' cannot be used as type parameter 'TKey' in the generic type or method 'Dictionary<TKey, TValue>'. Nullability of type argument 'string?' doesn't match 'notnull' constraint.

Environment (please complete the following information):

  • Mapperly Version: 4.1.1
  • Nullable reference types: enable
  • .NET Version: .NET 8.0
  • Target Framework: net8.0
  • Compiler Version: Compiler version: '4.12.0-3.24558.5 (21192bfc)'. Language version: 12.0.
  • C# Language Version: 13
  • IDE: console
  • OS: windows 24H2

latop2604 avatar Nov 29 '24 14:11 latop2604