Repository: mlange-42/arche
Pull request #252 (2023-05-01 22:21:49)

Add generic maps mathod `NewWith`
Add method `NewWith` to generic maps

coveralls: ## Pull Request Test Coverage Report for [Build 4855482869](https://coveralls.io/builds/59502860)

* **126** of **126**   **(100.0%)**  changed or added relevant lines in **1** file are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **100.0%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/59502860/badge)](https://coveralls.io/builds/59502860) |
| :-- | --: |
| Change from base [Build 4854848992](https://coveralls.io/builds/59500509): |  0.0% |
| Covered Lines: | 3410 |
| Relevant Lines: | 3410 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cac2758..9d9642a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,7 @@
 ### Breaking changes
 
 * Removed `World.Batch` for entity batch creation, use `Builder` instead (#239)
-* Rework of generic entity creation API, use `MapX.New`, `MapX.NewBatch` and `MapX.NewQuery` (#239)
+* Rework of generic entity creation API, use `MapX.New`, `MapX.NewWith`, `MapX.NewBatch` and `MapX.NewQuery` (#239, #252)
 
 ### Features
 
diff --git a/ecs/archetypes.go b/ecs/archetypes.go
index 4a33fe7..02dbad6 100644
--- a/ecs/archetypes.go
+++ b/ecs/archetypes.go
@@ -44,12 +44,12 @@ func (a *archetypePointers) Get(index int32) *archetype {
 	return a.pointers[index]
 }
 
-// Add adds an element.
+// Add an element.
 func (a *archetypePointers) Add(arch *archetype) {
 	a.pointers = append(a.pointers, arch)
 }
 
-// Add adds an element.
+// Remove an element.
 func (a *archetypePointers) Remove(arch *archetype) {
 	for i := 0; i < len(a.pointers); i++ {
 		arch2 := a.pointers[i]
diff --git a/ecs/world.go b/ecs/world.go
index 981fec7..a9abc6c 100644
--- a/ecs/world.go
+++ b/ecs/world.go
@@ -129,6 +129,7 @@ func fromConfig(conf Config) World {
 //	// even faster
 //	world.NewEntity(ids...)
 //
+// For more advanced and batched entity creation, see [Builder].
 // See also the generic variants under [github.com/mlange-42/arche/generic.Map1], etc.
 func (w *World) NewEntity(comps ...ID) Entity {
 	w.checkLocked()
@@ -155,6 +156,7 @@ func (w *World) NewEntity(comps ...ID) Entity {
 // Panics when called on a locked world.
 // Do not use during [Query] iteration!
 //
+// For more advanced and batched entity creation, see [Builder].
 // See also the generic variants under [github.com/mlange-42/arche/generic.Map1], etc.
 func (w *World) NewEntityWith(comps ...Component) Entity {
 	w.checkLocked()
diff --git a/generic/generate/map.go.txt b/generic/generate/map.go.txt
index d291788..9a82a86 100644
--- a/generic/generate/map.go.txt
+++ b/generic/generate/map.go.txt
@@ -112,6 +112,21 @@ func (m *Map{{ .Index }}{{ .Types }}) NewQuery(count int, target ...ecs.Entity)
 }
 
 {{if .ReturnAll}}
+// NewWith creates a new [ecs.Entity] with the Map{{ .Index }}'s components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map{{ .Index }}'s [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map{{ .Index }}{{ .Types }}) NewWith({{ .Arguments }}, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith({{ .Components }})
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, {{ .Components }}).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map{{ .Index }}'s components to the given entity.
 //
 // See also [ecs.World.Add].
diff --git a/generic/map_generated.go b/generic/map_generated.go
index bf17be8..83593fa 100644
--- a/generic/map_generated.go
+++ b/generic/map_generated.go
@@ -118,6 +118,21 @@ func (m *Map1[A]) NewQuery(count int, target ...ecs.Entity) Query1[A] {
 	}
 }
 
+// NewWith creates a new [ecs.Entity] with the Map1's components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map1's [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map1[A]) NewWith(a *A, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith(ecs.Component{ID: m.id0, Comp: a})
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, ecs.Component{ID: m.id0, Comp: a}).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map1's components to the given entity.
 //
 // See also [ecs.World.Add].
@@ -274,6 +289,25 @@ func (m *Map2[A, B]) NewQuery(count int, target ...ecs.Entity) Query2[A, B] {
 	}
 }
 
+// NewWith creates a new [ecs.Entity] with the Map2's components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map2's [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map2[A, B]) NewWith(a *A, b *B, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith(ecs.Component{ID: m.id0, Comp: a},
+			ecs.Component{ID: m.id1, Comp: b},
+		)
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, ecs.Component{ID: m.id0, Comp: a},
+		ecs.Component{ID: m.id1, Comp: b},
+	).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map2's components to the given entity.
 //
 // See also [ecs.World.Add].
@@ -436,6 +470,27 @@ func (m *Map3[A, B, C]) NewQuery(count int, target ...ecs.Entity) Query3[A, B, C
 	}
 }
 
+// NewWith creates a new [ecs.Entity] with the Map3's components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map3's [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map3[A, B, C]) NewWith(a *A, b *B, c *C, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith(ecs.Component{ID: m.id0, Comp: a},
+			ecs.Component{ID: m.id1, Comp: b},
+			ecs.Component{ID: m.id2, Comp: c},
+		)
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, ecs.Component{ID: m.id0, Comp: a},
+		ecs.Component{ID: m.id1, Comp: b},
+		ecs.Component{ID: m.id2, Comp: c},
+	).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map3's components to the given entity.
 //
 // See also [ecs.World.Add].
@@ -604,6 +659,29 @@ func (m *Map4[A, B, C, D]) NewQuery(count int, target ...ecs.Entity) Query4[A, B
 	}
 }
 
