Build errors after update to 2.0.5: references across templates for different roots are not allowed: use mapping labels or turn off incremental mode

Since I've updated MPS to 2.0.5/2.0.6 I've got the following error when I build my project:

references across templates for different roots are not allowed: use mapping labels or turn off incremental mode

With 2.0.4 everything works fine. Why does this error appear? Disabling incremental generation in the IDE settings does not make any difference. I don't know how "use mapping labels" is meant, of course I use labels to get my output nodes in the generator context.
Is this a bug or have I done something wrong?
6 comments
Comment actions Permalink
In 2.0 in some rare cases incremental generation could break down. While making correct model incrementally you encountered an error about unresolved reference. Rebuild solved the problem. In 2.0.5 we added a check, which detects the situation and points to a potentially bad template.

The reason is that incremental caches do not contain map of template nodes into output nodes (because of their huge size). These maps allow generator implicitly resolve references in templates, trying to find correct target given the input and template nodes. Note: the reference points to another template! Incremental generation tries to take unchanged root from the cache. Thus, references to loaded roots cannot be restored implicitly and should be handled via dynamic resolve mechanism or mapping labels. Now the limitation is reported in strict mode.

Error looks like this:

references across templates for different roots are not allowed: use mapping labels or turn off incremental mode, source root: [root] ConceptDeclaration ..., target root: ...
– was source: [actualArgument] StaticFieldReference ... in ...
– was target: [staticField] StaticFieldDeclaration "IS_DEPRECATED"... in ...

The first line navigates to the template. The later two to the output model of a broken step.

Solution:

0. (Temporarily, if you do not want to fix it immediately) Disable strict mode: Settings -> Generator -> uncheck Strict mode.
1. (labels) If the target is a conditional root, create mapping label and reference macro.
2. (dynamic resolving) For named elements (like methods or fields in baseLanguage) you can create a reference macro and return the name out of it.

Migrate carefully!
0
Comment actions Permalink
Thank you for the detailed replay!
I've resolved the problem, but I really don't understand how.
In my language there are two different root nodes, let's say One and Two. For each there is a root template, let's say A and B. The templates are baselanguage classes, which contain a static getInstance method (for the singelton pattern) and a generate member method, which is inherited from a common base class. The names of the classes are replaced with the names of my root nodes.
In a method of A I want to call the generate methods of all instances of B. Therefore I typed
B.getInstance().generate();
prettyPrint();
in a LOOP macro and set a reference macro for B. The reference macro gets the correct output with an label from an input node.
->[B].getInstance().generate();
prettyPrint();
At this point I got the error.
Now I've added another label for the getInstance method and use it in another reference macro. So the call looks like this:
->[B].->[getInstance()].generate();
prettyPrint();
At this point the error is gone, but I don't know why. The getInstance method do not contain any macros, so it will not differ in the generated classes. Would you expect this behavior?
0
Comment actions Permalink
Sure! MPS stores direct reference to a method, it is not a name - it is rather an address.

You have a reference to a method in template, but you generate several classes out of it. MPS can try to understand and resolve the method correctly (using the context input node), but it takes too much resources (esp memory).

If you create a reference macro with just return "getInstance", it invokes usual name resolving mechanism (obviously Java one, defined in baseLanguage) and you get the correct result.
0
Comment actions Permalink
Ok this sounds rational.
But what's with the generate method call. It's not mapped with a macro. Sure, the method is in a super class outside the template, so mps can store an fixed address to it. But what if in the actual class there is another method generate, which overrides the other one. A Java program must call the lower one, will mps recognize that there is another one available?
0
Comment actions Permalink
It is like when you invoke a method through an interface, referring to the one from the interface. baseLanguage doesn't care about real implementation (nor javac does). Polymorphic dispatch is performed by java at runtime.
0
Comment actions Permalink
I've got again the same problem in different circumstances and no idea how to solve it.

There is a simple java like inheritance in my language with interfaces. So instances can inherit members of an interface. There is no generation output for the interface itself but output for its members is generated at each instance, which implements that interface. There is a behavior method which returns a sequence of all members for each instance. So for each input node exist multiple output nodes. But this output nodes are not referenced from outside the template code. If I disable strict mode every thing works fine, but this shouldn't be the solution...
0

Please sign in to leave a comment.