Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement RFC 3323: restrictions #106074

Open
wants to merge 46 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
54b5eae
Introduce `MonoItemData`.
nnethercote Jul 14, 2023
1159f43
Store item size estimate in `MonoItemData`.
nnethercote Jul 14, 2023
71bfc57
Ignore unreachable inlined items in `debug_dump`.
nnethercote Jul 14, 2023
f4c4602
Remove `instance_def_size_estimate` query.
nnethercote Jul 14, 2023
bef6ff6
Auto merge of #113684 - nnethercote:streamline-size-estimates, r=<try>
bors Jul 14, 2023
2a30038
Introduce restrictions to the AST
jhpratt Jul 9, 2022
49cd517
Parse `impl` restriction on trait definitions
jhpratt Jul 9, 2022
b35b975
rustfmt `impl` restriction
jhpratt Jul 9, 2022
a89c303
Lower `impl` restriction to `rustc_middle`
jhpratt Jul 9, 2022
c938764
Error in implementation of restricted trait
jhpratt Jul 9, 2022
94bef5a
Place restrictions behind feature gate
jhpratt Jul 9, 2022
f5ea0f7
Update compiler error index
jhpratt Jul 10, 2022
bb278ab
Parse `mut` restriction on fields
jhpratt Jul 11, 2022
f6a6786
rustfmt `mut` restriction
jhpratt Jul 11, 2022
c162277
Lower `mut` restriction to `rustc_middle`
jhpratt Jul 11, 2022
ad7f018
Add query to obtain `mut` restriction
jhpratt Jul 16, 2022
f7ffd59
Lower struct field mut restriction to MIR
jhpratt Jul 22, 2022
75830d4
Get field definition from `TyCtxt` and `Field`
jhpratt Jul 22, 2022
1d0f756
Validate `mut` restriction on struct fields
jhpratt Jul 22, 2022
9dfdfea
Test `mut` restriction
jhpratt Jul 22, 2022
4a7aab2
Validate `mut` restriction on enum variant fields
jhpratt Jul 22, 2022
17ef482
Split feature in two
jhpratt Jul 24, 2022
0561a0b
Ban expressions with mut restricted fields
jhpratt Jul 28, 2022
e984d82
Improve diagnostics
jhpratt Jul 28, 2022
3421cb9
Turn construction restriction into a query
jhpratt Jul 26, 2022
400b4d0
Add stringify tests for restrictions
jhpratt Aug 10, 2022
8a85dc5
Improve diagnostics
jhpratt Oct 19, 2022
bd9c2db
Remove kw-only restriction, use shorthand properly
jhpratt Oct 21, 2022
ae5d13c
Fix tidy errors
Urgau May 25, 2023
cc4d414
Make impl restrictions work cross-crate
jhpratt Jan 5, 2023
7e22f74
Store mut restriction data in a table
jhpratt Jan 7, 2023
ae7a6a2
Remove outdated syntax
jhpratt Jan 8, 2023
716ecbd
Explicitly test tuple structs
jhpratt Jan 9, 2023
011e7c6
Simplify naming in impl restriction test
jhpratt Jan 9, 2023
bafce51
Remove unnecessary FIXME
jhpratt Jan 9, 2023
23f53bf
Change restriction kind into const generic
jhpratt Jan 9, 2023
2f7037c
Parse visibility as a restriction
jhpratt Jan 11, 2023
497f535
Bless HIR stats
Urgau May 25, 2023
7801c8f
Increase root limit path for newly added restrictions tests
Urgau May 25, 2023
eea7a35
Address review items
jhpratt Jun 15, 2023
5370b54
Fix build errors
jhpratt Jun 15, 2023
fb12bf1
Address some review items
jhpratt Jul 11, 2023
731bbd8
Invert `Restriction::is_restricted_in`
jhpratt Jul 11, 2023
f4a661f
Add type aliases for each restriction
jhpratt Jul 11, 2023
c4c73cd
Enforce using correct restriction in rustc_middle
jhpratt Jul 12, 2023
076a838
Use `LocalDefId` instead of `DefId`
jhpratt Jul 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3490,6 +3490,7 @@ dependencies = [
"rustc_privacy",
"rustc_query_system",
"rustc_resolve",
"rustc_restrictions",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
Expand Down Expand Up @@ -3777,6 +3778,7 @@ dependencies = [
"rustc_query_impl",
"rustc_query_system",
"rustc_resolve",
"rustc_restrictions",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
Expand Down Expand Up @@ -4189,6 +4191,20 @@ dependencies = [
"tracing",
]

[[package]]
name = "rustc_restrictions"
version = "0.0.0"
dependencies = [
"rustc_errors",
"rustc_fluent_macro",
"rustc_hir",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
"tracing",
]

[[package]]
name = "rustc_serialize"
version = "0.0.0"
Expand Down
145 changes: 145 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use std::fmt;
use std::marker::PhantomData;
use std::mem;
use thin_vec::{thin_vec, ThinVec};

Expand Down Expand Up @@ -2721,6 +2722,148 @@ impl VisibilityKind {
}
}

pub mod restriction_kind {
use super::*;

/// Helper macro to generate the type, derive the relevant bounds, and implement the sealed
/// trait.
macro_rules! define_restrictions {
($(Restriction {
requires_explicit_path: $requires_explicit_path:ident,
name: $name:ident,
keyword: $keyword_sym:path => $keyword_str:literal,
feature_gate: $feature_gate:expr $(,)?
}),* $(,)?) => {$(
#[derive(Debug, Clone, Copy, Encodable, Decodable)]
pub enum $name {}

impl RestrictionKind for $name {
const REQUIRES_EXPLICIT_PATH: bool = $requires_explicit_path;
const KEYWORD_SYM: Symbol = $keyword_sym;
const KEYWORD_STR: &'static str = $keyword_str;
const FEATURE_GATE: Option<Symbol> = $feature_gate;

const MIDDLE_KIND: u8 = ${index()};
}

impl sealed::Sealed for $name {}
)*};
}

// FIXME(jhpratt) After a bootstrap, replace this with the now-implemented native syntax.
mod sealed {
pub trait Sealed {}
}

pub trait RestrictionKind: sealed::Sealed {
const REQUIRES_EXPLICIT_PATH: bool;
const KEYWORD_SYM: Symbol;
const KEYWORD_STR: &'static str;
const FEATURE_GATE: Option<Symbol>;

const MIDDLE_KIND: u8;
}

define_restrictions![
Restriction {
requires_explicit_path: false,
name: Visibility,
keyword: kw::Pub => "pub",
feature_gate: None,
},
Restriction {
requires_explicit_path: true,
name: Impl,
keyword: kw::Impl => "impl",
feature_gate: Some(sym::impl_restriction),
},
Restriction {
requires_explicit_path: true,
name: Mut,
keyword: kw::Mut => "mut",
feature_gate: Some(sym::mut_restriction),
},
];
}
pub use restriction_kind::RestrictionKind;

// FIXME(jhpratt) Replace the generic with an enum once ADT const generics are not incomplete.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Restriction<Kind: RestrictionKind> {
pub level: RestrictionLevel,
pub span: Span,
pub kind: PhantomData<Kind>,
pub tokens: Option<LazyAttrTokenStream>,
}

