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 11, 2024
1 parent 78668c5 commit d0cdfab
Show file tree
Hide file tree
Showing 32 changed files with 1,566 additions and 66 deletions.
2 changes: 2 additions & 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 All @@ -444,6 +445,7 @@ impl WherePredicate {
f: impl FnOnce(&WherePredicateKind) -> WherePredicateKind,
) -> WherePredicate {
WherePredicate {
attrs: self.attrs.clone(),
kind: f(&self.kind),
id: DUMMY_NODE_ID,
span: ctxt.map_or(self.span, |ctxt| self.span.with_ctxt(ctxt)),
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
3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,8 +1002,9 @@ pub fn walk_flat_map_where_predicate<T: MutVisitor>(
vis: &mut T,
mut pred: WherePredicate,
) -> SmallVec<[WherePredicate; 1]> {
let WherePredicate { ref mut kind, ref mut id, ref mut span } = pred;
let WherePredicate { ref mut attrs, ref mut kind, ref mut id, ref mut span } = pred;
vis.visit_id(id);
visit_attrs(vis, attrs);
vis.visit_where_predicate_kind(kind);
vis.visit_span(span);
smallvec![pred]
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 @@ -789,7 +789,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);
self.lower_attrs(hir_id, &pred.attrs);
let kind = 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 @@ -547,6 +547,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(global_registration, "global registration is experimental");
gate_all!(return_type_notation, "return type notation is experimental");
gate_all!(pin_ergonomics, "pinned reference syntax is 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,8 +726,9 @@ impl<'a> State<'a> {
}

pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
let &ast::WherePredicate { ref kind, id, span: _ } = predicate;
let &ast::WherePredicate { ref attrs, ref kind, id, span: _ } = predicate;
self.ann.pre(self, AnnNode::SubItem(id));
self.print_outer_attributes(attrs);
match kind {
ast::WherePredicateKind::BoundPredicate(where_bound_predicate) => {
self.print_where_bound_predicate(where_bound_predicate);
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_builtin_macros/src/cfg_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ fn flat_map_annotatable(
vis.visit_crate(&mut krate);
Some(Annotatable::Crate(krate))
}
Annotatable::WherePredicate(predicate) => {
vis.flat_map_where_predicate(predicate).pop().map(Annotatable::WherePredicate)
}
}
}

Expand Down Expand Up @@ -114,6 +117,7 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
Annotatable::FieldDef(field) => CfgFinder.visit_field_def(field),
Annotatable::Variant(variant) => CfgFinder.visit_variant(variant),
Annotatable::Crate(krate) => CfgFinder.visit_crate(krate),
Annotatable::WherePredicate(predicate) => CfgFinder.visit_where_predicate(predicate),
};
res.is_break()
}
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,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
13 changes: 13 additions & 0 deletions compiler/rustc_expand/src/placeholders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,19 @@ 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 {
span,
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 @@ -389,6 +389,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
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 d0cdfab

Please sign in to comment.