diff --git a/Assets/UdonSharp/Editor/UdonSharpExpressionCapture.cs b/Assets/UdonSharp/Editor/UdonSharpExpressionCapture.cs index 724cbe84..43857f94 100644 --- a/Assets/UdonSharp/Editor/UdonSharpExpressionCapture.cs +++ b/Assets/UdonSharp/Editor/UdonSharpExpressionCapture.cs @@ -1460,19 +1460,30 @@ private SymbolDefinition HandleGenericUSharpGetComponent(MethodInfo targetMethod private SymbolDefinition InvokeExtern(SymbolDefinition[] invokeParams) { + // We use void as a placeholder for a null constant value getting passed in, if null is passed in and the target type is a reference type then we assume they are compatible + List typeList = invokeParams.Select(e => + { + if (e.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) && + e.symbolCsType == typeof(object) && + e.symbolDefaultValue == null) + return typeof(void); + + return e.symbolCsType; + }).ToList(); + // Find valid overrides - MethodBase targetMethod = visitorContext.resolverContext.FindBestOverloadFunction(captureMethods, invokeParams.Select(e => e.symbolCsType).ToList()); + MethodBase targetMethod = visitorContext.resolverContext.FindBestOverloadFunction(captureMethods, typeList); if (targetMethod == null) { - targetMethod = visitorContext.resolverContext.FindBestOverloadFunction(captureMethods, invokeParams.Select(e => e.symbolCsType).ToList(), false); + targetMethod = visitorContext.resolverContext.FindBestOverloadFunction(captureMethods, typeList, false); if (targetMethod != null && targetMethod.ReflectedType == typeof(VRC.Udon.UdonBehaviour) && targetMethod.Name.StartsWith("GetComponent") && ((MethodInfo)targetMethod).ReturnType.IsGenericParameter) { - // Uhh just skip the else stuff + // Uhh just skip the else stuff, this fixes GetComponent(s) on UdonBehaviour variables. } else { diff --git a/Assets/UdonSharp/Editor/UdonSharpSymbolTable.cs b/Assets/UdonSharp/Editor/UdonSharpSymbolTable.cs index 8aea58c5..884714b0 100644 --- a/Assets/UdonSharp/Editor/UdonSharpSymbolTable.cs +++ b/Assets/UdonSharp/Editor/UdonSharpSymbolTable.cs @@ -14,7 +14,7 @@ public enum SymbolDeclTypeFlags Private = 2, // Declared by the user as a private variable on a class Local = 4, // Declared by the user as a variable local to a specific scope Internal = 8, // Generated as an intermediate variable that stores intermediate calculations - Constant = 16, // Used to represent a constant value that does not change. This can either be statically defined constants + Constant = 16, // Used to represent a constant value set by the compiler that does not change after compile time. Variables with const/readonly use the Readonly flag. Array = 32, // If this symbol is an array type This = 64, // defines one of the 3 builtin `this` assignments for UdonBehaviour, GameObject, and Transform Reflection = 128, // Metadata information for type checking and other editor time info diff --git a/Assets/UdonSharp/Editor/UdonSharpUtils.cs b/Assets/UdonSharp/Editor/UdonSharpUtils.cs index 4aca8629..15475611 100644 --- a/Assets/UdonSharp/Editor/UdonSharpUtils.cs +++ b/Assets/UdonSharp/Editor/UdonSharpUtils.cs @@ -201,6 +201,10 @@ public static bool IsImplicitlyAssignableFrom(this System.Type targetType, Syste if (IsNumericImplicitCastValid(targetType, assignee)) return true; + // We use void as a placeholder for a null constant value getting passed in, if null is passed in and the target type is a reference type then we assume they are compatible + if (assignee == typeof(void) && !targetType.IsValueType) + return true; + // Handle user-defined implicit conversion operators defined on both sides // Roughly follows https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions#processing-of-user-defined-implicit-conversions diff --git a/Assets/UdonSharp/Tests/TestScripts/Core/MethodCallsTest.cs b/Assets/UdonSharp/Tests/TestScripts/Core/MethodCallsTest.cs index 69686e34..5ee10f1e 100644 --- a/Assets/UdonSharp/Tests/TestScripts/Core/MethodCallsTest.cs +++ b/Assets/UdonSharp/Tests/TestScripts/Core/MethodCallsTest.cs @@ -91,16 +91,14 @@ public void ExecuteTests() RigidbodyConstraints constraints = (RigidbodyConstraints)126; tester.TestAssertion("Enum cast", constraints == RigidbodyConstraints.FreezeAll); - } - //public void test(int a, bool b, float c = 5f, params float[] d) - //{ - // test(a, b); - //} + Transform currentParent = transform.parent; + + transform.SetParent(null); - //public void test2(params object[] strings) - //{ - // test2(new string[] { "aa", "bbb" }); - //} + tester.TestAssertion("Transform detach parent (null parameter method finding)", transform.parent == null); + + transform.SetParent(currentParent); + } } }