Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error MT4166 / MM4166 (Cannot register the method...) for generic property only in Release #15709

Open
snechaev opened this issue Aug 19, 2022 · 7 comments
Labels
bug If an issue is a bug or a pull request a bug fix
Milestone

Comments

@snechaev
Copy link
Contributor

snechaev commented Aug 19, 2022

Steps to Reproduce

  1. Grab the test project MT4166Repro.zip
  2. Build in Release
  3. Observe build errors

Expected Behavior

Project builds and works.

Actual Behavior

A lot of build errors. The main is

/MT4166Repro/AppDelegate.cs(0,0): Error MM4166: Cannot register the method 'get_Test()' because the signature contains a type (MT4166Repro.EnumWrapper`1) that isn't a reference type. (MM4166) (MT4166Repro)

get_Test() & EnumWrapper are declared as following, so it is definitely NSObject-inherited reference type, so seems to be all should be compatible with registrar.
Moreover, it works in Debug without any issues.

[Export("Test")]
public EnumWrapper<MyEnum> Test { get; } = EnumWrapper.Create(MyEnum.A);

public class EnumWrapper : NSObject
{
	public static EnumWrapper<T> Create<T>(T value) where T : Enum => new EnumWrapper<T>(value);
}

public class EnumWrapper<T> : EnumWrapper where T:Enum
{
	public T Value { get; }
	public EnumWrapper(T value) => this.Value = value;
}

Environment

Version information
Visual Studio Professional 2022 for Mac
Version 17.3.1 (build 411)
Installation UUID: 18b3b114-81b5-4a14-872e-231807c1b48b

Runtime
.NET 6.0.5 (64-bit)
Architecture: X64

Roslyn (Language Service)
4.3.0-3.22312.2+52adfb8b2dc71ed4278debcf13960f2116868608

NuGet
Version: 6.2.1.2

.NET SDK (x64)
SDK: /usr/local/share/dotnet/sdk/6.0.400/Sdks
SDK Versions:
	6.0.400
	3.1.422
MSBuild SDKs: /Applications/Visual Studio.app/Contents/MonoBundle/MSBuild/Current/bin/Sdks

.NET Runtime (x64)
Runtime: /usr/local/share/dotnet/dotnet
Runtime Versions:
	6.0.8
	3.1.28

Xamarin.Profiler
Version: 1.8.0.19
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

Updater
Version: 11

Apple Developer Tools
Xcode 13.4.1 (20504)
Build 13F100

Xamarin.Mac
Version: 8.12.0.2 (Visual Studio Professional)
Hash: 87f98a75e
Branch: d17-3
Build date: 2022-07-25 20:18:54-0400

Xamarin.iOS
Version: 15.12.0.2 (Visual Studio Professional)
Hash: 87f98a75e
Branch: d17-3
Build date: 2022-07-25 20:18:55-0400

Xamarin Designer
Version: 17.3.0.208
Hash: 0de472ea0
Branch: remotes/origin/d17-3
Build date: 2022-08-11 21:29:58 UTC

Xamarin.Android
Not Installed

Microsoft Build of OpenJDK
Java SDK: /Library/Java/JavaVirtualMachines/microsoft-11.jdk
11.0.12
Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

Eclipse Temurin JDK
Java SDK: /Library/Java/JavaVirtualMachines/temurin-8.jdk
1.8.0.302
Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

Android SDK Manager
Version: 17.3.0.23
Hash: 965bf40
Branch: remotes/origin/d17-3
Build date: 2022-08-11 21:30:03 UTC

Android Device Manager
Version: 0.0.0.1169
Hash: fafb1d5
Branch: fafb1d5
Build date: 2022-08-11 21:30:03 UTC

Build Information
Release ID: 1703010411
Git revision: 22408f3ad66bf33ab9530b882011bed98ebf1503
Build date: 2022-08-11 21:28:07+00
Build branch: release-17.3
Build lane: release-17.3

Operating System
Mac OS X 12.4.0
Darwin 21.5.0 Darwin Kernel Version 21.5.0
    Tue Apr 26 21:08:22 PDT 2022
    root:xnu-8020.121.3~4/RELEASE_X86_64 x86_64

Enabled user installed extensions
Log Monitor 0.7
.NET Core Extensions 0.4

Build Logs

msbuild.binlog.zip

Example Project (If Possible)

MT4166Repro.zip

Additional note: in the logs this error is called MM4166, but in the documentation (https://github.com/xamarin/xamarin-macios/blob/main/docs/website/mtouch-errors.md) it is called MT4166 with the same error message.

@snechaev
Copy link
Contributor Author

snechaev commented Aug 22, 2022

As a workaround we can use dynamic registrar for Release. To do so, the following should be added into the csproj

    <MonoBundlingExtraArgs>--registrar=dynamic</MonoBundlingExtraArgs>

Eventually I'm unsure if it is a bug or just a known limitations of the static registrar.

@chamons
Copy link
Contributor

chamons commented Aug 24, 2022

The code in question before the error:

if (sb [sb.Length - 1] != '*') {
	// I'm not sure if this is possible to hit (I couldn't come up with a test case), but better safe than sorry.
	AddException (ref exceptions, CreateException (4166, inMethod.Resolve () as MethodDefinition, "Cannot register the method '{0}' because the signature contains a type ({1}) that isn't a reference type.", descriptiveMethodName, GetTypeFullName (elementType)));
	return "id";
}

Introduced in 4371ea4.

Hey @rolfbjarne - You got your test case :)

@chamons chamons added this to the Future milestone Aug 24, 2022
@chamons chamons added the bug If an issue is a bug or a pull request a bug fix label Aug 24, 2022
@rolfbjarne
Copy link
Member

It looks like this works in the dynamic registrar by accident.

The generic signature for the Test property is not allowed according to: https://docs.microsoft.com/en-us/xamarin/ios/internals/api-design/nsobject-generics#generic-type-arguments-in-member-signatures

I believe it should be possible to do this instead:

[Export("Test")]
public EnumWrapperOfMyEnum Test { get; } = EnumWrapper.Create(MyEnum.A);

public class EnumWrapper : NSObject
{
	public static EnumWrapper<T> Create<T>(T value) where T : Enum => new EnumWrapper<T>(value);
}

public class EnumWrapper<T> : EnumWrapper where T:Enum
{
	public T Value { get; }
	public EnumWrapper(T value) => this.Value = value;
}

public class EnumWrapperOfMyEnum : EnumWrapper<MyEnum>
{
}

@snechaev
Copy link
Contributor Author

@rolfbjarne, could you please provide a little more details? I'm asking not out of idle curiosity, but would like to make pull request into documentation as the from current version I was almost sure that such a things are registrar-compatible.

I clearly understand why the following is prohibited (T assumed to be Enum below)

T Get()
void Set(T value)

The ObjC does not know how to work with T as it's not NSObject-inherited.

But for this one

EnumWrapper<T> Get()
void Set(EnumWrapper<T> value)

it looks like all instances is NSObjects and ObjC does not need any explicit knowledge about T at all (we have no raw T in any export, including internals of the EnumWrapper<T>). So, the corresponding selectors will always work with NSObject or a subclass of it.

PS: the workaround is clear, although it sadly produces a lot of boilerplate code.

@rolfbjarne
Copy link
Member

@snechaev I agree this is a case that we might be able to support, my point was really that according to the documentation, it seems it shouldn't be (although the documentation isn't 100% clear either because this case doesn't totally match).

@snechaev
Copy link
Contributor Author

@rolfbjarne, yes, I understood your point. The question is exactly about how can I better explain this case in the documentation (https://github.com/MicrosoftDocs/xamarin-docs/blob/live/docs/ios/internals/api-design/nsobject-generics.md) to make it 100% clear about this case. Could you please advise if something like "This is not supported by registrar yet" will be enough or it will be mandatory to provide some more detailed/deep explanation?

@rolfbjarne
Copy link
Member

@snechaev it's not mandatory to provide a deeper explanation (you could just link back to this issue).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug If an issue is a bug or a pull request a bug fix
Projects
None yet
Development

No branches or pull requests

3 participants