1
Fork 0

Auto merge of #137927 - matthiaskrgr:rollup-yj463ns, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #132388 (Implement `#[cfg]` in `where` clauses)
 - #134900 (Fix parsing of ranges after unary operators)
 - #136938 (Remove `:` from `stack-protector-heuristics-effect.rs` Filecheck Pattern)
 - #137054 (Make phantom variance markers transparent)
 - #137525 (Simplify parallelization in test-float-parse)
 - #137618 (Skip `tidy` in pre-push hook if the user is deleting a remote branch)
 - #137741 (Stop using `hash_raw_entry` in `CodegenCx::const_str`)
 - #137849 (Revert "Remove Win SDK 10.0.26100.0 from CI")
 - #137862 (ensure we always print all --print options in help)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-03-03 22:57:01 +00:00
commit 2010bba886
59 changed files with 3607 additions and 411 deletions

View file

@ -417,9 +417,11 @@ impl 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,
pub is_placeholder: bool,
}
/// Predicate kind in where-clause.

View file

@ -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.
@ -79,6 +79,7 @@ impl_has_node_id!(
Stmt,
Ty,
Variant,
WherePredicate,
);
impl<T: AstDeref<Target: HasNodeId>> HasNodeId for T {
@ -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> {
@ -279,6 +289,7 @@ impl_has_attrs!(
Param,
PatField,
Variant,
WherePredicate,
);
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);

View file

@ -338,8 +338,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) {
@ -1097,15 +1100,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, is_placeholder: _ } = &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) {

View file

@ -833,7 +833,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: _, is_placeholder: _ } = predicate;
walk_list!(visitor, visit_attribute, attrs);
visitor.visit_where_predicate_kind(kind)
}

View file

@ -1728,6 +1728,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, span);
let kind = self.arena.alloc(match &pred.kind {
WherePredicateKind::BoundPredicate(WhereBoundPredicate {
bound_generic_params,

View file

@ -503,6 +503,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(unsafe_binders, "unsafe binder types are experimental");
gate_all!(contracts, "contracts are incomplete");
gate_all!(contracts_internals, "contract internal machinery is for internal use only");
gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
if !visitor.features.never_patterns() {
if let Some(spans) = spans.get(&sym::never_patterns) {

View file

@ -735,7 +735,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: _, is_placeholder: _ } = predicate;
self.print_outer_attributes(attrs);
match kind {
ast::WherePredicateKind::BoundPredicate(where_bound_predicate) => {
self.print_where_bound_predicate(where_bound_predicate);

View file

@ -300,13 +300,16 @@ 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,
is_placeholder: false,
};
impl_generics.where_clause.predicates.push(predicate);
}
}
@ -388,8 +391,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

View file

@ -687,9 +687,11 @@ 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),
is_placeholder: false,
}
}));
@ -744,8 +746,13 @@ 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,
is_placeholder: false,
};
where_clause.predicates.push(predicate);
}
}

View file

@ -146,13 +146,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
fn const_str(&self, s: &str) -> (RValue<'gcc>, RValue<'gcc>) {
let str_global = *self
.const_str_cache
.borrow_mut()
.raw_entry_mut()
.from_key(s)
.or_insert_with(|| (s.to_owned(), self.global_string(s)))
.1;
let mut const_str_cache = self.const_str_cache.borrow_mut();
let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
let g = self.global_string(s);
const_str_cache.insert(s.to_owned(), g);
g
});
let len = s.len();
let cs = self.const_ptrcast(
str_global.get_address(None),

View file

@ -16,7 +16,7 @@
#![allow(internal_features)]
#![doc(rust_logo)]
#![feature(rustdoc_internals)]
#![feature(rustc_private, decl_macro, never_type, trusted_len, hash_raw_entry, let_chains)]
#![feature(rustc_private, decl_macro, never_type, trusted_len, let_chains)]
#![allow(broken_intra_doc_links)]
#![recursion_limit = "256"]
#![warn(rust_2018_idioms)]

View file

@ -209,28 +209,24 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
fn const_str(&self, s: &str) -> (&'ll Value, &'ll Value) {
let str_global = *self
.const_str_cache
.borrow_mut()
.raw_entry_mut()
.from_key(s)
.or_insert_with(|| {
let sc = self.const_bytes(s.as_bytes());
let sym = self.generate_local_symbol_name("str");
let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
bug!("symbol `{}` is already defined", sym);
});
llvm::set_initializer(g, sc);
unsafe {
llvm::LLVMSetGlobalConstant(g, True);
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
}
llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
// Cast to default address space if globals are in a different addrspace
let g = self.const_pointercast(g, self.type_ptr());
(s.to_owned(), g)
})
.1;
let mut const_str_cache = self.const_str_cache.borrow_mut();
let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
let sc = self.const_bytes(s.as_bytes());
let sym = self.generate_local_symbol_name("str");
let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
bug!("symbol `{}` is already defined", sym);
});
llvm::set_initializer(g, sc);
unsafe {
llvm::LLVMSetGlobalConstant(g, True);
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
}
llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
// Cast to default address space if globals are in a different addrspace
let g = self.const_pointercast(g, self.type_ptr());
const_str_cache.insert(s.to_owned(), g);
g
});
let len = s.len();
(str_global, self.const_usize(len as u64))
}

