authorbors <bors@rust-lang.org> 2026-06-27 14:41:51 UTC
committerbors <bors@rust-lang.org> 2026-06-27 14:41:51 UTC
log13f1859f2faf97a15664e655624baa7417fdc100
treed16489b0f679560b8a28af4c3767d9231aa1989c
parentcb41b6d3daa0c1ad088a8802a6d8700c61290865
parenta85522c1c72517c9ad3eb0b2c79d4e161ecc8bae

Auto merge of #158487 - JonathanBrouwer:rollup-ln8LEcs, r=JonathanBrouwer

Rollup of 13 pull requests Successful merges: - rust-lang/rust#157871 ([rustdoc] Update `doc_cfg` hide/show syntax) - rust-lang/rust#158234 (Cross-referencing tuple_trait tracking issue, source and the Unstable Book) - rust-lang/rust#158480 (add smoketest for std::net::hostname) - rust-lang/rust#157625 (Use infer tys for synthetic params when lowering const paths point to fns) - rust-lang/rust#158290 (add crashtests [1/N]) - rust-lang/rust#158306 (tests: modify s390x vector test to be robust to instruction scheduling) - rust-lang/rust#158313 (Move `check_target_feature` into the attribute parser) - rust-lang/rust#158431 (More lint cleanups) - rust-lang/rust#158452 (Add missing links in integer docs) - rust-lang/rust#158467 (Add proc macro for unused assignments and corresponding test) - rust-lang/rust#158472 (Add regression test for unexpected pointer dereference issue) - rust-lang/rust#158475 (Fix doc comment on get_debug_as_hex.) - rust-lang/rust#158476 (Fix doc comment on FormattingOptions::new().)