+// NewWith creates a new [ecs.Entity] with the Map4's components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map4's [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map4[A, B, C, D]) NewWith(a *A, b *B, c *C, d *D, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith(ecs.Component{ID: m.id0, Comp: a},
+			ecs.Component{ID: m.id1, Comp: b},
+			ecs.Component{ID: m.id2, Comp: c},
+			ecs.Component{ID: m.id3, Comp: d},
+		)
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, ecs.Component{ID: m.id0, Comp: a},
+		ecs.Component{ID: m.id1, Comp: b},
+		ecs.Component{ID: m.id2, Comp: c},
+		ecs.Component{ID: m.id3, Comp: d},
+	).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map4's components to the given entity.
 //
 // See also [ecs.World.Add].
@@ -778,6 +856,31 @@ func (m *Map5[A, B, C, D, E]) NewQuery(count int, target ...ecs.Entity) Query5[A
 	}
 }
 
+// NewWith creates a new [ecs.Entity] with the Map5's components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map5's [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map5[A, B, C, D, E]) NewWith(a *A, b *B, c *C, d *D, e *E, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith(ecs.Component{ID: m.id0, Comp: a},
+			ecs.Component{ID: m.id1, Comp: b},
+			ecs.Component{ID: m.id2, Comp: c},
+			ecs.Component{ID: m.id3, Comp: d},
+			ecs.Component{ID: m.id4, Comp: e},
+		)
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, ecs.Component{ID: m.id0, Comp: a},
+		ecs.Component{ID: m.id1, Comp: b},
+		ecs.Component{ID: m.id2, Comp: c},
+		ecs.Component{ID: m.id3, Comp: d},
+		ecs.Component{ID: m.id4, Comp: e},
+	).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map5's components to the given entity.
 //
 // See also [ecs.World.Add].
@@ -958,6 +1061,33 @@ func (m *Map6[A, B, C, D, E, F]) NewQuery(count int, target ...ecs.Entity) Query
 	}
 }
 
+// NewWith creates a new [ecs.Entity] with the Map6's components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map6's [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map6[A, B, C, D, E, F]) NewWith(a *A, b *B, c *C, d *D, e *E, f *F, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith(ecs.Component{ID: m.id0, Comp: a},
+			ecs.Component{ID: m.id1, Comp: b},
+			ecs.Component{ID: m.id2, Comp: c},
+			ecs.Component{ID: m.id3, Comp: d},
+			ecs.Component{ID: m.id4, Comp: e},
+			ecs.Component{ID: m.id5, Comp: f},
+		)
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, ecs.Component{ID: m.id0, Comp: a},
+		ecs.Component{ID: m.id1, Comp: b},
+		ecs.Component{ID: m.id2, Comp: c},
+		ecs.Component{ID: m.id3, Comp: d},
+		ecs.Component{ID: m.id4, Comp: e},
+		ecs.Component{ID: m.id5, Comp: f},
+	).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map6's components to the given entity.
 //
 // See also [ecs.World.Add].
