Skip to content

AOT Release shared library does not respect override methods #73076

@rodrigovaras

Description

@rodrigovaras

Description

It seems that our AOT generated shared library was crashing on a class that we run perfectly fine on Debug configuration. We have some custom dictionaries that allows to create a default value when the key was not found but on release mode it was throwing key not found since it was not respecting the class instance override method

Reproduction Steps

public class OrderedDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>
{
TValue IDictionary<TKey, TValue>.this[TKey key]
{
get
{
Console.WriteLine("OrderedDictionary -> []");

        return GetValue(key);
    }
    set
    {
        if (!ContainsKey(key))
        {
            _keys.Add(key);
        }

        base[key] = value;
    }
}
protected virtual TValue GetValue(TKey key)
{
    Console.WriteLine("OrderedDictionary -> GetValue");
    return base[key];
}

}

public class OrderedDictionaryWithDefault<TKey, TValue> : OrderedDictionary<TKey, TValue>
where TValue : new()
{
public OrderedDictionaryWithDefault()
{
Console.WriteLine("ctor -> OrderedDictionaryWithDefault");
}

protected override TValue GetValue(TKey key)
{
    Console.WriteLine("OrderedDictionaryWithDefault -> GetValue");

    if (!ContainsKey(key))
    {
        _keys.Add(key);
        base[key] = new TValue();
    }
    return base.GetValue(key);
}

}

We also have this:
public interface IDictionaryFactory
{
IDictionary<TKey, TValue> Create<TKey, TValue>() where TValue : new();
}

public class OrdereDictionaryFactory : IDictionaryFactory
{
public static OrdereDictionaryFactory Instance { get; } = new OrdereDictionaryFactory();

public IDictionary<TKey, TValue> Create<TKey, TValue>()
    where TValue : new()
{
    return new OrderedDictionaryWithDefault<TKey, TValue>();
}

}

On some other class type we have this:
public KeyframeNeighborhoodData(IDictionaryFactory dictionaryFactory)
{
this.keyframes = dictionaryFactory.Create<Guid, Keyframe>();
this.knAnchors = dictionaryFactory.Create<Guid, CompleteAnchor>();
}

Our test is very simple:
var kfnData = new KeyframeNeighborhoodData(OrdereDictionaryFactory.Instance);
kfnData.keyframes[id].hasAbsoluteLayoutInfo = true;
Console.WriteLine($"works...");

Expected behavior

The simple test code pass and the override method should be invoked from the class instance instead of the base class

Actual behavior

ctor -> OrderedDictionaryWithDefault
ctor -> OrderedDictionaryWithDefault
OrderedDictionary -> []
OrderedDictionary -> GetValue
Unhandled Exception: System.Collections.Generic.KeyNotFoundException: The given key 'ef188a25-461a-471e-913f-89b01274e231' was not present in the dictionary.
at System.ThrowHelper.ThrowKeyNotFoundExceptionT + 0x2b
at System.Collections.Generic.Dictionary2.get_Item(TKey) + 0x3a at MixedReality.EU.Common.OrderedDictionary2.System.Collections.Generic.IDictionary<TKey,TValue>.get_Item(TKey) + 0x41
at MixedReality.EU.Api.AOT!+0x40a2f4

Regression?

No response

Known Workarounds

Adding an additional constructor:
public KeyframeNeighborhoodData(IDictionary<Guid, Keyframe> keyframes, IDictionary<Guid, CompleteAnchor> knAnchors)
{
this.keyframes = keyframes;
this.knAnchors = knAnchors;
}

and using this:
var kfnData = new KeyframeNeighborhoodData(
OrdereDictionaryFactory.Instance.Create<Guid, KeyframeNeighborhoodData.Keyframe>(),
OrdereDictionaryFactory.Instance.Create<Guid, CompleteAnchor>()
);

Fixed the problem.

Configuration

The IL tools used is this ->7.0.0-RC.1.22363.4

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions