Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 325192

Summary: QVTo result assignment outside init block allowed but effectless
Product: [Modeling] QVTo Reporter: Dennis Hendriks <dh_tue>
Component: EngineAssignee: Project Inbox <mmt-qvt.operational-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: christopher.gerking, dh_tue, kutter, serg.boyko2011
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
See Also: https://git.eclipse.org/r/c/mmt/org.eclipse.qvto/+/187933
https://git.eclipse.org/r/c/mmt/org.eclipse.qvto/+/187965
https://git.eclipse.org/c/mmt/org.eclipse.qvto.git/commit/?id=cfdd8091913291545f19d5f3e717a35f98d97371
Whiteboard:
Attachments:
Description Flags
test.qvto: Correct behavior, result assigned in init block
none
test2.qvto: Weird behavior, result assigned outside of init block
none
Patch for error on non-incremental result assignments outside init-section
none
Patch for error on non-incremental result assignments outside init-section (updated copyright and contributors)
none
JUnit test patch
none
Updated patch
none
JUnit test patch
none
Prohibits re-assignment of 'result' outside init{} mapping section none

Description Dennis Hendriks CLA 2010-09-14 02:10:11 EDT
Build Identifier: Build id: 20100617-1415 (Helios)

Assigning the result variable in a QVTo mapping outside the init block, has no effect, as the automatically created object that was created at the end of the non-existing init block, is returned anyway.

I would expect it to be an error to assign result outside of the init block, or that assigning a new value to result outside the init block would actually change the result of the mapping. I'm not sure what the standard indicates, but the current behavior seems like the worst possible choice...

Reproducible: Always

Steps to Reproduce:
1. Observe the difference between test.qvto and test2.qvto, applied to any given .ecore file.
Comment 1 Dennis Hendriks CLA 2010-09-14 02:11:17 EDT
Created attachment 178787 [details]
test.qvto: Correct behavior, result assigned in init block
Comment 2 Dennis Hendriks CLA 2010-09-14 02:11:43 EDT
Created attachment 178788 [details]
test2.qvto: Weird behavior, result assigned outside of init block
Comment 3 Christopher Gerking CLA 2012-09-06 18:06:20 EDT
Created attachment 220815 [details]
Patch for error on non-incremental result assignments outside init-section

Assignments to the 'result' variable outside the init section are likely to be enabled by the patch proposed for bug 388325 (to support incremental assignments to the 'result' variable). 

Hence, the patch attached here prevents default assignments to the 'result' variable outside the init section by raising a proper compilation error. The error indication should be possible to be carried out safely, since the prevented assignments were effectless up to now either way.
Comment 4 Christopher Gerking CLA 2012-10-17 06:14:37 EDT
Created attachment 222456 [details]
Patch for error on non-incremental result assignments outside init-section (updated copyright and contributors)

Patch for error on non-incremental result assignments outside init-section (updated copyright and contributors)
Comment 5 Christopher Gerking CLA 2012-10-17 06:55:56 EDT
Created attachment 222463 [details]
JUnit test patch
Comment 6 Christopher Gerking CLA 2012-10-19 06:36:57 EDT
Created attachment 222562 [details]
Updated patch

Also fixes bug 302594, bug 310991 and bug 392157.
Comment 7 Christopher Gerking CLA 2012-11-16 12:46:39 EST
Created attachment 223667 [details]
JUnit test patch
Comment 8 Adolfo Sanchez-Barbudo Herrera CLA 2013-01-24 09:37:45 EST
Hi Christopher,

+1. 

Trivial comments:
- QvtOperationalVisitorCS has unproper copyright header.
- Again: when extendedClassifier instanceof EClass then always extendedClassifier != null.
Comment 9 Christopher Gerking CLA 2013-01-25 07:01:32 EST
Comment on attachment 222562 [details]
Updated patch

Patch set to obsolete, because it didn't provide a universal solution. Considering the eContainer is not enough, since assignments can be nested arbitrarily deep (not necessarily referring to MappingInitCS as container).

For a universal solution, I propose to "loop through" an additional boolean parameter value named e.g. 'resultAssignmentAllowed'. This one should only be true during the init section evaluation. If it is false and one attempts a non-incremental assignment, a compile error should be raised.
Comment 10 Christopher Gerking CLA 2013-01-25 07:04:39 EST
- The copyright header already looked improper before I changed anything, just wasn't sure about fixing it.
- The part with the null comparison is not used anymore.
Comment 11 Adolfo Sanchez-Barbudo Herrera CLA 2013-01-25 07:26:11 EST
Hi Christopher,

I'm being worried of making messier the already messy bunch of bugs we are reviewing/adding comments. Dont include more patches unless, there is a clear -1.

