@neocompose/cli 0.82.3 → 0.82.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/neo-runtime.mjs +118 -18
- package/dist/test-worker.mjs +42 -2
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/commands-and-sync.md +4 -0
- package/skills/neocompose-cli/references/declarations-and-construction.md +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.82.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7d9a013: Preserve generic arguments in Unity animation clip target types and reference lookup factories. Generate clip getters with the declared target type so clips targeting a base class compile correctly. Report incompatible owner/target generic bindings during export instead of emitting C# that cannot compile. Run `neo export` after updating to regenerate the corrected C#.
|
|
8
|
+
|
|
9
|
+
## 0.82.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 8ce5b54: Accept Reference<T> constructor and method parameters during record validation, including enum and scalar slots. Invalid callable parameters now report the parameter name and validation cause.
|
|
14
|
+
|
|
3
15
|
## 0.82.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/neo-runtime.mjs
CHANGED
|
@@ -15508,7 +15508,7 @@ var init_registry = __esm({
|
|
|
15508
15508
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
15509
15509
|
"use strict";
|
|
15510
15510
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
15511
|
-
cliVersion: "0.82.
|
|
15511
|
+
cliVersion: "0.82.5",
|
|
15512
15512
|
projectFileUploadBatchSize: 32,
|
|
15513
15513
|
documentRecords: {
|
|
15514
15514
|
member: {
|
|
@@ -24459,7 +24459,7 @@ function csharpPropertyValueType(ctx, member, saved = false, env, genericBinding
|
|
|
24459
24459
|
}
|
|
24460
24460
|
return csharpValueType(ctx, member, saved, env, genericBindingSaved);
|
|
24461
24461
|
}
|
|
24462
|
-
function animationClipTargetType(ctx, member, env) {
|
|
24462
|
+
function animationClipTargetType(ctx, member, env, ownerClassId) {
|
|
24463
24463
|
const clipClass = resolveInheritanceChain(member.classId, ctx.classes).find(
|
|
24464
24464
|
(candidate) => candidate.system?.worldKind === NeoWorldSystemClassKind.AnimationClip
|
|
24465
24465
|
);
|
|
@@ -24540,7 +24540,47 @@ function animationClipTargetType(ctx, member, env) {
|
|
|
24540
24540
|
});
|
|
24541
24541
|
return null;
|
|
24542
24542
|
}
|
|
24543
|
-
|
|
24543
|
+
const suffix = constructedTypeArgumentsSuffix(ctx, bindingMember, true, env);
|
|
24544
|
+
if (suffix === null) return null;
|
|
24545
|
+
const constructedTarget = `${targetType}${suffix}`;
|
|
24546
|
+
if (ownerClassId !== void 0) {
|
|
24547
|
+
const ownerName = ctx.typeNames.get(ownerClassId) ?? ownerClassId;
|
|
24548
|
+
if (!resolveInheritanceChain(ownerClassId, ctx.classes).some(
|
|
24549
|
+
(ancestor) => ancestor.id === bindingMember.classId
|
|
24550
|
+
)) {
|
|
24551
|
+
ctx.diagnostics.push({
|
|
24552
|
+
severity: "error",
|
|
24553
|
+
message: `Animation clip "${member.name}" targets ${constructedTarget}, which is not its owner ${ownerName} or a base of it.`,
|
|
24554
|
+
path: memberPath3
|
|
24555
|
+
});
|
|
24556
|
+
return null;
|
|
24557
|
+
}
|
|
24558
|
+
const ownerArguments = [];
|
|
24559
|
+
for (const { param } of resolveGenericScopeForEmission(
|
|
24560
|
+
ctx,
|
|
24561
|
+
bindingMember.classId
|
|
24562
|
+
)) {
|
|
24563
|
+
const argument2 = csharpGenericParamType(
|
|
24564
|
+
ctx,
|
|
24565
|
+
param.id,
|
|
24566
|
+
true,
|
|
24567
|
+
env,
|
|
24568
|
+
memberPath3
|
|
24569
|
+
);
|
|
24570
|
+
if (argument2 === null) return null;
|
|
24571
|
+
ownerArguments.push(argument2);
|
|
24572
|
+
}
|
|
24573
|
+
const ownerTarget = `${targetType}${ownerArguments.length === 0 ? "" : `<${ownerArguments.join(", ")}>`}`;
|
|
24574
|
+
if (ownerTarget !== constructedTarget) {
|
|
24575
|
+
ctx.diagnostics.push({
|
|
24576
|
+
severity: "error",
|
|
24577
|
+
message: `Animation clip "${member.name}" targets ${constructedTarget}, but owner ${ownerName} has target type ${ownerTarget}. A clip must target its owner or a constructed base of it.`,
|
|
24578
|
+
path: memberPath3
|
|
24579
|
+
});
|
|
24580
|
+
return null;
|
|
24581
|
+
}
|
|
24582
|
+
}
|
|
24583
|
+
return constructedTarget;
|
|
24544
24584
|
}
|
|
24545
24585
|
function csharpTypeInfoValueType(ctx, typeInfo, saved, genericEnv, genericBindingSaved = saved) {
|
|
24546
24586
|
const optional2 = !typeInfo.required;
|
|
@@ -128632,6 +128672,8 @@ function typeInfoInterfaceIds(value) {
|
|
|
128632
128672
|
}
|
|
128633
128673
|
if ("entryTypeInfo" in value)
|
|
128634
128674
|
ids.push(...typeInfoInterfaceIds(value.entryTypeInfo));
|
|
128675
|
+
if ("targetTypeInfo" in value)
|
|
128676
|
+
ids.push(...typeInfoInterfaceIds(value.targetTypeInfo));
|
|
128635
128677
|
if (isRecord8(value.typeArguments)) {
|
|
128636
128678
|
for (const argument2 of Object.values(value.typeArguments)) {
|
|
128637
128679
|
ids.push(...typeInfoInterfaceIds(argument2));
|
|
@@ -128711,6 +128753,15 @@ function isOpaqueNSTypeInfo(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
|
128711
128753
|
if (value.type === 22) {
|
|
128712
128754
|
return typeof value.interfaceId === "string" && value.interfaceId.length > 0;
|
|
128713
128755
|
}
|
|
128756
|
+
if (value.type === 29 /* Reference */) {
|
|
128757
|
+
if (ancestors.has(value)) return false;
|
|
128758
|
+
ancestors.add(value);
|
|
128759
|
+
try {
|
|
128760
|
+
return isOpaqueNSTypeInfo(value.targetTypeInfo, ancestors);
|
|
128761
|
+
} finally {
|
|
128762
|
+
ancestors.delete(value);
|
|
128763
|
+
}
|
|
128764
|
+
}
|
|
128714
128765
|
if (value.type === 25) {
|
|
128715
128766
|
if (!Array.isArray(value.argumentTypes) || ancestors.has(value)) {
|
|
128716
128767
|
return false;
|
|
@@ -128750,6 +128801,9 @@ function isOpaqueNSTypeInfo(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
|
128750
128801
|
}
|
|
128751
128802
|
function opaqueTypeInfoContainsUnknown(value) {
|
|
128752
128803
|
if (value.type === "Unknown") return true;
|
|
128804
|
+
if (value.type === 29 /* Reference */) {
|
|
128805
|
+
return isRecord8(value.targetTypeInfo) && opaqueTypeInfoContainsUnknown(value.targetTypeInfo);
|
|
128806
|
+
}
|
|
128753
128807
|
if (value.type === 5 /* Dictionary */ || value.type === 6 /* List */ || value.type === 28 /* Set */ || value.type === 9 /* Lookup */) {
|
|
128754
128808
|
return isRecord8(value.entryTypeInfo) && opaqueTypeInfoContainsUnknown(value.entryTypeInfo);
|
|
128755
128809
|
}
|
|
@@ -128838,6 +128892,7 @@ function opaqueFunctionGenericReference(value, matches) {
|
|
|
128838
128892
|
}
|
|
128839
128893
|
const children = [
|
|
128840
128894
|
value.entryTypeInfo,
|
|
128895
|
+
value.targetTypeInfo,
|
|
128841
128896
|
value.returnTypeInfo,
|
|
128842
128897
|
...Array.isArray(value.argumentTypes) ? value.argumentTypes : [],
|
|
128843
128898
|
...isRecord8(value.typeArguments) ? Object.values(value.typeArguments) : []
|
|
@@ -128855,7 +128910,38 @@ function isOpaqueNSFunctionReturnTypeInfo(value) {
|
|
|
128855
128910
|
return isOpaqueNSTypeInfo(value);
|
|
128856
128911
|
}
|
|
128857
128912
|
function isOpaqueCallableArgumentTypeInfo(value) {
|
|
128858
|
-
return
|
|
128913
|
+
return opaqueCallableArgumentError(value) === null;
|
|
128914
|
+
}
|
|
128915
|
+
function opaqueCallableArgumentError(value) {
|
|
128916
|
+
if (!isRecord8(value)) return "must be an argument type object.";
|
|
128917
|
+
const { type, required: required2 } = value;
|
|
128918
|
+
if (!isOpaqueNSTypeInfo(value)) {
|
|
128919
|
+
if (type === 29 /* Reference */) {
|
|
128920
|
+
if (typeof required2 !== "boolean") {
|
|
128921
|
+
return "Reference required must be a boolean.";
|
|
128922
|
+
}
|
|
128923
|
+
return "Reference targetTypeInfo is invalid.";
|
|
128924
|
+
}
|
|
128925
|
+
return "type information is invalid.";
|
|
128926
|
+
}
|
|
128927
|
+
if (!isOpaqueCallableArgumentIdentifier(value.name)) {
|
|
128928
|
+
return "name is invalid or reserved.";
|
|
128929
|
+
}
|
|
128930
|
+
if (opaqueTypeInfoContainsUnknown(value)) {
|
|
128931
|
+
return "type contains Unknown.";
|
|
128932
|
+
}
|
|
128933
|
+
if (!hasValidOpaqueParameterDefault(value)) {
|
|
128934
|
+
return "defaultValue is invalid for its type.";
|
|
128935
|
+
}
|
|
128936
|
+
return null;
|
|
128937
|
+
}
|
|
128938
|
+
function assertOpaqueCallableArgumentsValid(arguments_, owner) {
|
|
128939
|
+
for (const [index, argument2] of arguments_.entries()) {
|
|
128940
|
+
const error = opaqueCallableArgumentError(argument2);
|
|
128941
|
+
if (error === null) continue;
|
|
128942
|
+
const label = isRecord8(argument2) && typeof argument2.name === "string" ? `"${argument2.name}"` : `at index ${index}`;
|
|
128943
|
+
throw new Error(`${owner} parameter ${label} ${error}`);
|
|
128944
|
+
}
|
|
128859
128945
|
}
|
|
128860
128946
|
function hasValidOpaqueParameterDefault(value) {
|
|
128861
128947
|
const wrapper = value.defaultValue;
|
|
@@ -128914,7 +129000,7 @@ function assertOpaqueParameterDefaultsValid(member) {
|
|
|
128914
129000
|
for (const argument2 of argumentTypes) {
|
|
128915
129001
|
if (!isRecord8(argument2) || !hasValidOpaqueParameterDefault(argument2)) {
|
|
128916
129002
|
throw new Error(
|
|
128917
|
-
`Function "${member.name}" (${member.id})
|
|
129003
|
+
`Function "${member.name}" (${member.id}) parameter "${isRecord8(argument2) ? String(argument2.name) : "<invalid>"}" defaultValue is invalid for its type.`
|
|
128918
129004
|
);
|
|
128919
129005
|
}
|
|
128920
129006
|
parameters.push(argument2);
|
|
@@ -129756,6 +129842,15 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
|
|
|
129756
129842
|
)
|
|
129757
129843
|
};
|
|
129758
129844
|
}
|
|
129845
|
+
if (typeInfo.type === 29 /* Reference */) {
|
|
129846
|
+
return {
|
|
129847
|
+
...typeInfo,
|
|
129848
|
+
targetTypeInfo: substituteTypeInfoForClass(
|
|
129849
|
+
typeInfo.targetTypeInfo,
|
|
129850
|
+
schemaClass2
|
|
129851
|
+
)
|
|
129852
|
+
};
|
|
129853
|
+
}
|
|
129759
129854
|
if (typeInfo.type === 25 && Array.isArray(typeInfo.argumentTypes)) {
|
|
129760
129855
|
return {
|
|
129761
129856
|
...typeInfo,
|
|
@@ -130224,11 +130319,10 @@ function assertOpaqueConstructorValid(declaredConstructor) {
|
|
|
130224
130319
|
);
|
|
130225
130320
|
}
|
|
130226
130321
|
const argumentTypes = declaredConstructor.argumentTypes;
|
|
130227
|
-
|
|
130228
|
-
|
|
130229
|
-
|
|
130230
|
-
|
|
130231
|
-
}
|
|
130322
|
+
assertOpaqueCallableArgumentsValid(
|
|
130323
|
+
argumentTypes,
|
|
130324
|
+
`Constructor "${declaredConstructor.id}"`
|
|
130325
|
+
);
|
|
130232
130326
|
const names = /* @__PURE__ */ new Set();
|
|
130233
130327
|
for (const argument2 of argumentTypes) {
|
|
130234
130328
|
const name = argument2.name;
|
|
@@ -130529,9 +130623,10 @@ function assertOpaqueNSFunctionValid(member, membersById, typeInfoInDeclaringCla
|
|
|
130529
130623
|
if (!Array.isArray(member.argumentTypes)) {
|
|
130530
130624
|
throw new Error(`NSFunction "${member.id}" argumentTypes are invalid.`);
|
|
130531
130625
|
}
|
|
130532
|
-
|
|
130533
|
-
|
|
130534
|
-
|
|
130626
|
+
assertOpaqueCallableArgumentsValid(
|
|
130627
|
+
member.argumentTypes,
|
|
130628
|
+
`NSFunction "${member.id}"`
|
|
130629
|
+
);
|
|
130535
130630
|
const argumentNames = /* @__PURE__ */ new Set();
|
|
130536
130631
|
for (const argument2 of member.argumentTypes) {
|
|
130537
130632
|
const name = argument2.name;
|
|
@@ -181269,7 +181364,12 @@ function generateMember(ctx, schemaKey, memberId, saved, modifier, emitBody, own
|
|
|
181269
181364
|
);
|
|
181270
181365
|
}
|
|
181271
181366
|
if (isMemberClassBase(member) && (ctx.worldKinds.get(member.classId) ?? null) === NeoWorldSystemClassKind.AnimationClip) {
|
|
181272
|
-
const targetType = animationClipTargetType(
|
|
181367
|
+
const targetType = animationClipTargetType(
|
|
181368
|
+
ctx,
|
|
181369
|
+
member,
|
|
181370
|
+
genericEnv,
|
|
181371
|
+
ownerClassId
|
|
181372
|
+
);
|
|
181273
181373
|
if (targetType === null) {
|
|
181274
181374
|
return [`// Skipped invalid animation clip member: ${memberName}`];
|
|
181275
181375
|
}
|
|
@@ -181288,7 +181388,7 @@ function generateMember(ctx, schemaKey, memberId, saved, modifier, emitBody, own
|
|
|
181288
181388
|
"get",
|
|
181289
181389
|
"{",
|
|
181290
181390
|
...indent([
|
|
181291
|
-
`return client.GetOrCreateAnimationClip(this, "${escapeCSharpString(schemaKey)}");`
|
|
181391
|
+
`return client.GetOrCreateAnimationClip<${targetType}>(this, "${escapeCSharpString(schemaKey)}");`
|
|
181292
181392
|
]),
|
|
181293
181393
|
"}"
|
|
181294
181394
|
]),
|
|
@@ -183325,7 +183425,7 @@ function lookupSelectionFactory(ctx, member, selection2, saved, writeGuardMember
|
|
|
183325
183425
|
const targetClass = lookupTargetClassProjection(ctx, member, genericEnv);
|
|
183326
183426
|
if (targetClass === null) return null;
|
|
183327
183427
|
const typeName = ctx.typeNames.get(targetClass.classId) ?? "NeoNode";
|
|
183328
|
-
const savedTypeRef = qualifyGeneratedType(ctx, savedTypeName(typeName))
|
|
183428
|
+
const savedTypeRef = `${qualifyGeneratedType(ctx, savedTypeName(typeName))}${targetClass.constructedSuffix}`;
|
|
183329
183429
|
const writable = `writable${selection2[0].toUpperCase()}${selection2.slice(1)}`;
|
|
183330
183430
|
if (lookupHasRuntimeOwnership(member) && schemaClassHasWritableFamily(ctx, targetClass.classId))
|
|
183331
183431
|
return `${selection2} is NeoMemberClassWritable ${writable} ? ${savedTypeRef}.CreateWritable(client, ${writable}) : ${savedTypeRef}.Create(client, (NeoMemberClass)${selection2})`;
|
|
@@ -187038,7 +187138,7 @@ var UNITY_CODEGEN_REVISION;
|
|
|
187038
187138
|
var init_unity_codegen_revision = __esm({
|
|
187039
187139
|
"../src/models/exports/unity-codegen-revision.ts"() {
|
|
187040
187140
|
"use strict";
|
|
187041
|
-
UNITY_CODEGEN_REVISION = "
|
|
187141
|
+
UNITY_CODEGEN_REVISION = "2734215e6a19e5f077e5f76093f84e82b0ee6fe9e3bc92a4f44c43c2448c63ba";
|
|
187042
187142
|
}
|
|
187043
187143
|
});
|
|
187044
187144
|
|
|
@@ -208017,7 +208117,7 @@ var releaseWorkspaceLock = () => void 0;
|
|
|
208017
208117
|
async function main() {
|
|
208018
208118
|
const args = parseArgs(process.argv.slice(2));
|
|
208019
208119
|
if (args.command === "--version") {
|
|
208020
|
-
console.log("0.82.
|
|
208120
|
+
console.log("0.82.5");
|
|
208021
208121
|
return;
|
|
208022
208122
|
}
|
|
208023
208123
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/dist/test-worker.mjs
CHANGED
|
@@ -60511,7 +60511,7 @@ function csharpPropertyValueType(ctx, member, saved = false, env, genericBinding
|
|
|
60511
60511
|
}
|
|
60512
60512
|
return csharpValueType(ctx, member, saved, env, genericBindingSaved);
|
|
60513
60513
|
}
|
|
60514
|
-
function animationClipTargetType(ctx, member, env) {
|
|
60514
|
+
function animationClipTargetType(ctx, member, env, ownerClassId) {
|
|
60515
60515
|
const clipClass = resolveInheritanceChain(member.classId, ctx.classes).find(
|
|
60516
60516
|
(candidate) => candidate.system?.worldKind === NeoWorldSystemClassKind.AnimationClip
|
|
60517
60517
|
);
|
|
@@ -60592,7 +60592,47 @@ function animationClipTargetType(ctx, member, env) {
|
|
|
60592
60592
|
});
|
|
60593
60593
|
return null;
|
|
60594
60594
|
}
|
|
60595
|
-
|
|
60595
|
+
const suffix = constructedTypeArgumentsSuffix(ctx, bindingMember, true, env);
|
|
60596
|
+
if (suffix === null) return null;
|
|
60597
|
+
const constructedTarget = `${targetType}${suffix}`;
|
|
60598
|
+
if (ownerClassId !== void 0) {
|
|
60599
|
+
const ownerName = ctx.typeNames.get(ownerClassId) ?? ownerClassId;
|
|
60600
|
+
if (!resolveInheritanceChain(ownerClassId, ctx.classes).some(
|
|
60601
|
+
(ancestor) => ancestor.id === bindingMember.classId
|
|
60602
|
+
)) {
|
|
60603
|
+
ctx.diagnostics.push({
|
|
60604
|
+
severity: "error",
|
|
60605
|
+
message: `Animation clip "${member.name}" targets ${constructedTarget}, which is not its owner ${ownerName} or a base of it.`,
|
|
60606
|
+
path: memberPath
|
|
60607
|
+
});
|
|
60608
|
+
return null;
|
|
60609
|
+
}
|
|
60610
|
+
const ownerArguments = [];
|
|
60611
|
+
for (const { param } of resolveGenericScopeForEmission(
|
|
60612
|
+
ctx,
|
|
60613
|
+
bindingMember.classId
|
|
60614
|
+
)) {
|
|
60615
|
+
const argument2 = csharpGenericParamType(
|
|
60616
|
+
ctx,
|
|
60617
|
+
param.id,
|
|
60618
|
+
true,
|
|
60619
|
+
env,
|
|
60620
|
+
memberPath
|
|
60621
|
+
);
|
|
60622
|
+
if (argument2 === null) return null;
|
|
60623
|
+
ownerArguments.push(argument2);
|
|
60624
|
+
}
|
|
60625
|
+
const ownerTarget = `${targetType}${ownerArguments.length === 0 ? "" : `<${ownerArguments.join(", ")}>`}`;
|
|
60626
|
+
if (ownerTarget !== constructedTarget) {
|
|
60627
|
+
ctx.diagnostics.push({
|
|
60628
|
+
severity: "error",
|
|
60629
|
+
message: `Animation clip "${member.name}" targets ${constructedTarget}, but owner ${ownerName} has target type ${ownerTarget}. A clip must target its owner or a constructed base of it.`,
|
|
60630
|
+
path: memberPath
|
|
60631
|
+
});
|
|
60632
|
+
return null;
|
|
60633
|
+
}
|
|
60634
|
+
}
|
|
60635
|
+
return constructedTarget;
|
|
60596
60636
|
}
|
|
60597
60637
|
function csharpTypeInfoValueType(ctx, typeInfo, saved, genericEnv, genericBindingSaved = saved) {
|
|
60598
60638
|
const optional2 = !typeInfo.required;
|
package/package.json
CHANGED
|
@@ -129,7 +129,7 @@ wrappers.
|
|
|
129
129
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
130
130
|
|
|
131
131
|
```html
|
|
132
|
-
<!-- reviewed-through-cli: 0.82.
|
|
132
|
+
<!-- reviewed-through-cli: 0.82.5 -->
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -331,6 +331,10 @@ to earlier content reuses that result after verifying output bytes; changed or
|
|
|
331
331
|
missing outputs are regenerated. Edited content is validated
|
|
332
332
|
even when C# generation is skipped. After a CLI code-generation fix, run
|
|
333
333
|
`neo export` again; generator revision changes invalidate cached C# output.
|
|
334
|
+
Generated animation clip targets and reference lookup factories retain constructed
|
|
335
|
+
generic arguments, including supported forwarded bindings. Clip getters use the
|
|
336
|
+
declared target type when the owner is a derived class. Export reports an error
|
|
337
|
+
when a clip target does not match the owner or one of its constructed base types.
|
|
334
338
|
New instances that reuse existing member-localized text retain its shared ID
|
|
335
339
|
and translations in the export.
|
|
336
340
|
|
|
@@ -256,11 +256,11 @@ code types; see the NeoScript reference for handle and slot references.
|
|
|
256
256
|
`public Reference<Config> Config` selects one row and reads as `Config`.
|
|
257
257
|
`public Set<Reference<Config>> Configs` selects several and reads as
|
|
258
258
|
`Set<Config>`. `public Reference<int> TrackedStat` names another member's int.
|
|
259
|
-
`Reference<T>` also works as a
|
|
260
|
-
unbound generic argument such as
|
|
261
|
-
a single reference returns one
|
|
262
|
-
`@settings(collection:)` is an error; the language
|
|
263
|
-
it.
|
|
259
|
+
`Reference<T>` also works as a constructor or method parameter, a collection
|
|
260
|
+
element, a dictionary value, and an unbound generic argument such as
|
|
261
|
+
`Box<Reference<int>>`. An initializer body for a single reference returns one
|
|
262
|
+
row, never a set. `T` with `@settings(collection:)` is an error; the language
|
|
263
|
+
server's quick fix respells it.
|
|
264
264
|
|
|
265
265
|
`@settings(collection: Owner.Member)` binds a class reference to one
|
|
266
266
|
collection. Without it the reference is unbound: it selects any stored row of
|