dotnet / dotnet/orleans

Orleans 3.x code gen produces wrong namespace for internal class nested inside public class

Open
#8,213 0 comments 1 reaction 0 assignees View on GitHub
Needs: triage :mag:
Dominant language
C#
Stars
10.9k
Forks
2.1k
Avg merge
14h 42m
Merged PRs (30d)
354

Description

Found this bug while using Orleans with an F# project.
My F# module and the type of interest:

```
[]
module LibLifeCycleTypes_EcosystemTypes
...
[]
type CallOrigin =
| Inner // no payload
| External of ExternalCallOrigin // contents of the payload don't matter
```

F# module compiles to a globally-namespaced static class, union type compiles to an abstract class, specific union cases are nested sub-classes of CallOrigin class - which is either `internal` or `public` depending on presence of payload. Here's the code decompiled as C#:

```
public static class LibLifeCycleTypes_EcosystemTypes
{
...
public abstract class CallOrigin :
...
{
...
**internal** class _Internal : LibLifeCycleTypes_EcosystemTypes.CallOrigin
...
**public** class External : LibLifeCycleTypes_EcosystemTypes.CallOrigin
...
```

And this the fragment of output C# produced by Orleans code gen:

```
feature.AddKnownType("LibLifeCycleTypes_EcosystemTypes+CallOrigin+_Inner,LibLifeCycleTypes", "._Inner");
feature.AddKnownType("LibLifeCycleTypes_EcosystemTypes+CallOrigin+External,LibLifeCycleTypes", "...LibLifeCycleTypes_EcosystemTypes.CallOrigin.External");
```

This code doesn't work and in the end leads to System.TypeAccessException for the `Inner` case.

Here's the offending line in TypeUtils:

https://github.com/dotnet/orleans/blob/62336a12f369e2f499227651bc1ba95d425a7d48/src/Orleans.Core/Serialization/TypeUtilities.cs#L173

Can it simply be replaced with `if (t.IsNested)` ?

Possible workaround is to move the F# module into a namespace (it still generates invalid type prefix but apparently unique enough to make it work in Orleans). However this is library code which affects many client solutions and they will break

Contributor guide

Open the contributing guide

Research direction

Start at src/Orleans.Core/Serialization/TypeUtilities.cs around line 173 and compare its nested-type handling with the F#-compiled class structure in the report. Reproduce the generated AddKnownType entries and verify that nested internal and public types receive valid namespaces without causing the reported System.TypeAccessException.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, fsharp
Domain
backend, distributed-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.