Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[generator] Fix issue where generic types couldn't be found in SymbolTable (#543) #552

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

Merged
merged 2 commits into from
Jan 7, 2020

Conversation

jpobst
Copy link
Contributor

@jpobst jpobst commented Jan 3, 2020

Context: #543

In #450 we began stripping the arity from Cecil imported types so that we wouldn't write invalid types like System.Collections.Generic.IList'1<string>, resulting in the correctly formed System.Collections.Generic.IList<string>.

However when we try to resolve these types in the SymbolTable we only look at the type name, ignoring the generic types. In this case we are looking for System.Collections.Generic.IList but the type is stored in the symbol table with the arity to disambiguate types like Action'1 and Action'2. Therefore our lookup fails because the table key is System.Collections.Generic.IList'1.

With this PR, if the type is not found in the table and there are generic type parameters, calculate the arity from the generic type parameters and look in the table again.

That is, System.Collections.Generic.IList<string> is rechecked as System.Collections.Generic.IList'1, which allows the type to be found.

This is a relatively rare case because it comes from reference assemblies read in via Cecil, and there aren't many generics used in binding libraries. The only case in Mono.Android.dll is:

warning BG8800: Unknown parameter type System.Collections.Generic.IList<Java.Util.Locale.LanguageRange> in method Filter in managed type Java.Util.Locale.

@jpobst jpobst requested a review from jonpryor January 6, 2020 17:03
@jonpryor
Copy link
Contributor

jonpryor commented Jan 6, 2020

there aren't many generics used in binding libraries. The only case in Mono.Android.dll is:

I'm not sure how to interpret this. The BG8800 warning isn't within the Mono.Android.dll build -- nor would that make sense to me, as Cecil isn't involved in the Mono.Android.dll build! -- which in turn suggests that this is from a binding project.

Should that BG8800 warning continue to be emitted? What's the context for that warning? I'm not sure I understand the last two paragraphs.

@jpobst
Copy link
Contributor Author

jpobst commented Jan 6, 2020

Yeah, it isn't when building Mono.Android.dll itself, it is when binding a library that references Mono.Android.dll. We scan and resolve every type in Mono.Android.dll and it generates these warnings.

Presumably this could matter in situations where you are referencing another one of your own bound libraries that has had generics added to it. In the right situations it would make it impossible to bind some types/methods because it cannot resolve the type.

For example, something like this would probably fail:

LibraryA:

public class Foo {
    public virtual void Bar (IList<string> p0) { }
}

LibraryB references LibraryA

public class Foo2 : Foo {
    public override void Bar (IList<string> p0) { }
}

table.AddType (dict);

Assert.NotNull (table.Lookup ("System.Collections.Generic.IList<Java.Util.Locale.LanguageRange>"));
Assert.NotNull (table.Lookup ("System.Collections.Generic.IList<List<Java.Util.Locale.LanguageRange>>"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To ensure that the nested <...> logic works, we should also add:

Assert.NotNull (table.Lookup ("System.Collections.Generic.IList<Dictionary<string, Java.Util.Locale.LanguageRange>>"));

We might also want to assert that not only is the table.Lookup() not null, but also what the resulting value is.

@jonpryor jonpryor merged commit 4565369 into master Jan 7, 2020
@jonpryor jonpryor deleted the symbol-table-arity branch January 7, 2020 03:39
jonpryor pushed a commit that referenced this pull request Jan 7, 2020
Fixes: #543

In commit 262743b we began stripping the arity from Cecil imported
types so that we wouldn't write invalid types like
``System.Collections.Generic.IList`1<string>``, in order to correctly
emit `System.Collections.Generic.IList<string>`.

However when we try to resolve these types in the `SymbolTable` we
only look at the type name, ignoring the generic type parameters.  In
this case we are looking for `System.Collections.Generic.IList` but
the type is stored in the symbol table with the arity to disambiguate
types like ``Action`1`` and ``Action`2``.  Therefore our lookup fails
because the table key is ``System.Collections.Generic.IList`1``.

For example, if we have `LibraryA.dll` with:

	public class Foo : Java.Lang.Object {
	    public virtual void Bar (IList<string> p0) {…}
	}

And we attempt to bind a `LibraryB.jar` which references
`LibraryA.dll`, overriding `Foo.Bar()`:

	public class Foo2 : Foo {
	    public override void Bar (IList<string> p0) {…}
	}

Then `Foo2.Bar()` would elicit a BG8800 warning:

	warning BG8800: Unknown parameter type System.Collections.Generic.IList<System.String> in method Bar in managed type Foo2.

Fix type lookup so that if the type is not found in the `SymbolTable`
and there are generic type parameters, calculate the arity from the
generic type parameters and look in the table again.

That is, `System.Collections.Generic.IList<string>` is rechecked as
``System.Collections.Generic.IList`1``, which allows the type to be
found.
@github-actions github-actions bot locked and limited conversation to collaborators Apr 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants