Skip to content

Commit 81eb844

Browse files
authored
Rollup merge of #156824 - CoCo-Japan-pan:mut-restriction-parse, r=Urgau,jhpratt
Parse `mut` restrictions This PR is part of the progress implementing `mut` restrictions proposed in [RFC 3323](https://rust-lang.github.io/rfcs/3323-restrictions.html), and linked to a [GSoC proposal](https://rust-lang.zulipchat.com/#narrow/channel/421156-gsoc/topic/Project.3A.20Implementing.20impl.20and.20mut.20restrictions/with/592352432). This PR focuses solely on the parsing of `mut` restrictions. The keyword order is `pub(...) mut(...) unsafe field`. The new syntax is guared by `#[feature(mut_restriction)]` feature gate. Tracking Issue: #105077 r? @Urgau cc @jhpratt
2 parents a06c1ca + 572a2e4 commit 81eb844

26 files changed

Lines changed: 1068 additions & 59 deletions

File tree

compiler/rustc_ast/src/ast.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3582,6 +3582,13 @@ pub struct ImplRestriction {
35823582
pub tokens: Option<LazyAttrTokenStream>,
35833583
}
35843584

3585+
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
3586+
pub struct MutRestriction {
3587+
pub kind: RestrictionKind,
3588+
pub span: Span,
3589+
pub tokens: Option<LazyAttrTokenStream>,
3590+
}
3591+
35853592
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
35863593
pub enum RestrictionKind {
35873594
Unrestricted,
@@ -3597,6 +3604,7 @@ pub struct FieldDef {
35973604
pub id: NodeId,
35983605
pub span: Span,
35993606
pub vis: Visibility,
3607+
pub mut_restriction: MutRestriction,
36003608
pub safety: Safety,
36013609
pub ident: Option<Ident>,
36023610

compiler/rustc_ast/src/ast_traits.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use std::marker::PhantomData;
88
use crate::tokenstream::LazyAttrTokenStream;
99
use crate::{
1010
Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
11-
FieldDef, ForeignItem, GenericParam, ImplRestriction, Item, NodeId, Param, Pat, PatField, Path,
12-
Stmt, StmtKind, Ty, Variant, Visibility, WherePredicate,
11+
FieldDef, ForeignItem, GenericParam, ImplRestriction, Item, MutRestriction, NodeId, Param, Pat,
12+
PatField, Path, Stmt, StmtKind, Ty, Variant, Visibility, WherePredicate,
1313
};
1414

1515
/// A trait for AST nodes having an ID.
@@ -108,7 +108,8 @@ impl_has_tokens!(
108108
Path,
109109
Ty,
110110
Visibility,
111-
ImplRestriction
111+
ImplRestriction,
112+
MutRestriction,
112113
);
113114
impl_has_tokens_none!(
114115
Arm,
@@ -254,7 +255,17 @@ impl_has_attrs!(
254255
Variant,
255256
WherePredicate,
256257
);
257-
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility, ImplRestriction);
258+
impl_has_attrs_none!(
259+
Attribute,
260+
AttrItem,
261+
Block,
262+
Pat,
263+
Path,
264+
Ty,
265+
Visibility,
266+
ImplRestriction,
267+
MutRestriction
268+
);
258269

259270
impl<T: HasAttrs> HasAttrs for Box<T> {
260271
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;

compiler/rustc_ast/src/visit.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -582,12 +582,14 @@ macro_rules! common_visitor_and_walkers {
582582
fn visit_generics(Generics);
583583
fn visit_inline_asm(InlineAsm);
584584
fn visit_inline_asm_sym(InlineAsmSym);
585+
fn visit_impl_restriction(ImplRestriction);
585586
//fn visit_item(Item);
586587
fn visit_label(Label);
587588
fn visit_lifetime(Lifetime, _ctxt: LifetimeCtxt);
588589
fn visit_local(Local);
589590
fn visit_mac_call(MacCall);
590591
fn visit_macro_def(MacroDef);
592+
fn visit_mut_restriction(MutRestriction);
591593
fn visit_param_bound(GenericBound, _ctxt: BoundKind);
592594
fn visit_param(Param);
593595
fn visit_pat_field(PatField);
@@ -597,7 +599,6 @@ macro_rules! common_visitor_and_walkers {
597599
fn visit_poly_trait_ref(PolyTraitRef);
598600
fn visit_precise_capturing_arg(PreciseCapturingArg);
599601
fn visit_qself(QSelf);
600-
fn visit_impl_restriction(ImplRestriction);
601602
fn visit_trait_ref(TraitRef);
602603
fn visit_ty_pat(TyPat);
603604
fn visit_ty(Ty);
@@ -1106,12 +1107,14 @@ macro_rules! common_visitor_and_walkers {
11061107
pub fn walk_generics(Generics);
11071108
pub fn walk_inline_asm(InlineAsm);
11081109
pub fn walk_inline_asm_sym(InlineAsmSym);
1110+
pub fn walk_impl_restriction(ImplRestriction);
11091111
//pub fn walk_item(Item);
11101112
pub fn walk_label(Label);
11111113
pub fn walk_lifetime(Lifetime);
11121114
pub fn walk_local(Local);
11131115
pub fn walk_mac(MacCall);
11141116
pub fn walk_macro_def(MacroDef);
1117+
pub fn walk_mut_restriction(MutRestriction);
11151118
pub fn walk_param_bound(GenericBound);
11161119
pub fn walk_param(Param);
11171120
pub fn walk_pat_field(PatField);
@@ -1121,7 +1124,6 @@ macro_rules! common_visitor_and_walkers {
11211124
pub fn walk_poly_trait_ref(PolyTraitRef);
11221125
pub fn walk_precise_capturing_arg(PreciseCapturingArg);
11231126
pub fn walk_qself(QSelf);
1124-
pub fn walk_impl_restriction(ImplRestriction);
11251127
pub fn walk_trait_ref(TraitRef);
11261128
pub fn walk_ty_pat(TyPat);
11271129
pub fn walk_ty(Ty);

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
505505
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
506506
gate_all!(move_expr, "`move(expr)` syntax is experimental");
507507
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
508+
gate_all!(mut_restriction, "`mut` restrictions are experimental");
508509
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
509510
gate_all!(postfix_match, "postfix match is experimental");
510511
gate_all!(return_type_notation, "return type notation is experimental");

compiler/rustc_ast_pretty/src/pprust/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ pub fn impl_restriction_to_string(r: &ast::ImplRestriction) -> String {
8484
State::new().impl_restriction_to_string(r)
8585
}
8686

87+
pub fn mut_restriction_to_string(r: &ast::MutRestriction) -> String {
88+
State::new().mut_restriction_to_string(r)
89+
}
90+
8791
pub fn meta_list_item_to_string(li: &ast::MetaItemInner) -> String {
8892
State::new().meta_list_item_to_string(li)
8993
}

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
11531153
Self::to_string(|s| s.print_impl_restriction(r))
11541154
}
11551155

1156+
fn mut_restriction_to_string(&self, r: &ast::MutRestriction) -> String {
1157+
Self::to_string(|s| s.print_mut_restriction(r))
1158+
}
1159+
11561160
fn block_to_string(&self, blk: &ast::Block) -> String {
11571161
Self::to_string(|s| {
11581162
let (cb, ib) = s.head("");

compiler/rustc_ast_pretty/src/pprust/state/item.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,20 @@ impl<'a> State<'a> {
511511
}
512512
}
513513

514+
pub(crate) fn print_mut_restriction(&mut self, mut_restriction: &ast::MutRestriction) {
515+
match &mut_restriction.kind {
516+
ast::RestrictionKind::Restricted { path, shorthand, .. } => {
517+
let path = Self::to_string(|s| s.print_path(path, false, 0));
518+
if *shorthand {
519+
self.word_nbsp(format!("mut({path})"))
520+
} else {
521+
self.word_nbsp(format!("mut(in {path})"))
522+
}
523+
}
524+
ast::RestrictionKind::Unrestricted => {}
525+
}
526+
}
527+
514528
fn print_defaultness(&mut self, defaultness: ast::Defaultness) {
515529
if let ast::Defaultness::Default(_) = defaultness {
516530
self.word_nbsp("default");
@@ -537,6 +551,7 @@ impl<'a> State<'a> {
537551
s.maybe_print_comment(field.span.lo());
538552
s.print_outer_attributes(&field.attrs);
539553
s.print_visibility(&field.vis);
554+
s.print_mut_restriction(&field.mut_restriction);
540555
s.print_type(&field.ty)
541556
});
542557
self.pclose();
@@ -562,6 +577,7 @@ impl<'a> State<'a> {
562577
self.maybe_print_comment(field.span.lo());
563578
self.print_outer_attributes(&field.attrs);
564579
self.print_visibility(&field.vis);
580+
self.print_mut_restriction(&field.mut_restriction);
565581
self.print_ident(field.ident.unwrap());
566582
self.word_nbsp(":");
567583
self.print_type(&field.ty);

compiler/rustc_expand/src/placeholders.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ pub(crate) fn placeholder(
186186
ty: ty(),
187187
vis,
188188
is_placeholder: true,
189+
mut_restriction: ast::MutRestriction {
190+
kind: ast::RestrictionKind::Unrestricted,
191+
span: DUMMY_SP,
192+
tokens: None,
193+
},
189194
safety: Safety::Default,
190195
default: None,
191196
}]),

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,8 @@ declare_features! (
648648
(unstable, must_not_suspend, "1.57.0", Some(83310)),
649649
/// Allows `mut ref` and `mut ref mut` identifier patterns.
650650
(incomplete, mut_ref, "1.79.0", Some(123076)),
651+
/// Allows `mut(crate) field: Type` restrictions.
652+
(incomplete, mut_restriction, "CURRENT_RUSTC_VERSION", Some(105077)),
651653
/// Allows using `#[naked]` on `extern "Rust"` functions.
652654
(unstable, naked_functions_rustic_abi, "1.88.0", Some(138997)),
653655
/// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions.

compiler/rustc_parse/src/errors.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,26 @@ pub(crate) struct IncorrectImplRestriction {
12871287
pub inner_str: String,
12881288
}
12891289

1290+
#[derive(Diagnostic)]
1291+
#[diag("incorrect `mut` restriction")]
1292+
#[help(
1293+
"some possible `mut` restrictions are:
1294+
`mut(crate)`: can only be mutated in the current crate
1295+
`mut(super)`: can only be mutated in the parent module
1296+
`mut(self)`: can only be mutated in current module
1297+
`mut(in path::to::module)`: can only be mutated in the specified path"
1298+
)]
1299+
pub(crate) struct IncorrectMutRestriction {
1300+
#[primary_span]
1301+
#[suggestion(
1302+
"help: use `in` to restrict mutations to the path `{$inner_str}`",
1303+
code = "in {inner_str}",
1304+
applicability = "machine-applicable"
1305+
)]
1306+
pub span: Span,
1307+
pub inner_str: String,
1308+
}
1309+
12901310
#[derive(Diagnostic)]
12911311
#[diag("<assignment> ... else {\"{\"} ... {\"}\"} is not allowed")]
12921312
pub(crate) struct AssignmentElseNotAllowed {

0 commit comments

Comments
 (0)