@@ -1144,6 +1274,35 @@ func (m *Map7[A, B, C, D, E, F, G]) NewQuery(count int, target ...ecs.Entity) Qu
 	}
 }
 
+// NewWith creates a new [ecs.Entity] with the Map7's components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map7's [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map7[A, B, C, D, E, F, G]) NewWith(a *A, b *B, c *C, d *D, e *E, f *F, g *G, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith(ecs.Component{ID: m.id0, Comp: a},
+			ecs.Component{ID: m.id1, Comp: b},
+			ecs.Component{ID: m.id2, Comp: c},
+			ecs.Component{ID: m.id3, Comp: d},
+			ecs.Component{ID: m.id4, Comp: e},
+			ecs.Component{ID: m.id5, Comp: f},
+			ecs.Component{ID: m.id6, Comp: g},
+		)
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, ecs.Component{ID: m.id0, Comp: a},
+		ecs.Component{ID: m.id1, Comp: b},
+		ecs.Component{ID: m.id2, Comp: c},
+		ecs.Component{ID: m.id3, Comp: d},
+		ecs.Component{ID: m.id4, Comp: e},
+		ecs.Component{ID: m.id5, Comp: f},
+		ecs.Component{ID: m.id6, Comp: g},
+	).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map7's components to the given entity.
 //
 // See also [ecs.World.Add].
@@ -1336,6 +1495,37 @@ func (m *Map8[A, B, C, D, E, F, G, H]) NewQuery(count int, target ...ecs.Entity)
 	}
 }
 
+// NewWith creates a new [ecs.Entity] with the Map8's components, using the supplied values.
+//
+// The optional argument can be used to set the target [ecs.Entity] for the Map8's [ecs.Relation].
+//
+// See also [ecs.NewBuilderWith].
+func (m *Map8[A, B, C, D, E, F, G, H]) NewWith(a *A, b *B, c *C, d *D, e *E, f *F, g *G, h *H, target ...ecs.Entity) ecs.Entity {
+	if len(target) == 0 {
+		return m.world.NewEntityWith(ecs.Component{ID: m.id0, Comp: a},
+			ecs.Component{ID: m.id1, Comp: b},
+			ecs.Component{ID: m.id2, Comp: c},
+			ecs.Component{ID: m.id3, Comp: d},
+			ecs.Component{ID: m.id4, Comp: e},
+			ecs.Component{ID: m.id5, Comp: f},
+			ecs.Component{ID: m.id6, Comp: g},
+			ecs.Component{ID: m.id7, Comp: h},
+		)
+	}
+	if m.target < 0 {
+		panic("map has no relation defined")
+	}
+	return ecs.NewBuilderWith(m.world, ecs.Component{ID: m.id0, Comp: a},
+		ecs.Component{ID: m.id1, Comp: b},
+		ecs.Component{ID: m.id2, Comp: c},
+		ecs.Component{ID: m.id3, Comp: d},
+		ecs.Component{ID: m.id4, Comp: e},
+		ecs.Component{ID: m.id5, Comp: f},
+		ecs.Component{ID: m.id6, Comp: g},
+		ecs.Component{ID: m.id7, Comp: h},
+	).WithRelation(uint8(m.target)).New(target[0])
+}
+
 // Add the Map8's components to the given entity.
 //
 // See also [ecs.World.Add].


