Restricting trait implementability and field mutability
摘要
Rust 编译器团队宣布 RFC 3323 "Restrictions" 已在 nightly 上开放测试,包含两个特性:impl restriction 和 mut restriction。impl restriction 允许显式限制 trait 的实现范围(如 impl (crate)、impl (super)、impl (in path)),作为 sealed trait 模式的更直接替代方案,并能给出更清晰的错误信息。mut restriction 允许限制字段的可变访问范围(如 mut (crate)),提供 getter 方法的替代方案,且与借用检查器配合更好;该特性也适用于枚举变体和联合体的字段。为保持不变量,若当前作用域无法修改某个 mut 受限字段,则禁止使用结构体表达式构造该类型。文中附有代码示例和错误信息示例,并邀请社区在 nightly 上试用(需启用 #![feature (impl restriction)] 或 #![feature (mut restriction)]),反馈可提交至专门的 issue,语法问题仍是待解决的主要开放问题。该实现是 Google Summer of Code 2026 项目的一部分。
荐读理由
RFC 3323 的 impl 与 mut 限制已进 nightly 可测,能直接替代 sealed trait 模式并让字段只读访问绕过 getter,你写库时值得上手试
原文
Call for testing: Restricting trait implementability and field mutability
Aug. 10, 2026 · Ryosuke Yamano on behalf of The Compiler Team
We are excited to announce that RFC 3323 "Restrictions" is ready for testing on nightly Rust. In this post, we will briefly describe the features. If you are already familiar with them, you can skip ahead to the How can I help? section.
The RFC is split into two features: impl_restriction and mut_restriction.
What is impl_restriction?
The impl_restriction feature allows explicit restriction of the scope in which a trait may be implemented.
For example, consider a trait Foo with a method that we want users to be able to call, while preventing downstream crates from providing their own implementations. With this feature, we can write:
#![feature(impl_restriction)]
pub impl(crate) trait Foo {
fn method();
}
impl Foo for usize {
fn method() {}
}
The impl(crate) restriction prevents Foo from being implemented outside the current crate. As with pub, other paths can also be specified, such as impl(super) or impl(in path).
Without this feature, this use case is typically handled using the sealed trait pattern, which is described in the Rust API Guidelines.
In short, this pattern defines a public Sealed trait inside a private module and makes it a supertrait of Foo. Because downstream crates cannot name Sealed, they cannot implement Foo.
pub trait Foo: private::Sealed {
fn method();
}
impl Foo for usize {
fn method() {}
}
mod private {
pub trait Sealed {}
impl Sealed for usize {}
}
However, this pattern requires defining an additional Sealed trait. The new impl_restriction feature provides a more direct and concise way to express the same restriction.
The feature also allows the compiler to produce a more direct error message when an implementation is attempted outside the permitted scope.
For example, the following code:
#![feature(impl_restriction)]
pub mod foo {
pub mod bar {
pub(crate) impl(super) trait Foo {}
}
impl bar::Foo for i8 {}
}
impl foo::bar::Foo for u8 {}
results in the following error:
error: trait cannot be implemented outside `crate::foo`
--> src/lib.rs:12:1
|
12 | impl foo::bar::Foo for u8 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: trait restricted here
--> src/lib.rs:5:20
|
5 | pub(crate) impl(super) trait Foo {}
| ^^^^^^^^^^^
What is mut_restriction?
The mut_restriction feature allows explicit restriction of the scope in which a field may be mutated.
For example, consider a struct Bar with a field alpha that can be read from any crate but can only be mutated within the crate where Bar is defined. With this feature, we can write:
#![feature(mut_restriction)]
pub struct Bar {
pub mut(crate) alpha: u8,
}
The mut(crate) restriction prevents alpha from being mutated outside the current crate. As with pub, other paths can also be specified, such as mut(super) or mut(in path).
This provides an alternative to getter methods by allowing read-only access through direct field access. It can also work better with the borrow checker, which can track borrows at the field level and allow disjoint fields to be borrowed independently.
When code attempts to mutate a restricted field outside the permitted scope, the compiler produces a direct error message. For example, the following code:
#![feature(mut_restriction)]
pub mod foo {
pub struct Bar {
pub mut(self) alpha: &'static str,
}
impl Bar {
pub fn mutate_inner(&mut self) {
self.alpha = "inner";
}
}
}
impl foo::Bar {
pub fn mutate_outer(&mut self) {
self.alpha = "outer";
}
}
results in the following error:
error: field `alpha` cannot be mutated outside `crate::foo`
--> src/lib.rs:19:9
|
5 | pub mut(self) alpha: &'static str,
| --------- field restricted here
...
19 | self.alpha = "outer";
| ^^^^^^^^^^^^^^^^^^^^
The mut_restriction feature can also be used with fields of enum variants and unions. For example, we can write:
pub enum Foo {
Alpha { mut(crate) x: u8 },
Beta(mut(crate) u8),
}
pub union Bar {
pub mut(crate) i: i32,
pub f: f32,
}
pub struct Baz(pub mut(crate) u8);
Restricting construction with struct expressions
A common reason to use mut-restricted fields is to preserve an invariant. However, allowing unrestricted construction with struct expressions would let users create values that have not been validated, potentially violating that invariant.
Thus, we disallow struct expressions if any mut-restricted field cannot be mutated from the current scope. For example, the following code:
#![feature(mut_restriction)]
pub mod foo {
pub struct Baz {
pub alpha: u8,
pub mut(self) beta: u8,
}
}
fn main() {
let bar = foo::Baz { alpha: 0, beta: 1 };
}
results in the following error:
error: `Baz` cannot be constructed using a `struct` expression outside `crate::foo`
--> src/main.rs:11:15
|
6 | pub mut(self) beta: u8,
| --------- field restricted here
...
11 | let bar = foo::Baz { alpha: 0, beta: 1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
How can I help?
We'd love for you to try out these new features and share your feedback! To get started, use the latest Rust nightly compiler1 and enable #![feature(impl_restriction)] or #![feature(mut_restriction)].
Please share your feedback in the dedicated feedback issue.
In particular, the RFC lists several unresolved questions. One of the main open questions concerns the syntax, which is still open to discussion. Please try out the features and let us know what you think!
Acknowledgements
These features were implemented as part of a Google Summer of Code 2026 project. I would like to thank my mentors, Jacob Pratt and Urgau, for their guidance and support throughout the project.
- Make sure to run
rustup update nightlyfirst, as these features are very new and may not be available on an older nightly toolchain. ↩
这条对你有帮助吗?