View file

@ -12,7 +12,6 @@
#![feature(exact_size_is_empty)]
#![feature(extern_types)]
#![feature(file_buffered)]
#![feature(hash_raw_entry)]
#![feature(if_let_guard)]
#![feature(impl_trait_in_assoc_type)]
#![feature(iter_intersperse)]

View file

@ -53,6 +53,7 @@ pub enum Annotatable {
Param(ast::Param),
FieldDef(ast::FieldDef),
Variant(ast::Variant),
WherePredicate(ast::WherePredicate),
Crate(ast::Crate),
}
@ -71,6 +72,7 @@ impl Annotatable {
Annotatable::Param(p) => p.span,
Annotatable::FieldDef(sf) => sf.span,
Annotatable::Variant(v) => v.span,
Annotatable::WherePredicate(wp) => wp.span,
Annotatable::Crate(c) => c.spans.inner_span,
}
}
@ -89,6 +91,7 @@ impl Annotatable {
Annotatable::Param(p) => p.visit_attrs(f),
Annotatable::FieldDef(sf) => sf.visit_attrs(f),
Annotatable::Variant(v) => v.visit_attrs(f),
Annotatable::WherePredicate(wp) => wp.visit_attrs(f),
Annotatable::Crate(c) => c.visit_attrs(f),
}
}
@ -107,6 +110,7 @@ impl Annotatable {
Annotatable::Param(p) => visitor.visit_param(p),
Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
Annotatable::Variant(v) => visitor.visit_variant(v),
Annotatable::WherePredicate(wp) => visitor.visit_where_predicate(wp),
Annotatable::Crate(c) => visitor.visit_crate(c),
}
}
@ -128,6 +132,7 @@ impl Annotatable {
| Annotatable::Param(..)
| Annotatable::FieldDef(..)
| Annotatable::Variant(..)
| Annotatable::WherePredicate(..)
| Annotatable::Crate(..) => panic!("unexpected annotatable"),
}
}
@ -223,6 +228,13 @@ impl Annotatable {
}
}
pub fn expect_where_predicate(self) -> ast::WherePredicate {
match self {
Annotatable::WherePredicate(wp) => wp,
_ => panic!("expected where predicate"),
}
}
pub fn expect_crate(self) -> ast::Crate {
match self {
Annotatable::Crate(krate) => krate,
@ -446,6 +458,10 @@ pub trait MacResult {
None
}
fn make_where_predicates(self: Box<Self>) -> Option<SmallVec<[ast::WherePredicate; 1]>> {
None
}
fn make_crate(self: Box<Self>) -> Option<ast::Crate> {
// Fn-like macros cannot produce a crate.
unreachable!()

View file

@ -227,6 +227,12 @@ ast_fragments! {
Variants(SmallVec<[ast::Variant; 1]>) {
"variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
}
WherePredicates(SmallVec<[ast::WherePredicate; 1]>) {
"where predicate";
many fn flat_map_where_predicate;
fn visit_where_predicate();
fn make_where_predicates;
}
Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; }
}
@ -259,7 +265,8 @@ impl AstFragmentKind {
| AstFragmentKind::GenericParams
| AstFragmentKind::Params
| AstFragmentKind::FieldDefs
| AstFragmentKind::Variants => SupportsMacroExpansion::No,
| AstFragmentKind::Variants
| AstFragmentKind::WherePredicates => SupportsMacroExpansion::No,
}
}
@ -290,6 +297,9 @@ impl AstFragmentKind {
AstFragmentKind::Variants => {
AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
}
AstFragmentKind::WherePredicates => AstFragment::WherePredicates(
items.map(Annotatable::expect_where_predicate).collect(),
),
AstFragmentKind::Items => {
AstFragment::Items(items.map(Annotatable::expect_item).collect())
}
@ -865,7 +875,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;
@ -1002,7 +1013,8 @@ pub fn parse_ast_fragment<'a>(
| AstFragmentKind::GenericParams
| AstFragmentKind::Params
| AstFragmentKind::FieldDefs
| AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
| AstFragmentKind::Variants
| AstFragmentKind::WherePredicates => panic!("unexpected AST fragment kind"),
})
}
@ -1414,6 +1426,19 @@ impl InvocationCollectorNode for ast::Variant {
}
}
impl InvocationCollectorNode for ast::WherePredicate {
const KIND: AstFragmentKind = AstFragmentKind::WherePredicates;
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 ast::FieldDef {
const KIND: AstFragmentKind = AstFragmentKind::FieldDefs;
fn to_annotatable(self) -> Annotatable {
@ -2116,6 +2141,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
self.flat_map_node(node)
}
fn flat_map_where_predicate(
&mut self,
node: ast::WherePredicate,
) -> SmallVec<[ast::WherePredicate; 1]> {
self.flat_map_node(node)
}
fn flat_map_field_def(&mut self, node: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
self.flat_map_node(node)
}

View file

@ -188,6 +188,19 @@ pub(crate) fn placeholder(
vis,
is_placeholder: true,
}]),
AstFragmentKind::WherePredicates => {
AstFragment::WherePredicates(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(),
}),
is_placeholder: true,
}])
}
}
}
@ -267,6 +280,17 @@ impl MutVisitor for PlaceholderExpander {
}
}
fn flat_map_where_predicate(
&mut self,
predicate: ast::WherePredicate,
) -> SmallVec<[ast::WherePredicate; 1]> {
if predicate.is_placeholder {
self.remove(predicate.id).make_where_predicates()
} else {
walk_flat_map_where_predicate(self, predicate)
}
}
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
match item.kind {
ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),

