diff --git a/CHANGELOG.md b/CHANGELOG.md index b83f15e2e..ed6ac2e5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `emptyMap()` in equality comparison expressions does not cause code generation failures: PR [#814](https://github.com/tact-lang/tact/pull/814) - Maps with `coins` as value type are now correctly handled in structs: PR [#821](https://github.com/tact-lang/tact/pull/821) - Contract method calls in return statements: PR [#829](https://github.com/tact-lang/tact/pull/829) +- Disallow initializers for trait storage fields: PR [#831](https://github.com/tact-lang/tact/pull/831) ## [1.4.4] - 2024-08-18 diff --git a/src/types/__snapshots__/resolveDescriptors.spec.ts.snap b/src/types/__snapshots__/resolveDescriptors.spec.ts.snap index fc2f69cfe..d73af9ee0 100644 --- a/src/types/__snapshots__/resolveDescriptors.spec.ts.snap +++ b/src/types/__snapshots__/resolveDescriptors.spec.ts.snap @@ -575,6 +575,16 @@ Line 7, col 1: " `; +exports[`resolveDescriptors should fail descriptors for trait-field-initialized 1`] = ` +":2:14: Trait field cannot have an initializer +Line 2, col 14: + 1 | trait T { +> 2 | a: Int = 42; // error + ^~ + 3 | +" +`; + exports[`resolveDescriptors should fail descriptors for wf-type-const 1`] = ` ":4:19: Invalid map type. Check https://docs.tact-lang.org/book/maps#allowed-types Line 4, col 19: diff --git a/src/types/resolveDescriptors.ts b/src/types/resolveDescriptors.ts index dc55b0dea..f806e4477 100644 --- a/src/types/resolveDescriptors.ts +++ b/src/types/resolveDescriptors.ts @@ -538,65 +538,75 @@ export function resolveDescriptors(ctx: CompilerContext) { // Trait if (a.kind === "trait") { - for (const f of a.declarations) { - if (f.kind === "field_decl") { + for (const traitDecl of a.declarations) { + if (traitDecl.kind === "field_decl") { if ( types .get(idText(a.name))! - .fields.find((v) => eqNames(v.name, f.name)) + .fields.find((v) => eqNames(v.name, traitDecl.name)) ) { throwCompilationError( - `Field ${idTextErr(f.name)} already exists`, - f.loc, + `Field ${idTextErr(traitDecl.name)} already exists`, + traitDecl.loc, ); } - if (f.as) { + if (traitDecl.as) { throwCompilationError( `Trait field cannot have serialization specifier`, - f.loc, + traitDecl.loc, + ); + } + if (traitDecl.initializer) { + throwCompilationError( + `Trait field cannot have an initializer`, + traitDecl.initializer.loc, ); } types .get(idText(a.name))! .fields.push( buildFieldDescription( - f, + traitDecl, types.get(idText(a.name))!.fields.length, ), ); } else if ( - f.kind === "constant_def" || - f.kind === "constant_decl" + traitDecl.kind === "constant_def" || + traitDecl.kind === "constant_decl" ) { if ( types .get(idText(a.name))! - .fields.find((v) => eqNames(v.name, f.name)) + .fields.find((v) => eqNames(v.name, traitDecl.name)) ) { throwCompilationError( - `Field ${idTextErr(f.name)} already exists`, - f.loc, + `Field ${idTextErr(traitDecl.name)} already exists`, + traitDecl.loc, ); } if ( types .get(idText(a.name))! - .constants.find((v) => eqNames(v.name, f.name)) + .constants.find((v) => + eqNames(v.name, traitDecl.name), + ) ) { throwCompilationError( - `Constant ${idTextErr(f.name)} already exists`, - f.loc, + `Constant ${idTextErr(traitDecl.name)} already exists`, + traitDecl.loc, ); } - if (f.attributes.find((v) => v.type === "override")) { + if ( + traitDecl.attributes.find((v) => v.type === "override") + ) { throwCompilationError( `Trait constant cannot be overridden`, - f.loc, + traitDecl.loc, ); } types .get(idText(a.name))! - .constants.push(buildConstantDescription(f)); + .constants.push(buildConstantDescription(traitDecl)); } } } diff --git a/src/types/test-failed/trait-field-initialized.tact b/src/types/test-failed/trait-field-initialized.tact new file mode 100644 index 000000000..e7e327e6c --- /dev/null +++ b/src/types/test-failed/trait-field-initialized.tact @@ -0,0 +1,12 @@ +trait T { + a: Int = 42; // error + + get fun getA(): Int { + return self.a; + } +} + +contract Test with T { + a: Int = 19; +} +