94 files changed, 1539 insertions(+), 673 deletions(-)

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs+24-10
......@@ -10,7 +10,7 @@ use crate::attributes::AttributeSafety;
1010use crate::session_diagnostics::{
1111 EmptyExportName, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass,
1212 NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral,
13 SanitizeInvalidStatic,
13 SanitizeInvalidStatic, TargetFeatureOnLangItem,
1414};
1515use crate::target_checking::Policy::AllowSilent;
1616
......@@ -524,15 +524,6 @@ impl CombineAttributeParser for TargetFeatureParser {
524524 was_forced: false,
525525 };
526526 const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
527 const STABILITY: AttributeStability = AttributeStability::Stable;
528
529 fn extend(
530 cx: &mut AcceptContext<'_, '_>,
531 args: &ArgParser,
532 ) -> impl IntoIterator<Item = Self::Item> {
533 parse_tf_attribute(cx, args)
534 }
535
536527 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
537528 Allow(Target::Fn),
538529 Allow(Target::Method(MethodKind::Inherent)),
......@@ -544,6 +535,29 @@ impl CombineAttributeParser for TargetFeatureParser {
544535 Warn(Target::MacroDef),
545536 Warn(Target::MacroCall),
546537 ]);
538 const STABILITY: AttributeStability = AttributeStability::Stable;
539
540 fn extend(
541 cx: &mut AcceptContext<'_, '_>,
542 args: &ArgParser,
543 ) -> impl IntoIterator<Item = Self::Item> {
544 parse_tf_attribute(cx, args)
545 }
546
547 fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
548 // `#[target_feature]` is incompatible with lang item functions,
549 // except on WASM where calling target-feature functions is safe (see #84988).
550 if !cx.sess().target.is_like_wasm && !cx.sess().opts.actually_rustdoc {
551 // `#[panic_handler]` is checked first so it takes priority in the diagnostic.
552 let lang_kind = cx
553 .all_attrs
554 .iter()
555 .find_map(|a| [sym::panic_handler, sym::lang].into_iter().find(|&s| a.word_is(s)));
556 if let Some(kind) = lang_kind {
557 cx.emit_err(TargetFeatureOnLangItem { attr_span, kind, item_span: cx.target_span });
558 }
559 }
560 }
547561}
548562
549563pub(crate) struct ForceTargetFeatureParser;
compiler/rustc_attr_parsing/src/attributes/doc.rs+133-37
......@@ -1,25 +1,29 @@
11use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit};
2use rustc_data_structures::fx::{FxHashSet, FxIndexMap, IndexEntry};
23use rustc_errors::{Applicability, msg};
34use rustc_feature::AttributeStability;
45use rustc_hir::Target;
56use rustc_hir::attrs::{
6 AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow,
7 AttributeKind, CfgEntry, CfgHideShow, DocAttribute, DocCfgHideShow, DocCfgHideShowValue,
8 DocInline, HideOrShow,
79};
810use rustc_session::errors::feature_err;
911use rustc_span::{Span, Symbol, edition, sym};
10use thin_vec::ThinVec;
1112
1213use super::prelude::{ALL_TARGETS, AllowedTargets};
1314use super::{AcceptMapping, AttributeParser, template};
1415use crate::context::{AcceptContext, FinalizeContext};
1516use crate::diagnostics::{
1617 AttrCrateLevelOnly, DocAliasDuplicated, DocAutoCfgExpectsHideOrShow,
17 DocAutoCfgHideShowExpectsList, DocAutoCfgHideShowUnexpectedItem, DocAutoCfgWrongLiteral,
18 DocTestLiteral, DocTestTakesList, DocTestUnknown, DocUnknownAny, DocUnknownInclude,
19 DocUnknownPasses, DocUnknownPlugins, DocUnknownSpotlight, ExpectedNameValue, ExpectedNoArgs,
20 IllFormedAttributeInput, MalformedDoc,
18 DocAutoCfgHideShowExpectsList, DocAutoCfgHideShowNoIdentBeforeValues,
19 DocAutoCfgHideShowUnexpectedItem, DocAutoCfgHideShowUnexpectedItemAfterValues,
20 DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocTestLiteral, DocTestTakesList,
21 DocTestUnknown, DocUnknownAny, DocUnknownInclude, DocUnknownPasses, DocUnknownPlugins,
22 DocUnknownSpotlight, ExpectedNameValue, ExpectedNoArgs, IllFormedAttributeInput, MalformedDoc,
23};
24use crate::parser::{
25 ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser,
2126};
22use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser};
2327use crate::session_diagnostics::{
2428 DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel,
2529 DocAttributeNotAttribute, DocKeywordNotKeyword, UnusedDuplicate,
......@@ -304,6 +308,81 @@ impl DocParser {
304308 }
305309 }
306310
311 // Parses the `doc(auto_cfg(hide/show(..., values())))` attribute.
312 fn parse_auto_cfg_values(
313 &self,
314 cx: &mut AcceptContext<'_, '_>,
315 list: &MetaItemListParser,
316 values: &mut Option<DocCfgHideShow>,
317 ) {
318 let mut cfg_values = DocCfgHideShow::new();
319
320 let mut values_set = FxHashSet::default();
321 for item in list.mixed() {
322 match item {
323 // If it's a string literal, all good.
324 MetaItemOrLitParser::Lit(MetaItemLit {
325 kind: LitKind::Str(symbol, _),
326 span,
327 ..
328 }) => match &mut cfg_values {
329 DocCfgHideShow::Any(any_span) => {
330 cx.emit_lint(
331 rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
332 DocAutoCfgHideShowValuesMix { value_span: *span },
333 *any_span,
334 );
335 }
336 DocCfgHideShow::List(symbols) => {
337 if values_set.insert(symbol) {
338 symbols.push(DocCfgHideShowValue::new(*symbol, *span));
339 }
340 }
341 },
342 // If it's any other kind of literal, then it's wrong and we emit a lint.
343 MetaItemOrLitParser::Lit(lit) => cx.emit_lint(
344 rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
345 DocAutoCfgHideShowUnexpectedItem { attr_name: lit.symbol },
346 lit.span,
347 ),
348 // If it's a list, then only `any()` and `none()` are allowed and they must not
349 // contain any item.
350 MetaItemOrLitParser::MetaItemParser(sub_item) => {
351 if let Some(ident) = sub_item.ident()
352 && [sym::any, sym::none].contains(&ident.name)
353 && let ArgParser::List(list) = sub_item.args()
354 && list.mixed().count() == 0
355 {
356 if ident.name == sym::any {
357 if let DocCfgHideShow::List(values) = &cfg_values
358 && let Some(value) = values.first()
359 {
360 cx.emit_lint(
361 rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
362 DocAutoCfgHideShowValuesMix { value_span: value.span },
363 sub_item.span(),
364 );
365 } else {
366 cfg_values.merge_with(&DocCfgHideShow::Any(sub_item.span()));
367 }
368 } else {
369 cfg_values.push_none(sub_item.span());
370 }
371 } else {
372 cx.emit_lint(
373 rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
374 DocAutoCfgHideShowUnexpectedItem {
375 attr_name: sub_item.ident().unwrap().name,
376 },
377 sub_item.span(),
378 );
379 }
380 }
381 }
382 }
383 *values = Some(cfg_values);
384 }
385
307386 fn parse_auto_cfg(
308387 &mut self,
309388 cx: &mut AcceptContext<'_, '_>,
......@@ -315,7 +394,7 @@ impl DocParser {
315394 self.attribute.auto_cfg_change.push((true, path.span()));
316395 }
317396 ArgParser::List(list) => {
318 for meta in list.mixed() {
397 'main: for meta in list.mixed() {
319398 let MetaItemOrLitParser::MetaItemParser(item) = meta else {
320399 cx.emit_lint(
321400 rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
......@@ -324,6 +403,8 @@ impl DocParser {
324403 );
325404 continue;
326405 };
406 // Only `hide` and `show` are allowed in `auto_cfg` if it's a list, and both
407 // must be a list.
327408 let (kind, attr_name) = match item.path().word_sym() {
328409 Some(sym::hide) => (HideOrShow::Hide, sym::hide),
329410 Some(sym::show) => (HideOrShow::Show, sym::show),
......@@ -345,8 +426,10 @@ impl DocParser {
345426 continue;
346427 };
347428
348 let mut cfg_hide_show = CfgHideShow { kind, values: ThinVec::new() };
429 let mut cfg_hide_show = CfgHideShow { kind, values: FxIndexMap::default() };
349430
431 let mut cfg_names = FxHashSet::default();
432 let mut values = None;
350433 for item in list.mixed() {
351434 let MetaItemOrLitParser::MetaItemParser(sub_item) = item else {
352435 cx.emit_lint(
......@@ -354,47 +437,60 @@ impl DocParser {
354437 DocAutoCfgHideShowUnexpectedItem { attr_name },
355438 item.span(),
356439 );
357 continue;
440 continue 'main;
358441 };
359442 match sub_item.args() {
360 a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
443 ArgParser::NoArgs if values.is_none() => {
361444 let Some(name) = sub_item.path().word_sym() else {
362 // FIXME: remove this method once merged and uncomment the line
363 // below instead.
364 // cx.expected_identifier(sub_item.path().span());
445 cx.adcx().expected_identifier(sub_item.path().span());
446 continue 'main;
447 };
448 cfg_names.insert(name);
449 }
450 // The only accepted list is `values()`.
451 ArgParser::List(list) if values.is_none() => {
452 let Some(sym::values) = sub_item.path().word_sym() else {
453 cx.adcx().expected_identifier(sub_item.path().span());
454 continue 'main;
455 };
456 if cfg_names.is_empty() {
365457 cx.emit_lint(
366458 rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
367 MalformedDoc,
368 sub_item.path().span(),
369 );
370 continue;
371 };
372 if let Ok(CfgEntry::NameValue { name, value, .. }) =
373 super::cfg::parse_name_value(
374 name,
375 sub_item.path().span(),
376 a.as_name_value(),
459 DocAutoCfgHideShowNoIdentBeforeValues,
377460 sub_item.span(),
378 cx,
379 )
380 {
381 cfg_hide_show.values.push(CfgInfo {
382 name,
383 name_span: sub_item.path().span(),
384 // If `value` is `Some`, `a.name_value()` will always return
385 // `Some` as well.
386 value: value
387 .map(|v| (v, a.as_name_value().unwrap().value_span)),
388 })
461 );
462 continue 'main;
389463 }
464 self.parse_auto_cfg_values(cx, list, &mut values);
390465 }
391 _ => {
466 // No `name = value` is allowed.
467 ArgParser::NameValue(_) => {
392468 cx.emit_lint(
393469 rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
394470 DocAutoCfgHideShowUnexpectedItem { attr_name },
395471 sub_item.span(),
396472 );
397 continue;
473 }
474 // If `values()` was already used, no item should come after it.
475 _ => {
476 cx.emit_lint(
477 rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
478 DocAutoCfgHideShowUnexpectedItemAfterValues,
479 sub_item.span(),
480 );
481 }
482 }
483 }
484
485 let values = values.unwrap_or(DocCfgHideShow::new_with_only_key(item.span()));
486 #[allow(rustc::potential_query_instability)]
487 for cfg_name in &cfg_names {
488 match cfg_hide_show.values.entry(*cfg_name) {
489 IndexEntry::Vacant(v) => {
490 v.insert(values.clone());
491 }
492 IndexEntry::Occupied(mut o) => {
493 o.get_mut().merge_with(&values);
398494 }
399495 }
400496 }
compiler/rustc_attr_parsing/src/attributes/link_attrs.rs+1-1
......@@ -576,7 +576,7 @@ impl NoArgsAttributeParser for FfiPureParser {
576576 const STABILITY: AttributeStability = unstable!(ffi_pure);
577577 const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;
578578
579 fn finalize_check(attr_span: Span, cx: &FinalizeContext<'_, '_>) {
579 fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
580580 // `#[ffi_const]` functions cannot be `#[ffi_pure]`.
581581 if cx.all_attrs.iter().any(|a| a.word_is(sym::ffi_const)) {
582582 cx.emit_err(BothFfiConstAndPure { attr_span });
compiler/rustc_attr_parsing/src/attributes/mod.rs+15-6
......@@ -154,7 +154,7 @@ pub(crate) trait SingleAttributeParser: 'static {
154154 /// reject incompatible combinations. `attr_span` is the span of this attribute.
155155 ///
156156 /// Defaults to a no-op.
157 fn finalize_check(_attr_span: Span, _cx: &FinalizeContext<'_, '_>) {}
157 fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
158158}
159159
160160/// Use in combination with [`SingleAttributeParser`].
......@@ -187,7 +187,7 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> {
187187
188188 fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
189189 let (kind, span) = self.1?;
190 T::finalize_check(span, cx);
190 T::finalize_check(cx, span);
191191 Some(kind)
192192 }
193193}
......@@ -275,7 +275,7 @@ pub(crate) trait NoArgsAttributeParser: 'static {
275275 /// `attr_span` is the span of this attribute.
276276 ///
277277 /// Defaults to a no-op.
278 fn finalize_check(_attr_span: Span, _cx: &FinalizeContext<'_, '_>) {}
278 fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
279279}
280280
281281pub(crate) struct WithoutArgs<T: NoArgsAttributeParser>(PhantomData<T>);
......@@ -299,8 +299,8 @@ impl<T: NoArgsAttributeParser> SingleAttributeParser for WithoutArgs<T> {
299299 Some(T::CREATE(cx.attr_span))
300300 }
301301
302 fn finalize_check(attr_span: Span, cx: &FinalizeContext<'_, '_>) {
303 T::finalize_check(attr_span, cx)
302 fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
303 T::finalize_check(cx, attr_span)
304304 }
305305}
306306
......@@ -335,6 +335,14 @@ pub(crate) trait CombineAttributeParser: 'static {
335335 cx: &mut AcceptContext<'_, '_>,
336336 args: &ArgParser,
337337 ) -> impl IntoIterator<Item = Self::Item>;
338
339 /// Optional cross-attribute validation, run once during finalization after all
340 /// attributes on the item have been parsed. Has access to the sibling attributes via
341 /// [`FinalizeContext::all_attrs`], so it can reject incompatible combinations.
342 /// `attr_span` is the span of the first attribute that was encountered.
343 ///
344 /// Defaults to a no-op.
345 fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
338346}
339347
340348/// Use in combination with [`CombineAttributeParser`].
......@@ -367,8 +375,9 @@ impl<T: CombineAttributeParser> AttributeParser for Combine<T> {
367375 const ALLOWED_TARGETS: AllowedTargets<'_> = T::ALLOWED_TARGETS;
368376 const SAFETY: AttributeSafety = T::SAFETY;
369377
370 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
378 fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
371379 if let Some(first_span) = self.first_span {
380 T::finalize_check(cx, first_span);
372381 Some(T::CONVERT(self.items, first_span))
373382 } else {
374383 None
compiler/rustc_attr_parsing/src/diagnostics.rs+16-1
......@@ -169,11 +169,22 @@ pub(crate) struct DocAutoCfgExpectsHideOrShow;
169169pub(crate) struct AmbiguousDeriveHelpers;
170170
171171#[derive(Diagnostic)]
172#[diag("`#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items")]
172#[diag("`#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or `values(...)`")]
173173pub(crate) struct DocAutoCfgHideShowUnexpectedItem {
174174 pub attr_name: Symbol,
175175}
176176
177#[derive(Diagnostic)]
178#[diag("`any()` was used when other values were provided")]
179pub(crate) struct DocAutoCfgHideShowValuesMix {
180 #[label("value declared here")]
181 pub value_span: Span,
182}
183
184#[derive(Diagnostic)]
185#[diag("unexpected item after `values()`")]
186pub(crate) struct DocAutoCfgHideShowUnexpectedItemAfterValues;
187
177188#[derive(Diagnostic)]
178189#[diag("`#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items")]
179190pub(crate) struct DocAutoCfgHideShowExpectsList {
......@@ -239,6 +250,10 @@ pub(crate) struct DocUnknownAny {
239250#[diag("expected boolean for `#[doc(auto_cfg = ...)]`")]
240251pub(crate) struct DocAutoCfgWrongLiteral;
241252
253#[derive(Diagnostic)]
254#[diag("there must be at least one identifier before `values(...)`")]
255pub(crate) struct DocAutoCfgHideShowNoIdentBeforeValues;
256
242257#[derive(Diagnostic)]
243258#[diag("`#[doc(test(...)]` takes a list of attributes")]
244259pub(crate) struct DocTestTakesList;
compiler/rustc_attr_parsing/src/session_diagnostics.rs+20
......@@ -80,6 +80,26 @@ pub(crate) struct DocAttributeNotAttribute {
8080 pub attribute: Symbol,
8181}
8282
83#[derive(Diagnostic)]
84#[diag(
85 "`#[target_feature]` cannot be applied to a {$kind ->
86 [panic_handler] `#[panic_handler]`
87 *[other] lang item
88 } function"
89)]
90pub(crate) struct TargetFeatureOnLangItem {
91 #[primary_span]
92 pub attr_span: Span,
93 pub kind: Symbol,
94 #[label(
95 "{$kind ->
96 [panic_handler] `#[panic_handler]`
97 *[other] lang item
98 } function is not allowed to have `#[target_feature]`"
99 )]
100 pub item_span: Span,
101}
102
83103#[derive(Diagnostic)]
84104#[diag("missing 'since'", code = E0542)]
85105pub(crate) struct MissingSince {
compiler/rustc_hir/src/attrs/data_structures.rs+59-12
......@@ -515,19 +515,66 @@ pub enum HideOrShow {
515515 Show,
516516}
517517
518#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
519pub struct CfgInfo {
520 pub name: Symbol,
521 pub name_span: Span,
522 pub value: Option<(Symbol, Span)>,
518#[derive(Clone, Copy, Debug, StableHash, Encodable, Decodable, PrintAttribute, PartialEq)]
519pub struct DocCfgHideShowValue {
520 pub span: Span,
521 /// If `value` is `None`, then it's a `none()` value.
522 pub value: Option<Symbol>,
523}
524
525impl DocCfgHideShowValue {
526 pub fn new(value: Symbol, span: Span) -> Self {
527 Self { span, value: Some(value) }
528 }
529
530 pub fn new_none(span: Span) -> Self {
531 Self { span, value: None }
532 }
533}
534
535#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute, PartialEq)]
536pub enum DocCfgHideShow {
537 Any(Span),
538 List(ThinVec<DocCfgHideShowValue>),
523539}
524540
525impl CfgInfo {
526 pub fn span_for_name_and_value(&self) -> Span {
527 if let Some((_, value_span)) = self.value {
528 self.name_span.with_hi(value_span.hi())
529 } else {
530 self.name_span
541impl DocCfgHideShow {
542 pub fn new() -> Self {
543 Self::List(ThinVec::new())
544 }
545
546 pub fn new_with_only_key(span: Span) -> Self {
547 let mut values = ThinVec::with_capacity(1);
548 values.push(DocCfgHideShowValue { span, value: None });
549 Self::List(values)
550 }
551
552 pub fn push_none(&mut self, span: Span) {
553 if let Self::List(values) = self
554 && !values.iter().any(|v| v.value.is_none())
555 {
556 values.push(DocCfgHideShowValue { span, value: None });
557 }
558 }
559
560 pub fn merge_with(&mut self, other: &Self) {
561 match (self, other) {
562 (Self::Any(_), Self::Any(_) | Self::List(_)) => {
563 // Nothing to do.
564 }
565 (s, Self::Any(span)) => {
566 // We "upgrade" the list values to "all".
567 *s = Self::Any(*span);
568 }
569 (Self::List(values), Self::List(other_values)) => {
570 // Having duplicates is not an issue, we simply ignore them. Would be more
571 // convenient to have a `set` type though. T_T
572 for other in other_values {
573 if !values.iter().any(|value| value.value == other.value) {
574 values.push(*other);
575 }
576 }
577 }
531578 }
532579 }
533580}
......@@ -535,7 +582,7 @@ impl CfgInfo {
535582#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
536583pub struct CfgHideShow {
537584 pub kind: HideOrShow,
538 pub values: ThinVec<CfgInfo>,
585 pub values: FxIndexMap<Symbol, DocCfgHideShow>,
539586}
540587
541588#[derive(Clone, Debug, Default, StableHash, Decodable, PrintAttribute)]
compiler/rustc_hir/src/attrs/pretty_printing.rs+1-1
......@@ -81,7 +81,7 @@ impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
8181 p.word("]");
8282 }
8383}
84impl<T: PrintAttribute> PrintAttribute for FxIndexMap<T, Span> {
84impl<T: PrintAttribute, T2: PrintAttribute> PrintAttribute for FxIndexMap<T, T2> {
8585 fn should_render(&self) -> bool {
8686 self.is_empty() || self[0].should_render()
8787 }
compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs+21-1
......@@ -2862,7 +2862,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
28622862 did,
28632863 path.segments.last().unwrap(),
28642864 );
2865 ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args))
2865
2866 if self.tcx().generics_of(did).own_synthetic_params_count() == 0 {
2867 ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args))
2868 } else {
2869 let tcx = self.tcx();
2870 let generics = tcx.generics_of(did);
2871
2872 // Use infer tys for synthetic params; otherwise the impl header's trait ref may
2873 // contain callee-owned synthetic params and fail when instantiated with impl args.
2874 // See issue #155834
2875 let args = args.iter().enumerate().map(|(index, arg)| {
2876 let param = generics.param_at(index, tcx);
2877 if param.kind.is_synthetic() {
2878 self.ty_infer(Some(param), span).into()
2879 } else {
2880 arg
2881 }
2882 });
2883
2884 ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args))
2885 }
28662886 }
28672887
28682888 // Exhaustive match to be clear about what exactly we're considering to be
compiler/rustc_lint/src/context.rs+44-28
......@@ -46,21 +46,39 @@ type LateLintPassFactory =
4646 Box<dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync>;
4747
4848/// Information about the registered lints.
49//
50// About the pass factories: these should only be called once, but since we
51// want to avoid locks or interior mutability, we don't enforce this. Lints
52// should, in theory, be compatible with being constructed more than once,
53// though not necessarily in a sane manner. This is safe though.
4954pub struct LintStore {
5055 /// Registered lints.
5156 lints: Vec<&'static Lint>,
5257
53 /// Constructor functions for each variety of lint pass.
58 /// This lint pass kind is softly deprecated. It misses expanded code and has caused a few
59 /// errors in the past. Currently, it is only used in Clippy. New implementations
60 /// should avoid using this interface, as it might be removed in the future.
61 ///
62 /// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838)
63 /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518)
64 pub(crate) pre_expansion_lint_passes: Vec<EarlyLintPassFactory>,
65
66 /// These lint passes run on AST nodes.
67 pub(crate) early_lint_passes: Vec<EarlyLintPassFactory>,
68
69 /// These lint passes run on HIR nodes. Each one processes an entire crate. They don't benefit
70 /// from incremental compilation. `late_lint_mod_passes` should be used in preference where
71 /// possible; only use `late_lint_passes` for lints that implement `check_crate` and/or
72 /// `check_crate_post` and accumulate cross-module state.
5473 ///
55 /// These should only be called once, but since we want to avoid locks or
56 /// interior mutability, we don't enforce this (and lints should, in theory,
57 /// be compatible with being constructed more than once, though not
58 /// necessarily in a sane manner. This is safe though.)
59 pub pre_expansion_passes: Vec<EarlyLintPassFactory>,
60 pub early_passes: Vec<EarlyLintPassFactory>,
61 pub late_passes: Vec<LateLintPassFactory>,
62 /// This is unique in that we construct them per-module, so not once.
63 pub late_module_passes: Vec<LateLintPassFactory>,
74 /// The exception is Clippy, which uses `late_lint_passes` for all late lint passes. It needs
75 /// `check_crate`/`check_crate_post` for some of its lints and uses late lint passes throughout
76 /// for consistency. This is ok because Clippy isn't wired for incremental compilation.
77 pub(crate) late_lint_passes: Vec<LateLintPassFactory>,
78
79 /// These lint passes run on HIR nodes, and are constructed per-module (i.e. multiple times).
80 /// They benefit from incremental compilation.
81 pub(crate) late_lint_mod_passes: Vec<LateLintPassFactory>,
6482
6583 /// Lints indexed by name.
6684 by_name: UnordMap<String, TargetLint>,
......@@ -136,10 +154,10 @@ impl LintStore {
136154 pub fn new() -> LintStore {
137155 LintStore {
138156 lints: vec![],
139 pre_expansion_passes: vec![],
140 early_passes: vec![],
141 late_passes: vec![],
142 late_module_passes: vec![],
157 pre_expansion_lint_passes: vec![],
158 early_lint_passes: vec![],
159 late_lint_passes: vec![],
160 late_lint_mod_passes: vec![],
143161 by_name: Default::default(),
144162 lint_groups: Default::default(),
145163 }
......@@ -166,26 +184,24 @@ impl LintStore {
166184 self.lint_groups.keys().copied()
167185 }
168186
169 pub fn register_early_pass(&mut self, pass: EarlyLintPassFactory) {
170 self.early_passes.push(pass);
187 /// See the comment on `LintStore::pre_expansion_lint_passes`.
188 pub fn register_pre_expansion_lint_pass(&mut self, pass: EarlyLintPassFactory) {
189 self.pre_expansion_lint_passes.push(pass);
171190 }
172191
173 /// This lint pass is softly deprecated. It misses expanded code and has caused a few
174 /// errors in the past. Currently, it is only used in Clippy. New implementations
175 /// should avoid using this interface, as it might be removed in the future.
176 ///
177 /// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838)
178 /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518)
179 pub fn register_pre_expansion_pass(&mut self, pass: EarlyLintPassFactory) {
180 self.pre_expansion_passes.push(pass);
192 /// See the comment on `LintStore::early_lint_passes`.
193 pub fn register_early_lint_pass(&mut self, pass: EarlyLintPassFactory) {
194 self.early_lint_passes.push(pass);
181195 }
182196
183 pub fn register_late_pass(&mut self, pass: LateLintPassFactory) {
184 self.late_passes.push(pass);
197 /// See the comment on `LintStore::late_lint_passes`.
198 pub fn register_late_lint_pass(&mut self, pass: LateLintPassFactory) {
199 self.late_lint_passes.push(pass);
185200 }
186201
187 pub fn register_late_mod_pass(&mut self, pass: LateLintPassFactory) {
188 self.late_module_passes.push(pass);
202 /// See the comment on `LintStore::late_lint_mod_passes`.
203 pub fn register_late_lint_mod_pass(&mut self, pass: LateLintPassFactory) {
204 self.late_lint_mod_passes.push(pass);
189205 }
190206
191207 /// Helper method for register_early/late_pass
compiler/rustc_lint/src/early.rs+2-2
......@@ -329,11 +329,11 @@ pub fn check_ast_node<'a>(
329329
330330 let context = if pre_expansion {
331331 let builtin_lints = crate::BuiltinCombinedPreExpansionLintPass::new();
332 let passes = &lint_store.pre_expansion_passes;
332 let passes = &lint_store.pre_expansion_lint_passes;
333333 run_passes(check_node, context, builtin_lints, passes)
334334 } else {
335335 let builtin_lints = crate::BuiltinCombinedEarlyLintPass::new();
336 let passes = &lint_store.early_passes;
336 let passes = &lint_store.early_lint_passes;
337337 run_passes(check_node, context, builtin_lints, passes)
338338 };
339339
compiler/rustc_lint/src/late.rs+2-2
......@@ -355,7 +355,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
355355 // `builtin_lints` directly rather than bundling it up into the
356356 // `RuntimeCombinedLateLintPass`.
357357 let mut passes: Vec<_> = unerased_lint_store(tcx.sess)
358 .late_module_passes
358 .late_lint_mod_passes
359359 .iter()
360360 .map(|mk_pass| mk_pass(tcx))
361361 .filter(|pass| is_lint_pass_required(skippable_lints, &pass.get_lints()))
......@@ -403,7 +403,7 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
403403
404404 // Note: `passes` is often empty after filtering.
405405 let passes: Vec<_> = unerased_lint_store(tcx.sess)
406 .late_passes
406 .late_lint_passes
407407 .iter()
408408 .map(|mk_pass| mk_pass(tcx))
409409 .filter(|pass| is_lint_pass_required(skippable_lints, &pass.get_lints()))
compiler/rustc_lint/src/lib.rs+9-7
......@@ -154,7 +154,7 @@ pub fn provide(providers: &mut Providers) {
154154}
155155
156156fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
157 late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
157 late_lint_mod(tcx, module_def_id, BuiltinCombinedLateLintModPass::new());
158158}
159159
160160early_lint_methods!(
......@@ -207,7 +207,7 @@ early_lint_methods!(
207207late_lint_methods!(
208208 declare_combined_late_lint_pass,
209209 [
210 BuiltinCombinedModuleLateLintPass,
210 BuiltinCombinedLateLintModPass,
211211 [
212212 ForLoopsOverFallibles: ForLoopsOverFallibles,
213213 DefaultCouldBeDerived: DefaultCouldBeDerived,
......@@ -279,7 +279,7 @@ late_lint_methods!(
279279late_lint_methods!(
280280 declare_combined_late_lint_pass,
281281 [
282 InternalCombinedModuleLateLintPass,
282 InternalCombinedLateLintModPass,
283283 [
284284 DefaultHashTypes: DefaultHashTypes,
285285 QueryStability: QueryStability,
......@@ -317,7 +317,7 @@ fn register_builtins(store: &mut LintStore) {
317317
318318 store.register_lints(&BuiltinCombinedPreExpansionLintPass::lint_vec());
319319 store.register_lints(&BuiltinCombinedEarlyLintPass::lint_vec());
320 store.register_lints(&BuiltinCombinedModuleLateLintPass::lint_vec());
320 store.register_lints(&BuiltinCombinedLateLintModPass::lint_vec());
321321 store.register_lints(&foreign_modules::lint_vec());
322322 store.register_lints(&hardwired::lint_vec());
323323
......@@ -698,10 +698,12 @@ fn register_builtins(store: &mut LintStore) {
698698
699699fn register_internals(store: &mut LintStore) {
700700 store.register_lints(&InternalCombinedEarlyLintPass::lint_vec());
701 store.register_early_pass(Box::new(|| Box::new(InternalCombinedEarlyLintPass::new())));
701 store.register_early_lint_pass(Box::new(|| Box::new(InternalCombinedEarlyLintPass::new())));
702702
703 store.register_lints(&InternalCombinedModuleLateLintPass::lint_vec());
704 store.register_late_mod_pass(Box::new(|_| Box::new(InternalCombinedModuleLateLintPass::new())));
703 store.register_lints(&InternalCombinedLateLintModPass::lint_vec());
704 store.register_late_lint_mod_pass(Box::new(|_| {
705 Box::new(InternalCombinedLateLintModPass::new())
706 }));
705707
706708 store.register_group(
707709 false,
compiler/rustc_lint/src/passes.rs+1-1
......@@ -203,7 +203,7 @@ macro_rules! expand_combined_early_lint_pass_methods {
203203/// Combines multiple lints passes into a single lint pass, at compile time,
204204/// for maximum speed. Each `check_foo` method in `$methods` within this pass
205205/// simply calls `check_foo` once per `$pass`. Compare with
206/// `EarlyLintPassObjects`, which is similar, but combines lint passes at
206/// `RuntimeCombinedEarlyLintPass`, which is similar, but combines lint passes at
207207/// runtime.
208208#[macro_export]
209209macro_rules! declare_combined_early_lint_pass {
compiler/rustc_passes/src/check_attr.rs+1-34
......@@ -204,9 +204,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
204204 AttributeKind::Deprecated { span: attr_span, .. } => {
205205 self.check_deprecated(hir_id, *attr_span, target)
206206 }
207 AttributeKind::TargetFeature { attr_span, .. } => {
208 self.check_target_feature(hir_id, *attr_span, target, attrs)
209 }
210207 AttributeKind::RustcDumpObjectLifetimeDefaults => {
211208 self.check_dump_object_lifetime_defaults(hir_id);
212209 }
......@@ -406,6 +403,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
406403 AttributeKind::ShouldPanic { .. } => (),
407404 AttributeKind::Splat(..) => (),
408405 AttributeKind::Stability { .. } => (),
406 AttributeKind::TargetFeature { .. } => {}
409407 AttributeKind::TestRunner(..) => (),
410408 AttributeKind::ThreadLocal => (),
411409 AttributeKind::TypeLengthLimit { .. } => (),
......@@ -799,37 +797,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
799797 }
800798 }
801799
802 /// Checks if the `#[target_feature]` attribute on `item` is valid.
803 fn check_target_feature(
804 &self,
805 hir_id: HirId,
806 attr_span: Span,
807 target: Target,
808 attrs: &[Attribute],
809 ) {
810 match target {
811 Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
812 | Target::Fn => {
813 // `#[target_feature]` is not allowed in lang items.
814 if let Some(lang_item) = find_attr!(attrs, Lang(lang ) => lang)
815 // Calling functions with `#[target_feature]` is
816 // not unsafe on WASM, see #84988
817 && !self.tcx.sess.target.is_like_wasm
818 && !self.tcx.sess.opts.actually_rustdoc
819 {
820 let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
821
822 self.dcx().emit_err(diagnostics::LangItemWithTargetFeature {
823 attr_span,
824 name: lang_item.name(),
825 sig_span: sig.span,
826 });
827 }
828 }
829 _ => {}
830 }
831 }
832
833800 fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) {
834801 if let Some(location) = match target {
835802 Target::AssocTy => {
compiler/rustc_passes/src/diagnostics.rs-20
......@@ -362,26 +362,6 @@ pub(crate) struct LangItemWithTrackCaller {
362362 pub sig_span: Span,
363363}
364364
365#[derive(Diagnostic)]
366#[diag(
367 "{$name ->
368 [panic_impl] `#[panic_handler]`
369 *[other] `{$name}` lang item
370 } function is not allowed to have `#[target_feature]`"
371)]
372pub(crate) struct LangItemWithTargetFeature {
373 #[primary_span]
374 pub attr_span: Span,
375 pub name: Symbol,
376 #[label(
377 "{$name ->
378 [panic_impl] `#[panic_handler]`
379 *[other] `{$name}` lang item
380 } function is not allowed to have `#[target_feature]`"
381 )]
382 pub sig_span: Span,
383}
384
385365#[derive(Diagnostic)]
386366#[diag("duplicate diagnostic item in crate `{$crate_name}`: `{$name}`")]
387367pub(crate) struct DuplicateDiagnosticItemInCrate {
library/alloc/src/lib.rs+4-1
......@@ -65,7 +65,10 @@
6565 issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
6666 test(no_crate_inject, attr(allow(unused_variables, duplicate_features), deny(warnings)))
6767)]
68#![doc(auto_cfg(hide(no_global_oom_handling, no_rc, no_sync, target_has_atomic = "ptr")))]
68#![doc(auto_cfg(
69 hide(no_global_oom_handling, no_rc, no_sync),
70 hide(target_has_atomic, values("ptr")),
71))]
6972#![doc(rust_logo)]
7073#![feature(rustdoc_internals)]
7174#![no_std]
library/core/src/fmt/mod.rs+2-4
......@@ -332,9 +332,7 @@ mod flags {
332332}
333333
334334impl FormattingOptions {
335 /// Construct a new `FormatterBuilder` with the supplied `Write` trait
336 /// object for output that is equivalent to the `{}` formatting
337 /// specifier:
335 /// Construct a new `FormattingOptions` representing the plain `{}` formatting specifier:
338336 ///
339337 /// - no flags,
340338 /// - filled with spaces,
......@@ -518,7 +516,7 @@ impl FormattingOptions {
518516 pub const fn get_precision(&self) -> Option<u16> {
519517 if self.flags & flags::PRECISION_FLAG != 0 { Some(self.precision) } else { None }
520518 }
521 /// Returns the current precision.
519 /// Returns the current `x?` or `X?` flag.
522520 #[unstable(feature = "formatting_options", issue = "118117")]
523521 pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> {
524522 if self.flags & flags::DEBUG_LOWER_HEX_FLAG != 0 {
library/core/src/lib.rs+10-21
......@@ -51,27 +51,16 @@
5151 test(attr(allow(dead_code, deprecated, unused_variables, unused_mut, duplicate_features)))
5252)]
5353#![doc(rust_logo)]
54#![doc(auto_cfg(hide(
55 no_fp_fmt_parse,
56 target_pointer_width = "16",
57 target_pointer_width = "32",
58 target_pointer_width = "64",
59 target_has_atomic = "8",
60 target_has_atomic = "16",
61 target_has_atomic = "32",
62 target_has_atomic = "64",
63 target_has_atomic = "ptr",
64 target_has_atomic_primitive_alignment = "8",
65 target_has_atomic_primitive_alignment = "16",
66 target_has_atomic_primitive_alignment = "32",
67 target_has_atomic_primitive_alignment = "64",
68 target_has_atomic_primitive_alignment = "ptr",
69 target_has_atomic_load_store = "8",
70 target_has_atomic_load_store = "16",
71 target_has_atomic_load_store = "32",
72 target_has_atomic_load_store = "64",
73 target_has_atomic_load_store = "ptr",
74)))]
54#![doc(auto_cfg(
55 hide(no_fp_fmt_parse),
56 hide(target_pointer_width, values("16", "32", "64")),
57 hide(
58 target_has_atomic,
59 target_has_atomic_primitive_alignment,
60 target_has_atomic_load_store,
61 values("8", "16", "32", "64", "ptr"),
62 ),
63))]
7564#![no_core]
7665#![rustc_coherence_is_core]
7766#![rustc_preserve_ub_checks]
library/core/src/marker.rs+1-1
......@@ -1066,7 +1066,7 @@ pub const trait Destruct: PointeeSized {}
10661066///
10671067/// The implementation of this trait is built-in and cannot be implemented
10681068/// for any user type.
1069#[unstable(feature = "tuple_trait", issue = "none")]
1069#[unstable(feature = "tuple_trait", issue = "157987")]
10701070#[lang = "tuple_trait"]
10711071#[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")]
10721072#[rustc_deny_explicit_impl]
library/core/src/num/int_macros.rs+23-23
......@@ -983,7 +983,7 @@ macro_rules! int_impl {
983983 /// This function will always panic on overflow, regardless of whether overflow checks are enabled.
984984 ///
985985 /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where
986 /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
986 /// [`MIN`](Self::MIN) is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
987987 /// that is too large to represent in the type.
988988 ///
989989 /// # Examples
......@@ -1050,7 +1050,7 @@ macro_rules! int_impl {
10501050 /// This function will always panic on overflow, regardless of whether overflow checks are enabled.
10511051 ///
10521052 /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where
1053 /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
1053 /// [`MIN`](Self::MIN) is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
10541054 /// that is too large to represent in the type.
10551055 ///
10561056 /// # Examples
......@@ -1223,7 +1223,7 @@ macro_rules! int_impl {
12231223 /// This function will always panic on overflow, regardless of whether overflow checks are enabled.
12241224 ///
12251225 /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a
1226 /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts.
1226 /// signed type (where [`MIN`](Self::MIN) is the negative minimal value), which is invalid due to implementation artifacts.
12271227 ///
12281228 /// # Examples
12291229 ///
......@@ -1289,7 +1289,7 @@ macro_rules! int_impl {
12891289 /// This function will always panic on overflow, regardless of whether overflow checks are enabled.
12901290 ///
12911291 /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a
1292 /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts.
1292 /// signed type (where [`MIN`](Self::MIN) is the negative minimal value), which is invalid due to implementation artifacts.
12931293 ///
12941294 /// # Examples
12951295 ///
......@@ -2259,8 +2259,8 @@ macro_rules! int_impl {
22592259 /// boundary of the type.
22602260 ///
22612261 /// The only case where such wrapping can occur is when one divides `MIN / -1` on a signed type (where
2262 /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
2263 /// that is too large to represent in the type. In such a case, this function returns `MIN` itself.
2262 /// [`MIN`](Self::MIN) is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value
2263 /// that is too large to represent in the type. In such a case, this function returns [`MIN`](Self::MIN) itself.
22642264 ///
22652265 /// # Panics
22662266 ///
......@@ -2284,9 +2284,9 @@ macro_rules! int_impl {
22842284 /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`,
22852285 /// wrapping around at the boundary of the type.
22862286 ///
2287 /// Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value
2287 /// Wrapping will only occur in `MIN / -1` on a signed type (where [`MIN`](Self::MIN) is the negative minimal value
22882288 /// for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the
2289 /// type. In this case, this method returns `MIN` itself.
2289 /// type. In this case, this method returns [`MIN`](Self::MIN) itself.
22902290 ///
22912291 /// # Panics
22922292 ///
......@@ -2311,7 +2311,7 @@ macro_rules! int_impl {
23112311 /// boundary of the type.
23122312 ///
23132313 /// Such wrap-around never actually occurs mathematically; implementation artifacts make `x % y`
2314 /// invalid for `MIN / -1` on a signed type (where `MIN` is the negative minimal value). In such a case,
2314 /// invalid for `MIN / -1` on a signed type (where [`MIN`](Self::MIN) is the negative minimal value). In such a case,
23152315 /// this function returns `0`.
23162316 ///
23172317 /// # Panics
......@@ -2336,8 +2336,8 @@ macro_rules! int_impl {
23362336 /// Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around
23372337 /// at the boundary of the type.
23382338 ///
2339 /// Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value
2340 /// for the type). In this case, this method returns 0.
2339 /// Wrapping will only occur in `MIN % -1` on a signed type (where [`MIN`](Self::MIN) is
2340 /// the negative minimal value for the type). In this case, this method returns 0.
23412341 ///
23422342 /// # Panics
23432343 ///
......@@ -2361,9 +2361,9 @@ macro_rules! int_impl {
23612361 /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
23622362 /// of the type.
23632363 ///
2364 /// The only case where such wrapping can occur is when one negates `MIN` on a signed type (where `MIN`
2364 /// The only case where such wrapping can occur is when one negates [`MIN`](Self::MIN) on a signed type (where [`MIN`](Self::MIN)
23652365 /// is the negative minimal value for the type); this is a positive value that is too large to represent
2366 /// in the type. In such a case, this function returns `MIN` itself.
2366 /// in the type. In such a case, this function returns [`MIN`](Self::MIN) itself.
23672367 ///
23682368 /// # Examples
23692369 ///
......@@ -2460,7 +2460,7 @@ macro_rules! int_impl {
24602460 ///
24612461 /// The only case where such wrapping can occur is when one takes the absolute value of the negative
24622462 /// minimal value for the type; this is a positive value that is too large to represent in the type. In
2463 /// such a case, this function returns `MIN` itself.
2463 /// such a case, this function returns [`MIN`](Self::MIN) itself.
24642464 ///
24652465 /// # Examples
24662466 ///
......@@ -2772,7 +2772,7 @@ macro_rules! int_impl {
27722772 ///
27732773 /// # Examples
27742774 ///
2775 /// Please note that this example is shared among integer types, which is why `i32` is used.
2775 /// Please note that this example is shared among integer types, which is why [`i32`] is used.
27762776 ///
27772777 /// ```
27782778 /// #![feature(signed_bigint_helpers)]
......@@ -2950,7 +2950,7 @@ macro_rules! int_impl {
29502950 /// Negates self, overflowing if this is equal to the minimum value.
29512951 ///
29522952 /// Returns a tuple of the negated version of self along with a boolean indicating whether an overflow
2953 /// happened. If `self` is the minimum value (e.g., `i32::MIN` for values of type `i32`), then the
2953 /// happened. If `self` is the minimum value (e.g., [`i32::MIN`] for values of type [`i32`]), then the
29542954 /// minimum value will be returned again and `true` will be returned for an overflow happening.
29552955 ///
29562956 /// # Examples
......@@ -3020,7 +3020,7 @@ macro_rules! int_impl {
30203020 ///
30213021 /// Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow
30223022 /// happened. If self is the minimum value
3023 #[doc = concat!("(e.g., ", stringify!($SelfT), "::MIN for values of type ", stringify!($SelfT), "),")]
3023 #[doc = concat!("(e.g., [`", stringify!($SelfT), "::MIN`] for values of type [`", stringify!($SelfT), "`]),")]
30243024 /// then the minimum value will be returned again and true will be returned
30253025 /// for an overflow happening.
30263026 ///
......@@ -3177,7 +3177,7 @@ macro_rules! int_impl {
31773177 ///
31783178 /// # Panics
31793179 ///
3180 /// This function will panic if `rhs` is zero or if `self` is `Self::MIN`
3180 /// This function will panic if `rhs` is zero or if `self` is [`Self::MIN`]
31813181 /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag.
31823182 ///
31833183 /// # Examples
......@@ -3215,7 +3215,7 @@ macro_rules! int_impl {
32153215 ///
32163216 /// # Panics
32173217 ///
3218 /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` and
3218 /// This function will panic if `rhs` is zero or if `self` is [`Self::MIN`] and
32193219 /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag.
32203220 ///
32213221 /// # Examples
......@@ -3262,7 +3262,7 @@ macro_rules! int_impl {
32623262 ///
32633263 /// # Panics
32643264 ///
3265 /// This function will panic if `rhs` is zero or if `self` is `Self::MIN`
3265 /// This function will panic if `rhs` is zero or if `self` is [`Self::MIN`]
32663266 /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag.
32673267 ///
32683268 /// # Examples
......@@ -3304,7 +3304,7 @@ macro_rules! int_impl {
33043304 ///
33053305 /// # Panics
33063306 ///
3307 /// This function will panic if `rhs` is zero or if `self` is `Self::MIN`
3307 /// This function will panic if `rhs` is zero or if `self` is [`Self::MIN`]
33083308 /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag.
33093309 ///
33103310 /// # Examples
......@@ -3441,8 +3441,8 @@ macro_rules! int_impl {
34413441 /// rounded down.
34423442 ///
34433443 /// This method might not be optimized owing to implementation details;
3444 /// `ilog2` can produce results more efficiently for base 2, and `ilog10`
3445 /// can produce results more efficiently for base 10.
3444 /// [`ilog2`][Self::ilog2] can produce results more efficiently for base 2,
3445 /// and [`ilog10`](Self::ilog10) can produce results more efficiently for base 10.
34463446 ///
34473447 /// # Panics
34483448 ///
library/core/src/num/uint_macros.rs+2-2
......@@ -1721,8 +1721,8 @@ macro_rules! uint_impl {
17211721 /// rounded down.
17221722 ///
17231723 /// This method might not be optimized owing to implementation details;
1724 /// `ilog2` can produce results more efficiently for base 2, and `ilog10`
1725 /// can produce results more efficiently for base 10.
1724 /// [`ilog2`](Self::ilog2) can produce results more efficiently for base 2,
1725 /// and [`ilog10`](Self::ilog10) can produce results more efficiently for base 10.
17261726 ///
17271727 /// # Panics
17281728 ///
library/std/src/net/ip_addr/tests.rs+1-1
......@@ -1,5 +1,5 @@
11use crate::net::Ipv4Addr;
2use crate::net::test::{sa4, tsa};
2use crate::net::tests::{sa4, tsa};
33
44#[test]
55fn to_socket_addr_socketaddr() {
library/std/src/net/mod.rs+1-1
......@@ -43,7 +43,7 @@ mod ip_addr;
4343mod socket_addr;
4444mod tcp;
4545#[cfg(test)]
46pub(crate) mod test;
46pub(crate) mod tests;
4747mod udp;
4848
4949/// Possible values which can be passed to the [`TcpStream::shutdown`] method.
library/std/src/net/socket_addr/tests.rs+1-1
......@@ -1,4 +1,4 @@
1use crate::net::test::{sa4, sa6, tsa};
1use crate::net::tests::{sa4, sa6, tsa};
22use crate::net::*;
33
44#[test]
library/std/src/net/tcp/tests.rs+1-1
......@@ -3,7 +3,7 @@ use rand::Rng;
33use crate::io::prelude::*;
44use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut};
55use crate::mem::MaybeUninit;
6use crate::net::test::{LOCALHOST_IP4, LOCALHOST_IP6};
6use crate::net::tests::{LOCALHOST_IP4, LOCALHOST_IP6};
77use crate::net::*;
88use crate::sync::mpsc::channel;
99use crate::time::{Duration, Instant};
library/std/src/net/test.rs deleted-38
......@@ -1,38 +0,0 @@
1#![allow(warnings)] // not used on emscripten
2
3use crate::env;
4use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
5use crate::sync::atomic::{AtomicUsize, Ordering};
6
7/// A localhost address whose port will be picked automatically by the OS.
8pub const LOCALHOST_IP4: SocketAddr =
9 SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
10/// A localhost address whose port will be picked automatically by the OS.
11pub const LOCALHOST_IP6: SocketAddr =
12 SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0));
13
14pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr {
15 SocketAddr::V4(SocketAddrV4::new(a, p))
16}
17
18pub fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr {
19 SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0))
20}
21
22pub fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
23 match a.to_socket_addrs() {
24 Ok(a) => Ok(a.collect()),
25 Err(e) => Err(e.to_string()),
26 }
27}
28
29pub fn compare_ignore_zoneid(a: &SocketAddr, b: &SocketAddr) -> bool {
30 match (a, b) {
31 (SocketAddr::V6(a), SocketAddr::V6(b)) => {
32 a.ip().segments() == b.ip().segments()
33 && a.flowinfo() == b.flowinfo()
34 && a.port() == b.port()
35 }
36 _ => a == b,
37 }
38}
library/std/src/net/tests.rs created+48
......@@ -0,0 +1,48 @@
1#![allow(warnings)] // not used on emscripten
2
3use crate::env;
4use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
5use crate::sync::atomic::{AtomicUsize, Ordering};
6
7/// A localhost address whose port will be picked automatically by the OS.
8pub const LOCALHOST_IP4: SocketAddr =
9 SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
10/// A localhost address whose port will be picked automatically by the OS.
11pub const LOCALHOST_IP6: SocketAddr =
12 SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0));
13
14pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr {
15 SocketAddr::V4(SocketAddrV4::new(a, p))
16}
17
18pub fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr {
19 SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0))
20}
21
22pub fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
23 match a.to_socket_addrs() {
24 Ok(a) => Ok(a.collect()),
25 Err(e) => Err(e.to_string()),
26 }
27}
28
29pub fn compare_ignore_zoneid(a: &SocketAddr, b: &SocketAddr) -> bool {
30 match (a, b) {
31 (SocketAddr::V6(a), SocketAddr::V6(b)) => {
32 a.ip().segments() == b.ip().segments()
33 && a.flowinfo() == b.flowinfo()
34 && a.port() == b.port()
35 }
36 _ => a == b,
37 }
38}
39
40#[test]
41fn hostname_smoketest() {
42 // Just a smoke test to ensure it can be called.
43 let name = crate::net::hostname();
44 if cfg!(windows) || cfg!(unix) {
45 // At least on Windows and Unix, this should succeed.
46 name.unwrap();
47 }
48}
library/std/src/net/udp/tests.rs+1-1
......@@ -1,5 +1,5 @@
11use crate::io::ErrorKind;
2use crate::net::test::{LOCALHOST_IP4, LOCALHOST_IP6, compare_ignore_zoneid};
2use crate::net::tests::{LOCALHOST_IP4, LOCALHOST_IP6, compare_ignore_zoneid};
33use crate::net::*;
44use crate::sync::mpsc::channel;
55use crate::thread;
library/std/src/os/net/linux_ext/tests.rs+2-2
......@@ -1,6 +1,6 @@
11#[test]
22fn quickack() {
3 use crate::net::test::LOCALHOST_IP4;
3 use crate::net::tests::LOCALHOST_IP4;
44 use crate::net::{TcpListener, TcpStream};
55 use crate::os::net::linux_ext::tcp::TcpStreamExt;
66
......@@ -29,7 +29,7 @@ fn quickack() {
2929#[test]
3030#[cfg(target_os = "linux")]
3131fn deferaccept() {
32 use crate::net::test::LOCALHOST_IP4;
32 use crate::net::tests::LOCALHOST_IP4;
3333 use crate::net::{TcpListener, TcpStream};
3434 use crate::os::net::linux_ext::tcp::TcpStreamExt;
3535 use crate::time::Duration;
src/doc/rustc-dev-guide/src/diagnostics/lintstore.md+1-1
......@@ -97,7 +97,7 @@ The best way for drivers to get access to this is by overriding the
9797
9898Within the compiler, for performance reasons, we usually do not register dozens
9999of lint passes. Instead, we have a single lint pass of each variety (e.g.,
100`BuiltinCombinedModuleLateLintPass`) which will internally call all of the
100`BuiltinCombinedLateLintModPass`) which will internally call all of the
101101individual lint passes; this is because then we get the benefits of static over
102102dynamic dispatch for each of the (often empty) trait methods.
103103
src/doc/rustdoc/src/unstable-features.md+61-21
......@@ -850,12 +850,63 @@ pub mod futures {
850850
851851Then, the `unix` cfg will never be displayed into the documentation.
852852
853Rustdoc currently hides `doc` and `doctest` attributes by default and reserves the right to change the list of "hidden by default" attributes.
853The syntax of `hide` is as follows: you can list as many `cfg` name as you want:
854854
855The attribute accepts only a list of identifiers or key/value items. So you can write:
855```rust,ignore (nightly)
856#[doc(auto_cfg(hide(feature, target_os)))]
857```
858
859With the above example, it means that `#[cfg(feature)]` and `#[cfg(target_os)]` won't be displayed in the docs. However, `#[cfg(target_os = "linux)]` or `#[cfg(feature = "something")]` will be displayed because only the key without values was marked as hidden. if you want to hide some values, you can do:
860
861```rust,ignore (nightly)
862#[doc(auto_cfg(hide(feature, target_os, values("something", "linux"))))]
863```
864
865In this case, `#[cfg(feature = "linux")]`, `#[cfg(feature = "something")]`, `#[cfg(target_os = "something")]` and `#[cfg(target_os = "linux")]` will be hidden. All listed keys will be impacted by `values(...)`. You can split them by having two `hide`:
866
867```rust,ignore (nightly)
868#[doc(auto_cfg(
869 hide(feature, values("something")),
870 hide(target_os, values("linux")),
871))]
872```
873
874Now, only `#[cfg(feature = "something")]` and `#[cfg(target_os = "linux")]` will be hidden. If you want to hide a key and all its values, you can use `any()`:
875
876```rust,ignore (nightly)
877#[doc(auto_cfg(
878 hide(feature, values(any())),
879))]
880```
881
882If you want to hide only when there is no value you can use `none()`:
883
884```rust,ignore (nightly)
885#[doc(auto_cfg(
886 hide(feature, values("something", none())),
887))]
888```
889
890So now, if you want to forbid all values for a key, but allow the key itself, you can do:
891
892```rust,ignore (nightly)
893#[doc(auto_cfg(
894 hide(feature, values(any())), // We completely hide "feature".
895 show(feature), // We show again "feature" (but not any value).
896))]
897```
898
899If the previous example, both `#[cfg(feature)]` and `#[cfg(feature = "something")]` will be hidden.
900
901Rustdoc currently hides `test`, `doc` and `doctest` attributes by default and reserves the right to change the list of "hidden by default" attributes.
902
903The attribute accepts only a list of identifiers and `values()`. So you can write:
856904
857905```rust,ignore (nightly)
858#[doc(auto_cfg(hide(unix, doctest, feature = "something")))]
906#[doc(auto_cfg(
907 hide(unix, doctest),
908 hide(feature, values("something")),
909))]
859910#[doc(auto_cfg(hide()))]
860911```
861912
......@@ -865,7 +916,7 @@ But you cannot write:
865916#[doc(auto_cfg(hide(not(unix))))]
866917```
867918
868So if we use `doc(auto_cfg(hide(unix)))`, it means it will hide all mentions of `unix`:
919So if we use `doc(auto_cfg(hide(unix)))`, it means it will hide all mentions of `unix` without a value:
869920
870921```rust,ignore (nightly)
871922#[cfg(unix)] // nothing displayed
......@@ -879,14 +930,6 @@ However, it only impacts the `unix` cfg, not the feature:
879930#[cfg(feature = "unix")] // `feature = "unix"` is displayed
880931```
881932
882If `cfg_auto(show(...))` and `cfg_auto(hide(...))` are used to show/hide a same `cfg` on a same item, it'll emit an error. Example:
883
884```rust,ignore (nightly)
885#[doc(auto_cfg(hide(unix)))]
886#[doc(auto_cfg(show(unix)))] // Error!
887pub fn foo() {}
888```
889
890933Using this attribute will re-enable `auto_cfg` if it was disabled at this location:
891934
892935```rust,ignore (nightly)
......@@ -904,14 +947,6 @@ pub mod module {
904947}
905948```
906949
907However, using `doc(auto_cfg = ...)` and `doc(auto_cfg(...))` on the same item will emit an error:
908
909```rust,ignore (nightly)
910#[doc(auto_cfg = false)]
911#[doc(auto_cfg(hide(unix)))] // error
912pub fn foo() {}
913```
914
915950The reason behind this is that `doc(auto_cfg = ...)` enables or disables the feature, whereas `doc(auto_cfg(...))` enables it unconditionally, making the first attribute to appear useless as it will be overidden by the next `doc(auto_cfg)` attribute.
916951
917952### `#[doc(auto_cfg(show(...)))]`
......@@ -919,6 +954,8 @@ The reason behind this is that `doc(auto_cfg = ...)` enables or disables the fea
919954This attribute does the opposite of `#[doc(auto_cfg(hide(...)))]`: if you used `#[doc(auto_cfg(hide(...)))]` and want to revert its effect on an item and its descendants, you can use `#[doc(auto_cfg(show(...)))]`.
920955It only applies to `#[doc(auto_cfg = true)]`, not to `#[doc(cfg(...))]`.
921956
957It follows the same syntax rules as for `#[doc(auto_cfg(hide(...)))]`.
958
922959For example:
923960
924961```rust,ignore (nightly)
......@@ -936,7 +973,10 @@ pub mod futures {
936973The attribute accepts only a list of identifiers or key/value items. So you can write:
937974
938975```rust,ignore (nightly)
939#[doc(auto_cfg(show(unix, doctest, feature = "something")))]
976#[doc(auto_cfg(
977 show(unix, doctest),
978 show(feature, values("something")),
979))]
940980#[doc(auto_cfg(show()))]
941981```
942982
src/doc/unstable-book/src/library-features/tuple-trait.md created+5
......@@ -0,0 +1,5 @@
1# `tuple_trait`
2
3The tracking issue for this feature is [#157987].
4
5[#157987]: https://github.com/rust-lang/rust/issues/157987
src/librustdoc/clean/cfg.rs+108-88
......@@ -8,11 +8,13 @@ use std::sync::Arc;
88use std::{fmt, mem, ops};
99
1010use itertools::Either;
11use rustc_data_structures::fx::{FxHashMap, FxHashSet};
11use rustc_data_structures::fx::FxHashMap;
1212use rustc_data_structures::thin_vec::{ThinVec, thin_vec};
1313use rustc_hir as hir;
1414use rustc_hir::Attribute;
15use rustc_hir::attrs::{self, AttributeKind, CfgEntry, CfgHideShow, HideOrShow};
15use rustc_hir::attrs::{
16 AttributeKind, CfgEntry, CfgHideShow, DocCfgHideShow, DocCfgHideShowValue, HideOrShow,
17};
1618use rustc_middle::ty::TyCtxt;
1719use rustc_span::symbol::{Symbol, sym};
1820use rustc_span::{DUMMY_SP, Span};
......@@ -30,6 +32,87 @@ mod tests;
3032#[cfg_attr(test, derive(PartialEq))]
3133pub(crate) struct Cfg(CfgEntry);
3234
35// Similar to `hir::DocCfgHideShow` but allows to handle both `show` and `hide` as with the `except`
36// field in `Any` variant.
37#[derive(Clone, Debug)]
38enum DocCfgHide {
39 Any { except: ThinVec<DocCfgHideShowValue> },
40 List(ThinVec<DocCfgHideShowValue>),
41}
42
43impl DocCfgHide {
44 fn new() -> Self {
45 Self::List([DocCfgHideShowValue::new_none(DUMMY_SP)].into())
46 }
47
48 fn contains(&self, value: Option<Symbol>) -> bool {
49 match self {
50 // Contains any values except the ones listed in `except`.
51 Self::Any { except } => !except.iter().any(|e| e.value == value),
52 Self::List(values) => values.iter().any(|v| v.value == value),
53 }
54 }
55
56 fn merge_with(&mut self, other: &DocCfgHideShow) {
57 match (self, other) {
58 (Self::Any { except }, DocCfgHideShow::Any(_)) => {
59 except.clear();
60 }
61 (s, DocCfgHideShow::Any(_)) => {
62 // We "upgrade" the list values to "all".
63 *s = Self::Any { except: ThinVec::new() };
64 }
65 (Self::Any { except }, DocCfgHideShow::List(values)) => {
66 for other in values {
67 if let Some(index) = except.iter().position(|value| value.value == other.value)
68 {
69 except.remove(index);
70 }
71 }
72 }
73 (Self::List(values), DocCfgHideShow::List(other_values)) => {
74 for other in other_values {
75 if !values.iter().any(|value| value.value == other.value) {
76 values.push(*other);
77 }
78 }
79 }
80 }
81 }
82
83 fn remove(&mut self, other: &DocCfgHideShow) {
84 match (self, other) {
85 (s, DocCfgHideShow::Any(_)) => {
86 *s = Self::List(ThinVec::new());
87 }
88 (Self::Any { except }, DocCfgHideShow::List(other_values)) => {
89 for other in other_values {
90 if !except.iter().any(|value| value.value == other.value) {
91 except.push(*other);
92 }
93 }
94 }
95 (Self::List(values), DocCfgHideShow::List(other_values)) => {
96 for other in other_values {
97 if let Some(index) = values.iter().position(|value| value.value == other.value)
98 {
99 values.remove(index);
100 }
101 }
102 }
103 }
104 }
105}
106
107impl From<&DocCfgHideShow> for DocCfgHide {
108 fn from(from: &DocCfgHideShow) -> Self {
109 match from {
110 DocCfgHideShow::Any(_) => Self::Any { except: ThinVec::new() },
111 DocCfgHideShow::List(values) => Self::List(values.clone()),
112 }
113 }
114}
115
33116/// Whether the configuration consists of just `Cfg` or `Not`.
34117fn is_simple_cfg(cfg: &CfgEntry) -> bool {
35118 match cfg {
......@@ -53,14 +136,14 @@ fn is_any_cfg(cfg: &CfgEntry) -> bool {
53136 }
54137}
55138
56fn strip_hidden(cfg: &CfgEntry, hidden: &FxHashSet<NameValueCfg>) -> Option<CfgEntry> {
139fn strip_hidden(cfg: &CfgEntry, hidden: &FxHashMap<Symbol, DocCfgHide>) -> Option<CfgEntry> {
57140 match cfg {
58141 CfgEntry::Bool(..) => Some(cfg.clone()),
59 CfgEntry::NameValue { .. } => {
60 if !hidden.contains(&NameValueCfg::from(cfg)) {
61 Some(cfg.clone())
62 } else {
142 CfgEntry::NameValue { name, value, .. } => {
143 if hidden.get(name).is_some_and(|values| values.contains(*value)) {
63144 None
145 } else {
146 Some(cfg.clone())
64147 }
65148 }
66149 CfgEntry::Not(cfg, _) => {
......@@ -653,39 +736,12 @@ fn human_readable_target_env(env: Symbol) -> Option<&'static str> {
653736 })
654737}
655738
656#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
657struct NameValueCfg {
658 name: Symbol,
659 value: Option<Symbol>,
660}
661
662impl NameValueCfg {
663 fn new(name: Symbol) -> Self {
664 Self { name, value: None }
665 }
666}
667
668impl<'a> From<&'a CfgEntry> for NameValueCfg {
669 fn from(cfg: &'a CfgEntry) -> Self {
670 match cfg {
671 CfgEntry::NameValue { name, value, .. } => NameValueCfg { name: *name, value: *value },
672 _ => NameValueCfg { name: sym::empty, value: None },
673 }
674 }
675}
676
677impl<'a> From<&'a attrs::CfgInfo> for NameValueCfg {
678 fn from(cfg: &'a attrs::CfgInfo) -> Self {
679 Self { name: cfg.name, value: cfg.value.map(|(value, _)| value) }
680 }
681}
682
683739/// This type keeps track of (doc) cfg information as we go down the item tree.
684740#[derive(Clone, Debug)]
685741pub(crate) struct CfgInfo {
686742 /// List of currently active `doc(auto_cfg(hide(...)))` cfgs, minus currently active
687743 /// `doc(auto_cfg(show(...)))` cfgs.
688 hidden_cfg: FxHashSet<NameValueCfg>,
744 hidden_cfg: FxHashMap<Symbol, DocCfgHide>,
689745 /// Current computed `cfg`. Each time we enter a new item, this field is updated as well while
690746 /// taking into account the `hidden_cfg` information.
691747 current_cfg: Cfg,
......@@ -700,10 +756,10 @@ pub(crate) struct CfgInfo {
700756impl Default for CfgInfo {
701757 fn default() -> Self {
702758 Self {
703 hidden_cfg: FxHashSet::from_iter([
704 NameValueCfg::new(sym::test),
705 NameValueCfg::new(sym::doc),
706 NameValueCfg::new(sym::doctest),
759 hidden_cfg: FxHashMap::from_iter([
760 (sym::test, DocCfgHide::new()),
761 (sym::doc, DocCfgHide::new()),
762 (sym::doctest, DocCfgHide::new()),
707763 ]),
708764 current_cfg: Cfg(CfgEntry::Bool(true, DUMMY_SP)),
709765 auto_cfg_active: true,
......@@ -712,51 +768,24 @@ impl Default for CfgInfo {
712768 }
713769}
714770
715fn show_hide_show_conflict_error(
716 tcx: TyCtxt<'_>,
717 item_span: rustc_span::Span,
718 previous: rustc_span::Span,
719) {
720 let mut diag = tcx.sess.dcx().struct_span_err(
721 item_span,
722 format!(
723 "same `cfg` was in `auto_cfg(hide(...))` and `auto_cfg(show(...))` on the same item"
724 ),
725 );
726 diag.span_note(previous, "first change was here");
727 diag.emit();
728}
729
730771/// This functions updates the `hidden_cfg` field of the provided `cfg_info` argument.
731772///
732/// It also checks if a same `cfg` is present in both `auto_cfg(hide(...))` and
733/// `auto_cfg(show(...))` on the same item and emits an error if it's the case.
734///
735773/// Because we go through a list of `cfg`s, we keep track of the `cfg`s we saw in `new_show_attrs`
736774/// and in `new_hide_attrs` arguments.
737fn handle_auto_cfg_hide_show(
738 tcx: TyCtxt<'_>,
739 cfg_info: &mut CfgInfo,
740 attr: &CfgHideShow,
741 new_show_attrs: &mut FxHashMap<(Symbol, Option<Symbol>), rustc_span::Span>,
742 new_hide_attrs: &mut FxHashMap<(Symbol, Option<Symbol>), rustc_span::Span>,
743) {
744 for value in &attr.values {
745 let simple = NameValueCfg::from(value);
775fn handle_auto_cfg_hide_show(cfg_info: &mut CfgInfo, attr: &CfgHideShow) {
776 for (cfg_name, value) in &attr.values {
746777 if attr.kind == HideOrShow::Show {
747 if let Some(span) = new_hide_attrs.get(&(simple.name, simple.value)) {
748 show_hide_show_conflict_error(tcx, value.span_for_name_and_value(), *span);
749 } else {
750 new_show_attrs.insert((simple.name, simple.value), value.span_for_name_and_value());
751 }
752 cfg_info.hidden_cfg.remove(&simple);
778 cfg_info
779 .hidden_cfg
780 .entry(*cfg_name)
781 .and_modify(|entry| entry.remove(value))
782 .or_insert_with(|| value.into());
753783 } else {
754 if let Some(span) = new_show_attrs.get(&(simple.name, simple.value)) {
755 show_hide_show_conflict_error(tcx, value.span_for_name_and_value(), *span);
756 } else {
757 new_hide_attrs.insert((simple.name, simple.value), value.span_for_name_and_value());
758 }
759 cfg_info.hidden_cfg.insert(simple);
784 cfg_info
785 .hidden_cfg
786 .entry(*cfg_name)
787 .and_modify(|entry| entry.merge_with(value))
788 .or_insert_with(|| value.into());
760789 }
761790 }
762791}
......@@ -791,9 +820,6 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
791820 false
792821 }
793822
794 let mut new_show_attrs = FxHashMap::default();
795 let mut new_hide_attrs = FxHashMap::default();
796
797823 let mut doc_cfg = attrs
798824 .clone()
799825 .filter_map(|attr| match attr {
......@@ -844,13 +870,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
844870 return None;
845871 }
846872 for (value, _) in &d.auto_cfg {
847 handle_auto_cfg_hide_show(
848 tcx,
849 cfg_info,
850 value,
851 &mut new_show_attrs,
852 &mut new_hide_attrs,
853 );
873 handle_auto_cfg_hide_show(cfg_info, value);
854874 }
855875 }
856876 } else if let hir::Attribute::Parsed(AttributeKind::TargetFeature { features, .. }) = attr {
src/librustdoc/json/conversions.rs+34-15
......@@ -7,7 +7,9 @@ use rustc_ast::ast;
77use rustc_data_structures::fx::FxHashSet;
88use rustc_data_structures::thin_vec::ThinVec;
99use rustc_hir as hir;
10use rustc_hir::attrs::{self, DeprecatedSince, DocAttribute, DocInline, HideOrShow};
10use rustc_hir::attrs::{
11 self, DeprecatedSince, DocAttribute, DocCfgHideShow, DocInline, HideOrShow,
12};
1113use rustc_hir::def::{CtorKind, DefKind};
1214use rustc_hir::def_id::DefId;
1315use rustc_hir::{HeaderSafety, Safety, find_attr};
......@@ -1122,24 +1124,41 @@ fn maybe_from_hir_attr(attr: &hir::Attribute, item_id: ItemId, tcx: TyCtxt<'_>)
11221124 for sub_cfg in cfg {
11231125 ret.push(Attribute::Other(format!("#[doc(cfg({sub_cfg}))]")));
11241126 }
1125 for (auto_cfg, _) in auto_cfg {
1126 let kind = match auto_cfg.kind {
1127 HideOrShow::Hide => "hide",
1128 HideOrShow::Show => "show",
1129 };
1130 let mut out = format!("#[doc(auto_cfg({kind}(");
1131 for (pos, value) in auto_cfg.values.iter().enumerate() {
1132 if pos > 0 {
1127 if !auto_cfg.is_empty() {
1128 let mut out = format!("#[doc(auto_cfg(");
1129 for (index, (auto_cfg, _)) in auto_cfg.iter().enumerate() {
1130 let kind = match auto_cfg.kind {
1131 HideOrShow::Hide => "hide",
1132 HideOrShow::Show => "show",
1133 };
1134 if index > 0 {
11331135 out.push_str(", ");
11341136 }
1135 out.push_str(value.name.as_str());
1136 if let Some((value, _)) = value.value {
1137 // We use `as_str` and debug display to have characters escaped and `"`
1138 // characters surrounding the string.
1139 out.push_str(&format!(" = {:?}", value.as_str()));
1137 out.push_str(&format!("{kind}("));
1138 for (name, cfgs) in &auto_cfg.values {
1139 out.push_str(&format!("{name}, values("));
1140 match cfgs {
1141 DocCfgHideShow::Any(_) => {
1142 out.push_str("any()");
1143 }
1144 DocCfgHideShow::List(values) => {
1145 for (pos, value) in values.iter().enumerate() {
1146 let separator = if pos > 0 { ", " } else { "" };
1147 if let Some(value) = &value.value {
1148 // We use `as_str` and debug display to have characters escaped
1149 // and `"` characters surrounding the string.
1150 out.push_str(&format!("{separator}{:?}", value.as_str()));
1151 } else {
1152 out.push_str(&format!("{separator}none()"));
1153 }
1154 }
1155 }
1156 }
1157 out.push_str(")");
11401158 }
1159 out.push(')');
11411160 }
1142 out.push_str(")))]");
1161 out.push_str("))]");
11431162 ret.push(Attribute::Other(out));
11441163 }
11451164 for (change, _) in auto_cfg_change {
src/tools/clippy/clippy_lints/src/lib.rs+5-3
......@@ -454,7 +454,9 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
454454 // NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
455455 // Due to the architecture of the compiler, currently `cfg_attr` attributes on crate
456456 // level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass.
457 store.register_pre_expansion_pass(Box::new(move || Box::new(attrs::EarlyAttributes::new(conf))));
457 store.register_pre_expansion_lint_pass(
458 Box::new(move || Box::new(attrs::EarlyAttributes::new(conf)))
459 );
458460
459461 let format_args_storage = FormatArgsStorage::default();
460462 let attr_storage = AttrStorage::default();
......@@ -462,12 +464,12 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
462464 {
463465 let format_args = format_args_storage.clone();
464466 let attrs = attr_storage.clone();
465 store.early_passes.push(Box::new(move || {
467 store.register_early_lint_pass(Box::new(move || {
466468 Box::new(CombinedEarlyLintPass::new(conf, format_args.clone(), attrs.clone()))
467469 }));
468470 }
469471
470 store.late_passes.push(Box::new(move |tcx: TyCtxt<'_>| {
472 store.register_late_lint_pass(Box::new(move |tcx: TyCtxt<'_>| {
471473 let skippable_lints = tcx.skippable_lints(());
472474 let is_active = |lints: &rustc_lint::LintVec| is_lint_pass_required(skippable_lints, lints);
473475 Box::new(CombinedLateLintPass::new(
tests/assembly-llvm/s390x-vector-abi.rs+20-40
......@@ -62,16 +62,11 @@ unsafe extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
6262 *x
6363}
6464// CHECK-LABEL: vector_ret_large:
65// z10: vl %v0, 16(%r3), 4
66// z10-NEXT: vl %v1, 0(%r3), 4
67// z10-NEXT: vst %v0, 16(%r2), 4
68// z10-NEXT: vst %v1, 0(%r2), 4
69// z10-NEXT: br %r14
70// z13: vl %v0, 0(%r3), 4
71// z13-NEXT: vl %v1, 16(%r3), 4
72// z13-NEXT: vst %v1, 16(%r2), 4
73// z13-NEXT: vst %v0, 0(%r2), 4
74// z13-NEXT: br %r14
65// CHECK-DAG: vl [[REG1:%v[0-9]+]], 16(%r3), 4
66// CHECK-DAG: vl [[REG2:%v[0-9]+]], 0(%r3), 4
67// CHECK-DAG: vst [[REG1]], 16(%r2), 4
68// CHECK-DAG: vst [[REG2]], 0(%r2), 4
69// CHECK: br %r14
7570#[cfg_attr(no_vector, target_feature(enable = "vector"))]
7671#[no_mangle]
7772unsafe extern "C" fn vector_ret_large(x: &i8x32) -> i8x32 {
......@@ -95,16 +90,11 @@ unsafe extern "C" fn vector_wrapper_ret(x: &Wrapper<i8x16>) -> Wrapper<i8x16> {
9590 *x
9691}
9792// CHECK-LABEL: vector_wrapper_ret_large:
98// z10: vl %v0, 16(%r3), 4
99// z10-NEXT: vl %v1, 0(%r3), 4
100// z10-NEXT: vst %v0, 16(%r2), 4
101// z10-NEXT: vst %v1, 0(%r2), 4
102// z10-NEXT: br %r14
103// z13: vl %v0, 16(%r3), 4
104// z13-NEXT: vst %v0, 16(%r2), 4
105// z13-NEXT: vl %v0, 0(%r3), 4
106// z13-NEXT: vst %v0, 0(%r2), 4
107// z13-NEXT: br %r14
93// CHECK-DAG: vl [[REG1:%v[0-9]+]], 16(%r3), 4
94// CHECK-DAG: vl [[REG2:%v[0-9]+]], 0(%r3), 4
95// CHECK-DAG: vst [[REG1]], 16(%r2), 4
96// CHECK-DAG: vst [[REG2]], 0(%r2), 4
97// CHECK: br %r14
10898#[cfg_attr(no_vector, target_feature(enable = "vector"))]
10999#[no_mangle]
110100unsafe extern "C" fn vector_wrapper_ret_large(x: &Wrapper<i8x32>) -> Wrapper<i8x32> {
......@@ -141,16 +131,11 @@ unsafe extern "C" fn vector_wrapper_with_zst_ret(
141131 *x
142132}
143133// CHECK-LABEL: vector_wrapper_with_zst_ret_large:
144// z10: vl %v0, 16(%r3), 4
145// z10-NEXT: vl %v1, 0(%r3), 4
146// z10-NEXT: vst %v0, 16(%r2), 4
147// z10-NEXT: vst %v1, 0(%r2), 4
148// z10-NEXT: br %r14
149// z13: vl %v0, 16(%r3), 4
150// z13-NEXT: vst %v0, 16(%r2), 4
151// z13-NEXT: vl %v0, 0(%r3), 4
152// z13-NEXT: vst %v0, 0(%r2), 4
153// z13-NEXT: br %r14
134// CHECK-DAG: vl [[REG1:%v[0-9]+]], 16(%r3), 4
135// CHECK-DAG: vl [[REG2:%v[0-9]+]], 0(%r3), 4
136// CHECK-DAG: vst [[REG1]], 16(%r2), 4
137// CHECK-DAG: vst [[REG2]], 0(%r2), 4
138// CHECK: br %r14
154139#[cfg_attr(no_vector, target_feature(enable = "vector"))]
155140#[no_mangle]
156141unsafe extern "C" fn vector_wrapper_with_zst_ret_large(
......@@ -180,16 +165,11 @@ unsafe extern "C" fn vector_transparent_wrapper_ret(
180165 *x
181166}
182167// CHECK-LABEL: vector_transparent_wrapper_ret_large:
183// z10: vl %v0, 16(%r3), 4
184// z10-NEXT: vl %v1, 0(%r3), 4
185// z10-NEXT: vst %v0, 16(%r2), 4
186// z10-NEXT: vst %v1, 0(%r2), 4
187// z10-NEXT: br %r14
188// z13: vl %v0, 0(%r3), 4
189// z13-NEXT: vl %v1, 16(%r3), 4
190// z13-NEXT: vst %v1, 16(%r2), 4
191// z13-NEXT: vst %v0, 0(%r2), 4
192// z13-NEXT: br %r14
168// CHECK-DAG: vl [[REG1:%v[0-9]+]], 16(%r3), 4
169// CHECK-DAG: vl [[REG2:%v[0-9]+]], 0(%r3), 4
170// CHECK-DAG: vst [[REG1]], 16(%r2), 4
171// CHECK-DAG: vst [[REG2]], 0(%r2), 4
172// CHECK: br %r14
193173#[cfg_attr(no_vector, target_feature(enable = "vector"))]
194174#[no_mangle]
195175unsafe extern "C" fn vector_transparent_wrapper_ret_large(
tests/crashes/147719.rs created+16
......@@ -0,0 +1,16 @@
1//@ known-bug: #147719
2//@ edition: 2024
3trait NodeImpl {}
4struct Wrap<F, P>(F, P);
5impl<F, P> Wrap<F, P> {
6 fn new(_: F) -> Self {
7 loop {}
8 }
9}
10trait Arg {}
11impl<F, A> NodeImpl for Wrap<F, A> where A: Arg {}
12impl<F, Fut, A> NodeImpl for Wrap<F, (A,)> where F: Fn(&(), A) -> Fut {}
13fn trigger_ice() {
14 let _: &dyn NodeImpl = &Wrap::<_, (i128,)>::new(async |_: &(), i128| 0);
15}
16fn main() {}
tests/crashes/148511.rs created+42
......@@ -0,0 +1,42 @@
1//@ known-bug: #148511
2//@ edition: 2021
3use std::any::Any;
4
5fn main() {
6 use_service(make_service());
7 let _future = async {};
8}
9
10fn make_service() -> impl FooService<Box<dyn Any>, Response: Body> {}
11
12fn use_service<S, R>(_service: S)
13where
14 S: FooService<R>,
15 <S::Response as Body>::Data: Any,
16{
17}
18
19trait Service<Request> {
20 type Response: Body;
21}
22
23impl<T, Request> Service<Request> for T {
24 type Response = ();
25}
26
27trait FooService<Request>: Service<Request> {}
28
29impl<T, Request, Resp> FooService<Request> for T
30where
31 T: Service<Request, Response = Resp>,
32 Resp: Body,
33{
34}
35
36trait Body {
37 type Data;
38}
39
40impl<T> Body for T {
41 type Data = ();
42}
tests/crashes/148629.rs created+13
......@@ -0,0 +1,13 @@
1//@ known-bug: #148629
2#![feature(with_negative_coherence)]
3trait Foo {
4 type AssociatedType;
5}
6
7impl<const N: usize> Foo for [(); N] {}
8
9pub struct Happy;
10
11impl Foo for Happy {}
12
13impl<const N: usize> Foo for Happy where <[(); N] as Foo>::AssociatedType: Clone {}
tests/crashes/148630.rs created+13
......@@ -0,0 +1,13 @@
1//@ known-bug: #148630
2#![feature(unboxed_closures)]
3
4trait Tr {}
5trait Foo {
6 fn foo() -> impl Sized
7 where
8 for<'a> <() as FnOnce<&'a i32>>::Output: Tr,
9 {
10 }
11}
12
13fn main() {}
tests/crashes/148632.rs created+10
......@@ -0,0 +1,10 @@
1//@ known-bug: #148632
2trait D<C> {}
3
4trait Project {
5 const SELF: dyn D<Self>;
6}
7
8fn main() {
9 let _: &dyn Project<SELF = { 0 }>;
10}
tests/crashes/148890.rs created+6
......@@ -0,0 +1,6 @@
1//@ known-bug: #148890
2impl std::ops::Neg for u128 {}
3
4fn foo(-128..=127: u128) {}
5
6fn main() {}
tests/crashes/148891.rs created+14
......@@ -0,0 +1,14 @@
1//@ known-bug: #148891
2macro_rules! values {
3 ($inner:ty) => {
4 #[derive(Debug)]
5 pub enum TokenKind {
6 #[cfg(test)]
7 STRING ([u8; $inner]),
8 }
9 };
10}
11
12values!(String);
13
14pub fn main() {}
tests/crashes/149162.rs created+30
......@@ -0,0 +1,30 @@
1//@ known-bug: #149162
2use std::marker::PhantomData;
3pub trait ViewArgument {
4 type Params<'a>;
5}
6
7impl ViewArgument for () {
8 type Params<'a> = ();
9}
10
11pub trait View {}
12
13pub fn buttons() -> Option<impl View> {
14 Some(()).map(|()| text_button(|()| {}))
15}
16pub fn text_button<State: ViewArgument>(
17 _: impl Fn(<State as ViewArgument>::Params<'_>),
18) -> Button<State, impl Fn()> {
19 Button {
20 callback: || (),
21 phantom: PhantomData,
22 }
23}
24pub struct Button<State, F> {
25 pub callback: F,
26 pub phantom: PhantomData<State>,
27}
28
29impl<F> View for Button<(), F> {}
30fn main() {}
tests/crashes/149703.rs created+12
......@@ -0,0 +1,12 @@
1//@ known-bug: #149703
2#![feature(const_trait_impl)]
3trait Z {
4 type Assoc;
5}
6struct A;
7impl<T: const FnOnce()> Z for T {
8 type Assoc = ();
9}
10impl<T> From<<A as Z>::Assoc> for T {}
11
12fn main() {}
tests/crashes/152205.rs created+20
......@@ -0,0 +1,20 @@
1//@ known-bug: #152205
2#![deny(rust_2021_incompatible_closure_captures)]
3struct Foo;
4struct S;
5impl Drop for S {
6 fn drop(&mut self) {}
7}
8struct U(<Foo as NewTrait>::Assoc);
9fn test_precise_analysis_long_path(u: U) {
10 let _ = || {
11 let _x = u.0.0;
12 };
13}
14trait NewTrait {
15 type Assoc;
16}
17impl NewTrait for Foo {
18 type Assoc = (S,);
19}
20fn main(){}
tests/crashes/152295.rs created+11
......@@ -0,0 +1,11 @@
1//@ known-bug: #152295
2#![feature(type_alias_impl_trait)]
3type Tait = impl Sized;
4trait Foo: Bar<Tait> {}
5trait Bar<T> {
6 fn bar(&self);
7}
8fn test_correct2(x: &dyn Foo) {
9 x.bar();
10}
11fn main() {}
tests/crashes/154556.rs created+25
......@@ -0,0 +1,25 @@
1//@ known-bug: #154556
2#![feature(generic_const_exprs)]
3
4pub trait Foo {
5 // Has to take self or a reference to self to ICE.
6 fn eq(self);
7}
8
9pub trait Bar {
10 const NUMBER: usize;
11}
12
13impl<T: Bar> Foo for T
14where
15 [(); T::NUMBER]: Sized, // Bound required for ICE
16{
17 fn eq(self) {}
18}
19
20// As long as the method called below has the same name as the one defined in Foo, the ICE happens.
21fn baz() {
22 ().eq(&());
23}
24
25fn main() {}
tests/crashes/154964.rs created+9
......@@ -0,0 +1,9 @@
1//@ known-bug: #154964
2//@ edition: 2021
3//@ compile-flags: -Zprint-type-sizes
4fn main() {
5 |foo: Foo<_>| async { foo.bar };
6}
7struct Foo<F> {
8 bar: (),
9}
tests/crashes/157568.rs created+10
......@@ -0,0 +1,10 @@
1//@ known-bug: #157568
2//@ compile-flags: -Zpolonius
3#![warn(rust_2024_compatibility)]
4pub struct F;
5impl std::fmt::Debug for F {
6 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7 f.debug_struct("F").finish_non_exhaustive()
8 }
9}
10fn main() {}
tests/rustdoc-html/cfg-bool.rs deleted-17
......@@ -1,17 +0,0 @@
1#![feature(doc_cfg)]
2#![crate_name = "foo"]
3
4// regression test for https://github.com/rust-lang/rust/issues/138112
5
6//@ has 'foo/index.html'
7//@ has - '//*[@class="stab portability"]/@title' 'Available nowhere'
8
9//@ count 'foo/fn.foo.html' '//*[@class="stab portability"]' 1
10//@ has 'foo/fn.foo.html' '//*[@class="stab portability"]' 'Available nowhere'
11#[doc(cfg(false))]
12pub fn foo() {}
13
14// a cfg(true) will simply be omitted, as it is the same as no cfg.
15//@ count 'foo/fn.bar.html' '//*[@class="stab portability"]' 0
16#[doc(cfg(true))]
17pub fn bar() {}
tests/rustdoc-html/doc-auto-cfg-public-in-private.rs deleted-16
......@@ -1,16 +0,0 @@
1// This test ensures that even though private items are removed from generated docs,
2// their `cfg`s will still impact their child items.
3
4#![feature(doc_cfg)]
5#![crate_name = "foo"]
6
7pub struct X;
8
9#[cfg(not(feature = "blob"))]
10fn foo() {
11 impl X {
12 //@ has 'foo/struct.X.html'
13 //@ has - '//*[@class="stab portability"]' 'Available on non-crate feature blob only.'
14 pub fn bar() {}
15 }
16}
tests/rustdoc-html/doc-auto-cfg.rs deleted-35
......@@ -1,35 +0,0 @@
1#![feature(doc_cfg)]
2#![crate_name = "foo"]
3
4//@ has foo/fn.foo.html
5//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meowmeow'
6#[cfg(not(meowmeow))]
7pub fn foo() {}
8
9//@ has foo/fn.bar.html
10//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
11//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
12//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
13//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doctest'
14#[cfg(any(meowmeow, test, doc, doctest))]
15pub fn bar() {}
16
17//@ has foo/fn.appear_1.html
18//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
19//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
20//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test'
21#[cfg(any(meowmeow, doc, not(test)))]
22pub fn appear_1() {} // issue #98065
23
24//@ has foo/fn.appear_2.html
25//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
26//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
27//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
28#[cfg(any(meowmeow, doc, all(test)))]
29pub fn appear_2() {} // issue #98065
30
31//@ has foo/fn.appear_3.html
32//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
33//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
34#[cfg(any(meowmeow, doc, all()))]
35pub fn appear_3() {} // issue #98065
tests/rustdoc-html/doc-cfg/cfg-bool.rs created+17
......@@ -0,0 +1,17 @@
1#![feature(doc_cfg)]
2#![crate_name = "foo"]
3
4// regression test for https://github.com/rust-lang/rust/issues/138112
5
6//@ has 'foo/index.html'
7//@ has - '//*[@class="stab portability"]/@title' 'Available nowhere'
8
9//@ count 'foo/fn.foo.html' '//*[@class="stab portability"]' 1
10//@ has 'foo/fn.foo.html' '//*[@class="stab portability"]' 'Available nowhere'
11#[doc(cfg(false))]
12pub fn foo() {}
13
14// a cfg(true) will simply be omitted, as it is the same as no cfg.
15//@ count 'foo/fn.bar.html' '//*[@class="stab portability"]' 0
16#[doc(cfg(true))]
17pub fn bar() {}
tests/rustdoc-html/doc-cfg/decl-macro.rs+3-3
......@@ -45,7 +45,7 @@ pub mod auto_cfg_disabled {
4545}
4646
4747#[cfg(feature = "routing")]
48#[doc(auto_cfg(hide(feature = "routing")))]
48#[doc(auto_cfg(hide(feature, values("routing"))))]
4949pub mod auto_cfg_hidden {
5050 //@ count 'foo/macro.hidden_cfg_macro.html' '//*[@class="stab portability"]' 0
5151 #[macro_export]
......@@ -55,9 +55,9 @@ pub mod auto_cfg_hidden {
5555}
5656
5757#[cfg(feature = "routing")]
58#[doc(auto_cfg(hide(feature = "routing")))]
58#[doc(auto_cfg(hide(feature, values("routing"))))]
5959pub mod auto_cfg_shown {
60 #[doc(auto_cfg(show(feature = "routing")))]
60 #[doc(auto_cfg(show(feature, values("routing"))))]
6161 pub mod inner {
6262 //@ has 'foo/macro.shown_cfg_macro.html' '//*[@class="stab portability"]' 'Available on crate feature routing only.'
6363 #[macro_export]
tests/rustdoc-html/doc-cfg/doc-auto-cfg-2.rs created+77
......@@ -0,0 +1,77 @@
1// Basic tests covering RFC 3631 features.
2
3#![crate_name = "foo"]
4#![feature(doc_cfg)]
5#![doc(auto_cfg(hide(feature, values("hidden"))))]
6
7//@ has 'foo/index.html'
8//@ !has - '//*[@class="stab portability"]' 'Non-moustache'
9//@ has - '//*[@class="stab portability"]' 'Non-pistache'
10//@ count - '//*[@class="stab portability"]' 1
11
12//@ has 'foo/m/index.html'
13//@ count - '//*[@title="Available on non-crate feature `hidden` only"]' 2
14#[cfg(not(feature = "hidden"))]
15pub mod m {
16 //@ count 'foo/m/struct.A.html' '//*[@class="stab portability"]' 0
17 pub struct A;
18
19 //@ has 'foo/m/inner/index.html' '//*[@class="stab portability"]' 'Available on non-crate feature hidden only.'
20 #[doc(auto_cfg(show(feature, values("hidden"))))]
21 pub mod inner {
22 //@ has 'foo/m/inner/struct.B.html' '//*[@class="stab portability"]' 'Available on non-crate feature hidden only.'
23 pub struct B;
24
25 //@ count 'foo/m/inner/struct.A.html' '//*[@class="stab portability"]' 0
26 #[doc(auto_cfg(hide(feature, values("hidden"))))]
27 pub struct A;
28 }
29
30 //@ has 'foo/m/struct.B.html' '//*[@class="stab portability"]' 'Available on non-crate feature hidden only.'
31 #[doc(auto_cfg(show(feature, values("hidden"))))]
32 pub struct B;
33}
34
35//@ count 'foo/n/index.html' '//*[@title="Available on non-crate feature `moustache` only"]' 3
36//@ count - '//dl/dt' 4
37#[cfg(not(feature = "moustache"))]
38#[doc(auto_cfg = false)]
39pub mod n {
40 // Should not have `moustache` listed.
41 //@ count 'foo/n/struct.X.html' '//*[@class="stab portability"]' 0
42 pub struct X;
43
44 // Should re-enable `auto_cfg` and make `moustache` listed.
45 //@ has 'foo/n/struct.Y.html' '//*[@class="stab portability"]' \
46 // 'Available on non-crate feature moustache only.'
47 #[doc(auto_cfg)]
48 pub struct Y;
49
50 // Should re-enable `auto_cfg` and make `moustache` listed for itself
51 // and for `Y`.
52 //@ has 'foo/n/inner/index.html' '//*[@class="stab portability"]' \
53 // 'Available on non-crate feature moustache only.'
54 #[doc(auto_cfg = true)]
55 pub mod inner {
56 //@ has 'foo/n/inner/struct.Y.html' '//*[@class="stab portability"]' \
57 // 'Available on non-crate feature moustache only.'
58 pub struct Y;
59 }
60
61 // Should re-enable `auto_cfg` and make `moustache` listed.
62 //@ has 'foo/n/struct.Z.html' '//*[@class="stab portability"]' \
63 // 'Available on non-crate feature moustache only.'
64 #[doc(auto_cfg(hide(feature, values("hidden"))))]
65 pub struct Z;
66}
67
68// Checking inheritance.
69//@ has 'foo/o/index.html' '//*[@class="stab portability"]' \
70// 'Available on non-crate feature pistache only.'
71#[doc(cfg(not(feature = "pistache")))]
72pub mod o {
73 //@ has 'foo/o/struct.A.html' '//*[@class="stab portability"]' \
74 // 'Available on non-crate feature pistache and non-crate feature tarte only.'
75 #[doc(cfg(not(feature = "tarte")))]
76 pub struct A;
77}
tests/rustdoc-html/doc-cfg/doc-auto-cfg-public-in-private.rs created+16
......@@ -0,0 +1,16 @@
1// This test ensures that even though private items are removed from generated docs,
2// their `cfg`s will still impact their child items.
3
4#![feature(doc_cfg)]
5#![crate_name = "foo"]
6
7pub struct X;
8
9#[cfg(not(feature = "blob"))]
10fn foo() {
11 impl X {
12 //@ has 'foo/struct.X.html'
13 //@ has - '//*[@class="stab portability"]' 'Available on non-crate feature blob only.'
14 pub fn bar() {}
15 }
16}
tests/rustdoc-html/doc-cfg/doc-auto-cfg.rs created+35
......@@ -0,0 +1,35 @@
1#![feature(doc_cfg)]
2#![crate_name = "foo"]
3
4//@ has foo/fn.foo.html
5//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meowmeow'
6#[cfg(not(meowmeow))]
7pub fn foo() {}
8
9//@ has foo/fn.bar.html
10//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
11//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
12//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
13//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doctest'
14#[cfg(any(meowmeow, test, doc, doctest))]
15pub fn bar() {}
16
17//@ has foo/fn.appear_1.html
18//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
19//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
20//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test'
21#[cfg(any(meowmeow, doc, not(test)))]
22pub fn appear_1() {} // issue #98065
23
24//@ has foo/fn.appear_2.html
25//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
26//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
27//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
28#[cfg(any(meowmeow, doc, all(test)))]
29pub fn appear_2() {} // issue #98065
30
31//@ has foo/fn.appear_3.html
32//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
33//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
34#[cfg(any(meowmeow, doc, all()))]
35pub fn appear_3() {} // issue #98065
tests/rustdoc-html/doc-cfg/doc-cfg-hide.rs+1-1
......@@ -1,7 +1,7 @@
11#![crate_name = "oud"]
22#![feature(doc_cfg)]
33
4#![doc(auto_cfg(hide(feature = "solecism")))]
4#![doc(auto_cfg(hide(feature, values("solecism"))))]
55
66//@ has 'oud/struct.Solecism.html'
77//@ count - '//*[@class="stab portability"]' 0
tests/rustdoc-html/doc-cfg/doc_auto_cfg_reexports.rs created+35
......@@ -0,0 +1,35 @@
1// Checks that `cfg` are correctly applied on inlined reexports.
2
3#![crate_name = "foo"]
4#![feature(doc_cfg)]
5
6// Check with `std` item.
7//@ has 'foo/index.html' '//*[@class="stab portability"]' 'Non-moustache'
8//@ has 'foo/struct.C.html' '//*[@class="stab portability"]' \
9// 'Available on non-crate feature moustache only.'
10#[cfg(not(feature = "moustache"))]
11pub use std::cell::RefCell as C;
12
13// Check with local item.
14mod x {
15 pub struct B;
16}
17
18//@ has 'foo/index.html' '//*[@class="stab portability"]' 'Non-pistache'
19//@ has 'foo/struct.B.html' '//*[@class="stab portability"]' \
20// 'Available on non-crate feature pistache only.'
21#[cfg(not(feature = "pistache"))]
22pub use crate::x::B;
23
24// Now checking that `cfg`s are not applied on non-inlined reexports.
25pub mod pub_sub_mod {
26 //@ has 'foo/pub_sub_mod/index.html'
27 // There should be only only item with `cfg` note.
28 //@ count - '//*[@class="stab portability"]' 1
29 // And obviously the item should be "blabla".
30 //@ has - '//dt' 'blablaNon-pistache'
31 #[cfg(not(feature = "pistache"))]
32 pub fn blabla() {}
33
34 pub use self::blabla as another;
35}
tests/rustdoc-html/doc-cfg/hide-inheritance-key-only.rs created+26
......@@ -0,0 +1,26 @@
1// This test ensures that `auto_cfg(hide(key))` does not hide `key = value` and that
2// `auto_cfg(hide(key, values(none())))` does the same.
3
4#![feature(doc_cfg)]
5#![crate_name = "foo"]
6
7#![doc(auto_cfg(hide(meow)))]
8#![doc(auto_cfg(hide(another_meow, values(none()))))]
9
10//@ has foo/fn.foo.html
11//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob'
12//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow'
13//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-another_meow'
14#[cfg(not(meow))]
15#[cfg(not(another_meow))]
16#[cfg(not(blob))]
17pub fn foo() {}
18
19//@ has foo/fn.bar.html
20//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lol'
21//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lol'
22//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-another_meow=lol'
23#[cfg(not(meow = "lol"))]
24#[cfg(not(another_meow = "lol"))]
25#[cfg(not(blob = "lol"))]
26pub fn bar() {}
tests/rustdoc-html/doc-cfg/hide-inheritance.rs created+179
......@@ -0,0 +1,179 @@
1// This test ensures that using `auto_cfg(show(key))` works correctly.
2
3#![feature(doc_cfg)]
4#![crate_name = "foo"]
5
6#![doc(auto_cfg(hide(meow)))]
7#![doc(auto_cfg(hide(meow, values("lol"))))]
8
9//@ has foo/fn.foo.html
10//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob'
11//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow'
12#[cfg(not(meow))]
13#[cfg(not(blob))]
14pub fn foo() {}
15
16//@ has foo/fn.bar.html
17//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lol'
18//@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lol'
19#[cfg(not(meow = "lol"))]
20#[cfg(not(blob = "lol"))]
21pub fn bar() {}
22
23//@ has foo/fn.babar.html
24//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lola'
25//@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lola'
26#[cfg(not(meow = "lola"))]
27#[cfg(not(blob = "lola"))]
28pub fn babar() {}
29
30pub mod sub {
31 // We show again `meow`, however `meow="lol"` should still be hidden.
32 #![doc(auto_cfg(show(meow)))]
33
34 //@ has foo/sub/fn.foo.html
35 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob'
36 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow'
37 #[cfg(not(meow))]
38 #[cfg(not(blob))]
39 pub fn foo() {}
40
41 //@ has foo/sub/fn.bar.html
42 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lol'
43 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lol'
44 #[cfg(not(meow = "lol"))]
45 #[cfg(not(blob = "lol"))]
46 pub fn bar() {}
47
48 //@ has foo/sub/fn.babar.html
49 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lola'
50 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lola'
51 #[cfg(not(meow = "lola"))]
52 #[cfg(not(blob = "lola"))]
53 pub fn babar() {}
54}
55
56pub mod sub2 {
57 // We show again `meow = "lol`, however `meow` should still be hidden.
58 #![doc(auto_cfg(show(meow, values("lol"))))]
59
60 //@ has foo/sub2/fn.foo.html
61 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob'
62 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow'
63 #[cfg(not(meow))]
64 #[cfg(not(blob))]
65 pub fn foo() {}
66
67 //@ has foo/sub2/fn.bar.html
68 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lol'
69 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lol'
70 #[cfg(not(meow = "lol"))]
71 #[cfg(not(blob = "lol"))]
72 pub fn bar() {}
73
74 //@ has foo/sub2/fn.babar.html
75 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lola'
76 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lola'
77 #[cfg(not(meow = "lola"))]
78 #[cfg(not(blob = "lola"))]
79 pub fn babar() {}
80}
81
82pub mod sub3 {
83 // We show again `meow = "lol`, but by using `any()` this time.
84 #![doc(auto_cfg(show(meow, values(any()))))]
85
86 //@ has foo/sub3/fn.foo.html
87 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob'
88 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow'
89 #[cfg(not(meow))]
90 #[cfg(not(blob))]
91 pub fn foo() {}
92
93 //@ has foo/sub3/fn.bar.html
94 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lol'
95 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lol'
96 #[cfg(not(meow = "lol"))]
97 #[cfg(not(blob = "lol"))]
98 pub fn bar() {}
99
100 //@ has foo/sub3/fn.babar.html
101 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-blob=lola'
102 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meow=lola'
103 #[cfg(not(meow = "lola"))]
104 #[cfg(not(blob = "lola"))]
105 pub fn babar() {}
106}
107
108// This test the mix of values and `none()`.
109#[doc(auto_cfg(
110 hide(bla, values(none(), "tic")),
111 hide(alb, values(none())),
112))]
113pub mod sub4 {
114 //@ has foo/sub4/fn.foo.html
115 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla'
116 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla=tic'
117 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-alb'
118 #[cfg(not(bla))]
119 #[cfg(not(bla = "tic"))]
120 #[cfg(not(alb))]
121 pub fn foo() {}
122
123 //@ has foo/sub4/fn.foo2.html
124 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla'
125 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla=tic'
126 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-alb'
127 #[doc(auto_cfg(
128 show(bla, values(none(), "tic")),
129 show(alb, values(none())),
130 ))]
131 #[cfg(not(bla))]
132 #[cfg(not(bla = "tic"))]
133 #[cfg(not(alb))]
134 pub fn foo2() {}
135}
136
137// This test the mix of `any()` and values.
138#[doc(auto_cfg(
139 hide(alb, values(any())),
140 hide(bla, values(any())),
141 show(bla, values("top")),
142))]
143pub mod sub5 {
144 //@ has foo/sub5/fn.foo.html
145 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-alb'
146 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla=top'
147 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla=a'
148 #[cfg(not(alb))]
149 #[cfg(not(bla = "top"))]
150 #[cfg(not(bla = "a"))]
151 pub fn foo() {}
152
153 //@ has foo/sub5/fn.foo2.html
154 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-alb'
155 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla=top'
156 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla=a'
157 #[doc(auto_cfg(
158 show(alb, values(none())),
159 hide(bla, values("top")),
160 ))]
161 #[cfg(not(alb))]
162 #[cfg(not(bla = "top"))]
163 #[cfg(not(bla = "a"))]
164 pub fn foo2() {}
165
166 //@ has foo/sub5/fn.foo3.html
167 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-alb'
168 //@ !has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla=top'
169 //@ has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-bla=a'
170 #[doc(auto_cfg(
171 show(alb, values(any())),
172 show(bla, values(any())),
173 hide(bla, values(none(), "top")),
174 ))]
175 #[cfg(not(alb))]
176 #[cfg(not(bla = "top"))]
177 #[cfg(not(bla = "a"))]
178 pub fn foo3() {}
179}
tests/rustdoc-html/doc-cfg/trait-impls-manual.rs+3-3
......@@ -3,7 +3,7 @@
33
44#![feature(doc_cfg)]
55#![doc(auto_cfg(hide(
6 target_pointer_width = "64",
6 target_pointer_width, values("64"),
77)))]
88
99#![crate_name = "foo"]
......@@ -36,7 +36,7 @@ pub struct X;
3636//@count - '//*[@id="impl-Trait-for-X"]' 1
3737//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0
3838#[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))]
39#[doc(auto_cfg(hide(target_arch = "wasm32")))]
39#[doc(auto_cfg(hide(target_arch, values("wasm32"))))]
4040mod imp {
4141 impl super::Trait for super::X { fn f(&self) {} }
4242}
......@@ -64,7 +64,7 @@ pub struct Y;
6464//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1
6565//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0
6666#[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))]
67#[doc(auto_cfg(hide(target_arch = "wasm32")))]
67#[doc(auto_cfg(hide(target_arch, values("wasm32"))))]
6868mod imp4 {
6969 impl super::Y { pub fn plain_auto() {} }
7070}
tests/rustdoc-html/doc-cfg/trait-impls.rs+3-3
......@@ -3,7 +3,7 @@
33
44#![feature(doc_cfg)]
55#![doc(auto_cfg(hide(
6 target_pointer_width = "64",
6 target_pointer_width, values("64"),
77)))]
88
99#![crate_name = "foo"]
......@@ -36,7 +36,7 @@ pub struct X;
3636//@count - '//*[@id="impl-Trait-for-X"]' 1
3737//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0
3838#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
39#[doc(auto_cfg(hide(target_arch = "wasm32")))]
39#[doc(auto_cfg(hide(target_arch, values("wasm32"))))]
4040mod imp {
4141 impl super::Trait for super::X { fn f(&self) {} }
4242}
......@@ -64,7 +64,7 @@ pub struct Y;
6464//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1
6565//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0
6666#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
67#[doc(auto_cfg(hide(target_arch = "wasm32")))]
67#[doc(auto_cfg(hide(target_arch, values("wasm32"))))]
6868mod imp4 {
6969 impl super::Y { pub fn plain_auto() {} }
7070}
tests/rustdoc-html/doc_auto_cfg.rs deleted-77
......@@ -1,77 +0,0 @@
1// Basic tests covering RFC 3631 features.
2
3#![crate_name = "foo"]
4#![feature(doc_cfg)]
5#![doc(auto_cfg(hide(feature = "hidden")))]
6
7//@ has 'foo/index.html'
8//@ !has - '//*[@class="stab portability"]' 'Non-moustache'
9//@ has - '//*[@class="stab portability"]' 'Non-pistache'
10//@ count - '//*[@class="stab portability"]' 1
11
12//@ has 'foo/m/index.html'
13//@ count - '//*[@title="Available on non-crate feature `hidden` only"]' 2
14#[cfg(not(feature = "hidden"))]
15pub mod m {
16 //@ count 'foo/m/struct.A.html' '//*[@class="stab portability"]' 0
17 pub struct A;
18
19 //@ has 'foo/m/inner/index.html' '//*[@class="stab portability"]' 'Available on non-crate feature hidden only.'
20 #[doc(auto_cfg(show(feature = "hidden")))]
21 pub mod inner {
22 //@ has 'foo/m/inner/struct.B.html' '//*[@class="stab portability"]' 'Available on non-crate feature hidden only.'
23 pub struct B;
24
25 //@ count 'foo/m/inner/struct.A.html' '//*[@class="stab portability"]' 0
26 #[doc(auto_cfg(hide(feature = "hidden")))]
27 pub struct A;
28 }
29
30 //@ has 'foo/m/struct.B.html' '//*[@class="stab portability"]' 'Available on non-crate feature hidden only.'
31 #[doc(auto_cfg(show(feature = "hidden")))]
32 pub struct B;
33}
34
35//@ count 'foo/n/index.html' '//*[@title="Available on non-crate feature `moustache` only"]' 3
36//@ count - '//dl/dt' 4
37#[cfg(not(feature = "moustache"))]
38#[doc(auto_cfg = false)]
39pub mod n {
40 // Should not have `moustache` listed.
41 //@ count 'foo/n/struct.X.html' '//*[@class="stab portability"]' 0
42 pub struct X;
43
44 // Should re-enable `auto_cfg` and make `moustache` listed.
45 //@ has 'foo/n/struct.Y.html' '//*[@class="stab portability"]' \
46 // 'Available on non-crate feature moustache only.'
47 #[doc(auto_cfg)]
48 pub struct Y;
49
50 // Should re-enable `auto_cfg` and make `moustache` listed for itself
51 // and for `Y`.
52 //@ has 'foo/n/inner/index.html' '//*[@class="stab portability"]' \
53 // 'Available on non-crate feature moustache only.'
54 #[doc(auto_cfg = true)]
55 pub mod inner {
56 //@ has 'foo/n/inner/struct.Y.html' '//*[@class="stab portability"]' \
57 // 'Available on non-crate feature moustache only.'
58 pub struct Y;
59 }
60
61 // Should re-enable `auto_cfg` and make `moustache` listed.
62 //@ has 'foo/n/struct.Z.html' '//*[@class="stab portability"]' \
63 // 'Available on non-crate feature moustache only.'
64 #[doc(auto_cfg(hide(feature = "hidden")))]
65 pub struct Z;
66}
67
68// Checking inheritance.
69//@ has 'foo/o/index.html' '//*[@class="stab portability"]' \
70// 'Available on non-crate feature pistache only.'
71#[doc(cfg(not(feature = "pistache")))]
72pub mod o {
73 //@ has 'foo/o/struct.A.html' '//*[@class="stab portability"]' \
74 // 'Available on non-crate feature pistache and non-crate feature tarte only.'
75 #[doc(cfg(not(feature = "tarte")))]
76 pub struct A;
77}
tests/rustdoc-html/doc_auto_cfg_reexports.rs deleted-35
......@@ -1,35 +0,0 @@
1// Checks that `cfg` are correctly applied on inlined reexports.
2
3#![crate_name = "foo"]
4#![feature(doc_cfg)]
5
6// Check with `std` item.
7//@ has 'foo/index.html' '//*[@class="stab portability"]' 'Non-moustache'
8//@ has 'foo/struct.C.html' '//*[@class="stab portability"]' \
9// 'Available on non-crate feature moustache only.'
10#[cfg(not(feature = "moustache"))]
11pub use std::cell::RefCell as C;
12
13// Check with local item.
14mod x {
15 pub struct B;
16}
17
18//@ has 'foo/index.html' '//*[@class="stab portability"]' 'Non-pistache'
19//@ has 'foo/struct.B.html' '//*[@class="stab portability"]' \
20// 'Available on non-crate feature pistache only.'
21#[cfg(not(feature = "pistache"))]
22pub use crate::x::B;
23
24// Now checking that `cfg`s are not applied on non-inlined reexports.
25pub mod pub_sub_mod {
26 //@ has 'foo/pub_sub_mod/index.html'
27 // There should be only only item with `cfg` note.
28 //@ count - '//*[@class="stab portability"]' 1
29 // And obviously the item should be "blabla".
30 //@ has - '//dt' 'blablaNon-pistache'
31 #[cfg(not(feature = "pistache"))]
32 pub fn blabla() {}
33
34 pub use self::blabla as another;
35}
tests/rustdoc-json/doc_cfg.rs created+5
......@@ -0,0 +1,5 @@
1#![feature(doc_cfg)]
2
3//@ is "$.index[?(@.name=='f')].attrs" '[{"other": "#[doc(auto_cfg(hide(bar, values(none())), hide(blob, values(\"a\", \"14\"))))]"}]'
4#[doc(auto_cfg(hide(bar, values(none())), hide(blob, values("a", "14")),))]
5pub fn f() {}
tests/rustdoc-ui/cfg-hide-show-conflict.rs deleted-3
......@@ -1,3 +0,0 @@
1#![feature(doc_cfg)]
2#![doc(auto_cfg(hide(target_os = "linux")))]
3#![doc(auto_cfg(show(windows, target_os = "linux")))] //~ ERROR
tests/rustdoc-ui/cfg-hide-show-conflict.stderr+6-6
......@@ -1,14 +1,14 @@
11error: same `cfg` was in `auto_cfg(hide(...))` and `auto_cfg(show(...))` on the same item
2 --> $DIR/cfg-hide-show-conflict.rs:3:31
2 --> $DIR/cfg-hide-show-conflict.rs:3:55
33 |
4LL | #![doc(auto_cfg(show(windows, target_os = "linux")))]
5 | ^^^^^^^^^^^^^^^^^^^
4LL | #![doc(auto_cfg(show(windows), show(target_os, values("linux"))))]
5 | ^^^^^^^
66 |
77note: first change was here
8 --> $DIR/cfg-hide-show-conflict.rs:2:22
8 --> $DIR/cfg-hide-show-conflict.rs:2:40
99 |
10LL | #![doc(auto_cfg(hide(target_os = "linux")))]
11 | ^^^^^^^^^^^^^^^^^^^
10LL | #![doc(auto_cfg(hide(target_os, values("linux"))))]
11 | ^^^^^^^
1212
1313error: aborting due to 1 previous error
1414
tests/rustdoc-ui/doc-cfg-2.rs+1-3
......@@ -13,7 +13,5 @@
1313// Shouldn't lint
1414#[doc(auto_cfg(hide(windows)))]
1515#[doc(auto_cfg(hide(feature = "windows")))]
16//~^ WARN unexpected `cfg` condition name: `feature`
17#[doc(auto_cfg(hide(foo)))]
18//~^ WARN unexpected `cfg` condition name: `foo`
16//~^ ERROR `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)`
1917pub fn foo() {}
tests/rustdoc-ui/doc-cfg-2.stderr+5-17
......@@ -30,19 +30,19 @@ note: the lint level is defined here
3030LL | #![deny(invalid_doc_attributes)]
3131 | ^^^^^^^^^^^^^^^^^^^^^^
3232
33error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items
33error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)`
3434 --> $DIR/doc-cfg-2.rs:8:21
3535 |
3636LL | #[doc(auto_cfg(hide(true)))]
3737 | ^^^^
3838
39error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items
39error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)`
4040 --> $DIR/doc-cfg-2.rs:9:21
4141 |
4242LL | #[doc(auto_cfg(hide(42)))]
4343 | ^^
4444
45error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items
45error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)`
4646 --> $DIR/doc-cfg-2.rs:10:21
4747 |
4848LL | #[doc(auto_cfg(hide("a")))]
......@@ -60,23 +60,11 @@ error: expected boolean for `#[doc(auto_cfg = ...)]`
6060LL | #[doc(auto_cfg = "a")]
6161 | ^^^
6262
63warning: unexpected `cfg` condition name: `feature`
63error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)`
6464 --> $DIR/doc-cfg-2.rs:15:21
6565 |
6666LL | #[doc(auto_cfg(hide(feature = "windows")))]
6767 | ^^^^^^^^^^^^^^^^^^^
68 |
69 = help: to expect this configuration use `--check-cfg=cfg(feature, values("windows"))`
70 = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
71
72warning: unexpected `cfg` condition name: `foo`
73 --> $DIR/doc-cfg-2.rs:17:21
74 |
75LL | #[doc(auto_cfg(hide(foo)))]
76 | ^^^
77 |
78 = help: to expect this configuration use `--check-cfg=cfg(foo)`
79 = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
8068
81error: aborting due to 6 previous errors; 4 warnings emitted
69error: aborting due to 7 previous errors; 2 warnings emitted
8270
tests/rustdoc-ui/doc-cfg-3.rs created+7
......@@ -0,0 +1,7 @@
1// Checks that you cannot have `any()` and values at the same time.
2
3#![deny(invalid_doc_attributes)]
4#![feature(doc_cfg)]
5
6#![doc(auto_cfg(hide(target_os, values(any(), "linux"))))] //~ ERROR
7#![doc(auto_cfg(hide(target_os, values("linux", any()))))] //~ ERROR
tests/rustdoc-ui/doc-cfg-3.stderr created+22
......@@ -0,0 +1,22 @@
1error: `any()` was used when other values were provided
2 --> $DIR/doc-cfg-3.rs:6:40
3 |
4LL | #![doc(auto_cfg(hide(target_os, values(any(), "linux"))))]
5 | ^^^^^ ------- value declared here
6 |
7note: the lint level is defined here
8 --> $DIR/doc-cfg-3.rs:3:9
9 |
10LL | #![deny(invalid_doc_attributes)]
11 | ^^^^^^^^^^^^^^^^^^^^^^
12
13error: `any()` was used when other values were provided
14 --> $DIR/doc-cfg-3.rs:7:49
15 |
16LL | #![doc(auto_cfg(hide(target_os, values("linux", any()))))]
17 | ------- ^^^^^
18 | |
19 | value declared here
20
21error: aborting due to 2 previous errors
22
tests/rustdoc-ui/doc-cfg-4.rs created+7
......@@ -0,0 +1,7 @@
1// Checks that you cannot have any item inside `any()` and `none()`.
2
3#![deny(invalid_doc_attributes)]
4#![feature(doc_cfg)]
5
6#![doc(auto_cfg(hide(target_os, values(any("linux")))))] //~ ERROR
7#![doc(auto_cfg(hide(target_os, values(none("linux")))))] //~ ERROR
tests/rustdoc-ui/doc-cfg-4.stderr created+20
......@@ -0,0 +1,20 @@
1error: `#![doc(auto_cfg(any(...)))]` only accepts identifiers or `values(...)`
2 --> $DIR/doc-cfg-4.rs:6:40
3 |
4LL | #![doc(auto_cfg(hide(target_os, values(any("linux")))))]
5 | ^^^^^^^^^^^^
6 |
7note: the lint level is defined here
8 --> $DIR/doc-cfg-4.rs:3:9
9 |
10LL | #![deny(invalid_doc_attributes)]
11 | ^^^^^^^^^^^^^^^^^^^^^^
12
13error: `#![doc(auto_cfg(none(...)))]` only accepts identifiers or `values(...)`
14 --> $DIR/doc-cfg-4.rs:7:40
15 |
16LL | #![doc(auto_cfg(hide(target_os, values(none("linux")))))]
17 | ^^^^^^^^^^^^^
18
19error: aborting due to 2 previous errors
20
tests/rustdoc-ui/doc-cfg.rs+1-1
......@@ -6,5 +6,5 @@
66//~| ERROR
77#[doc(cfg())] //~ ERROR
88#[doc(cfg(foo, bar))] //~ ERROR
9#[doc(auto_cfg(hide(foo::bar)))]
9#[doc(auto_cfg(hide(foo::bar)))] //~ ERROR
1010pub fn foo() {}
tests/rustdoc-ui/doc-cfg.stderr+11-2
......@@ -62,6 +62,15 @@ LL - #[doc(cfg(foo, bar))]
6262LL + #[doc(cfg(any(foo, bar)))]
6363 |
6464
65error: aborting due to 4 previous errors
65error[E0565]: malformed `doc` attribute input
66 --> $DIR/doc-cfg.rs:9:1
67 |
68LL | #[doc(auto_cfg(hide(foo::bar)))]
69 | ^^^^^^^^^^^^^^^^^^^^--------^^^^
70 | |
71 | expected a valid identifier here
72
73error: aborting due to 5 previous errors
6674
67For more information about this error, try `rustc --explain E0805`.
75Some errors have detailed explanations: E0565, E0805.
76For more information about an error, try `rustc --explain E0565`.
tests/rustdoc-ui/lints/doc_cfg_hide-2.rs created+4
......@@ -0,0 +1,4 @@
1#![feature(doc_cfg)]
2
3#![deny(invalid_doc_attributes)]
4#![doc(auto_cfg(hide(not(windows))))] //~ ERROR
tests/rustdoc-ui/lints/doc_cfg_hide-2.stderr created+11
......@@ -0,0 +1,11 @@
1error[E0565]: malformed `doc` attribute input
2 --> $DIR/doc_cfg_hide-2.rs:4:1
3 |
4LL | #![doc(auto_cfg(hide(not(windows))))]
5 | ^^^^^^^^^^^^^^^^^^^^^---^^^^^^^^^^^^^
6 | |
7 | expected a valid identifier here
8
9error: aborting due to 1 previous error
10
11For more information about this error, try `rustc --explain E0565`.
tests/rustdoc-ui/lints/doc_cfg_hide.rs-1
......@@ -2,4 +2,3 @@
22#![feature(doc_cfg)]
33#![doc(auto_cfg(hide = "test"))] //~ ERROR
44#![doc(auto_cfg(hide))] //~ ERROR
5#![doc(auto_cfg(hide(not(windows))))] //~ ERROR
tests/rustdoc-ui/lints/doc_cfg_hide.stderr+1-7
......@@ -16,11 +16,5 @@ error: `#![doc(auto_cfg(hide(...)))]` expects a list of items
1616LL | #![doc(auto_cfg(hide))]
1717 | ^^^^
1818
19error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items
20 --> $DIR/doc_cfg_hide.rs:5:22
21 |
22LL | #![doc(auto_cfg(hide(not(windows))))]
23 | ^^^^^^^^^^^^
24
25error: aborting due to 3 previous errors
19error: aborting due to 2 previous errors
2620
tests/ui/const-generics/mgca/bad-impl-trait-with-apit.rs created+13
......@@ -0,0 +1,13 @@
1// Regression test for issue #155834
2
3#![expect(incomplete_features)]
4#![feature(min_generic_const_args)]
5
6trait Trait {}
7
8impl<'t> Trait for [(); N] {}
9//~^ ERROR the placeholder `_` is not allowed within types on item signatures for implementations
10
11fn N(arg: impl Trait) {}
12
13fn main() {}
tests/ui/const-generics/mgca/bad-impl-trait-with-apit.stderr created+9
......@@ -0,0 +1,9 @@
1error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations
2 --> $DIR/bad-impl-trait-with-apit.rs:8:25
3 |
4LL | impl<'t> Trait for [(); N] {}
5 | ^ not allowed in type signatures
6
7error: aborting due to 1 previous error
8
9For more information about this error, try `rustc --explain E0121`.
tests/ui/const-generics/mgca/synth-gen-arg-ice-158152.rs+1
......@@ -4,6 +4,7 @@ trait A<T> {}
44trait Trait<const N: usize> {}
55
66impl A<[usize; fn_item]> for () {}
7//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for implementations
78
89fn fn_item(_: impl Trait<usize>) {}
910//~^ ERROR: type provided when a constant was expected
tests/ui/const-generics/mgca/synth-gen-arg-ice-158152.stderr+10-3
......@@ -1,5 +1,11 @@
1error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations
2 --> $DIR/synth-gen-arg-ice-158152.rs:6:16
3 |
4LL | impl A<[usize; fn_item]> for () {}
5 | ^^^^^^^ not allowed in type signatures
6
17error[E0747]: type provided when a constant was expected
2 --> $DIR/synth-gen-arg-ice-158152.rs:8:26
8 --> $DIR/synth-gen-arg-ice-158152.rs:9:26
39 |
410LL | fn fn_item(_: impl Trait<usize>) {}
511 | ^^^^^
......@@ -9,6 +15,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
915LL | fn fn_item(_: impl Trait<{ usize }>) {}
1016 | + +
1117
12error: aborting due to 1 previous error
18error: aborting due to 2 previous errors
1319
14For more information about this error, try `rustc --explain E0747`.
20Some errors have detailed explanations: E0121, E0747.
21For more information about an error, try `rustc --explain E0121`.
tests/ui/lang-items/start_lang_item_with_target_feature.rs+1-1
......@@ -18,7 +18,7 @@ pub trait Sized: MetaSized {}
1818
1919#[lang = "start"]
2020#[target_feature(enable = "avx2")]
21//~^ ERROR `start` lang item function is not allowed to have `#[target_feature]`
21//~^ ERROR #[target_feature]` cannot be applied to a lang item function
2222fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
2323 0
2424}
tests/ui/lang-items/start_lang_item_with_target_feature.stderr+7-5
......@@ -1,11 +1,13 @@
1error: `start` lang item function is not allowed to have `#[target_feature]`
1error: `#[target_feature]` cannot be applied to a lang item function
22 --> $DIR/start_lang_item_with_target_feature.rs:20:1
33 |
4LL | #[target_feature(enable = "avx2")]
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4LL | #[target_feature(enable = "avx2")]
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66LL |
7LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
8 | ------------------------------------------------------------------------------------------- `start` lang item function is not allowed to have `#[target_feature]`
7LL | / fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
8LL | | 0
9LL | | }
10 | |_- lang item function is not allowed to have `#[target_feature]`
911
1012error: aborting due to 1 previous error
1113
tests/ui/liveness/auxiliary/aux_issue_147648.rs created+23
......@@ -0,0 +1,23 @@
1#![feature(proc_macro_quote)]
2
3extern crate proc_macro;
4use proc_macro::*;
5
6#[proc_macro_derive(UnusedAssign)]
7pub fn generate(ts: TokenStream) -> TokenStream {
8 let mut ts = ts.into_iter();
9 let _pub = ts.next();
10 let _struct = ts.next();
11 let name = ts.next().unwrap();
12 let TokenTree::Group(fields) = ts.next().unwrap() else { panic!() };
13 let mut fields = fields.stream().into_iter();
14 let field = fields.next().unwrap();
15
16 quote! {
17 impl Drop for $name {
18 fn drop(&mut self) {
19 let Self { $field } = self;
20 }
21 }
22 }
23}
tests/ui/liveness/unused-assignments-from-macro-147648.rs created+18
......@@ -0,0 +1,18 @@
1//@ check-pass
2//@ proc-macro: aux_issue_147648.rs
3
4#![deny(unused_assignments)]
5#![allow(dead_code)]
6#![allow(unused_variables)]
7
8extern crate aux_issue_147648;
9use aux_issue_147648::UnusedAssign;
10
11#[derive(UnusedAssign)]
12pub struct MyError {
13 source_code: (),
14}
15
16fn main() {
17 let _error = MyError { source_code: () };
18}
tests/ui/panic-handler/panic-handler-with-target-feature.rs+1-1
......@@ -8,7 +8,7 @@ use core::panic::PanicInfo;
88
99#[panic_handler]
1010#[target_feature(enable = "avx2")]
11//~^ ERROR `#[panic_handler]` function is not allowed to have `#[target_feature]`
11//~^ ERROR `#[target_feature]` cannot be applied to a `#[panic_handler]` function
1212fn panic(info: &PanicInfo) -> ! {
1313 unimplemented!();
1414}
tests/ui/panic-handler/panic-handler-with-target-feature.stderr+7-5
......@@ -1,11 +1,13 @@
1error: `#[panic_handler]` function is not allowed to have `#[target_feature]`
1error: `#[target_feature]` cannot be applied to a `#[panic_handler]` function
22 --> $DIR/panic-handler-with-target-feature.rs:10:1
33 |
4LL | #[target_feature(enable = "avx2")]
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4LL | #[target_feature(enable = "avx2")]
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66LL |
7LL | fn panic(info: &PanicInfo) -> ! {
8 | ------------------------------- `#[panic_handler]` function is not allowed to have `#[target_feature]`
7LL | / fn panic(info: &PanicInfo) -> ! {
8LL | | unimplemented!();
9LL | | }
10 | |_- `#[panic_handler]` function is not allowed to have `#[target_feature]`
911
1012error: aborting due to 1 previous error
1113
tests/ui/traits/next-solver/unexpected-pointer-deref-issue-154568.rs created+22
......@@ -0,0 +1,22 @@
1// Regression test for #154568
2//@ compile-flags: -Znext-solver=globally
3
4trait Role {
5 type Inner;
6}
7
8struct HandshakeCallback<C>(C);
9struct Handshake<R: Role>(R::Inner);
10
11fn main() {
12 let callback = HandshakeCallback(());
13 let handshake = Handshake(callback.0.clone());
14 //~^ ERROR type annotations needed
15 match &handshake {
16 hs if (|| {
17 let borrowed_inner = &hs.0;
18 borrowed_inner == &callback.0
19 })() => println!(),
20 _ => {}
21 }
22}
tests/ui/traits/next-solver/unexpected-pointer-deref-issue-154568.stderr created+20
......@@ -0,0 +1,20 @@
1error[E0283]: type annotations needed for `Handshake<_>`
2 --> $DIR/unexpected-pointer-deref-issue-154568.rs:13:9
3 |
4LL | let handshake = Handshake(callback.0.clone());
5 | ^^^^^^^^^ ----------------------------- type must be known at this point
6 |
7 = note: the type must implement `Role`
8note: required by a bound in `Handshake`
9 --> $DIR/unexpected-pointer-deref-issue-154568.rs:9:21
10 |
11LL | struct Handshake<R: Role>(R::Inner);
12 | ^^^^ required by this bound in `Handshake`
13help: consider giving `handshake` an explicit type, where the type for type parameter `R` is specified
14 |
15LL | let handshake: Handshake<R> = Handshake(callback.0.clone());
16 | ++++++++++++++
17
18error: aborting due to 1 previous error
19
20For more information about this error, try `rustc --explain E0283`.