|
| 1 | +--- |
| 2 | +title: "First Rust Patch" |
| 3 | +extensions: |
| 4 | + pygments: true |
| 5 | +--- |
| 6 | + |
| 7 | +# First Rust Patch |
| 8 | + |
| 9 | +As part of preparing for my Longhorn PHP talk about what is new in PHP 8.5, I |
| 10 | +have been going through various PHP tools and checking to what extent they |
| 11 | +support the new features. When the support is lacking, I have sometimes tried to |
| 12 | +add it myself; this led me to making my first patch in Rust. |
| 13 | + |
| 14 | +Most of the common tools for analyzing PHP code (e.g. PHPStan and PHP |
| 15 | +Codesniffer) are written in PHP. However, I recently came across a new tool |
| 16 | +currently in development, [`mago`][mago], that is written in Rust. I have |
| 17 | +approximately zero experience with Rust - I've seen some Rust code before, but I |
| 18 | +don't recall having written any myself. Until now. |
| 19 | + |
| 20 | +My last RFC for PHP 8.5 was |
| 21 | +[adding support for `#[\Deprecated]` on traits][rfc]. After I merged the |
| 22 | +implementation yesterday, I started working on patches for the various tools to |
| 23 | +add support for the new feature. I hadn't contributed to mago before, but I saw |
| 24 | +that mago already had support for reporting a trait as deprecated when it had a |
| 25 | +`@deprecated` comment, so I figured that it would be pretty simple to try and |
| 26 | +add warnings when the attribute is found. |
| 27 | + |
| 28 | +The logic to warn about using deprecated traits was already there. And, I was |
| 29 | +able to look at an [existing case][nodiscard-code] (processing of the |
| 30 | +`#[\NoDiscard]` attribute) to figure out how to examine attributes. The entirety |
| 31 | +of [my Rust code][mago-patch] was the addition of: |
| 32 | + |
| 33 | +```rust |
| 34 | +if class_like_metadata.attributes.iter().any(|attr| attr.name.eq_ignore_ascii_case("Deprecated")) { |
| 35 | + class_like_metadata.flags |= MetadataFlags::DEPRECATED; |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +to the `scan_class_like` function in the `codex` crate. |
| 40 | + |
| 41 | +I like learning, and I especially like learning new programming languages. Rust |
| 42 | +has been on my list for a while now, and this experience showed me that it has |
| 43 | +some features that PHP lacks. For example, the condition above, if implemented |
| 44 | +in PHP, would look something like |
| 45 | + |
| 46 | +```php startinline=True |
| 47 | +if (array_any($class_like_metadata->attributes, static fn ($attr) => strtolower($attr->name) === 'deprecated')) { |
| 48 | + $class_like_metadata->flags |= MetadataFlags::DEPRECATED; |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +PHP does not support methods on primitives types, and requires more boilerplate |
| 53 | +for its inline anonymous functions. (The ["scalar_objects"][scalar-objects] |
| 54 | +extension adds support for methods on primitive types, but has a disclaimer that |
| 55 | +it is intended to be just a proof of concept.) I can definitely see the appeal |
| 56 | +of Rust, even if I don't fully understand the code that I wrote. I probably |
| 57 | +shouldn't have skipped past the "Hello, World!" step. |
| 58 | + |
| 59 | +[mago]: https://github.com/carthage-software/mago |
| 60 | +[rfc]: https://wiki.php.net/rfc/deprecated_traits |
| 61 | +[nodiscard-code]: https://github.com/carthage-software/mago/blob/dbe604b045af4ffeb3dfc722f1842eb23006aefc/crates/analyzer/src/statement/mod.rs#L336 |
| 62 | +[mago-patch]: https://github.com/carthage-software/mago/pull/386 |
| 63 | +[scalar-objects]: https://github.com/nikic/scalar_objects |
0 commit comments