jamescourtney / FlatSharp

Fast, idiomatic C# implementation of Flatbuffers
Apache License 2.0
497 stars 50 forks source link

Members of descendent namespaces don't seem to inherit ancestor's scope #173

Closed TYoungSL closed 3 years ago

TYoungSL commented 3 years ago

Seems like there's problems with namespace scopes during compilation. Google's FBS parser seems to handle this scenario fine.

Shouldn't the descending namespaces should be able to access the inherited namespace's symbols?

A.fbs:

namespace Aa;
struct B { v:int; }

C.fbs:

include "A.fbs";
namespace Aa.Cc;
struct D { b:B; }

C.fbs gives the error:

Message=’Unable to resolve type: ‘B’. Context = ‘Aa.Cc.D’.’, Scope=$..Aa.Cc.D.b

jamescourtney commented 3 years ago

Types from other namespaces need to be fully qualified. So you need:

struct D { b : Aa.B; }

Does this work in flatc? If so, I'll treat it as a bug.

Rjvs commented 3 years ago

@jamescourtney The original code works in flatc, as does your suggestion but neither seems to work in FlatSharp.Compiler... the fully qualified version gives me the error:

The namespace 'Aa' already contains a definition for 'B'

jamescourtney commented 3 years ago

Sounds good. I'll take a look at this today, time permitting with my real job!

jamescourtney commented 3 years ago

Pull request is here: #174

This was a namespace resolution issue and not an include issue. I can't find any comprehensive documentation, but the Flatbuffer NS resolution rules seem to be:

I need to test a bit more and really make sure that this is indeed correct before releasing, but you should be able to get a preview from the artifacts on the build here: https://github.com/jamescourtney/FlatSharp/runs/2867639619

jamescourtney commented 3 years ago

My understanding of the rules was off. This is a bit more complicated, and may take some time. Here's the problem:

Consider this FBS file:

namespace A.B; table TB {}
namespace A.B.C.B; table TB {}
namespace A.B.C; table TC { V1 : B.TB; }

In this file, TC.V1 references A.B.C.B.TB. However, if we make this change to the FBS, we get a different answer:

namespace A.B; table TB {}
namespace A.B.C; table TC { V1 : B.TB; }
namespace A.B.C.B; table TB {}

Here, TC.V1 references A.B.TB.

My assumption as to the reason for this behavior is that flatc reads items progressively, like the C preprocessor. So when it encounters B.TB and A.B.C.B.TB is not yet defined, the best match is the parent namespace of B.TB.

This isn't trivial because FlatSharp actually reads the full file before attempting to do any sort of resolution of types, sort of like the C# compiler, so the answer is order-independent.

This is particularly annoying because FlatSharp's behavior in this case seems more correct to me, but I digress. In the short term, I can get a fix out that improves resolution for your case, but will still not have the flatc behavior.

jamescourtney commented 3 years ago

After clarification from the FlatBuffers team, the resolution rule is:

jamescourtney commented 3 years ago

Fixed in 5.4.1