{"record":{"id":"78505b2ad4a70008","repo":"egametang/ET","slug":"preservedmethod-method-methoddef-has-generic-p","errorCode":null,"errorMessage":"[PreservedMethod] method:{methodDef} has generic parameters","messagePattern":"\\[PreservedMethod\\] method:(.+?) has generic parameters","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.hybridclr/Scripts/Editor/Share/MethodBridge/Generator.cs","lineNumber":124,"sourceCode":"            string sigName = ToFullName(typeInfo.Klass);\n            if (!_sig2Types.TryGetValue(sigName, out var sharedTypeInfo))\n            {\n                sharedTypeInfo = typeInfo;\n                _sig2Types.Add(sigName, sharedTypeInfo);\n            }\n            return sharedTypeInfo;\n        }\n\n        private MethodDesc CreateMethodDesc(MethodDef methodDef, bool forceRemoveThis, TypeSig returnType, List<TypeSig> parameters)\n        {\n            var paramInfos = new List<ParamInfo>();\n            if (forceRemoveThis && !methodDef.IsStatic)\n            {\n                parameters.RemoveAt(0);\n            }\n            if (returnType.ContainsGenericParameter)\n            {\n                throw new Exception($\"[PreservedMethod] method:{methodDef} has generic parameters\");\n            }\n            foreach (var paramInfo in parameters)\n            {\n                if (paramInfo.ContainsGenericParameter)\n                {\n                    throw new Exception($\"[PreservedMethod] method:{methodDef} has generic parameters\");\n                }\n                paramInfos.Add(new ParamInfo() { Type = GetSharedTypeInfo(paramInfo) });\n            }\n            var mbs = new MethodDesc()\n            {\n                MethodDef = methodDef,\n                ReturnInfo = new ReturnInfo() { Type = returnType != null ? GetSharedTypeInfo(returnType) : TypeInfo.s_void },\n                ParamInfos = paramInfos,\n            };\n            return mbs;\n        }\n","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.hybridclr/Scripts/Editor/Share/MethodBridge/Generator.cs#L106-L142","documentation":"Thrown by Generator.CreateMethodDesc (the overload taking a MethodDef) when the method's return type ContainsGenericParameter. The method bridge generator requires fully concrete type signatures to emit bridge/wrapper functions; an open generic parameter on the return type means the signature was never inflated to a concrete type.","triggerScenarios":"CreateMethodDesc(methodDef, forceRemoveThis, returnType, parameters) is called with a returnType whose ContainsGenericParameter is true. This happens when ProcessMethod passed through a method whose generic arguments were not substituted (klassInst/methodInst both null but the method still carries open generics).","commonSituations":"A preserved method (annotated or referenced via reverse P/Invoke) is itself generic and was not instantiated before bridge generation; the AOT generic reference pass missed an instantiation; a code change introduced a generic method signature that HybridCLR cannot bridge.","solutions":["Ensure all generic method instantiations used across the AOT/hot-update boundary are captured by HybridCLR/Generate/AOTGenericReference first.","If a method is annotated [PreservedMethod] or [MonoPInvokeCallback], make sure it is non-generic or only used with concrete instantiations.","Re-run HybridCLR/Generate/All to regenerate bridge functions with the latest generic reference data.","Inspect the methodDef printed in the exception and refactor it to avoid open generic parameters at the bridge boundary."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before bridge generation, ensure no preserved method has open generics\nif (returnType.ContainsGenericParameter)\n    Debug.LogError(\"Method return type has open generic -- inflate or avoid bridging.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run AOTGenericReference generation before MethodBridge so all instantiations are known.","Avoid annotating generic methods with [PreservedMethod] / [MonoPInvokeCallback].","Review new generic APIs added at the managed/native boundary."],"tags":["hybridclr","method-bridge","generics","preserved-method"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}