Let's try to have the big one in, and any future change can be made once the big patch is pushed to master, well resolved bugs are closed, etc

Cheers,
Adolfo.
Comment 12 Christopher Gerking CLA 2013-01-25 08:39:28 EST
I agree that the proposed change should be postponed...
Comment 13 Sergey Boyko CLA 2013-03-20 15:44:12 EDT
Correct behavior for this request is to prohibit assignment of 'result' outside init{} section.

The reason is that such assignment breaks fundamental QVT invariant - relation trace is populated at the end of an implicit "instantiation section" (which is executed right after init{} section if this one is declared). From that point the relation is considered to hold and the trace data becomes available.

See QVT specification section "8.2.1.15 MappingOperation" topic "Executing a mapping operation".
Comment 14 Sergey Boyko CLA 2013-03-31 09:56:19 EDT
Created attachment 229195 [details]
Prohibits re-assignment of 'result' outside init{} mapping section

This patch also supports incremental assignment ('+=' operator) for mutable QVTo types - List and Dict.
Also it remediates problem with saving of incomplete Trace instance mentioned in https://bugs.eclipse.org/bugs/show_bug.cgi?id=388325#c19

Abbreviated .qvto snippet:

modeltype Ecore uses ecore('http://www.eclipse.org/emf/2002/Ecore');
transformation NewTransformation();

main() {
	var v1 : Set(EClass) = object EClass{}.map mapToSet();
	assert fatal (v1->size() = 2);

	var v2 : List(EClass) = object EClass{}.map mapToList();
	assert fatal (v2->size() = 2);
	v2->add(object EClass{});
	
	var resolved2 : List(EClass) = resolveoneIn(EClass::mapToList, List(EClass));
	assert fatal (resolved2->size() = 3);

}

mapping EClass::mapToSet() : Set(EClass) {
	init {
		result := object EClass{}->asSet();
		result += object EClass{};
	}
}

mapping EClass::mapToList() : List(EClass) {
	init {
		result := object EClass{}->asList();
	}
	result += object EClass{};
}
Comment 15 Christopher Gerking CLA 2013-03-31 12:46:18 EDT
I'm not sure if this solution is very comprehensible.

Although most collections are immutable, there is still support for "simulated" incremental assignments inside the init section. If I understand your latest patch correctly, all other sections should not support this simulation of incremental assignments, just because the trace record has already been stored before.

Can't we update the trace whenever 'result' is subject to an incremental assignment? Otherwise, +1 for your patch which at least ensures consistency.
Comment 16 Sergey Boyko CLA 2013-04-01 05:21:26 EDT
(In reply to comment #15)
> I'm not sure if this solution is very comprehensible.
> 
> Although most collections are immutable, there is still support for
> "simulated" incremental assignments inside the init section. If I understand
> your latest patch correctly, all other sections should not support this
> simulation of incremental assignments, just because the trace record has
> already been stored before.
> 

I'll try to describe the point once again:

1. Re-assignment of 'result' variable is not possible outside the init{} section by any means (https://bugs.eclipse.org/bugs/show_bug.cgi?id=325192#c13).

2. For mutable collections (that is for List) statement 'result +=' is shorthand for 'result->add()' method invocation.

3. For immutable collections (that is for Set, Sequence, etc.) statement 'result +=' is shorthand for 
  a) creation of new collection which consists of original plus new element and
  b) assignment of this new collection to 'result'.

As you see option 3b) complies with option 1 only inside the init{} section.

What you call "simulated incremental assignments inside the init section" is in fact just repetition of assignment.

Code snippet:
  mapping EClass::mapToSet() : Set(EClass) {
    init {
      result := object EClass{}->asSet();
      result += object EClass{};
    }
  }

Is equal to:
  mapping EClass::mapToSet() : Set(EClass) {
    init {
      result := object EClass{}->asSet();
      result := result->including(object EClass{});
    }
  }

As you might expect the number of re-assignments to 'result' in init{} section is not limited.
But 'result' can't be re-assigned after the end of init{} section.
Comment 17 Sergey Boyko CLA 2013-04-03 12:08:47 EDT
Pushed to master for Kepler M7.

Commit ID: 688d5773fb3bb2714459e9f7fe4b17c471581bac
Comment 18 Eclipse Genie CLA 2021-11-19 10:53:17 EST
New Gerrit change created: https://git.eclipse.org/r/c/mmt/org.eclipse.qvto/+/187933
Comment 19 Eclipse Genie CLA 2021-11-22 03:10:48 EST
New Gerrit change created: https://git.eclipse.org/r/c/mmt/org.eclipse.qvto/+/187965