View file

@ -661,6 +661,8 @@ declare_features! (
(unstable, unsized_tuple_coercion, "1.20.0", Some(42877)),
/// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
(unstable, used_with_arg, "1.60.0", Some(93798)),
/// Allows use of attributes in `where` clauses.
(unstable, where_clause_attrs, "CURRENT_RUSTC_VERSION", Some(115590)),
/// Allows use of x86 `AMX` target-feature attributes and intrinsics
(unstable, x86_amx_intrinsics, "1.81.0", Some(126622)),
/// Allows use of the `xop` target-feature

View file

@ -56,6 +56,7 @@ pub enum Target {
Param,
PatField,
ExprField,
WherePredicate,
}
impl Display for Target {
@ -96,7 +97,8 @@ impl Target {
| Target::MacroDef
| Target::Param
| Target::PatField
| Target::ExprField => false,
| Target::ExprField
| Target::WherePredicate => false,
}
}
@ -217,6 +219,7 @@ impl Target {
Target::Param => "function param",
Target::PatField => "pattern field",
Target::ExprField => "struct field",
Target::WherePredicate => "where predicate",
}
}
}

View file

@ -2386,6 +2386,7 @@ impl<'a> State<'a> {
}
fn print_where_predicate(&mut self, predicate: &hir::WherePredicate<'_>) {
self.print_attrs_as_outer(self.attrs(predicate.hir_id));
match *predicate.kind {
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params,

View file

@ -567,7 +567,11 @@ impl<'a> Parser<'a> {
fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
self.bump();
let attrs = self.parse_outer_attributes()?;
let expr = self.parse_expr_prefix(attrs)?;
let expr = if self.token.is_range_separator() {
self.parse_expr_prefix_range(attrs)
} else {
self.parse_expr_prefix(attrs)
}?;
let span = self.interpolated_or_expr_span(&expr);
Ok((lo.to(span), expr))
}

View file

@ -367,34 +367,47 @@ impl<'a> Parser<'a> {
loop {
let where_sp = where_lo.to(self.prev_token.span);
let attrs = self.parse_outer_attributes()?;
let pred_lo = self.token.span;
let kind = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
let lifetime = self.expect_lifetime();
// Bounds starting with a colon are mandatory, but possibly empty.
self.expect(exp!(Colon))?;
let bounds = self.parse_lt_param_bounds();
ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
lifetime,
bounds,
})
} else if self.check_type() {
match self.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
struct_, pred_lo, where_sp,
)? {
PredicateKindOrStructBody::PredicateKind(kind) => kind,
PredicateKindOrStructBody::StructBody(body) => {
tuple_struct_body = Some(body);
break;
}
let predicate = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
for attr in &attrs {
self.psess.gated_spans.gate(sym::where_clause_attrs, attr.span);
}
} else {
break;
};
where_clause.predicates.push(ast::WherePredicate {
kind,
id: DUMMY_NODE_ID,
span: pred_lo.to(self.prev_token.span),
});
let kind = if this.check_lifetime() && this.look_ahead(1, |t| !t.is_like_plus()) {
let lifetime = this.expect_lifetime();
// Bounds starting with a colon are mandatory, but possibly empty.
this.expect(exp!(Colon))?;
let bounds = this.parse_lt_param_bounds();
Some(ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
lifetime,
bounds,
}))
} else if this.check_type() {
match this.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
struct_, pred_lo, where_sp,
)? {
PredicateKindOrStructBody::PredicateKind(kind) => Some(kind),
PredicateKindOrStructBody::StructBody(body) => {
tuple_struct_body = Some(body);
None
}
}
} else {
None
};
let predicate = kind.map(|kind| ast::WherePredicate {
attrs,
kind,
id: DUMMY_NODE_ID,
span: pred_lo.to(this.prev_token.span),
is_placeholder: false,
});
Ok((predicate, Trailing::No, UsePreAttrPos::No))
})?;
match predicate {
Some(predicate) => where_clause.predicates.push(predicate),
None => break,
}
let prev_token = self.prev_token.span;
let ate_comma = self.eat(exp!(Comma));

