Maps of wildcard type propagate values incorrectly

Wildcard maps do not propagate their key/value types properly when assigned a map type. I was attempting to make a “Create map from Arrays” macro, as an example. If you assign a map variable to a wildcard map pin, in a macro like below, then it changes the “Value” pin to the type of the key, instead of the type of value, as shown below:

222685-arraystomap02.png

On a related note - it would be nice to have “Local Map of Wildcards” and “Local Set of Wildcards/ints” etc (like there are for arrays), that would make macros like this tidier to use (wouldn’t have to pass a map variable in by reference for modifying, can just output the created map). That said, I wouldn’t want to be the one coding anything to do with wildcards… seems like a nightmare of edge cases.

1 Like

Hello,

Thank you for submitting a bug report. I have reproduced this issue and logged a report for it here

You can track the report’s status as the issue is reviewed by our development staff. Please be aware that this issue may not be prioritized or fixed soon.

Thanks!

Bug not fixed in 4.22

1 Like

Any new issues on this topic or reasons, why this is backlogged? Still stumbling over the same limitation in 4.23 while trying to create simple map iteration macros…

1 Like

Giving a little bump here :^)

This actually has relevancy. If you’re working with maps a lot, you can avoid a LOT of duplicate logic with simple wildcard macros. Unfortunately, the type is incorrect.

3 Likes

Bug not fixed in 5.2

1 Like

still not fixed. Idk why marking it as won’t fix, thus I cannot event write my for each with map

1 Like

Is there any info on why this issue is marked as “Won’t fix”? I have this issue in C++ as well, trying to achieve the same as @Spoondog .

CollectionUtils.h

/** 
	 * Zips together two input arrays to create a map. Works similar to pythons "Zip" function, but:
	 * - Only indices existing in both arrays are inputted into the map.
	 * - Equal entries of `Keys` result in one map entry with the last value being present in the map
	 *
	 * @param	Keys			The input array to create keys from
	 * @param	Values			The input array to create values from
	 * @param	TargetMap		The map to fill from the two arrays
	 */
	UFUNCTION(BlueprintCallable, CustomThunk, meta=(DisplayName = "Zip", CompactNodeTitle = "ZIP", MapParam = "TargetMap", MapKeyParam = "Keys", MapValueParam = "Values", AutoCreateRefTerm = "Keys,Values"), Category = "Collection Utils")
	static void ZipToMap(const TArray<int32>& Keys, const TArray<int32>& Values, TMap<int32, int32>& TargetMap);
	
	DECLARE_FUNCTION(execZipToMap)
	{
		// `Keys` Array
		Stack.MostRecentProperty = nullptr;
		Stack.StepCompiledIn<FArrayProperty>(NULL);
		void* KeysAddr = Stack.MostRecentPropertyAddress;
		FArrayProperty* KeysProperty = CastField<FArrayProperty>(Stack.MostRecentProperty);
		if (!KeysProperty)
		{
			Stack.bArrayContextFailed = true;
			return;
		}

		// `Values` Array
		Stack.MostRecentProperty = nullptr;
		Stack.StepCompiledIn<FArrayProperty>(NULL);
		void* ValuesAddr = Stack.MostRecentPropertyAddress;
		FArrayProperty* ValuesProperty = CastField<FArrayProperty>(Stack.MostRecentProperty);
		if (!ValuesProperty)
		{
			Stack.bArrayContextFailed = true;
			return;
		}

		// `TargetMap` Map
		Stack.MostRecentProperty = nullptr;
		Stack.StepCompiledIn<FMapProperty>(NULL);
		void* TargetMapAddr = Stack.MostRecentPropertyAddress;
		FMapProperty* TargetMapProperty = CastField<FMapProperty>(Stack.MostRecentProperty);
		if (!TargetMapProperty)
		{
			Stack.bArrayContextFailed = true;
			return;
		}
		
		P_FINISH;
		P_NATIVE_BEGIN;
		GenericZipToMap(KeysAddr, KeysProperty, ValuesAddr, ValuesProperty, TargetMapAddr, TargetMapProperty);
		P_NATIVE_END

	}

	static void GenericZipToMap(
		const void* KeysAddr, const FArrayProperty* KeysProperty, 
		const void* ValuesAddr, const FArrayProperty* ValuesProperty, 
		const void* TargetMapAddr, const FMapProperty* TargetMapProperty);

CollectionUtils.cpp

void UCollectionUtils::GenericZipToMap(
	const void* KeysAddr, const FArrayProperty* KeysProperty, 
	const void* ValuesAddr, const FArrayProperty* ValuesProperty, 
	const void* TargetMapAddr, const FMapProperty* TargetMapProperty)
{
	if(KeysAddr && ValuesAddr && TargetMapAddr && 
		ensure(TargetMapProperty->KeyProp->GetID() == KeysProperty->Inner->GetID()) && 
		ensure(TargetMapProperty->ValueProp->GetID() == ValuesProperty->Inner->GetID()))
	{
		FScriptMapHelper TargetMapHelper(TargetMapProperty, TargetMapAddr);
		FScriptArrayHelper KeysArrayHelper(KeysProperty, KeysAddr);
		FScriptArrayHelper ValuesArrayHelper(ValuesProperty, ValuesAddr);
		KeysArrayHelper.EmptyValues();
		ValuesArrayHelper.EmptyValues();

		FProperty* KeysInnerProp = KeysProperty->Inner;
		FProperty* ValuesInnerProp = ValuesProperty->Inner;

		int32 Size = KeysArrayHelper.Num();
		for( int32 I = 0; Size; ++I )
		{
			if(KeysArrayHelper.IsValidIndex(I) && ValuesArrayHelper.IsValidIndex(I))
			{
				uint8* KeyElementPtr = KeysArrayHelper.GetRawPtr(I);
				uint8* ValueElementPtr = KeysArrayHelper.GetRawPtr(I);
				TargetMapHelper.AddPair(KeyElementPtr, ValueElementPtr);
			}
		}
	}
}

When using the function in Blueprint, I even get the correct color coding (more than @Spoondog showed in screenshots) and I can connect the arrays. But on compilation, I get errors that suggest that the value array is not interpreted correctly:

And here i was thinking it was my code’s fault and I wasn’t understanding what i was attempting to implement.

Instead it’s a 7 YEAR OLD defect in the engine…

Is OP able to update the ticket to include versions 5.3 & 5.4? it may trigger them to re-evaluate the wont-fix stance as it affects more than the V4.x variants of the engine.