Skip to content

Commit bef489b

Browse files
Rollup merge of #152943 - CoCo-Japan-pan:impl-restriction-parse, r=Urgau,jhpratt
Parse `impl` restrictions This PR implements the parsing logic for `impl` restrictions (e.g., `pub impl(crate) trait Foo {}`) as proposed in [RFC 3323](https://rust-lang.github.io/rfcs/3323-restrictions.html). As the first step of the RFC implementation, this PR focuses strictly on the parsing phase. The new syntax is guarded by the `#![feature(impl_restriction)]` feature gate. This implementation basically follows the pattern used in #141754. r? @jhpratt
2 parents 8b1ebb3 + 3dcefa3 commit bef489b

28 files changed

+1219
-20
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3553,6 +3553,19 @@ impl VisibilityKind {
35533553
}
35543554
}
35553555

3556+
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
3557+
pub struct ImplRestriction {
3558+
pub kind: RestrictionKind,
3559+
pub span: Span,
3560+
pub tokens: Option<LazyAttrTokenStream>,
3561+
}
3562+
3563+
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
3564+
pub enum RestrictionKind {
3565+
Unrestricted,
3566+
Restricted { path: Box<Path>, id: NodeId, shorthand: bool },
3567+
}
3568+
35563569
/// Field definition in a struct, variant or union.
35573570
///
35583571
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
@@ -3752,6 +3765,7 @@ pub struct Trait {
37523765
pub constness: Const,
37533766
pub safety: Safety,
37543767
pub is_auto: IsAuto,
3768+
pub impl_restriction: ImplRestriction,
37553769
pub ident: Ident,
37563770
pub generics: Generics,
37573771
#[visitable(extra = BoundKind::SuperTraits)]

compiler/rustc_ast/src/ast_traits.rs

Lines changed: 16 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, Item, NodeId, Param, Pat, PatField, Path, Stmt, StmtKind,
12-
Ty, Variant, Visibility, WherePredicate,
11+
FieldDef, ForeignItem, GenericParam, ImplRestriction, Item, NodeId, Param, Pat, PatField, Path,
12+
Stmt, StmtKind, Ty, Variant, Visibility, WherePredicate,
1313
};
1414

1515
/// A trait for AST nodes having an ID.
@@ -97,7 +97,19 @@ macro_rules! impl_has_tokens_none {
9797
};
9898
}
9999

100-
impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path, Ty, Visibility);
100+
impl_has_tokens!(
101+
AssocItem,
102+
AttrItem,
103+
Block,
104+
Expr,
105+
ForeignItem,
106+
Item,
107+
Pat,
108+
Path,
109+
Ty,
110+
Visibility,
111+
ImplRestriction
112+
);
101113
impl_has_tokens_none!(
102114
Arm,
103115
ExprField,
@@ -242,7 +254,7 @@ impl_has_attrs!(
242254
Variant,
243255
WherePredicate,
244256
);
245-
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);
257+
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility, ImplRestriction);
246258