View file

@ -779,6 +779,10 @@ passes_unstable_attr_for_already_stable_feature =
.item = the stability attribute annotates this item
.help = consider removing the attribute
passes_unsupported_attributes_in_where =
most attributes are not supported in `where` clauses
.help = only `#[cfg]` and `#[cfg_attr]` are supported
passes_unused =
unused attribute
.suggestion = remove this attribute

View file

@ -919,7 +919,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| Target::Arm
| Target::ForeignMod
| Target::Closure
| Target::Impl => Some(target.name()),
| Target::Impl
| Target::WherePredicate => Some(target.name()),
Target::ExternCrate
| Target::Use
| Target::Static
@ -2614,6 +2615,32 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
intravisit::walk_item(self, item)
}
fn visit_where_predicate(&mut self, where_predicate: &'tcx hir::WherePredicate<'tcx>) {
// FIXME(where_clause_attrs): Currently, as the following check shows,
// only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
// if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
// in where clauses. After that, only `self.check_attributes` should be enough.
const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr];
let spans = self
.tcx
.hir()
.attrs(where_predicate.hir_id)
.iter()
.filter(|attr| !ATTRS_ALLOWED.iter().any(|&sym| attr.has_name(sym)))
.map(|attr| attr.span())
.collect::<Vec<_>>();
if !spans.is_empty() {
self.tcx.dcx().emit_err(errors::UnsupportedAttributesInWhere { span: spans.into() });
}
self.check_attributes(
where_predicate.hir_id,
where_predicate.span,
Target::WherePredicate,
None,
);
intravisit::walk_where_predicate(self, where_predicate)
}
fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) {
let target = Target::from_generic_param(generic_param);
self.check_attributes(generic_param.hir_id, generic_param.span, target, None);

View file

@ -1909,3 +1909,11 @@ pub(crate) struct RustcConstStableIndirectPairing {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_unsupported_attributes_in_where)]
#[help]
pub(crate) struct UnsupportedAttributesInWhere {
#[primary_span]
pub span: MultiSpan,
}

View file

