Skip to content

Commit 93e0467

Browse files
mcmasn-amzndavid-perez
authored andcommitted
Fix for Rust compiler warning about derive helpers (#2581)
## Motivation and Context Follow-up to #2434 ## Description This provides a way to fix a compiler warning. Attributes created using RustMetadata.additionalAttributes may trigger compiler warnings (rust-lang/rust#79202) such as ``` warning: derive helper attribute is used before it is introduced --> src/model.rs:7674:3 | 7674 | #[serde(tag = "_type", content = "_content")] | ^^^^^ 7675 | #[derive( 7676 | serde::Deserialize, | ------------------ the attribute is introduced here | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79202 <rust-lang/rust#79202> ``` ## Testing Added a unit test to validate the sort order is applied correctly to Attributes with isDeriveHelper = true. --------- Co-authored-by: david-perez <[email protected]>
1 parent 6499909 commit 93e0467

File tree

2 files changed

+27
-3
lines changed
  • codegen-core/src
    • main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang
    • test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang

2 files changed

+27
-3
lines changed

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt

+14-3
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,17 @@ data class RustMetadata(
385385
this.copy(derives = derives - withoutDerives.toSet())
386386

387387
fun renderAttributes(writer: RustWriter): RustMetadata {
388-
additionalAttributes.forEach {
388+
val (deriveHelperAttrs, otherAttrs) = additionalAttributes.partition { it.isDeriveHelper }
389+
otherAttrs.forEach {
389390
it.render(writer)
390391
}
392+
391393
Attribute(derive(derives)).render(writer)
392394

395+
// Derive helper attributes must come after derive, see https://github.com/rust-lang/rust/issues/79202
396+
deriveHelperAttrs.forEach {
397+
it.render(writer)
398+
}
393399
return this
394400
}
395401

@@ -450,17 +456,22 @@ enum class AttributeKind {
450456
* [Attributes](https://doc.rust-lang.org/reference/attributes.html) are general free form metadata
451457
* that are interpreted by the compiler.
452458
*
459+
* If the attribute is a "derive helper", such as `#[serde]`, set `isDeriveHelper` to `true` so it is sorted correctly after
460+
* the derive attribute is rendered. (See https://github.com/rust-lang/rust/issues/79202 for why sorting matters.)
461+
*
453462
* For example:
454463
* ```rust
464+
* #[allow(missing_docs)] // <-- this is an attribute, and it is not a derive helper
455465
* #[derive(Clone, PartialEq, Serialize)] // <-- this is an attribute
456-
* #[serde(serialize_with = "abc")] // <-- this is an attribute
466+
* #[serde(serialize_with = "abc")] // <-- this attribute is a derive helper because the `Serialize` derive uses it
457467
* struct Abc {
458468
* a: i64
459469
* }
460470
* ```
461471
*/
462-
class Attribute(val inner: Writable) {
472+
class Attribute(val inner: Writable, val isDeriveHelper: Boolean = false) {
463473
constructor(str: String) : this(writable(str))
474+
constructor(str: String, isDeriveHelper: Boolean) : this(writable(str), isDeriveHelper)
464475
constructor(runtimeType: RuntimeType) : this(runtimeType.writable)
465476

466477
fun render(writer: RustWriter, attributeKind: AttributeKind = AttributeKind.Outer) {

codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt

+13
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ class RustWriterTest {
133133
sut.toString().shouldContain("#[foo]\n/// here's an attribute")
134134
}
135135

136+
@Test
137+
fun `attributes with derive helpers must come after derives`() {
138+
val attr = Attribute("foo", isDeriveHelper = true)
139+
val metadata = RustMetadata(
140+
derives = setOf(RuntimeType.Debug),
141+
additionalAttributes = listOf(Attribute.AllowDeprecated, attr),
142+
visibility = Visibility.PUBLIC,
143+
)
144+
val sut = RustWriter.root()
145+
metadata.render(sut)
146+
sut.toString().shouldContain("#[allow(deprecated)]\n#[derive(std::fmt::Debug)]\n#[foo]")
147+
}
148+
136149
@Test
137150
fun `deprecated attribute without any field`() {
138151
val sut = RustWriter.root()

0 commit comments

Comments
 (0)