| author | bors <bors@rust-lang.org> 2026-06-27 14:41:51 UTC |
| committer | bors <bors@rust-lang.org> 2026-06-27 14:41:51 UTC |
| log | 13f1859f2faf97a15664e655624baa7417fdc100 |
| tree | d16489b0f679560b8a28af4c3767d9231aa1989c |
| parent | cb41b6d3daa0c1ad088a8802a6d8700c61290865 |
| parent | a85522c1c72517c9ad3eb0b2c79d4e161ecc8bae |
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; |
| 10 | 10 | use crate::session_diagnostics::{ |
| 11 | 11 | EmptyExportName, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, |
| 12 | 12 | NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral, |
| 13 | SanitizeInvalidStatic, | |
| 13 | SanitizeInvalidStatic, TargetFeatureOnLangItem, | |
| 14 | 14 | }; |
| 15 | 15 | use crate::target_checking::Policy::AllowSilent; |
| 16 | 16 | |
| ... | ... | @@ -524,15 +524,6 @@ impl CombineAttributeParser for TargetFeatureParser { |
| 524 | 524 | was_forced: false, |
| 525 | 525 | }; |
| 526 | 526 | 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 | ||
| 536 | 527 | const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ |
| 537 | 528 | Allow(Target::Fn), |
| 538 | 529 | Allow(Target::Method(MethodKind::Inherent)), |
| ... | ... | @@ -544,6 +535,29 @@ impl CombineAttributeParser for TargetFeatureParser { |
| 544 | 535 | Warn(Target::MacroDef), |
| 545 | 536 | Warn(Target::MacroCall), |
| 546 | 537 | ]); |
| 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 | } | |
| 547 | 561 | } |
| 548 | 562 | |
| 549 | 563 | pub(crate) struct ForceTargetFeatureParser; |
compiler/rustc_attr_parsing/src/attributes/doc.rs+133-37| ... | ... | @@ -1,25 +1,29 @@ |
| 1 | 1 | use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit}; |
| 2 | use rustc_data_structures::fx::{FxHashSet, FxIndexMap, IndexEntry}; | |
| 2 | 3 | use rustc_errors::{Applicability, msg}; |
| 3 | 4 | use rustc_feature::AttributeStability; |
| 4 | 5 | use rustc_hir::Target; |
| 5 | 6 | use rustc_hir::attrs::{ |
| 6 | AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow, | |
| 7 | AttributeKind, CfgEntry, CfgHideShow, DocAttribute, DocCfgHideShow, DocCfgHideShowValue, | |
| 8 | DocInline, HideOrShow, | |
| 7 | 9 | }; |
| 8 | 10 | use rustc_session::errors::feature_err; |
| 9 | 11 | use rustc_span::{Span, Symbol, edition, sym}; |
| 10 | use thin_vec::ThinVec; | |
| 11 | 12 | |
| 12 | 13 | use super::prelude::{ALL_TARGETS, AllowedTargets}; |
| 13 | 14 | use super::{AcceptMapping, AttributeParser, template}; |
| 14 | 15 | use crate::context::{AcceptContext, FinalizeContext}; |
| 15 | 16 | use crate::diagnostics::{ |
| 16 | 17 | 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 | }; | |
| 24 | use crate::parser::{ | |
| 25 | ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser, | |
| 21 | 26 | }; |
| 22 | use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser}; | |
| 23 | 27 | use crate::session_diagnostics::{ |
| 24 | 28 | DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel, |
| 25 | 29 | DocAttributeNotAttribute, DocKeywordNotKeyword, UnusedDuplicate, |
| ... | ... | @@ -304,6 +308,81 @@ impl DocParser { |
| 304 | 308 | } |
| 305 | 309 | } |
| 306 | 310 | |
| 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 | ||
| 307 | 386 | fn parse_auto_cfg( |
| 308 | 387 | &mut self, |
| 309 | 388 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -315,7 +394,7 @@ impl DocParser { |
| 315 | 394 | self.attribute.auto_cfg_change.push((true, path.span())); |
| 316 | 395 | } |
| 317 | 396 | ArgParser::List(list) => { |
| 318 | for meta in list.mixed() { | |
| 397 | 'main: for meta in list.mixed() { | |
| 319 | 398 | let MetaItemOrLitParser::MetaItemParser(item) = meta else { |
| 320 | 399 | cx.emit_lint( |
| 321 | 400 | rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, |
| ... | ... | @@ -324,6 +403,8 @@ impl DocParser { |
| 324 | 403 | ); |
| 325 | 404 | continue; |
| 326 | 405 | }; |
| 406 | // Only `hide` and `show` are allowed in `auto_cfg` if it's a list, and both | |
| 407 | // must be a list. | |
| 327 | 408 | let (kind, attr_name) = match item.path().word_sym() { |
| 328 | 409 | Some(sym::hide) => (HideOrShow::Hide, sym::hide), |
| 329 | 410 | Some(sym::show) => (HideOrShow::Show, sym::show), |
| ... | ... | @@ -345,8 +426,10 @@ impl DocParser { |
| 345 | 426 | continue; |
| 346 | 427 | }; |
| 347 | 428 | |
| 348 | let mut cfg_hide_show = CfgHideShow { kind, values: ThinVec::new() }; | |
| 429 | let mut cfg_hide_show = CfgHideShow { kind, values: FxIndexMap::default() }; | |
| 349 | 430 | |
| 431 | let mut cfg_names = FxHashSet::default(); | |
| 432 | let mut values = None; | |
| 350 | 433 | for item in list.mixed() { |
| 351 | 434 | let MetaItemOrLitParser::MetaItemParser(sub_item) = item else { |
| 352 | 435 | cx.emit_lint( |
| ... | ... | @@ -354,47 +437,60 @@ impl DocParser { |
| 354 | 437 | DocAutoCfgHideShowUnexpectedItem { attr_name }, |
| 355 | 438 | item.span(), |
| 356 | 439 | ); |
| 357 | continue; | |
| 440 | continue 'main; | |
| 358 | 441 | }; |
| 359 | 442 | match sub_item.args() { |
| 360 | a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => { | |
| 443 | ArgParser::NoArgs if values.is_none() => { | |
| 361 | 444 | 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() { | |
| 365 | 457 | cx.emit_lint( |
| 366 | 458 | 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, | |
| 377 | 460 | 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; | |
| 389 | 463 | } |
| 464 | self.parse_auto_cfg_values(cx, list, &mut values); | |
| 390 | 465 | } |
| 391 | _ => { | |
| 466 | // No `name = value` is allowed. | |
| 467 | ArgParser::NameValue(_) => { | |
| 392 | 468 | cx.emit_lint( |
| 393 | 469 | rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, |
| 394 | 470 | DocAutoCfgHideShowUnexpectedItem { attr_name }, |
| 395 | 471 | sub_item.span(), |
| 396 | 472 | ); |
| 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); | |
| 398 | 494 | } |
| 399 | 495 | } |
| 400 | 496 | } |
compiler/rustc_attr_parsing/src/attributes/link_attrs.rs+1-1| ... | ... | @@ -576,7 +576,7 @@ impl NoArgsAttributeParser for FfiPureParser { |
| 576 | 576 | const STABILITY: AttributeStability = unstable!(ffi_pure); |
| 577 | 577 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; |
| 578 | 578 | |
| 579 | fn finalize_check(attr_span: Span, cx: &FinalizeContext<'_, '_>) { | |
| 579 | fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) { | |
| 580 | 580 | // `#[ffi_const]` functions cannot be `#[ffi_pure]`. |
| 581 | 581 | if cx.all_attrs.iter().any(|a| a.word_is(sym::ffi_const)) { |
| 582 | 582 | 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 { |
| 154 | 154 | /// reject incompatible combinations. `attr_span` is the span of this attribute. |
| 155 | 155 | /// |
| 156 | 156 | /// Defaults to a no-op. |
| 157 | fn finalize_check(_attr_span: Span, _cx: &FinalizeContext<'_, '_>) {} | |
| 157 | fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {} | |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 160 | /// Use in combination with [`SingleAttributeParser`]. |
| ... | ... | @@ -187,7 +187,7 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> { |
| 187 | 187 | |
| 188 | 188 | fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> { |
| 189 | 189 | let (kind, span) = self.1?; |
| 190 | T::finalize_check(span, cx); | |
| 190 | T::finalize_check(cx, span); | |
| 191 | 191 | Some(kind) |
| 192 | 192 | } |
| 193 | 193 | } |
| ... | ... | @@ -275,7 +275,7 @@ pub(crate) trait NoArgsAttributeParser: 'static { |
| 275 | 275 | /// `attr_span` is the span of this attribute. |
| 276 | 276 | /// |
| 277 | 277 | /// Defaults to a no-op. |
| 278 | fn finalize_check(_attr_span: Span, _cx: &FinalizeContext<'_, '_>) {} | |
| 278 | fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {} | |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | 281 | pub(crate) struct WithoutArgs<T: NoArgsAttributeParser>(PhantomData<T>); |
| ... | ... | @@ -299,8 +299,8 @@ impl<T: NoArgsAttributeParser> SingleAttributeParser for WithoutArgs<T> { |
| 299 | 299 | Some(T::CREATE(cx.attr_span)) |
| 300 | 300 | } |
| 301 | 301 | |
| 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) | |
| 304 | 304 | } |
| 305 | 305 | } |
| 306 | 306 | |
| ... | ... | @@ -335,6 +335,14 @@ pub(crate) trait CombineAttributeParser: 'static { |
| 335 | 335 | cx: &mut AcceptContext<'_, '_>, |
| 336 | 336 | args: &ArgParser, |
| 337 | 337 | ) -> 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) {} | |
| 338 | 346 | } |
| 339 | 347 | |
| 340 | 348 | /// Use in combination with [`CombineAttributeParser`]. |
| ... | ... | @@ -367,8 +375,9 @@ impl<T: CombineAttributeParser> AttributeParser for Combine<T> { |
| 367 | 375 | const ALLOWED_TARGETS: AllowedTargets<'_> = T::ALLOWED_TARGETS; |
| 368 | 376 | const SAFETY: AttributeSafety = T::SAFETY; |
| 369 | 377 | |
| 370 | fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> { | |
| 378 | fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> { | |
| 371 | 379 | if let Some(first_span) = self.first_span { |
| 380 | T::finalize_check(cx, first_span); | |
| 372 | 381 | Some(T::CONVERT(self.items, first_span)) |
| 373 | 382 | } else { |
| 374 | 383 | None |
compiler/rustc_attr_parsing/src/diagnostics.rs+16-1| ... | ... | @@ -169,11 +169,22 @@ pub(crate) struct DocAutoCfgExpectsHideOrShow; |
| 169 | 169 | pub(crate) struct AmbiguousDeriveHelpers; |
| 170 | 170 | |
| 171 | 171 | #[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(...)`")] | |
| 173 | 173 | pub(crate) struct DocAutoCfgHideShowUnexpectedItem { |
| 174 | 174 | pub attr_name: Symbol, |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | #[derive(Diagnostic)] | |
| 178 | #[diag("`any()` was used when other values were provided")] | |
| 179 | pub(crate) struct DocAutoCfgHideShowValuesMix { | |
| 180 | #[label("value declared here")] | |
| 181 | pub value_span: Span, | |
| 182 | } | |
| 183 | ||
| 184 | #[derive(Diagnostic)] | |
| 185 | #[diag("unexpected item after `values()`")] | |
| 186 | pub(crate) struct DocAutoCfgHideShowUnexpectedItemAfterValues; | |
| 187 | ||
| 177 | 188 | #[derive(Diagnostic)] |
| 178 | 189 | #[diag("`#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items")] |
| 179 | 190 | pub(crate) struct DocAutoCfgHideShowExpectsList { |
| ... | ... | @@ -239,6 +250,10 @@ pub(crate) struct DocUnknownAny { |
| 239 | 250 | #[diag("expected boolean for `#[doc(auto_cfg = ...)]`")] |
| 240 | 251 | pub(crate) struct DocAutoCfgWrongLiteral; |
| 241 | 252 | |
| 253 | #[derive(Diagnostic)] | |
| 254 | #[diag("there must be at least one identifier before `values(...)`")] | |
| 255 | pub(crate) struct DocAutoCfgHideShowNoIdentBeforeValues; | |
| 256 | ||
| 242 | 257 | #[derive(Diagnostic)] |
| 243 | 258 | #[diag("`#[doc(test(...)]` takes a list of attributes")] |
| 244 | 259 | pub(crate) struct DocTestTakesList; |
compiler/rustc_attr_parsing/src/session_diagnostics.rs+20| ... | ... | @@ -80,6 +80,26 @@ pub(crate) struct DocAttributeNotAttribute { |
| 80 | 80 | pub attribute: Symbol, |
| 81 | 81 | } |
| 82 | 82 | |
| 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 | )] | |
| 90 | pub(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 | ||
| 83 | 103 | #[derive(Diagnostic)] |
| 84 | 104 | #[diag("missing 'since'", code = E0542)] |
| 85 | 105 | pub(crate) struct MissingSince { |
compiler/rustc_hir/src/attrs/data_structures.rs+59-12| ... | ... | @@ -515,19 +515,66 @@ pub enum HideOrShow { |
| 515 | 515 | Show, |
| 516 | 516 | } |
| 517 | 517 | |
| 518 | #[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)] | |
| 519 | pub 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)] | |
| 519 | pub struct DocCfgHideShowValue { | |
| 520 | pub span: Span, | |
| 521 | /// If `value` is `None`, then it's a `none()` value. | |
| 522 | pub value: Option<Symbol>, | |
| 523 | } | |
| 524 | ||
| 525 | impl 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)] | |
| 536 | pub enum DocCfgHideShow { | |
| 537 | Any(Span), | |
| 538 | List(ThinVec<DocCfgHideShowValue>), | |
| 523 | 539 | } |
| 524 | 540 | |
| 525 | impl 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 | |
| 541 | impl 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 | } | |
| 531 | 578 | } |
| 532 | 579 | } |
| 533 | 580 | } |
| ... | ... | @@ -535,7 +582,7 @@ impl CfgInfo { |
| 535 | 582 | #[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)] |
| 536 | 583 | pub struct CfgHideShow { |
| 537 | 584 | pub kind: HideOrShow, |
| 538 | pub values: ThinVec<CfgInfo>, | |
| 585 | pub values: FxIndexMap<Symbol, DocCfgHideShow>, | |
| 539 | 586 | } |
| 540 | 587 | |
| 541 | 588 | #[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> { |
| 81 | 81 | p.word("]"); |
| 82 | 82 | } |
| 83 | 83 | } |
| 84 | impl<T: PrintAttribute> PrintAttribute for FxIndexMap<T, Span> { | |
| 84 | impl<T: PrintAttribute, T2: PrintAttribute> PrintAttribute for FxIndexMap<T, T2> { | |
| 85 | 85 | fn should_render(&self) -> bool { |
| 86 | 86 | self.is_empty() || self[0].should_render() |
| 87 | 87 | } |
compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs+21-1| ... | ... | @@ -2862,7 +2862,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 2862 | 2862 | did, |
| 2863 | 2863 | path.segments.last().unwrap(), |
| 2864 | 2864 | ); |
| 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 | } | |
| 2866 | 2886 | } |
| 2867 | 2887 | |
| 2868 | 2888 | // 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 = |
| 46 | 46 | Box<dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync>; |
| 47 | 47 | |
| 48 | 48 | /// 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. | |
| 49 | 54 | pub struct LintStore { |
| 50 | 55 | /// Registered lints. |
| 51 | 56 | lints: Vec<&'static Lint>, |
| 52 | 57 | |
| 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. | |
| 54 | 73 | /// |
| 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>, | |
| 64 | 82 | |
| 65 | 83 | /// Lints indexed by name. |
| 66 | 84 | by_name: UnordMap<String, TargetLint>, |
| ... | ... | @@ -136,10 +154,10 @@ impl LintStore { |
| 136 | 154 | pub fn new() -> LintStore { |
| 137 | 155 | LintStore { |
| 138 | 156 | 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![], | |
| 143 | 161 | by_name: Default::default(), |
| 144 | 162 | lint_groups: Default::default(), |
| 145 | 163 | } |
| ... | ... | @@ -166,26 +184,24 @@ impl LintStore { |
| 166 | 184 | self.lint_groups.keys().copied() |
| 167 | 185 | } |
| 168 | 186 | |
| 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); | |
| 171 | 190 | } |
| 172 | 191 | |
| 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); | |
| 181 | 195 | } |
| 182 | 196 | |
| 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); | |
| 185 | 200 | } |
| 186 | 201 | |
| 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); | |
| 189 | 205 | } |
| 190 | 206 | |
| 191 | 207 | /// 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>( |
| 329 | 329 | |
| 330 | 330 | let context = if pre_expansion { |
| 331 | 331 | let builtin_lints = crate::BuiltinCombinedPreExpansionLintPass::new(); |
| 332 | let passes = &lint_store.pre_expansion_passes; | |
| 332 | let passes = &lint_store.pre_expansion_lint_passes; | |
| 333 | 333 | run_passes(check_node, context, builtin_lints, passes) |
| 334 | 334 | } else { |
| 335 | 335 | let builtin_lints = crate::BuiltinCombinedEarlyLintPass::new(); |
| 336 | let passes = &lint_store.early_passes; | |
| 336 | let passes = &lint_store.early_lint_passes; | |
| 337 | 337 | run_passes(check_node, context, builtin_lints, passes) |
| 338 | 338 | }; |
| 339 | 339 |
compiler/rustc_lint/src/late.rs+2-2| ... | ... | @@ -355,7 +355,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( |
| 355 | 355 | // `builtin_lints` directly rather than bundling it up into the |
| 356 | 356 | // `RuntimeCombinedLateLintPass`. |
| 357 | 357 | let mut passes: Vec<_> = unerased_lint_store(tcx.sess) |
| 358 | .late_module_passes | |
| 358 | .late_lint_mod_passes | |
| 359 | 359 | .iter() |
| 360 | 360 | .map(|mk_pass| mk_pass(tcx)) |
| 361 | 361 | .filter(|pass| is_lint_pass_required(skippable_lints, &pass.get_lints())) |
| ... | ... | @@ -403,7 +403,7 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { |
| 403 | 403 | |
| 404 | 404 | // Note: `passes` is often empty after filtering. |
| 405 | 405 | let passes: Vec<_> = unerased_lint_store(tcx.sess) |
| 406 | .late_passes | |
| 406 | .late_lint_passes | |
| 407 | 407 | .iter() |
| 408 | 408 | .map(|mk_pass| mk_pass(tcx)) |
| 409 | 409 | .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) { |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | 156 | fn 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()); | |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 160 | early_lint_methods!( |
| ... | ... | @@ -207,7 +207,7 @@ early_lint_methods!( |
| 207 | 207 | late_lint_methods!( |
| 208 | 208 | declare_combined_late_lint_pass, |
| 209 | 209 | [ |
| 210 | BuiltinCombinedModuleLateLintPass, | |
| 210 | BuiltinCombinedLateLintModPass, | |
| 211 | 211 | [ |
| 212 | 212 | ForLoopsOverFallibles: ForLoopsOverFallibles, |
| 213 | 213 | DefaultCouldBeDerived: DefaultCouldBeDerived, |
| ... | ... | @@ -279,7 +279,7 @@ late_lint_methods!( |
| 279 | 279 | late_lint_methods!( |
| 280 | 280 | declare_combined_late_lint_pass, |
| 281 | 281 | [ |
| 282 | InternalCombinedModuleLateLintPass, | |
| 282 | InternalCombinedLateLintModPass, | |
| 283 | 283 | [ |
| 284 | 284 | DefaultHashTypes: DefaultHashTypes, |
| 285 | 285 | QueryStability: QueryStability, |
| ... | ... | @@ -317,7 +317,7 @@ fn register_builtins(store: &mut LintStore) { |
| 317 | 317 | |
| 318 | 318 | store.register_lints(&BuiltinCombinedPreExpansionLintPass::lint_vec()); |
| 319 | 319 | store.register_lints(&BuiltinCombinedEarlyLintPass::lint_vec()); |
| 320 | store.register_lints(&BuiltinCombinedModuleLateLintPass::lint_vec()); | |
| 320 | store.register_lints(&BuiltinCombinedLateLintModPass::lint_vec()); | |
| 321 | 321 | store.register_lints(&foreign_modules::lint_vec()); |
| 322 | 322 | store.register_lints(&hardwired::lint_vec()); |
| 323 | 323 | |
| ... | ... | @@ -698,10 +698,12 @@ fn register_builtins(store: &mut LintStore) { |
| 698 | 698 | |
| 699 | 699 | fn register_internals(store: &mut LintStore) { |
| 700 | 700 | 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()))); | |
| 702 | 702 | |
| 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 | })); | |
| 705 | 707 | |
| 706 | 708 | store.register_group( |
| 707 | 709 | false, |
compiler/rustc_lint/src/passes.rs+1-1| ... | ... | @@ -203,7 +203,7 @@ macro_rules! expand_combined_early_lint_pass_methods { |
| 203 | 203 | /// Combines multiple lints passes into a single lint pass, at compile time, |
| 204 | 204 | /// for maximum speed. Each `check_foo` method in `$methods` within this pass |
| 205 | 205 | /// 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 | |
| 207 | 207 | /// runtime. |
| 208 | 208 | #[macro_export] |
| 209 | 209 | macro_rules! declare_combined_early_lint_pass { |
compiler/rustc_passes/src/check_attr.rs+1-34| ... | ... | @@ -204,9 +204,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 204 | 204 | AttributeKind::Deprecated { span: attr_span, .. } => { |
| 205 | 205 | self.check_deprecated(hir_id, *attr_span, target) |
| 206 | 206 | } |
| 207 | AttributeKind::TargetFeature { attr_span, .. } => { | |
| 208 | self.check_target_feature(hir_id, *attr_span, target, attrs) | |
| 209 | } | |
| 210 | 207 | AttributeKind::RustcDumpObjectLifetimeDefaults => { |
| 211 | 208 | self.check_dump_object_lifetime_defaults(hir_id); |
| 212 | 209 | } |
| ... | ... | @@ -406,6 +403,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 406 | 403 | AttributeKind::ShouldPanic { .. } => (), |
| 407 | 404 | AttributeKind::Splat(..) => (), |
| 408 | 405 | AttributeKind::Stability { .. } => (), |
| 406 | AttributeKind::TargetFeature { .. } => {} | |
| 409 | 407 | AttributeKind::TestRunner(..) => (), |
| 410 | 408 | AttributeKind::ThreadLocal => (), |
| 411 | 409 | AttributeKind::TypeLengthLimit { .. } => (), |
| ... | ... | @@ -799,37 +797,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 799 | 797 | } |
| 800 | 798 | } |
| 801 | 799 | |
| 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 | ||
| 833 | 800 | fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) { |
| 834 | 801 | if let Some(location) = match target { |
| 835 | 802 | Target::AssocTy => { |
compiler/rustc_passes/src/diagnostics.rs-20| ... | ... | @@ -362,26 +362,6 @@ pub(crate) struct LangItemWithTrackCaller { |
| 362 | 362 | pub sig_span: Span, |
| 363 | 363 | } |
| 364 | 364 | |
| 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 | )] | |
| 372 | pub(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 | ||
| 385 | 365 | #[derive(Diagnostic)] |
| 386 | 366 | #[diag("duplicate diagnostic item in crate `{$crate_name}`: `{$name}`")] |
| 387 | 367 | pub(crate) struct DuplicateDiagnosticItemInCrate { |
library/alloc/src/lib.rs+4-1| ... | ... | @@ -65,7 +65,10 @@ |
| 65 | 65 | issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", |
| 66 | 66 | test(no_crate_inject, attr(allow(unused_variables, duplicate_features), deny(warnings))) |
| 67 | 67 | )] |
| 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 | ))] | |
| 69 | 72 | #![doc(rust_logo)] |
| 70 | 73 | #![feature(rustdoc_internals)] |
| 71 | 74 | #![no_std] |
library/core/src/fmt/mod.rs+2-4| ... | ... | @@ -332,9 +332,7 @@ mod flags { |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | 334 | impl 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: | |
| 338 | 336 | /// |
| 339 | 337 | /// - no flags, |
| 340 | 338 | /// - filled with spaces, |
| ... | ... | @@ -518,7 +516,7 @@ impl FormattingOptions { |
| 518 | 516 | pub const fn get_precision(&self) -> Option<u16> { |
| 519 | 517 | if self.flags & flags::PRECISION_FLAG != 0 { Some(self.precision) } else { None } |
| 520 | 518 | } |
| 521 | /// Returns the current precision. | |
| 519 | /// Returns the current `x?` or `X?` flag. | |
| 522 | 520 | #[unstable(feature = "formatting_options", issue = "118117")] |
| 523 | 521 | pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> { |
| 524 | 522 | if self.flags & flags::DEBUG_LOWER_HEX_FLAG != 0 { |
library/core/src/lib.rs+10-21| ... | ... | @@ -51,27 +51,16 @@ |
| 51 | 51 | test(attr(allow(dead_code, deprecated, unused_variables, unused_mut, duplicate_features))) |
| 52 | 52 | )] |
| 53 | 53 | #![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 | ))] | |
| 75 | 64 | #![no_core] |
| 76 | 65 | #![rustc_coherence_is_core] |
| 77 | 66 | #![rustc_preserve_ub_checks] |
library/core/src/marker.rs+1-1| ... | ... | @@ -1066,7 +1066,7 @@ pub const trait Destruct: PointeeSized {} |
| 1066 | 1066 | /// |
| 1067 | 1067 | /// The implementation of this trait is built-in and cannot be implemented |
| 1068 | 1068 | /// for any user type. |
| 1069 | #[unstable(feature = "tuple_trait", issue = "none")] | |
| 1069 | #[unstable(feature = "tuple_trait", issue = "157987")] | |
| 1070 | 1070 | #[lang = "tuple_trait"] |
| 1071 | 1071 | #[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")] |
| 1072 | 1072 | #[rustc_deny_explicit_impl] |
library/core/src/num/int_macros.rs+23-23| ... | ... | @@ -983,7 +983,7 @@ macro_rules! int_impl { |
| 983 | 983 | /// This function will always panic on overflow, regardless of whether overflow checks are enabled. |
| 984 | 984 | /// |
| 985 | 985 | /// 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 | |
| 987 | 987 | /// that is too large to represent in the type. |
| 988 | 988 | /// |
| 989 | 989 | /// # Examples |
| ... | ... | @@ -1050,7 +1050,7 @@ macro_rules! int_impl { |
| 1050 | 1050 | /// This function will always panic on overflow, regardless of whether overflow checks are enabled. |
| 1051 | 1051 | /// |
| 1052 | 1052 | /// 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 | |
| 1054 | 1054 | /// that is too large to represent in the type. |
| 1055 | 1055 | /// |
| 1056 | 1056 | /// # Examples |
| ... | ... | @@ -1223,7 +1223,7 @@ macro_rules! int_impl { |
| 1223 | 1223 | /// This function will always panic on overflow, regardless of whether overflow checks are enabled. |
| 1224 | 1224 | /// |
| 1225 | 1225 | /// 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. | |
| 1227 | 1227 | /// |
| 1228 | 1228 | /// # Examples |
| 1229 | 1229 | /// |
| ... | ... | @@ -1289,7 +1289,7 @@ macro_rules! int_impl { |
| 1289 | 1289 | /// This function will always panic on overflow, regardless of whether overflow checks are enabled. |
| 1290 | 1290 | /// |
| 1291 | 1291 | /// 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. | |
| 1293 | 1293 | /// |
| 1294 | 1294 | /// # Examples |
| 1295 | 1295 | /// |
| ... | ... | @@ -2259,8 +2259,8 @@ macro_rules! int_impl { |
| 2259 | 2259 | /// boundary of the type. |
| 2260 | 2260 | /// |
| 2261 | 2261 | /// 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. | |
| 2264 | 2264 | /// |
| 2265 | 2265 | /// # Panics |
| 2266 | 2266 | /// |
| ... | ... | @@ -2284,9 +2284,9 @@ macro_rules! int_impl { |
| 2284 | 2284 | /// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, |
| 2285 | 2285 | /// wrapping around at the boundary of the type. |
| 2286 | 2286 | /// |
| 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 | |
| 2288 | 2288 | /// 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. | |
| 2290 | 2290 | /// |
| 2291 | 2291 | /// # Panics |
| 2292 | 2292 | /// |
| ... | ... | @@ -2311,7 +2311,7 @@ macro_rules! int_impl { |
| 2311 | 2311 | /// boundary of the type. |
| 2312 | 2312 | /// |
| 2313 | 2313 | /// 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, | |
| 2315 | 2315 | /// this function returns `0`. |
| 2316 | 2316 | /// |
| 2317 | 2317 | /// # Panics |
| ... | ... | @@ -2336,8 +2336,8 @@ macro_rules! int_impl { |
| 2336 | 2336 | /// Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around |
| 2337 | 2337 | /// at the boundary of the type. |
| 2338 | 2338 | /// |
| 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. | |
| 2341 | 2341 | /// |
| 2342 | 2342 | /// # Panics |
| 2343 | 2343 | /// |
| ... | ... | @@ -2361,9 +2361,9 @@ macro_rules! int_impl { |
| 2361 | 2361 | /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary |
| 2362 | 2362 | /// of the type. |
| 2363 | 2363 | /// |
| 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) | |
| 2365 | 2365 | /// 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. | |
| 2367 | 2367 | /// |
| 2368 | 2368 | /// # Examples |
| 2369 | 2369 | /// |
| ... | ... | @@ -2460,7 +2460,7 @@ macro_rules! int_impl { |
| 2460 | 2460 | /// |
| 2461 | 2461 | /// The only case where such wrapping can occur is when one takes the absolute value of the negative |
| 2462 | 2462 | /// 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. | |
| 2464 | 2464 | /// |
| 2465 | 2465 | /// # Examples |
| 2466 | 2466 | /// |
| ... | ... | @@ -2772,7 +2772,7 @@ macro_rules! int_impl { |
| 2772 | 2772 | /// |
| 2773 | 2773 | /// # Examples |
| 2774 | 2774 | /// |
| 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. | |
| 2776 | 2776 | /// |
| 2777 | 2777 | /// ``` |
| 2778 | 2778 | /// #![feature(signed_bigint_helpers)] |
| ... | ... | @@ -2950,7 +2950,7 @@ macro_rules! int_impl { |
| 2950 | 2950 | /// Negates self, overflowing if this is equal to the minimum value. |
| 2951 | 2951 | /// |
| 2952 | 2952 | /// 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 | |
| 2954 | 2954 | /// minimum value will be returned again and `true` will be returned for an overflow happening. |
| 2955 | 2955 | /// |
| 2956 | 2956 | /// # Examples |
| ... | ... | @@ -3020,7 +3020,7 @@ macro_rules! int_impl { |
| 3020 | 3020 | /// |
| 3021 | 3021 | /// Returns a tuple of the absolute version of self along with a boolean indicating whether an overflow |
| 3022 | 3022 | /// 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), "`]),")] | |
| 3024 | 3024 | /// then the minimum value will be returned again and true will be returned |
| 3025 | 3025 | /// for an overflow happening. |
| 3026 | 3026 | /// |
| ... | ... | @@ -3177,7 +3177,7 @@ macro_rules! int_impl { |
| 3177 | 3177 | /// |
| 3178 | 3178 | /// # Panics |
| 3179 | 3179 | /// |
| 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`] | |
| 3181 | 3181 | /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. |
| 3182 | 3182 | /// |
| 3183 | 3183 | /// # Examples |
| ... | ... | @@ -3215,7 +3215,7 @@ macro_rules! int_impl { |
| 3215 | 3215 | /// |
| 3216 | 3216 | /// # Panics |
| 3217 | 3217 | /// |
| 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 | |
| 3219 | 3219 | /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. |
| 3220 | 3220 | /// |
| 3221 | 3221 | /// # Examples |
| ... | ... | @@ -3262,7 +3262,7 @@ macro_rules! int_impl { |
| 3262 | 3262 | /// |
| 3263 | 3263 | /// # Panics |
| 3264 | 3264 | /// |
| 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`] | |
| 3266 | 3266 | /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. |
| 3267 | 3267 | /// |
| 3268 | 3268 | /// # Examples |
| ... | ... | @@ -3304,7 +3304,7 @@ macro_rules! int_impl { |
| 3304 | 3304 | /// |
| 3305 | 3305 | /// # Panics |
| 3306 | 3306 | /// |
| 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`] | |
| 3308 | 3308 | /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. |
| 3309 | 3309 | /// |
| 3310 | 3310 | /// # Examples |
| ... | ... | @@ -3441,8 +3441,8 @@ macro_rules! int_impl { |
| 3441 | 3441 | /// rounded down. |
| 3442 | 3442 | /// |
| 3443 | 3443 | /// 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. | |
| 3446 | 3446 | /// |
| 3447 | 3447 | /// # Panics |
| 3448 | 3448 | /// |
library/core/src/num/uint_macros.rs+2-2| ... | ... | @@ -1721,8 +1721,8 @@ macro_rules! uint_impl { |
| 1721 | 1721 | /// rounded down. |
| 1722 | 1722 | /// |
| 1723 | 1723 | /// 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. | |
| 1726 | 1726 | /// |
| 1727 | 1727 | /// # Panics |
| 1728 | 1728 | /// |
library/std/src/net/ip_addr/tests.rs+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | use crate::net::Ipv4Addr; |
| 2 | use crate::net::test::{sa4, tsa}; | |
| 2 | use crate::net::tests::{sa4, tsa}; | |
| 3 | 3 | |
| 4 | 4 | #[test] |
| 5 | 5 | fn to_socket_addr_socketaddr() { |
library/std/src/net/mod.rs+1-1| ... | ... | @@ -43,7 +43,7 @@ mod ip_addr; |
| 43 | 43 | mod socket_addr; |
| 44 | 44 | mod tcp; |
| 45 | 45 | #[cfg(test)] |
| 46 | pub(crate) mod test; | |
| 46 | pub(crate) mod tests; | |
| 47 | 47 | mod udp; |
| 48 | 48 | |
| 49 | 49 | /// 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 @@ |
| 1 | use crate::net::test::{sa4, sa6, tsa}; | |
| 1 | use crate::net::tests::{sa4, sa6, tsa}; | |
| 2 | 2 | use crate::net::*; |
| 3 | 3 | |
| 4 | 4 | #[test] |
library/std/src/net/tcp/tests.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ use rand::Rng; |
| 3 | 3 | use crate::io::prelude::*; |
| 4 | 4 | use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut}; |
| 5 | 5 | use crate::mem::MaybeUninit; |
| 6 | use crate::net::test::{LOCALHOST_IP4, LOCALHOST_IP6}; | |
| 6 | use crate::net::tests::{LOCALHOST_IP4, LOCALHOST_IP6}; | |
| 7 | 7 | use crate::net::*; |
| 8 | 8 | use crate::sync::mpsc::channel; |
| 9 | 9 | use crate::time::{Duration, Instant}; |
library/std/src/net/test.rs deleted-38| ... | ... | @@ -1,38 +0,0 @@ |
| 1 | #![allow(warnings)] // not used on emscripten | |
| 2 | ||
| 3 | use crate::env; | |
| 4 | use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; | |
| 5 | use crate::sync::atomic::{AtomicUsize, Ordering}; | |
| 6 | ||
| 7 | /// A localhost address whose port will be picked automatically by the OS. | |
| 8 | pub 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. | |
| 11 | pub const LOCALHOST_IP6: SocketAddr = | |
| 12 | SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0)); | |
| 13 | ||
| 14 | pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr { | |
| 15 | SocketAddr::V4(SocketAddrV4::new(a, p)) | |
| 16 | } | |
| 17 | ||
| 18 | pub fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr { | |
| 19 | SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0)) | |
| 20 | } | |
| 21 | ||
| 22 | pub 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 | ||
| 29 | pub 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 | ||
| 3 | use crate::env; | |
| 4 | use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; | |
| 5 | use crate::sync::atomic::{AtomicUsize, Ordering}; | |
| 6 | ||
| 7 | /// A localhost address whose port will be picked automatically by the OS. | |
| 8 | pub 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. | |
| 11 | pub const LOCALHOST_IP6: SocketAddr = | |
| 12 | SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0)); | |
| 13 | ||
| 14 | pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr { | |
| 15 | SocketAddr::V4(SocketAddrV4::new(a, p)) | |
| 16 | } | |
| 17 | ||
| 18 | pub fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr { | |
| 19 | SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0)) | |
| 20 | } | |
| 21 | ||
| 22 | pub 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 | ||
| 29 | pub 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] | |
| 41 | fn 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 @@ |
| 1 | 1 | use crate::io::ErrorKind; |
| 2 | use crate::net::test::{LOCALHOST_IP4, LOCALHOST_IP6, compare_ignore_zoneid}; | |
| 2 | use crate::net::tests::{LOCALHOST_IP4, LOCALHOST_IP6, compare_ignore_zoneid}; | |
| 3 | 3 | use crate::net::*; |
| 4 | 4 | use crate::sync::mpsc::channel; |
| 5 | 5 | use crate::thread; |
library/std/src/os/net/linux_ext/tests.rs+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | #[test] |
| 2 | 2 | fn quickack() { |
| 3 | use crate::net::test::LOCALHOST_IP4; | |
| 3 | use crate::net::tests::LOCALHOST_IP4; | |
| 4 | 4 | use crate::net::{TcpListener, TcpStream}; |
| 5 | 5 | use crate::os::net::linux_ext::tcp::TcpStreamExt; |
| 6 | 6 | |
| ... | ... | @@ -29,7 +29,7 @@ fn quickack() { |
| 29 | 29 | #[test] |
| 30 | 30 | #[cfg(target_os = "linux")] |
| 31 | 31 | fn deferaccept() { |
| 32 | use crate::net::test::LOCALHOST_IP4; | |
| 32 | use crate::net::tests::LOCALHOST_IP4; | |
| 33 | 33 | use crate::net::{TcpListener, TcpStream}; |
| 34 | 34 | use crate::os::net::linux_ext::tcp::TcpStreamExt; |
| 35 | 35 | 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 |
| 97 | 97 | |
| 98 | 98 | Within the compiler, for performance reasons, we usually do not register dozens |
| 99 | 99 | of 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 | |
| 101 | 101 | individual lint passes; this is because then we get the benefits of static over |
| 102 | 102 | dynamic dispatch for each of the (often empty) trait methods. |
| 103 | 103 |
src/doc/rustdoc/src/unstable-features.md+61-21| ... | ... | @@ -850,12 +850,63 @@ pub mod futures { |
| 850 | 850 | |
| 851 | 851 | Then, the `unix` cfg will never be displayed into the documentation. |
| 852 | 852 | |
| 853 | Rustdoc currently hides `doc` and `doctest` attributes by default and reserves the right to change the list of "hidden by default" attributes. | |
| 853 | The syntax of `hide` is as follows: you can list as many `cfg` name as you want: | |
| 854 | 854 | |
| 855 | The 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 | ||
| 859 | With 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 | ||
| 865 | In 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 | ||
| 874 | Now, 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 | ||
| 882 | If 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 | ||
| 890 | So 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 | ||
| 899 | If the previous example, both `#[cfg(feature)]` and `#[cfg(feature = "something")]` will be hidden. | |
| 900 | ||
| 901 | Rustdoc currently hides `test`, `doc` and `doctest` attributes by default and reserves the right to change the list of "hidden by default" attributes. | |
| 902 | ||
| 903 | The attribute accepts only a list of identifiers and `values()`. So you can write: | |
| 856 | 904 | |
| 857 | 905 | ```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 | ))] | |
| 859 | 910 | #[doc(auto_cfg(hide()))] |
| 860 | 911 | ``` |
| 861 | 912 | |
| ... | ... | @@ -865,7 +916,7 @@ But you cannot write: |
| 865 | 916 | #[doc(auto_cfg(hide(not(unix))))] |
| 866 | 917 | ``` |
| 867 | 918 | |
| 868 | So if we use `doc(auto_cfg(hide(unix)))`, it means it will hide all mentions of `unix`: | |
| 919 | So if we use `doc(auto_cfg(hide(unix)))`, it means it will hide all mentions of `unix` without a value: | |
| 869 | 920 | |
| 870 | 921 | ```rust,ignore (nightly) |
| 871 | 922 | #[cfg(unix)] // nothing displayed |
| ... | ... | @@ -879,14 +930,6 @@ However, it only impacts the `unix` cfg, not the feature: |
| 879 | 930 | #[cfg(feature = "unix")] // `feature = "unix"` is displayed |
| 880 | 931 | ``` |
| 881 | 932 | |
| 882 | If `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! | |
| 887 | pub fn foo() {} | |
| 888 | ``` | |
| 889 | ||
| 890 | 933 | Using this attribute will re-enable `auto_cfg` if it was disabled at this location: |
| 891 | 934 | |
| 892 | 935 | ```rust,ignore (nightly) |
| ... | ... | @@ -904,14 +947,6 @@ pub mod module { |
| 904 | 947 | } |
| 905 | 948 | ``` |
| 906 | 949 | |
| 907 | However, 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 | |
| 912 | pub fn foo() {} | |
| 913 | ``` | |
| 914 | ||
| 915 | 950 | The 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. |
| 916 | 951 | |
| 917 | 952 | ### `#[doc(auto_cfg(show(...)))]` |
| ... | ... | @@ -919,6 +954,8 @@ The reason behind this is that `doc(auto_cfg = ...)` enables or disables the fea |
| 919 | 954 | This 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(...)))]`. |
| 920 | 955 | It only applies to `#[doc(auto_cfg = true)]`, not to `#[doc(cfg(...))]`. |
| 921 | 956 | |
| 957 | It follows the same syntax rules as for `#[doc(auto_cfg(hide(...)))]`. | |
| 958 | ||
| 922 | 959 | For example: |
| 923 | 960 | |
| 924 | 961 | ```rust,ignore (nightly) |
| ... | ... | @@ -936,7 +973,10 @@ pub mod futures { |
| 936 | 973 | The attribute accepts only a list of identifiers or key/value items. So you can write: |
| 937 | 974 | |
| 938 | 975 | ```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 | ))] | |
| 940 | 980 | #[doc(auto_cfg(show()))] |
| 941 | 981 | ``` |
| 942 | 982 |
src/doc/unstable-book/src/library-features/tuple-trait.md created+5| ... | ... | @@ -0,0 +1,5 @@ |
| 1 | # `tuple_trait` | |
| 2 | ||
| 3 | The 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; |
| 8 | 8 | use std::{fmt, mem, ops}; |
| 9 | 9 | |
| 10 | 10 | use itertools::Either; |
| 11 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; | |
| 11 | use rustc_data_structures::fx::FxHashMap; | |
| 12 | 12 | use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; |
| 13 | 13 | use rustc_hir as hir; |
| 14 | 14 | use rustc_hir::Attribute; |
| 15 | use rustc_hir::attrs::{self, AttributeKind, CfgEntry, CfgHideShow, HideOrShow}; | |
| 15 | use rustc_hir::attrs::{ | |
| 16 | AttributeKind, CfgEntry, CfgHideShow, DocCfgHideShow, DocCfgHideShowValue, HideOrShow, | |
| 17 | }; | |
| 16 | 18 | use rustc_middle::ty::TyCtxt; |
| 17 | 19 | use rustc_span::symbol::{Symbol, sym}; |
| 18 | 20 | use rustc_span::{DUMMY_SP, Span}; |
| ... | ... | @@ -30,6 +32,87 @@ mod tests; |
| 30 | 32 | #[cfg_attr(test, derive(PartialEq))] |
| 31 | 33 | pub(crate) struct Cfg(CfgEntry); |
| 32 | 34 | |
| 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)] | |
| 38 | enum DocCfgHide { | |
| 39 | Any { except: ThinVec<DocCfgHideShowValue> }, | |
| 40 | List(ThinVec<DocCfgHideShowValue>), | |
| 41 | } | |
| 42 | ||
| 43 | impl 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 | ||
| 107 | impl 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 | ||
| 33 | 116 | /// Whether the configuration consists of just `Cfg` or `Not`. |
| 34 | 117 | fn is_simple_cfg(cfg: &CfgEntry) -> bool { |
| 35 | 118 | match cfg { |
| ... | ... | @@ -53,14 +136,14 @@ fn is_any_cfg(cfg: &CfgEntry) -> bool { |
| 53 | 136 | } |
| 54 | 137 | } |
| 55 | 138 | |
| 56 | fn strip_hidden(cfg: &CfgEntry, hidden: &FxHashSet<NameValueCfg>) -> Option<CfgEntry> { | |
| 139 | fn strip_hidden(cfg: &CfgEntry, hidden: &FxHashMap<Symbol, DocCfgHide>) -> Option<CfgEntry> { | |
| 57 | 140 | match cfg { |
| 58 | 141 | 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)) { | |
| 63 | 144 | None |
| 145 | } else { | |
| 146 | Some(cfg.clone()) | |
| 64 | 147 | } |
| 65 | 148 | } |
| 66 | 149 | CfgEntry::Not(cfg, _) => { |
| ... | ... | @@ -653,39 +736,12 @@ fn human_readable_target_env(env: Symbol) -> Option<&'static str> { |
| 653 | 736 | }) |
| 654 | 737 | } |
| 655 | 738 | |
| 656 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | |
| 657 | struct NameValueCfg { | |
| 658 | name: Symbol, | |
| 659 | value: Option<Symbol>, | |
| 660 | } | |
| 661 | ||
| 662 | impl NameValueCfg { | |
| 663 | fn new(name: Symbol) -> Self { | |
| 664 | Self { name, value: None } | |
| 665 | } | |
| 666 | } | |
| 667 | ||
| 668 | impl<'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 | ||
| 677 | impl<'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 | ||
| 683 | 739 | /// This type keeps track of (doc) cfg information as we go down the item tree. |
| 684 | 740 | #[derive(Clone, Debug)] |
| 685 | 741 | pub(crate) struct CfgInfo { |
| 686 | 742 | /// List of currently active `doc(auto_cfg(hide(...)))` cfgs, minus currently active |
| 687 | 743 | /// `doc(auto_cfg(show(...)))` cfgs. |
| 688 | hidden_cfg: FxHashSet<NameValueCfg>, | |
| 744 | hidden_cfg: FxHashMap<Symbol, DocCfgHide>, | |
| 689 | 745 | /// Current computed `cfg`. Each time we enter a new item, this field is updated as well while |
| 690 | 746 | /// taking into account the `hidden_cfg` information. |
| 691 | 747 | current_cfg: Cfg, |
| ... | ... | @@ -700,10 +756,10 @@ pub(crate) struct CfgInfo { |
| 700 | 756 | impl Default for CfgInfo { |
| 701 | 757 | fn default() -> Self { |
| 702 | 758 | 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()), | |
| 707 | 763 | ]), |
| 708 | 764 | current_cfg: Cfg(CfgEntry::Bool(true, DUMMY_SP)), |
| 709 | 765 | auto_cfg_active: true, |
| ... | ... | @@ -712,51 +768,24 @@ impl Default for CfgInfo { |
| 712 | 768 | } |
| 713 | 769 | } |
| 714 | 770 | |
| 715 | fn 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 | ||
| 730 | 771 | /// This functions updates the `hidden_cfg` field of the provided `cfg_info` argument. |
| 731 | 772 | /// |
| 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 | /// | |
| 735 | 773 | /// Because we go through a list of `cfg`s, we keep track of the `cfg`s we saw in `new_show_attrs` |
| 736 | 774 | /// and in `new_hide_attrs` arguments. |
| 737 | fn 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); | |
| 775 | fn handle_auto_cfg_hide_show(cfg_info: &mut CfgInfo, attr: &CfgHideShow) { | |
| 776 | for (cfg_name, value) in &attr.values { | |
| 746 | 777 | 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()); | |
| 753 | 783 | } 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()); | |
| 760 | 789 | } |
| 761 | 790 | } |
| 762 | 791 | } |
| ... | ... | @@ -791,9 +820,6 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> |
| 791 | 820 | false |
| 792 | 821 | } |
| 793 | 822 | |
| 794 | let mut new_show_attrs = FxHashMap::default(); | |
| 795 | let mut new_hide_attrs = FxHashMap::default(); | |
| 796 | ||
| 797 | 823 | let mut doc_cfg = attrs |
| 798 | 824 | .clone() |
| 799 | 825 | .filter_map(|attr| match attr { |
| ... | ... | @@ -844,13 +870,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> |
| 844 | 870 | return None; |
| 845 | 871 | } |
| 846 | 872 | 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); | |
| 854 | 874 | } |
| 855 | 875 | } |
| 856 | 876 | } 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; |
| 7 | 7 | use rustc_data_structures::fx::FxHashSet; |
| 8 | 8 | use rustc_data_structures::thin_vec::ThinVec; |
| 9 | 9 | use rustc_hir as hir; |
| 10 | use rustc_hir::attrs::{self, DeprecatedSince, DocAttribute, DocInline, HideOrShow}; | |
| 10 | use rustc_hir::attrs::{ | |
| 11 | self, DeprecatedSince, DocAttribute, DocCfgHideShow, DocInline, HideOrShow, | |
| 12 | }; | |
| 11 | 13 | use rustc_hir::def::{CtorKind, DefKind}; |
| 12 | 14 | use rustc_hir::def_id::DefId; |
| 13 | 15 | use rustc_hir::{HeaderSafety, Safety, find_attr}; |
| ... | ... | @@ -1122,24 +1124,41 @@ fn maybe_from_hir_attr(attr: &hir::Attribute, item_id: ItemId, tcx: TyCtxt<'_>) |
| 1122 | 1124 | for sub_cfg in cfg { |
| 1123 | 1125 | ret.push(Attribute::Other(format!("#[doc(cfg({sub_cfg}))]"))); |
| 1124 | 1126 | } |
| 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 { | |
| 1133 | 1135 | out.push_str(", "); |
| 1134 | 1136 | } |
| 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(")"); | |
| 1140 | 1158 | } |
| 1159 | out.push(')'); | |
| 1141 | 1160 | } |
| 1142 | out.push_str(")))]"); | |
| 1161 | out.push_str("))]"); | |
| 1143 | 1162 | ret.push(Attribute::Other(out)); |
| 1144 | 1163 | } |
| 1145 | 1164 | 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 |
| 454 | 454 | // NOTE: Do not add any more pre-expansion passes. These should be removed eventually. |
| 455 | 455 | // Due to the architecture of the compiler, currently `cfg_attr` attributes on crate |
| 456 | 456 | // 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 | ); | |
| 458 | 460 | |
| 459 | 461 | let format_args_storage = FormatArgsStorage::default(); |
| 460 | 462 | let attr_storage = AttrStorage::default(); |
| ... | ... | @@ -462,12 +464,12 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co |
| 462 | 464 | { |
| 463 | 465 | let format_args = format_args_storage.clone(); |
| 464 | 466 | let attrs = attr_storage.clone(); |
| 465 | store.early_passes.push(Box::new(move || { | |
| 467 | store.register_early_lint_pass(Box::new(move || { | |
| 466 | 468 | Box::new(CombinedEarlyLintPass::new(conf, format_args.clone(), attrs.clone())) |
| 467 | 469 | })); |
| 468 | 470 | } |
| 469 | 471 | |
| 470 | store.late_passes.push(Box::new(move |tcx: TyCtxt<'_>| { | |
| 472 | store.register_late_lint_pass(Box::new(move |tcx: TyCtxt<'_>| { | |
| 471 | 473 | let skippable_lints = tcx.skippable_lints(()); |
| 472 | 474 | let is_active = |lints: &rustc_lint::LintVec| is_lint_pass_required(skippable_lints, lints); |
| 473 | 475 | 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 { |
| 62 | 62 | *x |
| 63 | 63 | } |
| 64 | 64 | // 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 | |
| 75 | 70 | #[cfg_attr(no_vector, target_feature(enable = "vector"))] |
| 76 | 71 | #[no_mangle] |
| 77 | 72 | unsafe 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> { |
| 95 | 90 | *x |
| 96 | 91 | } |
| 97 | 92 | // 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 | |
| 108 | 98 | #[cfg_attr(no_vector, target_feature(enable = "vector"))] |
| 109 | 99 | #[no_mangle] |
| 110 | 100 | unsafe 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( |
| 141 | 131 | *x |
| 142 | 132 | } |
| 143 | 133 | // 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 | |
| 154 | 139 | #[cfg_attr(no_vector, target_feature(enable = "vector"))] |
| 155 | 140 | #[no_mangle] |
| 156 | 141 | unsafe extern "C" fn vector_wrapper_with_zst_ret_large( |
| ... | ... | @@ -180,16 +165,11 @@ unsafe extern "C" fn vector_transparent_wrapper_ret( |
| 180 | 165 | *x |
| 181 | 166 | } |
| 182 | 167 | // 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 | |
| 193 | 173 | #[cfg_attr(no_vector, target_feature(enable = "vector"))] |
| 194 | 174 | #[no_mangle] |
| 195 | 175 | unsafe 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 | |
| 3 | trait NodeImpl {} | |
| 4 | struct Wrap<F, P>(F, P); | |
| 5 | impl<F, P> Wrap<F, P> { | |
| 6 | fn new(_: F) -> Self { | |
| 7 | loop {} | |
| 8 | } | |
| 9 | } | |
| 10 | trait Arg {} | |
| 11 | impl<F, A> NodeImpl for Wrap<F, A> where A: Arg {} | |
| 12 | impl<F, Fut, A> NodeImpl for Wrap<F, (A,)> where F: Fn(&(), A) -> Fut {} | |
| 13 | fn trigger_ice() { | |
| 14 | let _: &dyn NodeImpl = &Wrap::<_, (i128,)>::new(async |_: &(), i128| 0); | |
| 15 | } | |
| 16 | fn main() {} |
tests/crashes/148511.rs created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | //@ known-bug: #148511 | |
| 2 | //@ edition: 2021 | |
| 3 | use std::any::Any; | |
| 4 | ||
| 5 | fn main() { | |
| 6 | use_service(make_service()); | |
| 7 | let _future = async {}; | |
| 8 | } | |
| 9 | ||
| 10 | fn make_service() -> impl FooService<Box<dyn Any>, Response: Body> {} | |
| 11 | ||
| 12 | fn use_service<S, R>(_service: S) | |
| 13 | where | |
| 14 | S: FooService<R>, | |
| 15 | <S::Response as Body>::Data: Any, | |
| 16 | { | |
| 17 | } | |
| 18 | ||
| 19 | trait Service<Request> { | |
| 20 | type Response: Body; | |
| 21 | } | |
| 22 | ||
| 23 | impl<T, Request> Service<Request> for T { | |
| 24 | type Response = (); | |
| 25 | } | |
| 26 | ||
| 27 | trait FooService<Request>: Service<Request> {} | |
| 28 | ||
| 29 | impl<T, Request, Resp> FooService<Request> for T | |
| 30 | where | |
| 31 | T: Service<Request, Response = Resp>, | |
| 32 | Resp: Body, | |
| 33 | { | |
| 34 | } | |
| 35 | ||
| 36 | trait Body { | |
| 37 | type Data; | |
| 38 | } | |
| 39 | ||
| 40 | impl<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)] | |
| 3 | trait Foo { | |
| 4 | type AssociatedType; | |
| 5 | } | |
| 6 | ||
| 7 | impl<const N: usize> Foo for [(); N] {} | |
| 8 | ||
| 9 | pub struct Happy; | |
| 10 | ||
| 11 | impl Foo for Happy {} | |
| 12 | ||
| 13 | impl<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 | ||
| 4 | trait Tr {} | |
| 5 | trait Foo { | |
| 6 | fn foo() -> impl Sized | |
| 7 | where | |
| 8 | for<'a> <() as FnOnce<&'a i32>>::Output: Tr, | |
| 9 | { | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | fn main() {} |
tests/crashes/148632.rs created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | //@ known-bug: #148632 | |
| 2 | trait D<C> {} | |
| 3 | ||
| 4 | trait Project { | |
| 5 | const SELF: dyn D<Self>; | |
| 6 | } | |
| 7 | ||
| 8 | fn main() { | |
| 9 | let _: &dyn Project<SELF = { 0 }>; | |
| 10 | } |
tests/crashes/148890.rs created+6| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | //@ known-bug: #148890 | |
| 2 | impl std::ops::Neg for u128 {} | |
| 3 | ||
| 4 | fn foo(-128..=127: u128) {} | |
| 5 | ||
| 6 | fn main() {} |
tests/crashes/148891.rs created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | //@ known-bug: #148891 | |
| 2 | macro_rules! values { | |
| 3 | ($inner:ty) => { | |
| 4 | #[derive(Debug)] | |
| 5 | pub enum TokenKind { | |
| 6 | #[cfg(test)] | |
| 7 | STRING ([u8; $inner]), | |
| 8 | } | |
| 9 | }; | |
| 10 | } | |
| 11 | ||
| 12 | values!(String); | |
| 13 | ||
| 14 | pub fn main() {} |
tests/crashes/149162.rs created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | //@ known-bug: #149162 | |
| 2 | use std::marker::PhantomData; | |
| 3 | pub trait ViewArgument { | |
| 4 | type Params<'a>; | |
| 5 | } | |
| 6 | ||
| 7 | impl ViewArgument for () { | |
| 8 | type Params<'a> = (); | |
| 9 | } | |
| 10 | ||
| 11 | pub trait View {} | |
| 12 | ||
| 13 | pub fn buttons() -> Option<impl View> { | |
| 14 | Some(()).map(|()| text_button(|()| {})) | |
| 15 | } | |
| 16 | pub 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 | } | |
| 24 | pub struct Button<State, F> { | |
| 25 | pub callback: F, | |
| 26 | pub phantom: PhantomData<State>, | |
| 27 | } | |
| 28 | ||
| 29 | impl<F> View for Button<(), F> {} | |
| 30 | fn main() {} |
tests/crashes/149703.rs created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | //@ known-bug: #149703 | |
| 2 | #![feature(const_trait_impl)] | |
| 3 | trait Z { | |
| 4 | type Assoc; | |
| 5 | } | |
| 6 | struct A; | |
| 7 | impl<T: const FnOnce()> Z for T { | |
| 8 | type Assoc = (); | |
| 9 | } | |
| 10 | impl<T> From<<A as Z>::Assoc> for T {} | |
| 11 | ||
| 12 | fn main() {} |
tests/crashes/152205.rs created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | //@ known-bug: #152205 | |
| 2 | #![deny(rust_2021_incompatible_closure_captures)] | |
| 3 | struct Foo; | |
| 4 | struct S; | |
| 5 | impl Drop for S { | |
| 6 | fn drop(&mut self) {} | |
| 7 | } | |
| 8 | struct U(<Foo as NewTrait>::Assoc); | |
| 9 | fn test_precise_analysis_long_path(u: U) { | |
| 10 | let _ = || { | |
| 11 | let _x = u.0.0; | |
| 12 | }; | |
| 13 | } | |
| 14 | trait NewTrait { | |
| 15 | type Assoc; | |
| 16 | } | |
| 17 | impl NewTrait for Foo { | |
| 18 | type Assoc = (S,); | |
| 19 | } | |
| 20 | fn main(){} |
tests/crashes/152295.rs created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | //@ known-bug: #152295 | |
| 2 | #![feature(type_alias_impl_trait)] | |
| 3 | type Tait = impl Sized; | |
| 4 | trait Foo: Bar<Tait> {} | |
| 5 | trait Bar<T> { | |
| 6 | fn bar(&self); | |
| 7 | } | |
| 8 | fn test_correct2(x: &dyn Foo) { | |
| 9 | x.bar(); | |
| 10 | } | |
| 11 | fn main() {} |
tests/crashes/154556.rs created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | //@ known-bug: #154556 | |
| 2 | #![feature(generic_const_exprs)] | |
| 3 | ||
| 4 | pub trait Foo { | |
| 5 | // Has to take self or a reference to self to ICE. | |
| 6 | fn eq(self); | |
| 7 | } | |
| 8 | ||
| 9 | pub trait Bar { | |
| 10 | const NUMBER: usize; | |
| 11 | } | |
| 12 | ||
| 13 | impl<T: Bar> Foo for T | |
| 14 | where | |
| 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. | |
| 21 | fn baz() { | |
| 22 | ().eq(&()); | |
| 23 | } | |
| 24 | ||
| 25 | fn main() {} |
tests/crashes/154964.rs created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | //@ known-bug: #154964 | |
| 2 | //@ edition: 2021 | |
| 3 | //@ compile-flags: -Zprint-type-sizes | |
| 4 | fn main() { | |
| 5 | |foo: Foo<_>| async { foo.bar }; | |
| 6 | } | |
| 7 | struct 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)] | |
| 4 | pub struct F; | |
| 5 | impl 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 | } | |
| 10 | fn 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))] | |
| 12 | pub 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))] | |
| 17 | pub 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 | ||
| 7 | pub struct X; | |
| 8 | ||
| 9 | #[cfg(not(feature = "blob"))] | |
| 10 | fn 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))] | |
| 7 | pub 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))] | |
| 15 | pub 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)))] | |
| 22 | pub 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)))] | |
| 29 | pub 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()))] | |
| 35 | pub 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))] | |
| 12 | pub 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))] | |
| 17 | pub fn bar() {} |
tests/rustdoc-html/doc-cfg/decl-macro.rs+3-3| ... | ... | @@ -45,7 +45,7 @@ pub mod auto_cfg_disabled { |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | #[cfg(feature = "routing")] |
| 48 | #[doc(auto_cfg(hide(feature = "routing")))] | |
| 48 | #[doc(auto_cfg(hide(feature, values("routing"))))] | |
| 49 | 49 | pub mod auto_cfg_hidden { |
| 50 | 50 | //@ count 'foo/macro.hidden_cfg_macro.html' '//*[@class="stab portability"]' 0 |
| 51 | 51 | #[macro_export] |
| ... | ... | @@ -55,9 +55,9 @@ pub mod auto_cfg_hidden { |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | #[cfg(feature = "routing")] |
| 58 | #[doc(auto_cfg(hide(feature = "routing")))] | |
| 58 | #[doc(auto_cfg(hide(feature, values("routing"))))] | |
| 59 | 59 | pub mod auto_cfg_shown { |
| 60 | #[doc(auto_cfg(show(feature = "routing")))] | |
| 60 | #[doc(auto_cfg(show(feature, values("routing"))))] | |
| 61 | 61 | pub mod inner { |
| 62 | 62 | //@ has 'foo/macro.shown_cfg_macro.html' '//*[@class="stab portability"]' 'Available on crate feature routing only.' |
| 63 | 63 | #[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"))] | |
| 15 | pub 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)] | |
| 39 | pub 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")))] | |
| 72 | pub 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 | ||
| 7 | pub struct X; | |
| 8 | ||
| 9 | #[cfg(not(feature = "blob"))] | |
| 10 | fn 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))] | |
| 7 | pub 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))] | |
| 15 | pub 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)))] | |
| 22 | pub 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)))] | |
| 29 | pub 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()))] | |
| 35 | pub fn appear_3() {} // issue #98065 |
tests/rustdoc-html/doc-cfg/doc-cfg-hide.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![crate_name = "oud"] |
| 2 | 2 | #![feature(doc_cfg)] |
| 3 | 3 | |
| 4 | #![doc(auto_cfg(hide(feature = "solecism")))] | |
| 4 | #![doc(auto_cfg(hide(feature, values("solecism"))))] | |
| 5 | 5 | |
| 6 | 6 | //@ has 'oud/struct.Solecism.html' |
| 7 | 7 | //@ 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"))] | |
| 11 | pub use std::cell::RefCell as C; | |
| 12 | ||
| 13 | // Check with local item. | |
| 14 | mod 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"))] | |
| 22 | pub use crate::x::B; | |
| 23 | ||
| 24 | // Now checking that `cfg`s are not applied on non-inlined reexports. | |
| 25 | pub 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))] | |
| 17 | pub 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"))] | |
| 26 | pub 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))] | |
| 14 | pub 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"))] | |
| 21 | pub 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"))] | |
| 28 | pub fn babar() {} | |
| 29 | ||
| 30 | pub 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 | ||
| 56 | pub 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 | ||
| 82 | pub 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 | ))] | |
| 113 | pub 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 | ))] | |
| 143 | pub 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 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(doc_cfg)] |
| 5 | 5 | #![doc(auto_cfg(hide( |
| 6 | target_pointer_width = "64", | |
| 6 | target_pointer_width, values("64"), | |
| 7 | 7 | )))] |
| 8 | 8 | |
| 9 | 9 | #![crate_name = "foo"] |
| ... | ... | @@ -36,7 +36,7 @@ pub struct X; |
| 36 | 36 | //@count - '//*[@id="impl-Trait-for-X"]' 1 |
| 37 | 37 | //@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0 |
| 38 | 38 | #[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"))))] | |
| 40 | 40 | mod imp { |
| 41 | 41 | impl super::Trait for super::X { fn f(&self) {} } |
| 42 | 42 | } |
| ... | ... | @@ -64,7 +64,7 @@ pub struct Y; |
| 64 | 64 | //@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1 |
| 65 | 65 | //@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0 |
| 66 | 66 | #[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"))))] | |
| 68 | 68 | mod imp4 { |
| 69 | 69 | impl super::Y { pub fn plain_auto() {} } |
| 70 | 70 | } |
tests/rustdoc-html/doc-cfg/trait-impls.rs+3-3| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(doc_cfg)] |
| 5 | 5 | #![doc(auto_cfg(hide( |
| 6 | target_pointer_width = "64", | |
| 6 | target_pointer_width, values("64"), | |
| 7 | 7 | )))] |
| 8 | 8 | |
| 9 | 9 | #![crate_name = "foo"] |
| ... | ... | @@ -36,7 +36,7 @@ pub struct X; |
| 36 | 36 | //@count - '//*[@id="impl-Trait-for-X"]' 1 |
| 37 | 37 | //@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0 |
| 38 | 38 | #[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"))))] | |
| 40 | 40 | mod imp { |
| 41 | 41 | impl super::Trait for super::X { fn f(&self) {} } |
| 42 | 42 | } |
| ... | ... | @@ -64,7 +64,7 @@ pub struct Y; |
| 64 | 64 | //@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1 |
| 65 | 65 | //@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0 |
| 66 | 66 | #[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"))))] | |
| 68 | 68 | mod imp4 { |
| 69 | 69 | impl super::Y { pub fn plain_auto() {} } |
| 70 | 70 | } |
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"))] | |
| 15 | pub 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)] | |
| 39 | pub 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")))] | |
| 72 | pub 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"))] | |
| 11 | pub use std::cell::RefCell as C; | |
| 12 | ||
| 13 | // Check with local item. | |
| 14 | mod 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"))] | |
| 22 | pub use crate::x::B; | |
| 23 | ||
| 24 | // Now checking that `cfg`s are not applied on non-inlined reexports. | |
| 25 | pub 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")),))] | |
| 5 | pub 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 @@ |
| 1 | 1 | error: 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 | |
| 3 | 3 | | |
| 4 | LL | #![doc(auto_cfg(show(windows, target_os = "linux")))] | |
| 5 | | ^^^^^^^^^^^^^^^^^^^ | |
| 4 | LL | #![doc(auto_cfg(show(windows), show(target_os, values("linux"))))] | |
| 5 | | ^^^^^^^ | |
| 6 | 6 | | |
| 7 | 7 | note: first change was here |
| 8 | --> $DIR/cfg-hide-show-conflict.rs:2:22 | |
| 8 | --> $DIR/cfg-hide-show-conflict.rs:2:40 | |
| 9 | 9 | | |
| 10 | LL | #![doc(auto_cfg(hide(target_os = "linux")))] | |
| 11 | | ^^^^^^^^^^^^^^^^^^^ | |
| 10 | LL | #![doc(auto_cfg(hide(target_os, values("linux"))))] | |
| 11 | | ^^^^^^^ | |
| 12 | 12 | |
| 13 | 13 | error: aborting due to 1 previous error |
| 14 | 14 |
tests/rustdoc-ui/doc-cfg-2.rs+1-3| ... | ... | @@ -13,7 +13,5 @@ |
| 13 | 13 | // Shouldn't lint |
| 14 | 14 | #[doc(auto_cfg(hide(windows)))] |
| 15 | 15 | #[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(...)` | |
| 19 | 17 | pub fn foo() {} |
tests/rustdoc-ui/doc-cfg-2.stderr+5-17| ... | ... | @@ -30,19 +30,19 @@ note: the lint level is defined here |
| 30 | 30 | LL | #![deny(invalid_doc_attributes)] |
| 31 | 31 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 32 | 32 | |
| 33 | error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items | |
| 33 | error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)` | |
| 34 | 34 | --> $DIR/doc-cfg-2.rs:8:21 |
| 35 | 35 | | |
| 36 | 36 | LL | #[doc(auto_cfg(hide(true)))] |
| 37 | 37 | | ^^^^ |
| 38 | 38 | |
| 39 | error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items | |
| 39 | error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)` | |
| 40 | 40 | --> $DIR/doc-cfg-2.rs:9:21 |
| 41 | 41 | | |
| 42 | 42 | LL | #[doc(auto_cfg(hide(42)))] |
| 43 | 43 | | ^^ |
| 44 | 44 | |
| 45 | error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items | |
| 45 | error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)` | |
| 46 | 46 | --> $DIR/doc-cfg-2.rs:10:21 |
| 47 | 47 | | |
| 48 | 48 | LL | #[doc(auto_cfg(hide("a")))] |
| ... | ... | @@ -60,23 +60,11 @@ error: expected boolean for `#[doc(auto_cfg = ...)]` |
| 60 | 60 | LL | #[doc(auto_cfg = "a")] |
| 61 | 61 | | ^^^ |
| 62 | 62 | |
| 63 | warning: unexpected `cfg` condition name: `feature` | |
| 63 | error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)` | |
| 64 | 64 | --> $DIR/doc-cfg-2.rs:15:21 |
| 65 | 65 | | |
| 66 | 66 | LL | #[doc(auto_cfg(hide(feature = "windows")))] |
| 67 | 67 | | ^^^^^^^^^^^^^^^^^^^ |
| 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 | ||
| 72 | warning: unexpected `cfg` condition name: `foo` | |
| 73 | --> $DIR/doc-cfg-2.rs:17:21 | |
| 74 | | | |
| 75 | LL | #[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 | |
| 80 | 68 | |
| 81 | error: aborting due to 6 previous errors; 4 warnings emitted | |
| 69 | error: aborting due to 7 previous errors; 2 warnings emitted | |
| 82 | 70 |
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 @@ |
| 1 | error: `any()` was used when other values were provided | |
| 2 | --> $DIR/doc-cfg-3.rs:6:40 | |
| 3 | | | |
| 4 | LL | #![doc(auto_cfg(hide(target_os, values(any(), "linux"))))] | |
| 5 | | ^^^^^ ------- value declared here | |
| 6 | | | |
| 7 | note: the lint level is defined here | |
| 8 | --> $DIR/doc-cfg-3.rs:3:9 | |
| 9 | | | |
| 10 | LL | #![deny(invalid_doc_attributes)] | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error: `any()` was used when other values were provided | |
| 14 | --> $DIR/doc-cfg-3.rs:7:49 | |
| 15 | | | |
| 16 | LL | #![doc(auto_cfg(hide(target_os, values("linux", any()))))] | |
| 17 | | ------- ^^^^^ | |
| 18 | | | | |
| 19 | | value declared here | |
| 20 | ||
| 21 | error: 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 @@ |
| 1 | error: `#![doc(auto_cfg(any(...)))]` only accepts identifiers or `values(...)` | |
| 2 | --> $DIR/doc-cfg-4.rs:6:40 | |
| 3 | | | |
| 4 | LL | #![doc(auto_cfg(hide(target_os, values(any("linux")))))] | |
| 5 | | ^^^^^^^^^^^^ | |
| 6 | | | |
| 7 | note: the lint level is defined here | |
| 8 | --> $DIR/doc-cfg-4.rs:3:9 | |
| 9 | | | |
| 10 | LL | #![deny(invalid_doc_attributes)] | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error: `#![doc(auto_cfg(none(...)))]` only accepts identifiers or `values(...)` | |
| 14 | --> $DIR/doc-cfg-4.rs:7:40 | |
| 15 | | | |
| 16 | LL | #![doc(auto_cfg(hide(target_os, values(none("linux")))))] | |
| 17 | | ^^^^^^^^^^^^^ | |
| 18 | ||
| 19 | error: aborting due to 2 previous errors | |
| 20 |
tests/rustdoc-ui/doc-cfg.rs+1-1| ... | ... | @@ -6,5 +6,5 @@ |
| 6 | 6 | //~| ERROR |
| 7 | 7 | #[doc(cfg())] //~ ERROR |
| 8 | 8 | #[doc(cfg(foo, bar))] //~ ERROR |
| 9 | #[doc(auto_cfg(hide(foo::bar)))] | |
| 9 | #[doc(auto_cfg(hide(foo::bar)))] //~ ERROR | |
| 10 | 10 | pub fn foo() {} |
tests/rustdoc-ui/doc-cfg.stderr+11-2| ... | ... | @@ -62,6 +62,15 @@ LL - #[doc(cfg(foo, bar))] |
| 62 | 62 | LL + #[doc(cfg(any(foo, bar)))] |
| 63 | 63 | | |
| 64 | 64 | |
| 65 | error: aborting due to 4 previous errors | |
| 65 | error[E0565]: malformed `doc` attribute input | |
| 66 | --> $DIR/doc-cfg.rs:9:1 | |
| 67 | | | |
| 68 | LL | #[doc(auto_cfg(hide(foo::bar)))] | |
| 69 | | ^^^^^^^^^^^^^^^^^^^^--------^^^^ | |
| 70 | | | | |
| 71 | | expected a valid identifier here | |
| 72 | ||
| 73 | error: aborting due to 5 previous errors | |
| 66 | 74 | |
| 67 | For more information about this error, try `rustc --explain E0805`. | |
| 75 | Some errors have detailed explanations: E0565, E0805. | |
| 76 | For 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 @@ |
| 1 | error[E0565]: malformed `doc` attribute input | |
| 2 | --> $DIR/doc_cfg_hide-2.rs:4:1 | |
| 3 | | | |
| 4 | LL | #![doc(auto_cfg(hide(not(windows))))] | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^---^^^^^^^^^^^^^ | |
| 6 | | | | |
| 7 | | expected a valid identifier here | |
| 8 | ||
| 9 | error: aborting due to 1 previous error | |
| 10 | ||
| 11 | For more information about this error, try `rustc --explain E0565`. |
tests/rustdoc-ui/lints/doc_cfg_hide.rs-1| ... | ... | @@ -2,4 +2,3 @@ |
| 2 | 2 | #![feature(doc_cfg)] |
| 3 | 3 | #![doc(auto_cfg(hide = "test"))] //~ ERROR |
| 4 | 4 | #![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 |
| 16 | 16 | LL | #![doc(auto_cfg(hide))] |
| 17 | 17 | | ^^^^ |
| 18 | 18 | |
| 19 | error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items | |
| 20 | --> $DIR/doc_cfg_hide.rs:5:22 | |
| 21 | | | |
| 22 | LL | #![doc(auto_cfg(hide(not(windows))))] | |
| 23 | | ^^^^^^^^^^^^ | |
| 24 | ||
| 25 | error: aborting due to 3 previous errors | |
| 19 | error: aborting due to 2 previous errors | |
| 26 | 20 |
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 | ||
| 6 | trait Trait {} | |
| 7 | ||
| 8 | impl<'t> Trait for [(); N] {} | |
| 9 | //~^ ERROR the placeholder `_` is not allowed within types on item signatures for implementations | |
| 10 | ||
| 11 | fn N(arg: impl Trait) {} | |
| 12 | ||
| 13 | fn main() {} |
tests/ui/const-generics/mgca/bad-impl-trait-with-apit.stderr created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations | |
| 2 | --> $DIR/bad-impl-trait-with-apit.rs:8:25 | |
| 3 | | | |
| 4 | LL | impl<'t> Trait for [(); N] {} | |
| 5 | | ^ not allowed in type signatures | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 | ||
| 9 | For 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> {} |
| 4 | 4 | trait Trait<const N: usize> {} |
| 5 | 5 | |
| 6 | 6 | impl A<[usize; fn_item]> for () {} |
| 7 | //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for implementations | |
| 7 | 8 | |
| 8 | 9 | fn fn_item(_: impl Trait<usize>) {} |
| 9 | 10 | //~^ 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 @@ |
| 1 | error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations | |
| 2 | --> $DIR/synth-gen-arg-ice-158152.rs:6:16 | |
| 3 | | | |
| 4 | LL | impl A<[usize; fn_item]> for () {} | |
| 5 | | ^^^^^^^ not allowed in type signatures | |
| 6 | ||
| 1 | 7 | error[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 | |
| 3 | 9 | | |
| 4 | 10 | LL | fn fn_item(_: impl Trait<usize>) {} |
| 5 | 11 | | ^^^^^ |
| ... | ... | @@ -9,6 +15,7 @@ help: if this generic argument was intended as a const parameter, surround it wi |
| 9 | 15 | LL | fn fn_item(_: impl Trait<{ usize }>) {} |
| 10 | 16 | | + + |
| 11 | 17 | |
| 12 | error: aborting due to 1 previous error | |
| 18 | error: aborting due to 2 previous errors | |
| 13 | 19 | |
| 14 | For more information about this error, try `rustc --explain E0747`. | |
| 20 | Some errors have detailed explanations: E0121, E0747. | |
| 21 | For 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 {} |
| 18 | 18 | |
| 19 | 19 | #[lang = "start"] |
| 20 | 20 | #[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 | |
| 22 | 22 | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { |
| 23 | 23 | 0 |
| 24 | 24 | } |
tests/ui/lang-items/start_lang_item_with_target_feature.stderr+7-5| ... | ... | @@ -1,11 +1,13 @@ |
| 1 | error: `start` lang item function is not allowed to have `#[target_feature]` | |
| 1 | error: `#[target_feature]` cannot be applied to a lang item function | |
| 2 | 2 | --> $DIR/start_lang_item_with_target_feature.rs:20:1 |
| 3 | 3 | | |
| 4 | LL | #[target_feature(enable = "avx2")] | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 4 | LL | #[target_feature(enable = "avx2")] | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | 6 | LL | |
| 7 | LL | 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]` | |
| 7 | LL | / fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { | |
| 8 | LL | | 0 | |
| 9 | LL | | } | |
| 10 | | |_- lang item function is not allowed to have `#[target_feature]` | |
| 9 | 11 | |
| 10 | 12 | error: aborting due to 1 previous error |
| 11 | 13 |
tests/ui/liveness/auxiliary/aux_issue_147648.rs created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | #![feature(proc_macro_quote)] | |
| 2 | ||
| 3 | extern crate proc_macro; | |
| 4 | use proc_macro::*; | |
| 5 | ||
| 6 | #[proc_macro_derive(UnusedAssign)] | |
| 7 | pub 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 | ||
| 8 | extern crate aux_issue_147648; | |
| 9 | use aux_issue_147648::UnusedAssign; | |
| 10 | ||
| 11 | #[derive(UnusedAssign)] | |
| 12 | pub struct MyError { | |
| 13 | source_code: (), | |
| 14 | } | |
| 15 | ||
| 16 | fn 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; |
| 8 | 8 | |
| 9 | 9 | #[panic_handler] |
| 10 | 10 | #[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 | |
| 12 | 12 | fn panic(info: &PanicInfo) -> ! { |
| 13 | 13 | unimplemented!(); |
| 14 | 14 | } |
tests/ui/panic-handler/panic-handler-with-target-feature.stderr+7-5| ... | ... | @@ -1,11 +1,13 @@ |
| 1 | error: `#[panic_handler]` function is not allowed to have `#[target_feature]` | |
| 1 | error: `#[target_feature]` cannot be applied to a `#[panic_handler]` function | |
| 2 | 2 | --> $DIR/panic-handler-with-target-feature.rs:10:1 |
| 3 | 3 | | |
| 4 | LL | #[target_feature(enable = "avx2")] | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 4 | LL | #[target_feature(enable = "avx2")] | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | 6 | LL | |
| 7 | LL | fn panic(info: &PanicInfo) -> ! { | |
| 8 | | ------------------------------- `#[panic_handler]` function is not allowed to have `#[target_feature]` | |
| 7 | LL | / fn panic(info: &PanicInfo) -> ! { | |
| 8 | LL | | unimplemented!(); | |
| 9 | LL | | } | |
| 10 | | |_- `#[panic_handler]` function is not allowed to have `#[target_feature]` | |
| 9 | 11 | |
| 10 | 12 | error: aborting due to 1 previous error |
| 11 | 13 |
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 | ||
| 4 | trait Role { | |
| 5 | type Inner; | |
| 6 | } | |
| 7 | ||
| 8 | struct HandshakeCallback<C>(C); | |
| 9 | struct Handshake<R: Role>(R::Inner); | |
| 10 | ||
| 11 | fn 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 @@ |
| 1 | error[E0283]: type annotations needed for `Handshake<_>` | |
| 2 | --> $DIR/unexpected-pointer-deref-issue-154568.rs:13:9 | |
| 3 | | | |
| 4 | LL | let handshake = Handshake(callback.0.clone()); | |
| 5 | | ^^^^^^^^^ ----------------------------- type must be known at this point | |
| 6 | | | |
| 7 | = note: the type must implement `Role` | |
| 8 | note: required by a bound in `Handshake` | |
| 9 | --> $DIR/unexpected-pointer-deref-issue-154568.rs:9:21 | |
| 10 | | | |
| 11 | LL | struct Handshake<R: Role>(R::Inner); | |
| 12 | | ^^^^ required by this bound in `Handshake` | |
| 13 | help: consider giving `handshake` an explicit type, where the type for type parameter `R` is specified | |
| 14 | | | |
| 15 | LL | let handshake: Handshake<R> = Handshake(callback.0.clone()); | |
| 16 | | ++++++++++++++ | |
| 17 | ||
| 18 | error: aborting due to 1 previous error | |
| 19 | ||
| 20 | For more information about this error, try `rustc --explain E0283`. |