Skip to content

Commit

Permalink
Implment #[cfg] in where clauses
Browse files Browse the repository at this point in the history
  • Loading branch information
frank-king committed Nov 26, 2024
1 parent f2abf82 commit 3411185
Show file tree
Hide file tree
Showing 34 changed files with 1,587 additions and 88 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ impl Default for WhereClause {
/// A single predicate in a where-clause.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WherePredicate {
pub attrs: AttrVec,
pub kind: WherePredicateKind,
pub id: NodeId,
pub span: Span,
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_ast/src/ast_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::tokenstream::LazyAttrTokenStream;
use crate::{
Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
FieldDef, ForeignItem, GenericParam, Item, NodeId, Param, Pat, PatField, Path, Stmt, StmtKind,
Ty, Variant, Visibility,
Ty, Variant, Visibility, WherePredicate,
};

/// A utility trait to reduce boilerplate.
Expand Down Expand Up @@ -79,6 +79,7 @@ impl_has_node_id!(
Stmt,
Ty,
Variant,
WherePredicate,
);

impl<T: AstDeref<Target: HasNodeId>> HasNodeId for T {
Expand Down Expand Up @@ -127,7 +128,16 @@ macro_rules! impl_has_tokens_none {
}

impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path, Ty, Visibility);
impl_has_tokens_none!(Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant);
impl_has_tokens_none!(
Arm,
ExprField,
FieldDef,
GenericParam,
Param,
PatField,
Variant,
WherePredicate
);

impl<T: AstDeref<Target: HasTokens>> HasTokens for T {
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
Expand Down Expand Up @@ -289,6 +299,7 @@ impl_has_attrs!(
Param,
PatField,
Variant,
WherePredicate,
);
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);

Expand Down
18 changes: 13 additions & 5 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,11 @@ pub trait MutVisitor: Sized {
walk_where_clause(self, where_clause);
}

fn visit_where_predicate(&mut self, where_predicate: &mut WherePredicate) {
walk_where_predicate(self, where_predicate)
fn flat_map_where_predicate(
&mut self,
where_predicate: WherePredicate,
) -> SmallVec<[WherePredicate; 1]> {
walk_flat_map_where_predicate(self, where_predicate)
}

fn visit_where_predicate_kind(&mut self, kind: &mut WherePredicateKind) {
Expand Down Expand Up @@ -1065,15 +1068,20 @@ fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWh

fn walk_where_clause<T: MutVisitor>(vis: &mut T, wc: &mut WhereClause) {
let WhereClause { has_where_token: _, predicates, span } = wc;
visit_thin_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
predicates.flat_map_in_place(|predicate| vis.flat_map_where_predicate(predicate));
vis.visit_span(span);
}

pub fn walk_where_predicate<T: MutVisitor>(vis: &mut T, pred: &mut WherePredicate) {
let WherePredicate { kind, id, span } = pred;
pub fn walk_flat_map_where_predicate<T: MutVisitor>(
vis: &mut T,
mut pred: WherePredicate,
) -> SmallVec<[WherePredicate; 1]> {
let WherePredicate { attrs, kind, id, span } = &mut pred;
vis.visit_id(id);
visit_attrs(vis, attrs);
vis.visit_where_predicate_kind(kind);
vis.visit_span(span);
smallvec![pred]
}

pub fn walk_where_predicate_kind<T: MutVisitor>(vis: &mut T, kind: &mut WherePredicateKind) {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,8 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(
visitor: &mut V,
predicate: &'a WherePredicate,
) -> V::Result {
let WherePredicate { kind, id: _, span: _ } = predicate;
let WherePredicate { attrs, kind, id: _, span: _ } = predicate;
walk_list!(visitor, visit_attribute, attrs);
visitor.visit_where_predicate_kind(kind)
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1579,6 +1579,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
let hir_id = self.lower_node_id(pred.id);
let span = self.lower_span(pred.span);
self.lower_attrs(hir_id, &pred.attrs);
let kind = self.arena.alloc(match &pred.kind {
WherePredicateKind::BoundPredicate(WhereBoundPredicate {
bound_generic_params,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(return_type_notation, "return type notation is experimental");
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
gate_all!(unsafe_fields, "`unsafe` fields are experimental");
gate_all!(cfg_attribute_in_where, "`#[cfg]` attribute in `where` clause is unstable");

if !visitor.features.never_patterns() {
if let Some(spans) = spans.get(&sym::never_patterns) {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,8 @@ impl<'a> State<'a> {
}

pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
let ast::WherePredicate { kind, id: _, span: _ } = predicate;
let ast::WherePredicate { attrs, kind, id: _, span: _ } = predicate;
self.print_outer_attributes(attrs);
match kind {
ast::WherePredicateKind::BoundPredicate(where_bound_predicate) => {
self.print_where_bound_predicate(where_bound_predicate);
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,15 @@ pub(crate) fn expand_deriving_coerce_pointee(
to_ty: &s_ty,
rewritten: false,
};
let mut predicate = ast::WherePredicate {
kind: ast::WherePredicateKind::BoundPredicate(bound.clone()),
span: predicate.span,
id: ast::DUMMY_NODE_ID,
};
substitution.visit_where_predicate(&mut predicate);
let mut kind = ast::WherePredicateKind::BoundPredicate(bound.clone());
substitution.visit_where_predicate_kind(&mut kind);
if substitution.rewritten {
let predicate = ast::WherePredicate {
attrs: predicate.attrs.clone(),
kind,
span: predicate.span,
id: ast::DUMMY_NODE_ID,
};
impl_generics.where_clause.predicates.push(predicate);
}
}
Expand Down Expand Up @@ -383,8 +385,8 @@ impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> {
}
}

fn visit_where_predicate(&mut self, where_predicate: &mut ast::WherePredicate) {
match &mut where_predicate.kind {
fn visit_where_predicate_kind(&mut self, kind: &mut ast::WherePredicateKind) {
match kind {
rustc_ast::WherePredicateKind::BoundPredicate(bound) => {
bound
.bound_generic_params
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ impl<'a> TraitDef<'a> {
// and similarly for where clauses
where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| {
ast::WherePredicate {
attrs: clause.attrs.clone(),
kind: clause.kind.clone(),
id: ast::DUMMY_NODE_ID,
span: clause.span.with_ctxt(ctxt),
Expand Down Expand Up @@ -748,8 +749,12 @@ impl<'a> TraitDef<'a> {
};

let kind = ast::WherePredicateKind::BoundPredicate(predicate);
let predicate =
ast::WherePredicate { kind, id: ast::DUMMY_NODE_ID, span: self.span };
let predicate = ast::WherePredicate {
attrs: ThinVec::new(),
kind,
id: ast::DUMMY_NODE_ID,
span: self.span,
};
where_clause.predicates.push(predicate);
}
}
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub enum Annotatable {
FieldDef(ast::FieldDef),
Variant(ast::Variant),
Crate(ast::Crate),
WherePredicate(ast::WherePredicate),
}

impl Annotatable {
Expand All @@ -71,6 +72,7 @@ impl Annotatable {
Annotatable::FieldDef(sf) => sf.span,
Annotatable::Variant(v) => v.span,
Annotatable::Crate(c) => c.spans.inner_span,
Annotatable::WherePredicate(wp) => wp.span,
}
}

Expand All @@ -89,6 +91,7 @@ impl Annotatable {
Annotatable::FieldDef(sf) => sf.visit_attrs(f),
Annotatable::Variant(v) => v.visit_attrs(f),
Annotatable::Crate(c) => c.visit_attrs(f),
Annotatable::WherePredicate(wp) => wp.visit_attrs(f),
}
}

Expand All @@ -107,6 +110,7 @@ impl Annotatable {
Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
Annotatable::Variant(v) => visitor.visit_variant(v),
Annotatable::Crate(c) => visitor.visit_crate(c),
Annotatable::WherePredicate(wp) => visitor.visit_where_predicate(wp),
}
}

Expand All @@ -127,7 +131,8 @@ impl Annotatable {
| Annotatable::Param(..)
| Annotatable::FieldDef(..)
| Annotatable::Variant(..)
| Annotatable::Crate(..) => panic!("unexpected annotatable"),
| Annotatable::Crate(..)
| Annotatable::WherePredicate(..) => panic!("unexpected annotatable"),
}
}

Expand Down Expand Up @@ -228,6 +233,13 @@ impl Annotatable {
_ => panic!("expected krate"),
}
}

pub fn expect_where_predicate(self) -> ast::WherePredicate {
match self {
Annotatable::WherePredicate(wp) => wp,
_ => panic!("expected where predicate"),
}
}
}

/// Result of an expansion that may need to be retried.
Expand Down Expand Up @@ -449,6 +461,10 @@ pub trait MacResult {
// Fn-like macros cannot produce a crate.
unreachable!()
}

fn make_where_predicates(self: Box<Self>) -> Option<SmallVec<[ast::WherePredicate; 1]>> {
None
}
}

macro_rules! make_MacEager {
Expand Down
38 changes: 35 additions & 3 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@ ast_fragments! {
"variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
}
Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; }
WherePredicate(SmallVec<[ast::WherePredicate; 1]>) {
"where predicate";
many fn flat_map_where_predicate;
fn visit_where_predicate();
fn make_where_predicates;
}
}

pub enum SupportsMacroExpansion {
Expand Down Expand Up @@ -260,7 +266,8 @@ impl AstFragmentKind {
| AstFragmentKind::GenericParams
| AstFragmentKind::Params
| AstFragmentKind::FieldDefs
| AstFragmentKind::Variants => SupportsMacroExpansion::No,
| AstFragmentKind::Variants
| AstFragmentKind::WherePredicate => SupportsMacroExpansion::No,
}
}

Expand Down Expand Up @@ -318,6 +325,9 @@ impl AstFragmentKind {
AstFragmentKind::Crate => {
AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate())
}
AstFragmentKind::WherePredicate => AstFragment::WherePredicate(
items.map(Annotatable::expect_where_predicate).collect(),
),
AstFragmentKind::Pat | AstFragmentKind::Ty => {
panic!("patterns and types aren't annotatable")
}
Expand Down Expand Up @@ -866,7 +876,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
| Annotatable::GenericParam(..)
| Annotatable::Param(..)
| Annotatable::FieldDef(..)
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
| Annotatable::Variant(..)
| Annotatable::WherePredicate(..) => panic!("unexpected annotatable"),
};
if self.cx.ecfg.features.proc_macro_hygiene() {
return;
Expand Down Expand Up @@ -1003,7 +1014,8 @@ pub fn parse_ast_fragment<'a>(
| AstFragmentKind::GenericParams
| AstFragmentKind::Params
| AstFragmentKind::FieldDefs
| AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
| AstFragmentKind::Variants
| AstFragmentKind::WherePredicate => panic!("unexpected AST fragment kind"),
})
}

Expand Down Expand Up @@ -1587,6 +1599,19 @@ impl InvocationCollectorNode for ast::Crate {
}
}

impl InvocationCollectorNode for ast::WherePredicate {
const KIND: AstFragmentKind = AstFragmentKind::WherePredicate;
fn to_annotatable(self) -> Annotatable {
Annotatable::WherePredicate(self)
}
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
fragment.make_where_predicates()
}
fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
walk_flat_map_where_predicate(visitor, self)
}
}

impl InvocationCollectorNode for P<ast::Ty> {
type OutputTy = P<ast::Ty>;
const KIND: AstFragmentKind = AstFragmentKind::Ty;
Expand Down Expand Up @@ -2179,6 +2204,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
self.visit_node(node)
}

fn flat_map_where_predicate(
&mut self,
node: ast::WherePredicate,
) -> SmallVec<[ast::WherePredicate; 1]> {
self.flat_map_node(node)
}

fn visit_expr(&mut self, node: &mut P<ast::Expr>) {
// FIXME: Feature gating is performed inconsistently between `Expr` and `OptExpr`.
if let Some(attr) = node.attrs.first() {
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_expand/src/placeholders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,18 @@ pub(crate) fn placeholder(
vis,
is_placeholder: true,
}]),
AstFragmentKind::WherePredicate => {
AstFragment::WherePredicate(smallvec![ast::WherePredicate {
attrs: Default::default(),
id,
span,
kind: ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
bound_generic_params: Default::default(),
bounded_ty: ty(),
bounds: Default::default(),
}),
}])
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ declare_features! (
(unstable, async_for_loop, "1.77.0", Some(118898)),
/// Allows using C-variadics.
(unstable, c_variadic, "1.34.0", Some(44930)),
/// Allows the use of `#[cfg]` in `where` clauses.
(unstable, cfg_attribute_in_where, "CURRENT_RUSTC_VERSION", Some(115590)),
/// Allows the use of `#[cfg(<true/false>)]`.
(unstable, cfg_boolean_literals, "1.83.0", Some(131204)),
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_hir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub enum Target {
Param,
PatField,
ExprField,
WherePredicate,
}

impl Display for Target {
Expand Down Expand Up @@ -96,7 +97,8 @@ impl Target {
| Target::MacroDef
| Target::Param
| Target::PatField
| Target::ExprField => false,
| Target::ExprField
| Target::WherePredicate => false,
}
}

Expand Down Expand Up @@ -217,6 +219,7 @@ impl Target {
Target::Param => "function param",
Target::PatField => "pattern field",
Target::ExprField => "struct field",
Target::WherePredicate => "where predicate",
}
}
}
1 change: 1 addition & 0 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2161,6 +2161,7 @@ impl<'a> State<'a> {
}

fn print_where_predicate(&mut self, predicate: &hir::WherePredicate<'_>) {
self.print_outer_attributes(self.attrs(predicate.hir_id));
match *predicate.kind {
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params,
Expand Down
Loading

0 comments on commit 3411185

Please sign in to comment.