#[derive(Clone, Encodable, Decodable, Debug)]
pub enum RestrictionLevel {
// kw
Unrestricted,
// kw(path)
Restricted { path: P<Path>, id: NodeId, shorthand: bool },
// nothing
Implied,
}

pub type VisibilityRestriction = Restriction<restriction_kind::Visibility>;
pub type ImplRestriction = Restriction<restriction_kind::Impl>;
pub type MutRestriction = Restriction<restriction_kind::Mut>;

impl From<VisibilityRestriction> for Visibility {
fn from(restriction: VisibilityRestriction) -> Self {
match restriction.level {
RestrictionLevel::Unrestricted => Self {
kind: VisibilityKind::Public,
span: restriction.span,
tokens: restriction.tokens,
},
RestrictionLevel::Restricted { path, id, shorthand } => Self {
kind: VisibilityKind::Restricted { path, id, shorthand },
span: restriction.span,
tokens: restriction.tokens,
},
RestrictionLevel::Implied => Self {
kind: VisibilityKind::Inherited,
span: restriction.span,
tokens: restriction.tokens,
},
}
}
}

impl<Kind: RestrictionKind> Restriction<Kind> {
pub fn unrestricted() -> Self {
Self {
level: RestrictionLevel::Unrestricted,
span: DUMMY_SP,
tokens: None,
kind: PhantomData,
}
}

pub fn restricted(path: P<Path>, id: NodeId, shorthand: bool) -> Self {
Self {
level: RestrictionLevel::Restricted { path, id, shorthand },
span: DUMMY_SP,
tokens: None,
kind: PhantomData,
}
}

pub fn implied() -> Self {
Self { level: RestrictionLevel::Implied, span: DUMMY_SP, tokens: None, kind: PhantomData }
}

pub fn with_span(self, span: Span) -> Self {
Self { span, ..self }
}

pub fn with_tokens(self, tokens: LazyAttrTokenStream) -> Self {
Self { tokens: Some(tokens), ..self }
}
}