@ -1529,6 +1529,14 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
visit::walk_variant(self, variant);
}
fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) {
if p.is_placeholder {
self.visit_invoc(p.id);
} else {
visit::walk_where_predicate(self, p);
}
}
fn visit_crate(&mut self, krate: &'a ast::Crate) {
if krate.is_placeholder {
self.visit_invoc_in_module(krate.id);

View file

@ -285,6 +285,14 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
});
}
fn visit_where_predicate(&mut self, pred: &'a WherePredicate) {
if pred.is_placeholder {
self.visit_macro_invoc(pred.id)
} else {
visit::walk_where_predicate(self, pred)
}
}
fn visit_variant_data(&mut self, data: &'a VariantData) {
// The assumption here is that non-`cfg` macro expansion cannot change field indices.
// It currently holds because only inert attributes are accepted on fields,

View file

@ -42,6 +42,32 @@ mod cfg;
mod native_libs;
pub mod sigpipe;
pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
// tidy-alphabetical-start
("all-target-specs-json", PrintKind::AllTargetSpecs),
("calling-conventions", PrintKind::CallingConventions),
("cfg", PrintKind::Cfg),
("check-cfg", PrintKind::CheckCfg),
("code-models", PrintKind::CodeModels),
("crate-name", PrintKind::CrateName),
("deployment-target", PrintKind::DeploymentTarget),
("file-names", PrintKind::FileNames),
("host-tuple", PrintKind::HostTuple),
("link-args", PrintKind::LinkArgs),
("native-static-libs", PrintKind::NativeStaticLibs),
("relocation-models", PrintKind::RelocationModels),
("split-debuginfo", PrintKind::SplitDebuginfo),
("stack-protector-strategies", PrintKind::StackProtectorStrategies),
("sysroot", PrintKind::Sysroot),
("target-cpus", PrintKind::TargetCPUs),
("target-features", PrintKind::TargetFeatures),
("target-libdir", PrintKind::TargetLibdir),
("target-list", PrintKind::TargetList),
("target-spec-json", PrintKind::TargetSpec),
("tls-models", PrintKind::TlsModels),
// tidy-alphabetical-end
];
/// The different settings that the `-C strip` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum Strip {
@ -1508,6 +1534,13 @@ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE
)
});
static PRINT_KINDS_STRING: LazyLock<String> = LazyLock::new(|| {
format!(
"[{}]",
PRINT_KINDS.iter().map(|(name, _)| format!("{name}")).collect::<Vec<_>>().join("|")
)
});
/// Returns all rustc command line options, including metadata for
/// each option, such as whether the option is stable.
pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
@ -1568,10 +1601,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
"",
"print",
"Compiler information to print on stdout",
"[crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|\
target-list|target-cpus|target-features|relocation-models|code-models|\
tls-models|target-spec-json|all-target-specs-json|native-static-libs|\
stack-protector-strategies|link-args|deployment-target]",
&PRINT_KINDS_STRING,
),
opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),
@ -1999,32 +2029,6 @@ fn collect_print_requests(
cg.target_feature = String::new();
}
const PRINT_KINDS: &[(&str, PrintKind)] = &[
// tidy-alphabetical-start
("all-target-specs-json", PrintKind::AllTargetSpecs),
("calling-conventions", PrintKind::CallingConventions),
("cfg", PrintKind::Cfg),
("check-cfg", PrintKind::CheckCfg),
("code-models", PrintKind::CodeModels),
("crate-name", PrintKind::CrateName),
("deployment-target", PrintKind::DeploymentTarget),
("file-names", PrintKind::FileNames),
("host-tuple", PrintKind::HostTuple),
("link-args", PrintKind::LinkArgs),
("native-static-libs", PrintKind::NativeStaticLibs),
("relocation-models", PrintKind::RelocationModels),
("split-debuginfo", PrintKind::SplitDebuginfo),
("stack-protector-strategies", PrintKind::StackProtectorStrategies),
("sysroot", PrintKind::Sysroot),
("target-cpus", PrintKind::TargetCPUs),
("target-features", PrintKind::TargetFeatures),
("target-libdir", PrintKind::TargetLibdir),
("target-list", PrintKind::TargetList),
("target-spec-json", PrintKind::TargetSpec),
("tls-models", PrintKind::TlsModels),
// tidy-alphabetical-end
];
// We disallow reusing the same path in multiple prints, such as `--print
// cfg=output.txt --print link-args=output.txt`, because outputs are printed
// by disparate pieces of the compiler, and keeping track of which files

View file

@ -2234,6 +2234,7 @@ symbols! {
wasm_abi,
wasm_import_module,
wasm_target_feature,
where_clause_attrs,
while_let,
windows,
windows_subsystem,