Test patch:
diff --git a/generic/map_generated_test.go b/generic/map_generated_test.go
index 09e09ca..59a5512 100644
--- a/generic/map_generated_test.go
+++ b/generic/map_generated_test.go
@@ -32,6 +32,12 @@ func TestMap1Generated(t *testing.T) {
 	e = mut.New()
 	assert.True(t, map0.Has(e))
 
+	e = mut.NewWith(&testStruct0{})
+
+	assert.Panics(t, func() {
+		mut.NewWith(&testStruct0{}, e)
+	})
+
 	s0 = mut.Get(e)
 	assert.NotNil(t, s0)
 
@@ -43,7 +49,7 @@ func TestMap1Generated(t *testing.T) {
 	mut.GetUnchecked(e)
 
 	cnt := mut.RemoveEntities(true)
-	assert.Equal(t, 7, cnt)
+	assert.Equal(t, 8, cnt)
 	cnt = mut.RemoveEntities(false)
 	assert.Equal(t, 0, cnt)
 
@@ -63,6 +69,10 @@ func TestMap1Generated(t *testing.T) {
 	q2 := mut2.NewQuery(5, target)
 	assert.Equal(t, 5, q2.Count())
 	q2.Close()
+
+	e = mut2.NewWith(&testRelationA{}, target)
+	mapper := NewMap[testRelationA](&w)
+	assert.Equal(t, target, mapper.GetRelation(e))
 }
 
 func TestMap2Generated(t *testing.T) {
@@ -96,6 +106,12 @@ func TestMap2Generated(t *testing.T) {
 	assert.True(t, map0.Has(e))
 	assert.True(t, map1.Has(e))
 
+	e = mut.NewWith(&testStruct0{}, &testStruct1{})
+
+	assert.Panics(t, func() {
+		mut.NewWith(&testStruct0{}, &testStruct1{}, e)
+	})
+
 	s0, s1 = mut.Get(e)
 	assert.NotNil(t, s0)
 	assert.NotNil(t, s1)
@@ -130,6 +146,10 @@ func TestMap2Generated(t *testing.T) {
 	q2 := mut2.NewQuery(5, target)
 	assert.Equal(t, 5, q2.Count())
 	q2.Close()
+
+	e = mut2.NewWith(&testRelationA{}, &testStruct1{}, target)
+	mapper := NewMap[testRelationA](&w)
+	assert.Equal(t, target, mapper.GetRelation(e))
 }
 
 func TestMap3Generated(t *testing.T) {
@@ -167,6 +187,12 @@ func TestMap3Generated(t *testing.T) {
 	assert.True(t, map0.Has(e))
 	assert.True(t, map1.Has(e))
 
+	e = mut.NewWith(&testStruct0{}, &testStruct1{}, &testStruct2{})
+
+	assert.Panics(t, func() {
+		mut.NewWith(&testStruct0{}, &testStruct1{}, &testStruct2{}, e)
+	})
+
 	s0, s1, _ = mut.Get(e)
 	assert.NotNil(t, s0)
 	assert.NotNil(t, s1)
@@ -201,6 +227,10 @@ func TestMap3Generated(t *testing.T) {
 	q2 := mut2.NewQuery(5, target)
 	assert.Equal(t, 5, q2.Count())
 	q2.Close()
+
+	e = mut2.NewWith(&testRelationA{}, &testStruct1{}, &testStruct2{}, target)
+	mapper := NewMap[testRelationA](&w)
+	assert.Equal(t, target, mapper.GetRelation(e))
 }
 
 func TestMap4Generated(t *testing.T) {
@@ -238,6 +268,15 @@ func TestMap4Generated(t *testing.T) {
 	assert.True(t, map0.Has(e))
 	assert.True(t, map1.Has(e))
 
+	e = mut.NewWith(&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{})
+
+	assert.Panics(t, func() {
+		mut.NewWith(
+			&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+			e,
+		)
+	})
+
 	s0, s1, _, _ = mut.Get(e)
 	assert.NotNil(t, s0)
 	assert.NotNil(t, s1)
@@ -272,6 +311,10 @@ func TestMap4Generated(t *testing.T) {
 	q2 := mut2.NewQuery(5, target)
 	assert.Equal(t, 5, q2.Count())
 	q2.Close()
+
+	e = mut2.NewWith(&testRelationA{}, &testStruct1{}, &testStruct2{}, &testStruct3{}, target)
+	mapper := NewMap[testRelationA](&w)
+	assert.Equal(t, target, mapper.GetRelation(e))
 }
 
 func TestMap5Generated(t *testing.T) {
@@ -311,6 +354,19 @@ func TestMap5Generated(t *testing.T) {
 	assert.True(t, map0.Has(e))
 	assert.True(t, map1.Has(e))
 
+	e = mut.NewWith(
+		&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+		&testStruct4{},
+	)
+
+	assert.Panics(t, func() {
+		mut.NewWith(
+			&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+			&testStruct4{},
+			e,
+		)
+	})
+
 	s0, s1, _, _, _ = mut.Get(e)
 	assert.NotNil(t, s0)
 	assert.NotNil(t, s1)
@@ -347,6 +403,14 @@ func TestMap5Generated(t *testing.T) {
 	q2 := mut2.NewQuery(5, target)
 	assert.Equal(t, 5, q2.Count())
 	q2.Close()
+
+	e = mut2.NewWith(
+		&testRelationA{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+		&testStruct4{},
+		target,
+	)
+	mapper := NewMap[testRelationA](&w)
+	assert.Equal(t, target, mapper.GetRelation(e))
 }
 
 func TestMap6Generated(t *testing.T) {
@@ -386,6 +450,19 @@ func TestMap6Generated(t *testing.T) {
 	assert.True(t, map0.Has(e))
 	assert.True(t, map1.Has(e))
 
+	e = mut.NewWith(
+		&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+		&testStruct4{}, &testStruct5{},
+	)
+
+	assert.Panics(t, func() {
+		mut.NewWith(
+			&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+			&testStruct4{}, &testStruct5{},
+			e,
+		)
+	})
+
 	s0, s1, _, _, _, _ = mut.Get(e)
 	assert.NotNil(t, s0)
 	assert.NotNil(t, s1)
@@ -422,6 +499,14 @@ func TestMap6Generated(t *testing.T) {
 	q2 := mut2.NewQuery(5, target)
 	assert.Equal(t, 5, q2.Count())
 	q2.Close()
+
+	e = mut2.NewWith(
+		&testRelationA{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+		&testStruct4{}, &testStruct5{},
+		target,
+	)
+	mapper := NewMap[testRelationA](&w)
+	assert.Equal(t, target, mapper.GetRelation(e))
 }
 
 func TestMap7Generated(t *testing.T) {
@@ -461,6 +546,19 @@ func TestMap7Generated(t *testing.T) {
 	assert.True(t, map0.Has(e))
 	assert.True(t, map1.Has(e))
 
+	e = mut.NewWith(
+		&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+		&testStruct4{}, &testStruct5{}, &testStruct6{},
+	)
+
+	assert.Panics(t, func() {
+		mut.NewWith(
+			&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+			&testStruct4{}, &testStruct5{}, &testStruct6{},
+			e,
+		)
+	})
+
 	s0, s1, _, _, _, _, _ = mut.Get(e)
 	assert.NotNil(t, s0)
 	assert.NotNil(t, s1)
@@ -497,6 +595,14 @@ func TestMap7Generated(t *testing.T) {
 	q2 := mut2.NewQuery(5, target)
 	assert.Equal(t, 5, q2.Count())
 	q2.Close()
+
+	e = mut2.NewWith(
+		&testRelationA{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+		&testStruct4{}, &testStruct5{}, &testStruct6{},
+		target,
+	)
+	mapper := NewMap[testRelationA](&w)
+	assert.Equal(t, target, mapper.GetRelation(e))
 }
 
 func TestMap8Generated(t *testing.T) {
@@ -536,6 +642,19 @@ func TestMap8Generated(t *testing.T) {
 	assert.True(t, map0.Has(e))
 	assert.True(t, map1.Has(e))
 
+	e = mut.NewWith(
+		&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+		&testStruct4{}, &testStruct5{}, &testStruct6{}, &testStruct7{},
+	)
+
+	assert.Panics(t, func() {
+		mut.NewWith(
+			&testStruct0{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+			&testStruct4{}, &testStruct5{}, &testStruct6{}, &testStruct7{},
+			e,
+		)
+	})
+
 	s0, s1, _, _, _, _, _, _ = mut.Get(e)
 	assert.NotNil(t, s0)
 	assert.NotNil(t, s1)
@@ -572,4 +691,12 @@ func TestMap8Generated(t *testing.T) {
 	q2 := mut2.NewQuery(5, target)
 	assert.Equal(t, 5, q2.Count())
 	q2.Close()
+
+	e = mut2.NewWith(
+		&testRelationA{}, &testStruct1{}, &testStruct2{}, &testStruct3{},
+		&testStruct4{}, &testStruct5{}, &testStruct6{}, &testStruct7{},
+		target,
+	)
+	mapper := NewMap[testRelationA](&w)
+	assert.Equal(t, target, mapper.GetRelation(e))
 }