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?
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?
Please sign in to leave a comment.
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!
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
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.
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:
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?
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.
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?
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...