/// Field definition in a struct, variant or union.
///
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
Expand All @@ -2730,6 +2873,7 @@ pub struct FieldDef {
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub mut_restriction: MutRestriction,
pub ident: Option<Ident>,

pub ty: P<Ty>,
Expand Down Expand Up @@ -2869,6 +3013,7 @@ impl Default for FnHeader {

#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Trait {
pub impl_restriction: ImplRestriction,
pub unsafety: Unsafe,
pub is_auto: IsAuto,
pub generics: Generics,
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_ast/src/ast_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::token::Nonterminal;
use crate::tokenstream::LazyAttrTokenStream;
use crate::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
use crate::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
use crate::{AttrItem, AttrKind, Block, Pat, Path, Restriction, Ty, Visibility};
use crate::{AttrVec, Attribute, Stmt, StmtKind};

use rustc_span::Span;
Expand Down Expand Up @@ -110,6 +110,12 @@ macro_rules! impl_has_span {

impl_has_span!(AssocItem, Block, Expr, ForeignItem, Item, Pat, Path, Stmt, Ty, Visibility);

impl<Kind: crate::RestrictionKind> HasSpan for Restriction<Kind> {
fn span(&self) -> Span {
self.span
}
}

impl<T: AstDeref<Target: HasSpan>> HasSpan for T {
fn span(&self) -> Span {
self.ast_deref().span()
Expand Down Expand Up @@ -326,6 +332,14 @@ impl_has_attrs!(
);
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);

impl<Kind: crate::RestrictionKind> HasAttrs for Restriction<Kind> {
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;
fn attrs(&self) -> &[Attribute] {
&[]
}
fn visit_attrs(&mut self, _f: impl FnOnce(&mut AttrVec)) {}
}

impl<T: AstDeref<Target: HasAttrs>> HasAttrs for T {
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::Target::SUPPORTS_CUSTOM_INNER_ATTRS;
fn attrs(&self) -> &[Attribute] {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#![feature(const_trait_impl)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(macro_metavar_expr)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(stmt_expr_attributes)]
Expand Down
31 changes: 29 additions & 2 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,13 @@ pub trait MutVisitor: Sized {
noop_visit_vis(vis, self);
}

fn visit_restriction<Kind: crate::RestrictionKind>(
&mut self,
restriction: &mut Restriction<Kind>,
) {
noop_visit_restriction(restriction, self);
}

fn visit_id(&mut self, _id: &mut NodeId) {
// Do nothing.
}
Expand Down Expand Up @@ -990,9 +997,10 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
mut fd: FieldDef,
visitor: &mut T,
) -> SmallVec<[FieldDef; 1]> {
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd;
let FieldDef { span, ident, vis, mut_restriction, id, ty, attrs, is_placeholder: _ } = &mut fd;
visitor.visit_span(span);
visit_opt(ident, |ident| visitor.visit_ident(ident));
visitor.visit_restriction(mut_restriction);
visitor.visit_vis(vis);
visitor.visit_id(id);
visitor.visit_ty(ty);
Expand Down Expand Up @@ -1092,7 +1100,15 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
vis.visit_ty(self_ty);
items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
}
ItemKind::Trait(box Trait { unsafety, is_auto: _, generics, bounds, items }) => {
ItemKind::Trait(box Trait {
impl_restriction,
unsafety,
is_auto: _,
generics,
bounds,
items,
}) => {
vis.visit_restriction(impl_restriction);
visit_unsafety(unsafety, vis);
vis.visit_generics(generics);
visit_bounds(bounds, vis);
Expand Down Expand Up @@ -1554,6 +1570,17 @@ pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
vis.visit_span(&mut visibility.span);
}

pub fn noop_visit_restriction<T: MutVisitor, Kind: crate::RestrictionKind>(
restriction: &mut Restriction<Kind>,
vis: &mut T,
) {
if let RestrictionLevel::Restricted { path, id, shorthand: _ } = &mut restriction.level {
vis.visit_path(path);
vis.visit_id(id);
}
vis.visit_span(&mut restriction.span);
}

/// Some value for the AST node that is valid but possibly meaningless.
pub trait DummyAstNode {
fn dummy() -> Self;
Expand Down
28 changes: 27 additions & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@ pub trait Visitor<'ast>: Sized {
fn visit_vis(&mut self, vis: &'ast Visibility) {
walk_vis(self, vis)
}
fn visit_restriction<Kind: crate::RestrictionKind>(
&mut self,
restriction: &'ast Restriction<Kind>,
) {
walk_restriction(self, restriction)
}
fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) {
walk_fn_ret_ty(self, ret_ty)
}
Expand Down Expand Up @@ -357,10 +363,18 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
visitor.visit_generics(generics);
visitor.visit_variant_data(struct_definition);
}
ItemKind::Trait(box Trait { unsafety: _, is_auto: _, generics, bounds, items }) => {
ItemKind::Trait(box Trait {
impl_restriction,
unsafety: _,
is_auto: _,
generics,
bounds,
items,
}) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
visitor.visit_restriction(impl_restriction);
}
ItemKind::TraitAlias(generics, bounds) => {
visitor.visit_generics(generics);
Expand Down Expand Up @@ -705,6 +719,7 @@ pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef)
if let Some(ident) = field.ident {
visitor.visit_ident(ident);
}
visitor.visit_restriction(&field.mut_restriction);
visitor.visit_ty(&field.ty);
walk_list!(visitor, visit_attribute, &field.attrs);
}
Expand Down Expand Up @@ -949,6 +964,17 @@ pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) {
}
}

pub fn walk_restriction<'a, V: Visitor<'a>, Kind: crate::RestrictionKind>(
visitor: &mut V,
restriction: &'a Restriction<Kind>,
) {
match restriction.level {
RestrictionLevel::Unrestricted => {}
RestrictionLevel::Restricted { ref path, id, shorthand: _ } => visitor.visit_path(path, id),
RestrictionLevel::Implied => {}
}
}

pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) {
match &attr.kind {
AttrKind::Normal(normal) => walk_attr_args(visitor, &normal.item.args),
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
items: new_impl_items,
}))
}
ItemKind::Trait(box Trait { is_auto, unsafety, generics, bounds, items }) => {
ItemKind::Trait(box Trait {
impl_restriction: _,
is_auto,
unsafety,
generics,
bounds,
items,
}) => {
// FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible
let constness = attrs
.unwrap_or(&[])
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(const_closures, "const closures are experimental");
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
gate_all!(explicit_tail_calls, "`become` expression is experimental");
gate_all!(impl_restriction, "restrictions are experimental");
gate_all!(mut_restriction, "restrictions are experimental");

if !visitor.features.negative_bounds {
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
Expand Down
Loading