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 #[cfg] in where clauses #132388

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
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 {
frank-king marked this conversation as resolved.
Show resolved Hide resolved
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
Loading