247259
impl<T: HasAttrs> HasAttrs for Box<T> {
248260
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;

compiler/rustc_ast/src/visit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ macro_rules! common_visitor_and_walkers {
467467
RangeEnd,
468468
RangeSyntax,
469469
Recovered,
470+
RestrictionKind,
470471
Safety,
471472
StaticItem,
472473
StrLit,
@@ -595,6 +596,7 @@ macro_rules! common_visitor_and_walkers {
595596
fn visit_poly_trait_ref(PolyTraitRef);
596597
fn visit_precise_capturing_arg(PreciseCapturingArg);
597598
fn visit_qself(QSelf);
599+
fn visit_impl_restriction(ImplRestriction);
598600
fn visit_trait_ref(TraitRef);
599601
fn visit_ty_pat(TyPat);
600602
fn visit_ty(Ty);
@@ -1117,6 +1119,7 @@ macro_rules! common_visitor_and_walkers {
11171119
pub fn walk_poly_trait_ref(PolyTraitRef);
11181120
pub fn walk_precise_capturing_arg(PreciseCapturingArg);
11191121
pub fn walk_qself(QSelf);
1122+
pub fn walk_impl_restriction(ImplRestriction);
11201123
pub fn walk_trait_ref(TraitRef);
11211124
pub fn walk_ty_pat(TyPat);
11221125
pub fn walk_ty(Ty);

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
512512
constness,
513513
is_auto,
514514
safety,
515+
// FIXME(impl_restrictions): lower to HIR
516+
impl_restriction: _,
515517
ident,
516518
generics,
517519
bounds,

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
590590
gate_all!(coroutines, "coroutine syntax is experimental");
591591
gate_all!(const_block_items, "const block items are experimental");
592592
gate_all!(final_associated_functions, "`final` on trait functions is experimental");
593+
gate_all!(impl_restriction, "`impl` restrictions are experimental");
593594

594595
if !visitor.features.never_patterns() {
595596
if let Some(spans) = spans.get(&sym::never_patterns) {

compiler/rustc_ast_pretty/src/pprust/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
8080
State::new().vis_to_string(v)
8181
}
8282

83+
pub fn impl_restriction_to_string(r: &ast::ImplRestriction) -> String {
84+
State::new().impl_restriction_to_string(r)
85+
}
86+
8387
pub fn meta_list_item_to_string(li: &ast::MetaItemInner) -> String {
8488
State::new().meta_list_item_to_string(li)
8589
}

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
11101110
Self::to_string(|s| s.print_visibility(v))
11111111
}
11121112

1113+
fn impl_restriction_to_string(&self, r: &ast::ImplRestriction) -> String {
1114+
Self::to_string(|s| s.print_impl_restriction(r))
1115+
}
1116+
11131117
fn block_to_string(&self, blk: &ast::Block) -> String {
11141118
Self::to_string(|s| {
11151119
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
@@ -365,6 +365,7 @@ impl<'a> State<'a> {
365365
constness,
366366
safety,
367367
is_auto,
368+
impl_restriction,
368369
ident,
369370
generics,
370371
bounds,
@@ -375,6 +376,7 @@ impl<'a> State<'a> {
375376
self.print_constness(*constness);
376377
self.print_safety(*safety);
377378
self.print_is_auto(*is_auto);
379+
self.print_impl_restriction(impl_restriction);
378380
self.word_nbsp("trait");
379381
self.print_ident(*ident);
380382
self.print_generic_params(&generics.params);
@@ -483,6 +485,20 @@ impl<'a> State<'a> {
483485
}
484486
}
485487

488+
pub(crate) fn print_impl_restriction(&mut self, impl_restriction: &ast::ImplRestriction) {
489+
match &impl_restriction.kind {
490+
ast::RestrictionKind::Restricted { path, shorthand, .. } => {
491+
let path = Self::to_string(|s| s.print_path(path, false, 0));
492+
if *shorthand {
493+
self.word_nbsp(format!("impl({path})"))
494+
} else {
495+
self.word_nbsp(format!("impl(in {path})"))
496+
}
497+
}
498+
ast::RestrictionKind::Unrestricted => {}
499+
}
500+
}
501+
486502
fn print_defaultness(&mut self, defaultness: ast::Defaultness) {
487503
if let ast::Defaultness::Default(_) = defaultness {
488504
self.word_nbsp("default");

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,8 @@ declare_features! (
520520
(unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)),
521521
/// Target features on hexagon.
522522
(unstable, hexagon_target_feature, "1.27.0", Some(150250)),
523+
/// Allows `impl(crate) trait Foo` restrictions.
524+
(incomplete, impl_restriction, "CURRENT_RUSTC_VERSION", Some(105077)),
523525
/// Allows `impl Trait` to be used inside associated types (RFC 2515).
524526
(unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)),
525527
/// Allows `impl Trait` in bindings (`let`).

compiler/rustc_parse/src/errors.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,26 @@ pub(crate) struct IncorrectVisibilityRestriction {
12691269
pub inner_str: String,
12701270
}
12711271

1272+
#[derive(Diagnostic)]
1273+
#[diag("incorrect `impl` restriction")]
1274+
#[help(
1275+
"some possible `impl` restrictions are:
1276+
`impl(crate)`: can only be implemented in the current crate
1277+
`impl(super)`: can only be implemented in the parent module
1278+
`impl(self)`: can only be implemented in current module
1279+
`impl(in path::to::module)`: can only be implemented in the specified path"
1280+
)]
1281+
pub(crate) struct IncorrectImplRestriction {
1282+
#[primary_span]
1283+
#[suggestion(
1284+
"help: use `in` to restrict implementations to the path `{$inner_str}`",
1285+
code = "in {inner_str}",
1286+
applicability = "machine-applicable"
1287+
)]
1288+
pub span: Span,
1289+
pub inner_str: String,
1290+
}
1291+
12721292
#[derive(Diagnostic)]
12731293
#[diag("<assignment> ... else {\"{\"} ... {\"}\"} is not allowed")]
12741294
pub(crate) struct AssignmentElseNotAllowed {
@@ -2403,6 +2423,14 @@ pub(crate) struct TraitAliasCannotBeUnsafe {
24032423
pub span: Span,
24042424
}
24052425

2426+
#[derive(Diagnostic)]
2427+
#[diag("trait aliases cannot be `impl`-restricted")]
2428+
pub(crate) struct TraitAliasCannotBeImplRestricted {
2429+
#[primary_span]
2430+
#[label("trait aliases cannot be `impl`-restricted")]
2431+
pub span: Span,
2432+
}
2433+
24062434
#[derive(Diagnostic)]
24072435
#[diag("associated `static` items are not allowed")]
24082436
pub(crate) struct AssociatedStaticItemNotAllowed {

0 commit comments

Comments
 (0)