| author | bors <bors@rust-lang.org> 2026-06-02 12:44:47 UTC |
| committer | bors <bors@rust-lang.org> 2026-06-02 12:44:47 UTC |
| log | 48f976c7131e76b6a1ba6ba316c90d97ffdfe184 |
| tree | f41d5b39c18777539cb2b583be7c32d865b7f27c |
| parent | 4f84d9fac456d973d592cf3fb48db958ecf22506 |
| parent | f38205f18d1385e0f53a34f4107a71d070379a98 |
Rollup of 14 pull requests
Successful merges:
- rust-lang/rust#156467 (mark the 'import linkage' statics as unnamed_addr)
- rust-lang/rust#156923 (Couple of diagnostics improvements for EII)
- rust-lang/rust#157240 (Enable Enzyme for aarch64-apple-darwin)
- rust-lang/rust#157244 (Privacy: tweak macros + more tests)
- rust-lang/rust#157276 (miri subtree update)
- rust-lang/rust#157130 (Use a `ArrayVec` in `CastTarget`)
- rust-lang/rust#157131 (Add regression test for issue rust-lang/rust#144888)
- rust-lang/rust#157195 (Move feature gating to the new attr parsing infrastructure)
- rust-lang/rust#157233 (rustdoc: Fix trait impl ordering)
- rust-lang/rust#157256 (tests: adapt for LLVM codegen change)
- rust-lang/rust#157265 (Update books)
- rust-lang/rust#157277 (triagebot.toml: add LawnGnome to libs reviewers)
- rust-lang/rust#157291 (Clean up attribute target checking diagnostics)
- rust-lang/rust#157301 (Remove unused import from a test)219 files changed, 4733 insertions(+), 1825 deletions(-)
Cargo.lock+1| ... | ... | @@ -4756,6 +4756,7 @@ dependencies = [ |
| 4756 | 4756 | name = "rustc_target" |
| 4757 | 4757 | version = "0.0.0" |
| 4758 | 4758 | dependencies = [ |
| 4759 | "arrayvec", | |
| 4759 | 4760 | "bitflags", |
| 4760 | 4761 | "object 0.37.3", |
| 4761 | 4762 | "rustc_abi", |
compiler/rustc_ast_passes/src/feature_gate.rs+1-10| ... | ... | @@ -2,7 +2,7 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; |
| 2 | 2 | use rustc_ast::{self as ast, AttrVec, GenericBound, NodeId, PatKind, attr, token}; |
| 3 | 3 | use rustc_attr_parsing::AttributeParser; |
| 4 | 4 | use rustc_errors::msg; |
| 5 | use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features}; | |
| 5 | use rustc_feature::Features; | |
| 6 | 6 | use rustc_hir::Attribute; |
| 7 | 7 | use rustc_hir::attrs::AttributeKind; |
| 8 | 8 | use rustc_session::Session; |
| ... | ... | @@ -155,15 +155,6 @@ impl<'a> PostExpansionVisitor<'a> { |
| 155 | 155 | |
| 156 | 156 | impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { |
| 157 | 157 | fn visit_attribute(&mut self, attr: &ast::Attribute) { |
| 158 | let attr_info = attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name)); | |
| 159 | // Check feature gates for built-in attributes. | |
| 160 | if let Some(BuiltinAttribute { | |
| 161 | gate: AttributeGate::Gated { feature, message, check, notes, .. }, | |
| 162 | .. | |
| 163 | }) = attr_info | |
| 164 | { | |
| 165 | gate_alt!(self, check(self.features), *feature, attr.span, *message, *notes); | |
| 166 | } | |
| 167 | 158 | // Check unstable flavors of the `#[doc]` attribute. |
| 168 | 159 | if attr.has_name(sym::doc) { |
| 169 | 160 | for meta_item_inner in attr.meta_item_list().unwrap_or_default() { |
compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs+8-3| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | use std::iter; |
| 2 | 2 | |
| 3 | use rustc_feature::AttributeStability; | |
| 4 | ||
| 3 | 5 | use super::prelude::*; |
| 4 | 6 | use crate::session_diagnostics; |
| 5 | 7 | |
| ... | ... | @@ -16,6 +18,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser { |
| 16 | 18 | Warn(Target::Arm), |
| 17 | 19 | ]); |
| 18 | 20 | const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); |
| 21 | const STABILITY: AttributeStability = unstable!(allow_internal_unstable); | |
| 19 | 22 | |
| 20 | 23 | fn extend( |
| 21 | 24 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -32,6 +35,7 @@ impl CombineAttributeParser for UnstableFeatureBoundParser { |
| 32 | 35 | const PATH: &[rustc_span::Symbol] = &[sym::unstable_feature_bound]; |
| 33 | 36 | type Item = (Symbol, Span); |
| 34 | 37 | const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items); |
| 38 | const STABILITY: AttributeStability = unstable!(staged_api); | |
| 35 | 39 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 36 | 40 | Allow(Target::Fn), |
| 37 | 41 | Allow(Target::Impl { of_trait: true }), |
| ... | ... | @@ -43,9 +47,6 @@ impl CombineAttributeParser for UnstableFeatureBoundParser { |
| 43 | 47 | cx: &mut AcceptContext<'_, '_>, |
| 44 | 48 | args: &ArgParser, |
| 45 | 49 | ) -> impl IntoIterator<Item = Self::Item> { |
| 46 | if !cx.features().staged_api() { | |
| 47 | cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span }); | |
| 48 | } | |
| 49 | 50 | parse_unstable(cx, args, <Self as CombineAttributeParser>::PATH[0]) |
| 50 | 51 | .into_iter() |
| 51 | 52 | .zip(iter::repeat(cx.attr_span)) |
| ... | ... | @@ -65,6 +66,10 @@ impl CombineAttributeParser for RustcAllowConstFnUnstableParser { |
| 65 | 66 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 66 | 67 | ]); |
| 67 | 68 | const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); |
| 69 | const STABILITY: AttributeStability = unstable!( | |
| 70 | rustc_attrs, | |
| 71 | "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" | |
| 72 | ); | |
| 68 | 73 | |
| 69 | 74 | fn extend( |
| 70 | 75 | cx: &mut AcceptContext<'_, '_>, |
compiler/rustc_attr_parsing/src/attributes/autodiff.rs+3-1| ... | ... | @@ -2,7 +2,7 @@ use std::str::FromStr; |
| 2 | 2 | |
| 3 | 3 | use rustc_ast::LitKind; |
| 4 | 4 | use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode}; |
| 5 | use rustc_feature::{AttributeTemplate, template}; | |
| 5 | use rustc_feature::{AttributeStability, AttributeTemplate, template}; | |
| 6 | 6 | use rustc_hir::attrs::{AttributeKind, RustcAutodiff}; |
| 7 | 7 | use rustc_hir::{MethodKind, Target}; |
| 8 | 8 | use rustc_span::{Symbol, sym}; |
| ... | ... | @@ -13,6 +13,7 @@ use crate::attributes::prelude::Allow; |
| 13 | 13 | use crate::context::AcceptContext; |
| 14 | 14 | use crate::parser::{ArgParser, MetaItemOrLitParser}; |
| 15 | 15 | use crate::target_checking::AllowedTargets; |
| 16 | use crate::unstable; | |
| 16 | 17 | |
| 17 | 18 | pub(crate) struct RustcAutodiffParser; |
| 18 | 19 | |
| ... | ... | @@ -29,6 +30,7 @@ impl SingleAttributeParser for RustcAutodiffParser { |
| 29 | 30 | List: &["MODE", "WIDTH", "INPUT_ACTIVITIES", "OUTPUT_ACTIVITY"], |
| 30 | 31 | "https://doc.rust-lang.org/std/autodiff/index.html" |
| 31 | 32 | ); |
| 33 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 32 | 34 | |
| 33 | 35 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 34 | 36 | let list = match args { |
compiler/rustc_attr_parsing/src/attributes/body.rs+3| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | //! Attributes that can be found in function body. |
| 2 | 2 | |
| 3 | use rustc_feature::AttributeStability; | |
| 4 | ||
| 3 | 5 | use super::prelude::*; |
| 4 | 6 | |
| 5 | 7 | pub(crate) struct CoroutineParser; |
| ... | ... | @@ -7,5 +9,6 @@ pub(crate) struct CoroutineParser; |
| 7 | 9 | impl NoArgsAttributeParser for CoroutineParser { |
| 8 | 10 | const PATH: &[Symbol] = &[sym::coroutine]; |
| 9 | 11 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); |
| 12 | const STABILITY: AttributeStability = unstable!(coroutines); | |
| 10 | 13 | const CREATE: fn(rustc_span::Span) -> AttributeKind = |_| AttributeKind::Coroutine; |
| 11 | 14 | } |
compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs+3| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | pub(crate) struct CfiEncodingParser; |
| 3 | 5 | impl SingleAttributeParser for CfiEncodingParser { |
| ... | ... | @@ -9,6 +11,7 @@ impl SingleAttributeParser for CfiEncodingParser { |
| 9 | 11 | Allow(Target::Union), |
| 10 | 12 | ]); |
| 11 | 13 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "encoding"); |
| 14 | const STABILITY: AttributeStability = unstable!(cfi_encoding); | |
| 12 | 15 | |
| 13 | 16 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 14 | 17 | let name_value = cx.expect_name_value(args, cx.attr_span, Some(sym::cfi_encoding))?; |
compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs+18-3| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy}; |
| 2 | 3 | use rustc_session::errors::feature_err; |
| 3 | 4 | use rustc_span::edition::Edition::Edition2024; |
| ... | ... | @@ -22,6 +23,7 @@ impl SingleAttributeParser for OptimizeParser { |
| 22 | 23 | Allow(Target::Method(MethodKind::Inherent)), |
| 23 | 24 | ]); |
| 24 | 25 | const TEMPLATE: AttributeTemplate = template!(List: &["size", "speed", "none"]); |
| 26 | const STABILITY: AttributeStability = unstable!(optimize_attribute); | |
| 25 | 27 | |
| 26 | 28 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 27 | 29 | let single = cx.expect_single_element_list(args, cx.attr_span)?; |
| ... | ... | @@ -54,6 +56,7 @@ impl NoArgsAttributeParser for ColdParser { |
| 54 | 56 | Allow(Target::ForeignFn), |
| 55 | 57 | Allow(Target::Closure), |
| 56 | 58 | ]); |
| 59 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 57 | 60 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Cold; |
| 58 | 61 | } |
| 59 | 62 | |
| ... | ... | @@ -73,6 +76,7 @@ impl SingleAttributeParser for CoverageParser { |
| 73 | 76 | Allow(Target::Crate), |
| 74 | 77 | ]); |
| 75 | 78 | const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]); |
| 79 | const STABILITY: AttributeStability = unstable!(coverage_attribute); | |
| 76 | 80 | |
| 77 | 81 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 78 | 82 | let arg = cx.expect_single_element_list(args, cx.attr_span)?; |
| ... | ... | @@ -116,6 +120,7 @@ impl SingleAttributeParser for ExportNameParser { |
| 116 | 120 | Warn(Target::MacroCall), |
| 117 | 121 | ]); |
| 118 | 122 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); |
| 123 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 119 | 124 | |
| 120 | 125 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 121 | 126 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -143,6 +148,7 @@ impl SingleAttributeParser for RustcObjcClassParser { |
| 143 | 148 | const ALLOWED_TARGETS: AllowedTargets = |
| 144 | 149 | AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]); |
| 145 | 150 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "ClassName"); |
| 151 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 146 | 152 | |
| 147 | 153 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 148 | 154 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -170,6 +176,7 @@ impl SingleAttributeParser for RustcObjcSelectorParser { |
| 170 | 176 | const ALLOWED_TARGETS: AllowedTargets = |
| 171 | 177 | AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]); |
| 172 | 178 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "methodName"); |
| 179 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 173 | 180 | |
| 174 | 181 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 175 | 182 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -197,7 +204,7 @@ pub(crate) struct NakedParser { |
| 197 | 204 | |
| 198 | 205 | impl AttributeParser for NakedParser { |
| 199 | 206 | const ATTRIBUTES: AcceptMapping<Self> = |
| 200 | &[(&[sym::naked], template!(Word), |this, cx, args| { | |
| 207 | &[(&[sym::naked], template!(Word), AttributeStability::Stable, |this, cx, args| { | |
| 201 | 208 | let Some(()) = cx.expect_no_args(args) else { |
| 202 | 209 | return; |
| 203 | 210 | }; |
| ... | ... | @@ -331,6 +338,7 @@ impl NoArgsAttributeParser for TrackCallerParser { |
| 331 | 338 | Warn(Target::Field), |
| 332 | 339 | Warn(Target::MacroCall), |
| 333 | 340 | ]); |
| 341 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 334 | 342 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller; |
| 335 | 343 | } |
| 336 | 344 | |
| ... | ... | @@ -347,6 +355,7 @@ impl NoArgsAttributeParser for NoMangleParser { |
| 347 | 355 | AllowSilent(Target::Const), // Handled in the `InvalidNoMangleItems` pass |
| 348 | 356 | Error(Target::Closure), |
| 349 | 357 | ]); |
| 358 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 350 | 359 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoMangle; |
| 351 | 360 | } |
| 352 | 361 | |
| ... | ... | @@ -365,6 +374,7 @@ impl AttributeParser for UsedParser { |
| 365 | 374 | const ATTRIBUTES: AcceptMapping<Self> = &[( |
| 366 | 375 | &[sym::used], |
| 367 | 376 | template!(Word, List: &["compiler", "linker"]), |
| 377 | AttributeStability::Stable, | |
| 368 | 378 | |group: &mut Self, cx, args| { |
| 369 | 379 | let used_by = match args { |
| 370 | 380 | ArgParser::NoArgs => UsedBy::Default, |
| ... | ... | @@ -502,6 +512,7 @@ impl CombineAttributeParser for TargetFeatureParser { |
| 502 | 512 | was_forced: false, |
| 503 | 513 | }; |
| 504 | 514 | const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]); |
| 515 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 505 | 516 | |
| 506 | 517 | fn extend( |
| 507 | 518 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -541,6 +552,7 @@ impl CombineAttributeParser for ForceTargetFeatureParser { |
| 541 | 552 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 542 | 553 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 543 | 554 | ]); |
| 555 | const STABILITY: AttributeStability = unstable!(effective_target_features); | |
| 544 | 556 | |
| 545 | 557 | fn extend( |
| 546 | 558 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -554,10 +566,8 @@ pub(crate) struct SanitizeParser; |
| 554 | 566 | |
| 555 | 567 | impl SingleAttributeParser for SanitizeParser { |
| 556 | 568 | const PATH: &[Symbol] = &[sym::sanitize]; |
| 557 | ||
| 558 | 569 | // FIXME: still checked in check_attrs.rs |
| 559 | 570 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); |
| 560 | ||
| 561 | 571 | const TEMPLATE: AttributeTemplate = template!(List: &[ |
| 562 | 572 | r#"address = "on|off""#, |
| 563 | 573 | r#"kernel_address = "on|off""#, |
| ... | ... | @@ -571,6 +581,7 @@ impl SingleAttributeParser for SanitizeParser { |
| 571 | 581 | r#"thread = "on|off""#, |
| 572 | 582 | r#"realtime = "nonblocking|blocking|caller""#, |
| 573 | 583 | ]); |
| 584 | const STABILITY: AttributeStability = unstable!(sanitize); | |
| 574 | 585 | |
| 575 | 586 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 576 | 587 | let list = cx.expect_list(args, cx.attr_span)?; |
| ... | ... | @@ -667,6 +678,7 @@ impl NoArgsAttributeParser for ThreadLocalParser { |
| 667 | 678 | const PATH: &[Symbol] = &[sym::thread_local]; |
| 668 | 679 | const ALLOWED_TARGETS: AllowedTargets = |
| 669 | 680 | AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]); |
| 681 | const STABILITY: AttributeStability = unstable!(thread_local); | |
| 670 | 682 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ThreadLocal; |
| 671 | 683 | } |
| 672 | 684 | |
| ... | ... | @@ -675,6 +687,7 @@ pub(crate) struct RustcPassIndirectlyInNonRusticAbisParser; |
| 675 | 687 | impl NoArgsAttributeParser for RustcPassIndirectlyInNonRusticAbisParser { |
| 676 | 688 | const PATH: &[Symbol] = &[sym::rustc_pass_indirectly_in_non_rustic_abis]; |
| 677 | 689 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); |
| 690 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 678 | 691 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassIndirectlyInNonRusticAbis; |
| 679 | 692 | } |
| 680 | 693 | |
| ... | ... | @@ -684,6 +697,7 @@ impl NoArgsAttributeParser for RustcEiiForeignItemParser { |
| 684 | 697 | const PATH: &[Symbol] = &[sym::rustc_eii_foreign_item]; |
| 685 | 698 | const ALLOWED_TARGETS: AllowedTargets = |
| 686 | 699 | AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]); |
| 700 | const STABILITY: AttributeStability = unstable!(eii_internals); | |
| 687 | 701 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEiiForeignItem; |
| 688 | 702 | } |
| 689 | 703 | |
| ... | ... | @@ -693,6 +707,7 @@ impl SingleAttributeParser for PatchableFunctionEntryParser { |
| 693 | 707 | const PATH: &[Symbol] = &[sym::patchable_function_entry]; |
| 694 | 708 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 695 | 709 | const TEMPLATE: AttributeTemplate = template!(List: &["prefix_nops = m, entry_nops = n"]); |
| 710 | const STABILITY: AttributeStability = unstable!(patchable_function_entry); | |
| 696 | 711 | |
| 697 | 712 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 698 | 713 | let meta_item_list = cx.expect_list(args, cx.attr_span)?; |
compiler/rustc_attr_parsing/src/attributes/confusables.rs+3| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | use crate::session_diagnostics::EmptyConfusables; |
| 3 | 5 | |
| ... | ... | @@ -11,6 +13,7 @@ impl AttributeParser for ConfusablesParser { |
| 11 | 13 | const ATTRIBUTES: AcceptMapping<Self> = &[( |
| 12 | 14 | &[sym::rustc_confusables], |
| 13 | 15 | template!(List: &[r#""name1", "name2", ..."#]), |
| 16 | unstable!(rustc_attrs), | |
| 14 | 17 | |this, cx, args| { |
| 15 | 18 | let Some(list) = cx.expect_list(args, cx.attr_span) else { return }; |
| 16 | 19 |
compiler/rustc_attr_parsing/src/attributes/crate_level.rs+24-2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::{CrateType, WindowsSubsystemKind}; |
| 2 | 3 | use rustc_session::lint::builtin::UNKNOWN_CRATE_TYPES; |
| 3 | 4 | use rustc_span::Symbol; |
| ... | ... | @@ -13,6 +14,7 @@ impl SingleAttributeParser for CrateNameParser { |
| 13 | 14 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; |
| 14 | 15 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); |
| 15 | 16 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 17 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 16 | 18 | |
| 17 | 19 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 18 | 20 | let n = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -29,11 +31,10 @@ impl CombineAttributeParser for CrateTypeParser { |
| 29 | 31 | const PATH: &[Symbol] = &[sym::crate_type]; |
| 30 | 32 | type Item = CrateType; |
| 31 | 33 | const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::CrateType(items); |
| 32 | ||
| 33 | 34 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 34 | ||
| 35 | 35 | const TEMPLATE: AttributeTemplate = |
| 36 | 36 | template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html"); |
| 37 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 37 | 38 | |
| 38 | 39 | fn extend( |
| 39 | 40 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -74,6 +75,7 @@ impl SingleAttributeParser for RecursionLimitParser { |
| 74 | 75 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; |
| 75 | 76 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"); |
| 76 | 77 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 78 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 77 | 79 | |
| 78 | 80 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 79 | 81 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -88,6 +90,7 @@ impl SingleAttributeParser for MoveSizeLimitParser { |
| 88 | 90 | const PATH: &[Symbol] = &[sym::move_size_limit]; |
| 89 | 91 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); |
| 90 | 92 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 93 | const STABILITY: AttributeStability = unstable!(large_assignments); | |
| 91 | 94 | |
| 92 | 95 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 93 | 96 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -103,6 +106,7 @@ impl SingleAttributeParser for TypeLengthLimitParser { |
| 103 | 106 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; |
| 104 | 107 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); |
| 105 | 108 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 109 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 106 | 110 | |
| 107 | 111 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 108 | 112 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -117,6 +121,10 @@ impl SingleAttributeParser for PatternComplexityLimitParser { |
| 117 | 121 | const PATH: &[Symbol] = &[sym::pattern_complexity_limit]; |
| 118 | 122 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); |
| 119 | 123 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 124 | const STABILITY: AttributeStability = unstable!( | |
| 125 | rustc_attrs, | |
| 126 | "the `#[pattern_complexity_limit]` attribute is used for rustc unit tests" | |
| 127 | ); | |
| 120 | 128 | |
| 121 | 129 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 122 | 130 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -130,6 +138,7 @@ pub(crate) struct NoCoreParser; |
| 130 | 138 | impl NoArgsAttributeParser for NoCoreParser { |
| 131 | 139 | const PATH: &[Symbol] = &[sym::no_core]; |
| 132 | 140 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 141 | const STABILITY: AttributeStability = unstable!(no_core); | |
| 133 | 142 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoCore; |
| 134 | 143 | } |
| 135 | 144 | |
| ... | ... | @@ -139,6 +148,7 @@ impl NoArgsAttributeParser for NoStdParser { |
| 139 | 148 | const PATH: &[Symbol] = &[sym::no_std]; |
| 140 | 149 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; |
| 141 | 150 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 151 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 142 | 152 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoStd; |
| 143 | 153 | } |
| 144 | 154 | |
| ... | ... | @@ -148,6 +158,7 @@ impl NoArgsAttributeParser for NoMainParser { |
| 148 | 158 | const PATH: &[Symbol] = &[sym::no_main]; |
| 149 | 159 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; |
| 150 | 160 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 161 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 151 | 162 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain; |
| 152 | 163 | } |
| 153 | 164 | |
| ... | ... | @@ -156,6 +167,7 @@ pub(crate) struct RustcCoherenceIsCoreParser; |
| 156 | 167 | impl NoArgsAttributeParser for RustcCoherenceIsCoreParser { |
| 157 | 168 | const PATH: &[Symbol] = &[sym::rustc_coherence_is_core]; |
| 158 | 169 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 170 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 159 | 171 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoherenceIsCore; |
| 160 | 172 | } |
| 161 | 173 | |
| ... | ... | @@ -166,6 +178,7 @@ impl SingleAttributeParser for WindowsSubsystemParser { |
| 166 | 178 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; |
| 167 | 179 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 168 | 180 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"); |
| 181 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 169 | 182 | |
| 170 | 183 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 171 | 184 | let nv = cx.expect_name_value(args, cx.inner_span, Some(sym::windows_subsystem))?; |
| ... | ... | @@ -191,6 +204,7 @@ pub(crate) struct PanicRuntimeParser; |
| 191 | 204 | impl NoArgsAttributeParser for PanicRuntimeParser { |
| 192 | 205 | const PATH: &[Symbol] = &[sym::panic_runtime]; |
| 193 | 206 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 207 | const STABILITY: AttributeStability = unstable!(panic_runtime); | |
| 194 | 208 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime; |
| 195 | 209 | } |
| 196 | 210 | |
| ... | ... | @@ -199,6 +213,7 @@ pub(crate) struct NeedsPanicRuntimeParser; |
| 199 | 213 | impl NoArgsAttributeParser for NeedsPanicRuntimeParser { |
| 200 | 214 | const PATH: &[Symbol] = &[sym::needs_panic_runtime]; |
| 201 | 215 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 216 | const STABILITY: AttributeStability = unstable!(needs_panic_runtime); | |
| 202 | 217 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; |
| 203 | 218 | } |
| 204 | 219 | |
| ... | ... | @@ -207,6 +222,7 @@ pub(crate) struct ProfilerRuntimeParser; |
| 207 | 222 | impl NoArgsAttributeParser for ProfilerRuntimeParser { |
| 208 | 223 | const PATH: &[Symbol] = &[sym::profiler_runtime]; |
| 209 | 224 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 225 | const STABILITY: AttributeStability = unstable!(profiler_runtime); | |
| 210 | 226 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; |
| 211 | 227 | } |
| 212 | 228 | |
| ... | ... | @@ -216,6 +232,7 @@ impl NoArgsAttributeParser for NoBuiltinsParser { |
| 216 | 232 | const PATH: &[Symbol] = &[sym::no_builtins]; |
| 217 | 233 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; |
| 218 | 234 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 235 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 219 | 236 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; |
| 220 | 237 | } |
| 221 | 238 | |
| ... | ... | @@ -224,6 +241,7 @@ pub(crate) struct RustcPreserveUbChecksParser; |
| 224 | 241 | impl NoArgsAttributeParser for RustcPreserveUbChecksParser { |
| 225 | 242 | const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; |
| 226 | 243 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 244 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 227 | 245 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; |
| 228 | 246 | } |
| 229 | 247 | |
| ... | ... | @@ -232,6 +250,7 @@ pub(crate) struct RustcNoImplicitBoundsParser; |
| 232 | 250 | impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { |
| 233 | 251 | const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; |
| 234 | 252 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 253 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 235 | 254 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; |
| 236 | 255 | } |
| 237 | 256 | |
| ... | ... | @@ -240,6 +259,7 @@ pub(crate) struct DefaultLibAllocatorParser; |
| 240 | 259 | impl NoArgsAttributeParser for DefaultLibAllocatorParser { |
| 241 | 260 | const PATH: &[Symbol] = &[sym::default_lib_allocator]; |
| 242 | 261 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 262 | const STABILITY: AttributeStability = unstable!(allocator_internals); | |
| 243 | 263 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator; |
| 244 | 264 | } |
| 245 | 265 | |
| ... | ... | @@ -251,6 +271,7 @@ impl CombineAttributeParser for FeatureParser { |
| 251 | 271 | const CONVERT: ConvertFn<Self::Item> = AttributeKind::Feature; |
| 252 | 272 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 253 | 273 | const TEMPLATE: AttributeTemplate = template!(List: &["feature1, feature2, ..."]); |
| 274 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 254 | 275 | |
| 255 | 276 | fn extend( |
| 256 | 277 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -295,6 +316,7 @@ impl CombineAttributeParser for RegisterToolParser { |
| 295 | 316 | const CONVERT: ConvertFn<Self::Item> = |tools, _span| AttributeKind::RegisterTool(tools); |
| 296 | 317 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); |
| 297 | 318 | const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]); |
| 319 | const STABILITY: AttributeStability = unstable!(register_tool); | |
| 298 | 320 | |
| 299 | 321 | fn extend( |
| 300 | 322 | cx: &mut AcceptContext<'_, '_>, |
compiler/rustc_attr_parsing/src/attributes/debugger.rs+4-2| ... | ... | @@ -1,10 +1,11 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::{DebugVisualizer, DebuggerVisualizerType}; |
| 2 | 3 | |
| 3 | 4 | use super::prelude::*; |
| 4 | 5 | |
| 5 | pub(crate) struct DebuggerViualizerParser; | |
| 6 | pub(crate) struct DebuggerVisualizerParser; | |
| 6 | 7 | |
| 7 | impl CombineAttributeParser for DebuggerViualizerParser { | |
| 8 | impl CombineAttributeParser for DebuggerVisualizerParser { | |
| 8 | 9 | const PATH: &[Symbol] = &[sym::debugger_visualizer]; |
| 9 | 10 | const ALLOWED_TARGETS: AllowedTargets = |
| 10 | 11 | AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]); |
| ... | ... | @@ -12,6 +13,7 @@ impl CombineAttributeParser for DebuggerViualizerParser { |
| 12 | 13 | List: &[r#"natvis_file = "...", gdb_script_file = "...""#], |
| 13 | 14 | "https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute" |
| 14 | 15 | ); |
| 16 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 15 | 17 | |
| 16 | 18 | type Item = DebugVisualizer; |
| 17 | 19 | const CONVERT: ConvertFn<Self::Item> = |v, _| AttributeKind::DebuggerVisualizer(v); |
compiler/rustc_attr_parsing/src/attributes/deprecation.rs+2| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | use rustc_ast::LitKind; |
| 2 | use rustc_feature::AttributeStability; | |
| 2 | 3 | use rustc_hir::attrs::{DeprecatedSince, Deprecation}; |
| 3 | 4 | use rustc_hir::{RustcVersion, VERSION_PLACEHOLDER}; |
| 4 | 5 | |
| ... | ... | @@ -62,6 +63,7 @@ impl SingleAttributeParser for DeprecatedParser { |
| 62 | 63 | List: &[r#"since = "version""#, r#"note = "reason""#, r#"since = "version", note = "reason""#], |
| 63 | 64 | NameValueStr: "reason" |
| 64 | 65 | ); |
| 66 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 65 | 67 | |
| 66 | 68 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 67 | 69 | let features = cx.features(); |
compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs+2-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | use rustc_feature::{AttributeTemplate, template}; | |
| 1 | use rustc_feature::{AttributeStability, AttributeTemplate, template}; | |
| 2 | 2 | use rustc_hir::Target; |
| 3 | 3 | use rustc_hir::attrs::AttributeKind; |
| 4 | 4 | use rustc_session::lint::builtin::{ |
| ... | ... | @@ -19,6 +19,7 @@ impl SingleAttributeParser for DoNotRecommendParser { |
| 19 | 19 | // "Allowed" on any target, noop on all but trait impls |
| 20 | 20 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); |
| 21 | 21 | const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */); |
| 22 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 22 | 23 | |
| 23 | 24 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 24 | 25 | let attr_span = cx.attr_span; |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs+2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::diagnostic::Directive; |
| 2 | 3 | use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; |
| 3 | 4 | |
| ... | ... | @@ -14,6 +15,7 @@ impl AttributeParser for OnConstParser { |
| 14 | 15 | const ATTRIBUTES: AcceptMapping<Self> = &[( |
| 15 | 16 | &[sym::diagnostic, sym::on_const], |
| 16 | 17 | template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), |
| 18 | AttributeStability::Stable, // Unstable, stability checked manually in the parser | |
| 17 | 19 | |this, cx, args| { |
| 18 | 20 | if !cx.features().diagnostic_on_const() { |
| 19 | 21 | // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs+2-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | use rustc_feature::template; | |
| 1 | use rustc_feature::{AttributeStability, template}; | |
| 2 | 2 | use rustc_hir::attrs::AttributeKind; |
| 3 | 3 | use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; |
| 4 | 4 | use rustc_span::sym; |
| ... | ... | @@ -43,6 +43,7 @@ impl AttributeParser for OnMoveParser { |
| 43 | 43 | const ATTRIBUTES: AcceptMapping<Self> = &[( |
| 44 | 44 | &[sym::diagnostic, sym::on_move], |
| 45 | 45 | template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), |
| 46 | AttributeStability::Stable, // Unstable, stability checked manually in the parser | |
| 46 | 47 | |this, cx, args| { |
| 47 | 48 | this.parse(cx, args, Mode::DiagnosticOnMove); |
| 48 | 49 | }, |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs+6| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::diagnostic::Directive; |
| 2 | 3 | use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; |
| 3 | 4 | |
| ... | ... | @@ -38,6 +39,7 @@ impl AttributeParser for OnUnimplementedParser { |
| 38 | 39 | ( |
| 39 | 40 | &[sym::diagnostic, sym::on_unimplemented], |
| 40 | 41 | template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), |
| 42 | AttributeStability::Stable, | |
| 41 | 43 | |this, cx, args| { |
| 42 | 44 | this.parse(cx, args, Mode::DiagnosticOnUnimplemented); |
| 43 | 45 | }, |
| ... | ... | @@ -45,6 +47,10 @@ impl AttributeParser for OnUnimplementedParser { |
| 45 | 47 | ( |
| 46 | 48 | &[sym::rustc_on_unimplemented], |
| 47 | 49 | template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), |
| 50 | unstable!( | |
| 51 | rustc_attrs, | |
| 52 | "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute" | |
| 53 | ), | |
| 48 | 54 | |this, cx, args| { |
| 49 | 55 | this.parse(cx, args, Mode::RustcOnUnimplemented); |
| 50 | 56 | }, |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs+2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::diagnostic::Directive; |
| 2 | 3 | use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; |
| 3 | 4 | |
| ... | ... | @@ -50,6 +51,7 @@ impl AttributeParser for OnUnknownParser { |
| 50 | 51 | const ATTRIBUTES: AcceptMapping<Self> = &[( |
| 51 | 52 | &[sym::diagnostic, sym::on_unknown], |
| 52 | 53 | template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), |
| 54 | AttributeStability::Stable, // Unstable, stability checked manually in the parser | |
| 53 | 55 | |this, cx, args| { |
| 54 | 56 | this.parse(cx, args, Mode::DiagnosticOnUnknown); |
| 55 | 57 | }, |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatch_args.rs+2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::diagnostic::Directive; |
| 2 | 3 | use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; |
| 3 | 4 | |
| ... | ... | @@ -15,6 +16,7 @@ impl AttributeParser for OnUnmatchArgsParser { |
| 15 | 16 | const ATTRIBUTES: AcceptMapping<Self> = &[( |
| 16 | 17 | &[sym::diagnostic, sym::on_unmatch_args], |
| 17 | 18 | template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), |
| 19 | AttributeStability::Stable, // Unstable, stability checked manually in the parser | |
| 18 | 20 | |this, cx, args| { |
| 19 | 21 | if !cx.features().diagnostic_on_unmatch_args() { |
| 20 | 22 | return; |
compiler/rustc_attr_parsing/src/attributes/doc.rs+3-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit}; |
| 2 | 2 | use rustc_errors::{Applicability, msg}; |
| 3 | use rustc_feature::template; | |
| 3 | use rustc_feature::{AttributeStability, template}; | |
| 4 | 4 | use rustc_hir::Target; |
| 5 | 5 | use rustc_hir::attrs::{ |
| 6 | 6 | AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow, |
| ... | ... | @@ -41,7 +41,7 @@ fn check_keyword(cx: &mut AcceptContext<'_, '_>, keyword: Symbol, span: Span) -> |
| 41 | 41 | |
| 42 | 42 | fn check_attribute(cx: &mut AcceptContext<'_, '_>, attribute: Symbol, span: Span) -> bool { |
| 43 | 43 | // FIXME: This should support attributes with namespace like `diagnostic::do_not_recommend`. |
| 44 | if rustc_feature::BUILTIN_ATTRIBUTE_MAP.contains_key(&attribute) { | |
| 44 | if rustc_feature::BUILTIN_ATTRIBUTE_MAP.contains(&attribute) { | |
| 45 | 45 | return true; |
| 46 | 46 | } |
| 47 | 47 | cx.emit_err(DocAttributeNotAttribute { span, attribute }); |
| ... | ... | @@ -704,6 +704,7 @@ impl AttributeParser for DocParser { |
| 704 | 704 | ], |
| 705 | 705 | NameValueStr: "string" |
| 706 | 706 | ), |
| 707 | AttributeStability::Stable, // Some parts of the attribute are unstable, manually checked in parser | |
| 707 | 708 | |this, cx, args| { |
| 708 | 709 | this.accept_single_doc_attr(cx, args); |
| 709 | 710 | }, |
compiler/rustc_attr_parsing/src/attributes/dummy.rs+4-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | use rustc_feature::{AttributeTemplate, template}; | |
| 1 | use rustc_feature::{AttributeStability, AttributeTemplate, template}; | |
| 2 | 2 | use rustc_hir::attrs::AttributeKind; |
| 3 | 3 | use rustc_span::{Symbol, sym}; |
| 4 | 4 | |
| ... | ... | @@ -6,6 +6,7 @@ use crate::attributes::{OnDuplicate, SingleAttributeParser}; |
| 6 | 6 | use crate::context::AcceptContext; |
| 7 | 7 | use crate::parser::ArgParser; |
| 8 | 8 | use crate::target_checking::{ALL_TARGETS, AllowedTargets}; |
| 9 | use crate::unstable; | |
| 9 | 10 | |
| 10 | 11 | pub(crate) struct RustcDummyParser; |
| 11 | 12 | impl SingleAttributeParser for RustcDummyParser { |
| ... | ... | @@ -13,6 +14,8 @@ impl SingleAttributeParser for RustcDummyParser { |
| 13 | 14 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; |
| 14 | 15 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); |
| 15 | 16 | const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really |
| 17 | const STABILITY: AttributeStability = | |
| 18 | unstable!(rustc_attrs, "the `#[rustc_dummy]` attribute is used for rustc unit tests"); | |
| 16 | 19 | |
| 17 | 20 | fn convert(_: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 18 | 21 | args.ignore_args(); |
compiler/rustc_attr_parsing/src/attributes/inline.rs+4-1| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | // note: need to model better how duplicate attr errors work when not using |
| 3 | 3 | // SingleAttributeParser which is what we have two of here. |
| 4 | 4 | |
| 5 | use rustc_feature::AttributeStability; | |
| 5 | 6 | use rustc_hir::attrs::{AttributeKind, InlineAttr}; |
| 6 | 7 | use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; |
| 7 | 8 | |
| ... | ... | @@ -32,6 +33,7 @@ impl SingleAttributeParser for InlineParser { |
| 32 | 33 | List: &["always", "never"], |
| 33 | 34 | "https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute" |
| 34 | 35 | ); |
| 36 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 35 | 37 | |
| 36 | 38 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 37 | 39 | match args { |
| ... | ... | @@ -68,7 +70,8 @@ impl SingleAttributeParser for RustcForceInlineParser { |
| 68 | 70 | Allow(Target::Fn), |
| 69 | 71 | Allow(Target::Method(MethodKind::Inherent)), |
| 70 | 72 | ]); |
| 71 | ||
| 73 | const STABILITY: AttributeStability = | |
| 74 | unstable!(rustc_attrs, "`#[rustc_force_inline]` forces a free function to be inlined"); | |
| 72 | 75 | const TEMPLATE: AttributeTemplate = template!(Word, List: &["reason"], NameValueStr: "reason"); |
| 73 | 76 | |
| 74 | 77 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
compiler/rustc_attr_parsing/src/attributes/instruction_set.rs+2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::InstructionSetAttr; |
| 2 | 3 | |
| 3 | 4 | use super::prelude::*; |
| ... | ... | @@ -15,6 +16,7 @@ impl SingleAttributeParser for InstructionSetParser { |
| 15 | 16 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 16 | 17 | ]); |
| 17 | 18 | const TEMPLATE: AttributeTemplate = template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"); |
| 19 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 18 | 20 | |
| 19 | 21 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 20 | 22 | const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32]; |
compiler/rustc_attr_parsing/src/attributes/link_attrs.rs+12-3| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | use rustc_errors::msg; |
| 2 | use rustc_feature::Features; | |
| 2 | use rustc_feature::{AttributeStability, Features}; | |
| 3 | 3 | use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; |
| 4 | 4 | use rustc_hir::attrs::*; |
| 5 | 5 | use rustc_session::Session; |
| ... | ... | @@ -34,6 +34,7 @@ impl SingleAttributeParser for LinkNameParser { |
| 34 | 34 | NameValueStr: "name", |
| 35 | 35 | "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute" |
| 36 | 36 | ); |
| 37 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 37 | 38 | |
| 38 | 39 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 39 | 40 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -70,6 +71,7 @@ impl CombineAttributeParser for LinkParser { |
| 70 | 71 | r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#, |
| 71 | 72 | ], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute"); |
| 72 | 73 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` |
| 74 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 73 | 75 | |
| 74 | 76 | fn extend( |
| 75 | 77 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -487,6 +489,7 @@ impl SingleAttributeParser for LinkSectionParser { |
| 487 | 489 | const PATH: &[Symbol] = &[sym::link_section]; |
| 488 | 490 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; |
| 489 | 491 | const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; |
| 492 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 490 | 493 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ |
| 491 | 494 | Allow(Target::Static), |
| 492 | 495 | Allow(Target::Fn), |
| ... | ... | @@ -529,6 +532,7 @@ pub(crate) struct ExportStableParser; |
| 529 | 532 | impl NoArgsAttributeParser for ExportStableParser { |
| 530 | 533 | const PATH: &[Symbol] = &[sym::export_stable]; |
| 531 | 534 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` |
| 535 | const STABILITY: AttributeStability = unstable!(export_stable); | |
| 532 | 536 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable; |
| 533 | 537 | } |
| 534 | 538 | |
| ... | ... | @@ -537,6 +541,7 @@ impl NoArgsAttributeParser for FfiConstParser { |
| 537 | 541 | const PATH: &[Symbol] = &[sym::ffi_const]; |
| 538 | 542 | const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; |
| 539 | 543 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); |
| 544 | const STABILITY: AttributeStability = unstable!(ffi_const); | |
| 540 | 545 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::FfiConst; |
| 541 | 546 | } |
| 542 | 547 | |
| ... | ... | @@ -545,6 +550,7 @@ impl NoArgsAttributeParser for FfiPureParser { |
| 545 | 550 | const PATH: &[Symbol] = &[sym::ffi_pure]; |
| 546 | 551 | const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; |
| 547 | 552 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); |
| 553 | const STABILITY: AttributeStability = unstable!(ffi_pure); | |
| 548 | 554 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; |
| 549 | 555 | } |
| 550 | 556 | |
| ... | ... | @@ -557,6 +563,7 @@ impl NoArgsAttributeParser for RustcStdInternalSymbolParser { |
| 557 | 563 | Allow(Target::Static), |
| 558 | 564 | Allow(Target::ForeignStatic), |
| 559 | 565 | ]); |
| 566 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 560 | 567 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcStdInternalSymbol; |
| 561 | 568 | } |
| 562 | 569 | |
| ... | ... | @@ -573,6 +580,7 @@ impl SingleAttributeParser for LinkOrdinalParser { |
| 573 | 580 | List: &["ordinal"], |
| 574 | 581 | "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute" |
| 575 | 582 | ); |
| 583 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 576 | 584 | |
| 577 | 585 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 578 | 586 | let ordinal = parse_single_integer(cx, args)?; |
| ... | ... | @@ -603,7 +611,6 @@ pub(crate) struct LinkageParser; |
| 603 | 611 | |
| 604 | 612 | impl SingleAttributeParser for LinkageParser { |
| 605 | 613 | const PATH: &[Symbol] = &[sym::linkage]; |
| 606 | ||
| 607 | 614 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 608 | 615 | Allow(Target::Fn), |
| 609 | 616 | Allow(Target::Method(MethodKind::Inherent)), |
| ... | ... | @@ -614,7 +621,6 @@ impl SingleAttributeParser for LinkageParser { |
| 614 | 621 | Allow(Target::ForeignFn), |
| 615 | 622 | Warn(Target::Method(MethodKind::Trait { body: false })), // Not inherited |
| 616 | 623 | ]); |
| 617 | ||
| 618 | 624 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: [ |
| 619 | 625 | "available_externally", |
| 620 | 626 | "common", |
| ... | ... | @@ -626,6 +632,7 @@ impl SingleAttributeParser for LinkageParser { |
| 626 | 632 | "weak", |
| 627 | 633 | "weak_odr", |
| 628 | 634 | ]); |
| 635 | const STABILITY: AttributeStability = unstable!(linkage); | |
| 629 | 636 | |
| 630 | 637 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 631 | 638 | let name_value = cx.expect_name_value(args, cx.attr_span, Some(sym::linkage))?; |
| ... | ... | @@ -681,6 +688,7 @@ pub(crate) struct NeedsAllocatorParser; |
| 681 | 688 | impl NoArgsAttributeParser for NeedsAllocatorParser { |
| 682 | 689 | const PATH: &[Symbol] = &[sym::needs_allocator]; |
| 683 | 690 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 691 | const STABILITY: AttributeStability = unstable!(allocator_internals); | |
| 684 | 692 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; |
| 685 | 693 | } |
| 686 | 694 | |
| ... | ... | @@ -689,5 +697,6 @@ pub(crate) struct CompilerBuiltinsParser; |
| 689 | 697 | impl NoArgsAttributeParser for CompilerBuiltinsParser { |
| 690 | 698 | const PATH: &[Symbol] = &[sym::compiler_builtins]; |
| 691 | 699 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 700 | const STABILITY: AttributeStability = unstable!(compiler_builtins); | |
| 692 | 701 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CompilerBuiltins; |
| 693 | 702 | } |
compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs+7| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct RustcAsPtrParser; |
| ... | ... | @@ -10,6 +12,7 @@ impl NoArgsAttributeParser for RustcAsPtrParser { |
| 10 | 12 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 11 | 13 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 12 | 14 | ]); |
| 15 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 13 | 16 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAsPtr; |
| 14 | 17 | } |
| 15 | 18 | |
| ... | ... | @@ -21,6 +24,7 @@ impl NoArgsAttributeParser for RustcPubTransparentParser { |
| 21 | 24 | Allow(Target::Enum), |
| 22 | 25 | Allow(Target::Union), |
| 23 | 26 | ]); |
| 27 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 24 | 28 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent; |
| 25 | 29 | } |
| 26 | 30 | |
| ... | ... | @@ -32,6 +36,7 @@ impl NoArgsAttributeParser for RustcPassByValueParser { |
| 32 | 36 | Allow(Target::Enum), |
| 33 | 37 | Allow(Target::TyAlias), |
| 34 | 38 | ]); |
| 39 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 35 | 40 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPassByValue; |
| 36 | 41 | } |
| 37 | 42 | |
| ... | ... | @@ -42,6 +47,7 @@ impl NoArgsAttributeParser for RustcShouldNotBeCalledOnConstItemsParser { |
| 42 | 47 | Allow(Target::Method(MethodKind::Inherent)), |
| 43 | 48 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 44 | 49 | ]); |
| 50 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 45 | 51 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcShouldNotBeCalledOnConstItems; |
| 46 | 52 | } |
| 47 | 53 | |
| ... | ... | @@ -54,5 +60,6 @@ impl NoArgsAttributeParser for AutomaticallyDerivedParser { |
| 54 | 60 | Error(Target::Crate), |
| 55 | 61 | Error(Target::WherePredicate), |
| 56 | 62 | ]); |
| 63 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 57 | 64 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::AutomaticallyDerived; |
| 58 | 65 | } |
compiler/rustc_attr_parsing/src/attributes/loop_match.rs+4| ... | ... | @@ -1,9 +1,12 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct LoopMatchParser; |
| 4 | 6 | impl NoArgsAttributeParser for LoopMatchParser { |
| 5 | 7 | const PATH: &[Symbol] = &[sym::loop_match]; |
| 6 | 8 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]); |
| 9 | const STABILITY: AttributeStability = unstable!(loop_match); | |
| 7 | 10 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::LoopMatch; |
| 8 | 11 | } |
| 9 | 12 | |
| ... | ... | @@ -11,5 +14,6 @@ pub(crate) struct ConstContinueParser; |
| 11 | 14 | impl NoArgsAttributeParser for ConstContinueParser { |
| 12 | 15 | const PATH: &[Symbol] = &[sym::const_continue]; |
| 13 | 16 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]); |
| 17 | const STABILITY: AttributeStability = unstable!(loop_match); | |
| 14 | 18 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstContinue; |
| 15 | 19 | } |
compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs+7| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::{CollapseMacroDebuginfo, MacroUseArgs}; |
| 2 | 3 | use rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS; |
| 3 | 4 | |
| ... | ... | @@ -8,6 +9,7 @@ impl NoArgsAttributeParser for MacroEscapeParser { |
| 8 | 9 | const PATH: &[Symbol] = &[sym::macro_escape]; |
| 9 | 10 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; |
| 10 | 11 | const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS; |
| 12 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 11 | 13 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::MacroEscape; |
| 12 | 14 | } |
| 13 | 15 | |
| ... | ... | @@ -41,6 +43,7 @@ impl AttributeParser for MacroUseParser { |
| 41 | 43 | const ATTRIBUTES: AcceptMapping<Self> = &[( |
| 42 | 44 | &[sym::macro_use], |
| 43 | 45 | MACRO_USE_TEMPLATE, |
| 46 | AttributeStability::Stable, | |
| 44 | 47 | |group: &mut Self, cx: &mut AcceptContext<'_, '_>, args| { |
| 45 | 48 | let span = cx.attr_span; |
| 46 | 49 | group.first_span.get_or_insert(span); |
| ... | ... | @@ -122,6 +125,7 @@ impl NoArgsAttributeParser for AllowInternalUnsafeParser { |
| 122 | 125 | Warn(Target::Field), |
| 123 | 126 | Warn(Target::Arm), |
| 124 | 127 | ]); |
| 128 | const STABILITY: AttributeStability = unstable!(allow_internal_unsafe); | |
| 125 | 129 | const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); |
| 126 | 130 | } |
| 127 | 131 | |
| ... | ... | @@ -136,6 +140,7 @@ impl SingleAttributeParser for MacroExportParser { |
| 136 | 140 | Error(Target::WherePredicate), |
| 137 | 141 | Error(Target::Crate), |
| 138 | 142 | ]); |
| 143 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 139 | 144 | |
| 140 | 145 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 141 | 146 | let local_inner_macros = match args { |
| ... | ... | @@ -171,6 +176,7 @@ impl SingleAttributeParser for CollapseDebugInfoParser { |
| 171 | 176 | "https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute" |
| 172 | 177 | ); |
| 173 | 178 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); |
| 179 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 174 | 180 | |
| 175 | 181 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 176 | 182 | let single = cx.expect_single_element_list(args, cx.attr_span)?; |
| ... | ... | @@ -200,5 +206,6 @@ pub(crate) struct RustcProcMacroDeclsParser; |
| 200 | 206 | impl NoArgsAttributeParser for RustcProcMacroDeclsParser { |
| 201 | 207 | const PATH: &[Symbol] = &[sym::rustc_proc_macro_decls]; |
| 202 | 208 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]); |
| 209 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 203 | 210 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcProcMacroDecls; |
| 204 | 211 | } |
compiler/rustc_attr_parsing/src/attributes/mod.rs+15-6| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | |
| 17 | 17 | use std::marker::PhantomData; |
| 18 | 18 | |
| 19 | use rustc_feature::{AttributeTemplate, template}; | |
| 19 | use rustc_feature::{AttributeStability, AttributeTemplate, template}; | |
| 20 | 20 | use rustc_hir::attrs::AttributeKind; |
| 21 | 21 | use rustc_span::edition::Edition; |
| 22 | 22 | use rustc_span::{Span, Symbol}; |
| ... | ... | @@ -71,7 +71,8 @@ pub(crate) mod transparency; |
| 71 | 71 | pub(crate) mod util; |
| 72 | 72 | |
| 73 | 73 | type AcceptFn<T> = for<'sess> fn(&mut T, &mut AcceptContext<'_, 'sess>, &ArgParser); |
| 74 | type AcceptMapping<T> = &'static [(&'static [Symbol], AttributeTemplate, AcceptFn<T>)]; | |
| 74 | type AcceptMapping<T> = | |
| 75 | &'static [(&'static [Symbol], AttributeTemplate, AttributeStability, AcceptFn<T>)]; | |
| 75 | 76 | |
| 76 | 77 | /// An [`AttributeParser`] is a type which searches for syntactic attributes. |
| 77 | 78 | /// |
| ... | ... | @@ -130,6 +131,7 @@ pub(crate) trait SingleAttributeParser: 'static { |
| 130 | 131 | /// applied more than once on the same syntax node. |
| 131 | 132 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; |
| 132 | 133 | const SAFETY: AttributeSafety = AttributeSafety::Normal; |
| 134 | const STABILITY: AttributeStability; | |
| 133 | 135 | |
| 134 | 136 | const ALLOWED_TARGETS: AllowedTargets; |
| 135 | 137 | |
| ... | ... | @@ -151,8 +153,11 @@ impl<T: SingleAttributeParser> Default for Single<T> { |
| 151 | 153 | } |
| 152 | 154 | |
| 153 | 155 | impl<T: SingleAttributeParser> AttributeParser for Single<T> { |
| 154 | const ATTRIBUTES: AcceptMapping<Self> = | |
| 155 | &[(T::PATH, <T as SingleAttributeParser>::TEMPLATE, |group: &mut Single<T>, cx, args| { | |
| 156 | const ATTRIBUTES: AcceptMapping<Self> = &[( | |
| 157 | T::PATH, | |
| 158 | <T as SingleAttributeParser>::TEMPLATE, | |
| 159 | T::STABILITY, | |
| 160 | |group: &mut Single<T>, cx, args| { | |
| 156 | 161 | if let Some(pa) = T::convert(cx, args) { |
| 157 | 162 | if let Some((_, used)) = group.1 { |
| 158 | 163 | T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span); |
| ... | ... | @@ -160,7 +165,8 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> { |
| 160 | 165 | group.1 = Some((pa, cx.attr_span)); |
| 161 | 166 | } |
| 162 | 167 | } |
| 163 | })]; | |
| 168 | }, | |
| 169 | )]; | |
| 164 | 170 | const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; |
| 165 | 171 | const SAFETY: AttributeSafety = T::SAFETY; |
| 166 | 172 | |
| ... | ... | @@ -237,6 +243,7 @@ pub(crate) trait NoArgsAttributeParser: 'static { |
| 237 | 243 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; |
| 238 | 244 | const ALLOWED_TARGETS: AllowedTargets; |
| 239 | 245 | const SAFETY: AttributeSafety = AttributeSafety::Normal; |
| 246 | const STABILITY: AttributeStability; | |
| 240 | 247 | |
| 241 | 248 | /// Create the [`AttributeKind`] given attribute's [`Span`]. |
| 242 | 249 | const CREATE: fn(Span) -> AttributeKind; |
| ... | ... | @@ -254,6 +261,7 @@ impl<T: NoArgsAttributeParser> SingleAttributeParser for WithoutArgs<T> { |
| 254 | 261 | const PATH: &[Symbol] = T::PATH; |
| 255 | 262 | const ON_DUPLICATE: OnDuplicate = T::ON_DUPLICATE; |
| 256 | 263 | const SAFETY: AttributeSafety = T::SAFETY; |
| 264 | const STABILITY: AttributeStability = T::STABILITY; | |
| 257 | 265 | const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; |
| 258 | 266 | const TEMPLATE: AttributeTemplate = template!(Word); |
| 259 | 267 | |
| ... | ... | @@ -282,6 +290,7 @@ pub(crate) trait CombineAttributeParser: 'static { |
| 282 | 290 | /// where `x` is a vec of these individual reprs. |
| 283 | 291 | const CONVERT: ConvertFn<Self::Item>; |
| 284 | 292 | const SAFETY: AttributeSafety = AttributeSafety::Normal; |
| 293 | const STABILITY: AttributeStability; | |
| 285 | 294 | |
| 286 | 295 | const ALLOWED_TARGETS: AllowedTargets; |
| 287 | 296 | |
| ... | ... | @@ -317,7 +326,7 @@ impl<T: CombineAttributeParser> Default for Combine<T> { |
| 317 | 326 | |
| 318 | 327 | impl<T: CombineAttributeParser> AttributeParser for Combine<T> { |
| 319 | 328 | const ATTRIBUTES: AcceptMapping<Self> = |
| 320 | &[(T::PATH, T::TEMPLATE, |group: &mut Combine<T>, cx, args| { | |
| 329 | &[(T::PATH, T::TEMPLATE, T::STABILITY, |group: &mut Combine<T>, cx, args| { | |
| 321 | 330 | // Keep track of the span of the first attribute, for diagnostics |
| 322 | 331 | group.first_span.get_or_insert(cx.attr_span); |
| 323 | 332 | group.items.extend(T::extend(cx, args)) |
compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs+3| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct MustNotSuspendParser; |
| ... | ... | @@ -11,6 +13,7 @@ impl SingleAttributeParser for MustNotSuspendParser { |
| 11 | 13 | Allow(Target::Trait), |
| 12 | 14 | ]); |
| 13 | 15 | const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]); |
| 16 | const STABILITY: AttributeStability = unstable!(must_not_suspend); | |
| 14 | 17 | |
| 15 | 18 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 16 | 19 | let reason = match args { |
compiler/rustc_attr_parsing/src/attributes/must_use.rs+3| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct MustUseParser; |
| ... | ... | @@ -24,6 +26,7 @@ impl SingleAttributeParser for MustUseParser { |
| 24 | 26 | Word, NameValueStr: "reason", |
| 25 | 27 | "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute" |
| 26 | 28 | ); |
| 29 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 27 | 30 | |
| 28 | 31 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 29 | 32 | Some(AttributeKind::MustUse { |
compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs+3| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct NoImplicitPreludeParser; |
| ... | ... | @@ -7,5 +9,6 @@ impl NoArgsAttributeParser for NoImplicitPreludeParser { |
| 7 | 9 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; |
| 8 | 10 | const ALLOWED_TARGETS: AllowedTargets = |
| 9 | 11 | AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Allow(Target::Crate)]); |
| 12 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 10 | 13 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoImplicitPrelude; |
| 11 | 14 | } |
compiler/rustc_attr_parsing/src/attributes/no_link.rs+3| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct NoLinkParser; |
| ... | ... | @@ -10,5 +12,6 @@ impl NoArgsAttributeParser for NoLinkParser { |
| 10 | 12 | Warn(Target::Arm), |
| 11 | 13 | Warn(Target::MacroDef), |
| 12 | 14 | ]); |
| 15 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 13 | 16 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoLink; |
| 14 | 17 | } |
compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs+2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::Target; |
| 2 | 3 | use rustc_hir::attrs::AttributeKind; |
| 3 | 4 | use rustc_span::{Span, Symbol, sym}; |
| ... | ... | @@ -20,5 +21,6 @@ impl NoArgsAttributeParser for NonExhaustiveParser { |
| 20 | 21 | Warn(Target::MacroDef), |
| 21 | 22 | Warn(Target::MacroCall), |
| 22 | 23 | ]); |
| 24 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 23 | 25 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive; |
| 24 | 26 | } |
compiler/rustc_attr_parsing/src/attributes/path.rs+3| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct PathParser; |
| ... | ... | @@ -11,6 +13,7 @@ impl SingleAttributeParser for PathParser { |
| 11 | 13 | NameValueStr: "file", |
| 12 | 14 | "https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute" |
| 13 | 15 | ); |
| 16 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 14 | 17 | |
| 15 | 18 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 16 | 19 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
compiler/rustc_attr_parsing/src/attributes/pin_v2.rs+3| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::Target; |
| 2 | 3 | use rustc_hir::attrs::AttributeKind; |
| 3 | 4 | use rustc_span::{Span, Symbol, sym}; |
| ... | ... | @@ -5,6 +6,7 @@ use rustc_span::{Span, Symbol, sym}; |
| 5 | 6 | use crate::attributes::NoArgsAttributeParser; |
| 6 | 7 | use crate::target_checking::AllowedTargets; |
| 7 | 8 | use crate::target_checking::Policy::Allow; |
| 9 | use crate::unstable; | |
| 8 | 10 | |
| 9 | 11 | pub(crate) struct PinV2Parser; |
| 10 | 12 | |
| ... | ... | @@ -15,5 +17,6 @@ impl NoArgsAttributeParser for PinV2Parser { |
| 15 | 17 | Allow(Target::Struct), |
| 16 | 18 | Allow(Target::Union), |
| 17 | 19 | ]); |
| 20 | const STABILITY: AttributeStability = unstable!(pin_ergonomics); | |
| 18 | 21 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::PinV2; |
| 19 | 22 | } |
compiler/rustc_attr_parsing/src/attributes/prelude.rs+2| ... | ... | @@ -25,3 +25,5 @@ pub(super) use crate::parser::*; |
| 25 | 25 | pub(super) use crate::target_checking::Policy::{Allow, Error, Warn}; |
| 26 | 26 | #[doc(hidden)] |
| 27 | 27 | pub(super) use crate::target_checking::{ALL_TARGETS, AllowedTargets}; |
| 28 | #[doc(hidden)] | |
| 29 | pub(super) use crate::unstable; |
compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs+5| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_session::lint::builtin::AMBIGUOUS_DERIVE_HELPERS; |
| 2 | 3 | |
| 3 | 4 | use super::prelude::*; |
| ... | ... | @@ -9,6 +10,7 @@ pub(crate) struct ProcMacroParser; |
| 9 | 10 | impl NoArgsAttributeParser for ProcMacroParser { |
| 10 | 11 | const PATH: &[Symbol] = &[sym::proc_macro]; |
| 11 | 12 | const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS; |
| 13 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 12 | 14 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProcMacro; |
| 13 | 15 | } |
| 14 | 16 | |
| ... | ... | @@ -16,6 +18,7 @@ pub(crate) struct ProcMacroAttributeParser; |
| 16 | 18 | impl NoArgsAttributeParser for ProcMacroAttributeParser { |
| 17 | 19 | const PATH: &[Symbol] = &[sym::proc_macro_attribute]; |
| 18 | 20 | const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS; |
| 21 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 19 | 22 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProcMacroAttribute; |
| 20 | 23 | } |
| 21 | 24 | |
| ... | ... | @@ -27,6 +30,7 @@ impl SingleAttributeParser for ProcMacroDeriveParser { |
| 27 | 30 | List: &["TraitName", "TraitName, attributes(name1, name2, ...)"], |
| 28 | 31 | "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros" |
| 29 | 32 | ); |
| 33 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 30 | 34 | |
| 31 | 35 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 32 | 36 | let (trait_name, helper_attrs) = parse_derive_like(cx, args, true)?; |
| ... | ... | @@ -43,6 +47,7 @@ impl SingleAttributeParser for RustcBuiltinMacroParser { |
| 43 | 47 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); |
| 44 | 48 | const TEMPLATE: AttributeTemplate = |
| 45 | 49 | template!(List: &["TraitName", "TraitName, attributes(name1, name2, ...)"]); |
| 50 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 46 | 51 | |
| 47 | 52 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 48 | 53 | let (builtin_name, helper_attrs) = parse_derive_like(cx, args, false)?; |
compiler/rustc_attr_parsing/src/attributes/prototype.rs+3-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //! Attributes that are only used on function prototypes. |
| 2 | 2 | |
| 3 | use rustc_feature::{AttributeTemplate, template}; | |
| 3 | use rustc_feature::{AttributeStability, AttributeTemplate, template}; | |
| 4 | 4 | use rustc_hir::Target; |
| 5 | 5 | use rustc_hir::attrs::{AttributeKind, MirDialect, MirPhase}; |
| 6 | 6 | use rustc_span::{Span, Symbol, sym}; |
| ... | ... | @@ -8,14 +8,15 @@ use rustc_span::{Span, Symbol, sym}; |
| 8 | 8 | use crate::attributes::SingleAttributeParser; |
| 9 | 9 | use crate::context::AcceptContext; |
| 10 | 10 | use crate::parser::{ArgParser, NameValueParser}; |
| 11 | use crate::session_diagnostics; | |
| 12 | 11 | use crate::target_checking::AllowedTargets; |
| 13 | 12 | use crate::target_checking::Policy::Allow; |
| 13 | use crate::{session_diagnostics, unstable}; | |
| 14 | 14 | |
| 15 | 15 | pub(crate) struct CustomMirParser; |
| 16 | 16 | |
| 17 | 17 | impl SingleAttributeParser for CustomMirParser { |
| 18 | 18 | const PATH: &[rustc_span::Symbol] = &[sym::custom_mir]; |
| 19 | const STABILITY: AttributeStability = unstable!(custom_mir); | |
| 19 | 20 | |
| 20 | 21 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 21 | 22 |
compiler/rustc_attr_parsing/src/attributes/repr.rs+6-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | use rustc_abi::{Align, Size}; |
| 2 | 2 | use rustc_ast::{IntTy, LitIntType, LitKind, UintTy}; |
| 3 | use rustc_feature::AttributeStability; | |
| 3 | 4 | use rustc_hir::attrs::IntType::{SignedInt, UnsignedInt}; |
| 4 | 5 | use rustc_hir::attrs::ReprAttr; |
| 5 | 6 | |
| ... | ... | @@ -55,6 +56,7 @@ impl CombineAttributeParser for ReprParser { |
| 55 | 56 | //FIXME Still checked fully in `check_attr.rs` |
| 56 | 57 | //This one is slightly more complicated because the allowed targets depend on the arguments |
| 57 | 58 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); |
| 59 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 58 | 60 | } |
| 59 | 61 | |
| 60 | 62 | fn parse_repr(cx: &mut AcceptContext<'_, '_>, param: &MetaItemParser) -> Option<ReprAttr> { |
| ... | ... | @@ -223,7 +225,8 @@ impl RustcAlignParser { |
| 223 | 225 | } |
| 224 | 226 | |
| 225 | 227 | impl AttributeParser for RustcAlignParser { |
| 226 | const ATTRIBUTES: AcceptMapping<Self> = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; | |
| 228 | const ATTRIBUTES: AcceptMapping<Self> = | |
| 229 | &[(Self::PATH, Self::TEMPLATE, unstable!(fn_align), Self::parse)]; | |
| 227 | 230 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 228 | 231 | Allow(Target::Fn), |
| 229 | 232 | Allow(Target::Method(MethodKind::Inherent)), |
| ... | ... | @@ -252,7 +255,8 @@ impl RustcAlignStaticParser { |
| 252 | 255 | } |
| 253 | 256 | |
| 254 | 257 | impl AttributeParser for RustcAlignStaticParser { |
| 255 | const ATTRIBUTES: AcceptMapping<Self> = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; | |
| 258 | const ATTRIBUTES: AcceptMapping<Self> = | |
| 259 | &[(Self::PATH, Self::TEMPLATE, unstable!(static_align), Self::parse)]; | |
| 256 | 260 | const ALLOWED_TARGETS: AllowedTargets = |
| 257 | 261 | AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]); |
| 258 | 262 |
compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs+7| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct RustcAllocatorParser; |
| ... | ... | @@ -6,6 +8,7 @@ impl NoArgsAttributeParser for RustcAllocatorParser { |
| 6 | 8 | const PATH: &[Symbol] = &[sym::rustc_allocator]; |
| 7 | 9 | const ALLOWED_TARGETS: AllowedTargets = |
| 8 | 10 | AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); |
| 11 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 9 | 12 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocator; |
| 10 | 13 | } |
| 11 | 14 | |
| ... | ... | @@ -15,6 +18,7 @@ impl NoArgsAttributeParser for RustcAllocatorZeroedParser { |
| 15 | 18 | const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed]; |
| 16 | 19 | const ALLOWED_TARGETS: AllowedTargets = |
| 17 | 20 | AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); |
| 21 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 18 | 22 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocatorZeroed; |
| 19 | 23 | } |
| 20 | 24 | |
| ... | ... | @@ -25,6 +29,7 @@ impl SingleAttributeParser for RustcAllocatorZeroedVariantParser { |
| 25 | 29 | const ALLOWED_TARGETS: AllowedTargets = |
| 26 | 30 | AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); |
| 27 | 31 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "function"); |
| 32 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 28 | 33 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 29 | 34 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| 30 | 35 | let name = cx.expect_string_literal(nv)?; |
| ... | ... | @@ -39,6 +44,7 @@ impl NoArgsAttributeParser for RustcDeallocatorParser { |
| 39 | 44 | const PATH: &[Symbol] = &[sym::rustc_deallocator]; |
| 40 | 45 | const ALLOWED_TARGETS: AllowedTargets = |
| 41 | 46 | AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); |
| 47 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 42 | 48 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDeallocator; |
| 43 | 49 | } |
| 44 | 50 | |
| ... | ... | @@ -48,5 +54,6 @@ impl NoArgsAttributeParser for RustcReallocatorParser { |
| 48 | 54 | const PATH: &[Symbol] = &[sym::rustc_reallocator]; |
| 49 | 55 | const ALLOWED_TARGETS: AllowedTargets = |
| 50 | 56 | AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); |
| 57 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 51 | 58 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcReallocator; |
| 52 | 59 | } |
compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs+18| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::{AttributeKind, RustcDumpLayoutKind}; |
| 2 | 3 | use rustc_hir::{MethodKind, Target}; |
| 3 | 4 | use rustc_span::{Span, Symbol, sym}; |
| ... | ... | @@ -10,6 +11,7 @@ pub(crate) struct RustcDumpUserArgsParser; |
| 10 | 11 | impl NoArgsAttributeParser for RustcDumpUserArgsParser { |
| 11 | 12 | const PATH: &[Symbol] = &[sym::rustc_dump_user_args]; |
| 12 | 13 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 14 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 13 | 15 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpUserArgs; |
| 14 | 16 | } |
| 15 | 17 | |
| ... | ... | @@ -18,6 +20,7 @@ pub(crate) struct RustcDumpDefParentsParser; |
| 18 | 20 | impl NoArgsAttributeParser for RustcDumpDefParentsParser { |
| 19 | 21 | const PATH: &[Symbol] = &[sym::rustc_dump_def_parents]; |
| 20 | 22 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 23 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 21 | 24 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents; |
| 22 | 25 | } |
| 23 | 26 | |
| ... | ... | @@ -35,6 +38,7 @@ impl SingleAttributeParser for RustcDumpDefPathParser { |
| 35 | 38 | Allow(Target::Impl { of_trait: false }), |
| 36 | 39 | ]); |
| 37 | 40 | const TEMPLATE: AttributeTemplate = template!(Word); |
| 41 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 38 | 42 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 39 | 43 | cx.expect_no_args(args)?; |
| 40 | 44 | Some(AttributeKind::RustcDumpDefPath(cx.attr_span)) |
| ... | ... | @@ -46,6 +50,7 @@ pub(crate) struct RustcDumpHiddenTypeOfOpaquesParser; |
| 46 | 50 | impl NoArgsAttributeParser for RustcDumpHiddenTypeOfOpaquesParser { |
| 47 | 51 | const PATH: &[Symbol] = &[sym::rustc_dump_hidden_type_of_opaques]; |
| 48 | 52 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 53 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 49 | 54 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpHiddenTypeOfOpaques; |
| 50 | 55 | } |
| 51 | 56 | |
| ... | ... | @@ -59,6 +64,7 @@ impl NoArgsAttributeParser for RustcDumpInferredOutlivesParser { |
| 59 | 64 | Allow(Target::Union), |
| 60 | 65 | Allow(Target::TyAlias), |
| 61 | 66 | ]); |
| 67 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 62 | 68 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpInferredOutlives; |
| 63 | 69 | } |
| 64 | 70 | |
| ... | ... | @@ -67,6 +73,7 @@ pub(crate) struct RustcDumpItemBoundsParser; |
| 67 | 73 | impl NoArgsAttributeParser for RustcDumpItemBoundsParser { |
| 68 | 74 | const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds]; |
| 69 | 75 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocTy)]); |
| 76 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 70 | 77 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds; |
| 71 | 78 | } |
| 72 | 79 | |
| ... | ... | @@ -88,6 +95,8 @@ impl CombineAttributeParser for RustcDumpLayoutParser { |
| 88 | 95 | |
| 89 | 96 | const TEMPLATE: AttributeTemplate = |
| 90 | 97 | template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]); |
| 98 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 99 | ||
| 91 | 100 | fn extend( |
| 92 | 101 | cx: &mut AcceptContext<'_, '_>, |
| 93 | 102 | args: &ArgParser, |
| ... | ... | @@ -155,6 +164,7 @@ impl NoArgsAttributeParser for RustcDumpObjectLifetimeDefaultsParser { |
| 155 | 164 | Allow(Target::TyAlias), |
| 156 | 165 | Allow(Target::Union), |
| 157 | 166 | ]); |
| 167 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 158 | 168 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpObjectLifetimeDefaults; |
| 159 | 169 | } |
| 160 | 170 | |
| ... | ... | @@ -182,6 +192,7 @@ impl NoArgsAttributeParser for RustcDumpPredicatesParser { |
| 182 | 192 | Allow(Target::TyAlias), |
| 183 | 193 | Allow(Target::Union), |
| 184 | 194 | ]); |
| 195 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 185 | 196 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates; |
| 186 | 197 | } |
| 187 | 198 | |
| ... | ... | @@ -199,6 +210,7 @@ impl SingleAttributeParser for RustcDumpSymbolNameParser { |
| 199 | 210 | Allow(Target::Impl { of_trait: false }), |
| 200 | 211 | ]); |
| 201 | 212 | const TEMPLATE: AttributeTemplate = template!(Word); |
| 213 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 202 | 214 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 203 | 215 | cx.expect_no_args(args)?; |
| 204 | 216 | Some(AttributeKind::RustcDumpSymbolName(cx.attr_span)) |
| ... | ... | @@ -219,6 +231,10 @@ impl NoArgsAttributeParser for RustcDumpVariancesParser { |
| 219 | 231 | Allow(Target::Struct), |
| 220 | 232 | Allow(Target::Union), |
| 221 | 233 | ]); |
| 234 | const STABILITY: AttributeStability = unstable!( | |
| 235 | rustc_attrs, | |
| 236 | "the `#[rustc_dump_variances]` attribute is used for rustc unit tests" | |
| 237 | ); | |
| 222 | 238 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariances; |
| 223 | 239 | } |
| 224 | 240 | |
| ... | ... | @@ -227,6 +243,7 @@ pub(crate) struct RustcDumpVariancesOfOpaquesParser; |
| 227 | 243 | impl NoArgsAttributeParser for RustcDumpVariancesOfOpaquesParser { |
| 228 | 244 | const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques]; |
| 229 | 245 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 246 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 230 | 247 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques; |
| 231 | 248 | } |
| 232 | 249 | |
| ... | ... | @@ -238,5 +255,6 @@ impl NoArgsAttributeParser for RustcDumpVtableParser { |
| 238 | 255 | Allow(Target::Impl { of_trait: true }), |
| 239 | 256 | Allow(Target::TyAlias), |
| 240 | 257 | ]); |
| 258 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 241 | 259 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDumpVtable; |
| 242 | 260 | } |
compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs+72-10| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | use std::path::PathBuf; |
| 2 | 2 | |
| 3 | 3 | use rustc_ast::{LitIntType, LitKind, MetaItemLit}; |
| 4 | use rustc_feature::AttributeStability; | |
| 4 | 5 | use rustc_hir::LangItem; |
| 5 | 6 | use rustc_hir::attrs::{ |
| 6 | 7 | BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior, |
| ... | ... | @@ -20,6 +21,10 @@ pub(crate) struct RustcMainParser; |
| 20 | 21 | impl NoArgsAttributeParser for RustcMainParser { |
| 21 | 22 | const PATH: &[Symbol] = &[sym::rustc_main]; |
| 22 | 23 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 24 | const STABILITY: AttributeStability = unstable!( | |
| 25 | rustc_attrs, | |
| 26 | "the `#[rustc_main]` attribute is used internally to specify test entry point function" | |
| 27 | ); | |
| 23 | 28 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain; |
| 24 | 29 | } |
| 25 | 30 | |
| ... | ... | @@ -28,6 +33,10 @@ pub(crate) struct RustcMustImplementOneOfParser; |
| 28 | 33 | impl SingleAttributeParser for RustcMustImplementOneOfParser { |
| 29 | 34 | const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of]; |
| 30 | 35 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 36 | const STABILITY: AttributeStability = unstable!( | |
| 37 | rustc_attrs, | |
| 38 | "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait. Its syntax and semantics are highly experimental and will be subject to change before stabilization" | |
| 39 | ); | |
| 31 | 40 | const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]); |
| 32 | 41 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 33 | 42 | let list = cx.expect_list(args, cx.attr_span)?; |
| ... | ... | @@ -75,6 +84,8 @@ impl NoArgsAttributeParser for RustcNeverReturnsNullPtrParser { |
| 75 | 84 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 76 | 85 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 77 | 86 | ]); |
| 87 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 88 | ||
| 78 | 89 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPtr; |
| 79 | 90 | } |
| 80 | 91 | pub(crate) struct RustcNoImplicitAutorefsParser; |
| ... | ... | @@ -88,6 +99,7 @@ impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser { |
| 88 | 99 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 89 | 100 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 90 | 101 | ]); |
| 102 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 91 | 103 | |
| 92 | 104 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs; |
| 93 | 105 | } |
| ... | ... | @@ -98,6 +110,7 @@ impl SingleAttributeParser for RustcLegacyConstGenericsParser { |
| 98 | 110 | const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics]; |
| 99 | 111 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 100 | 112 | const TEMPLATE: AttributeTemplate = template!(List: &["N"]); |
| 113 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 101 | 114 | |
| 102 | 115 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 103 | 116 | let meta_items = cx.expect_list(args, cx.attr_span)?; |
| ... | ... | @@ -141,6 +154,7 @@ impl NoArgsAttributeParser for RustcInheritOverflowChecksParser { |
| 141 | 154 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 142 | 155 | Allow(Target::Closure), |
| 143 | 156 | ]); |
| 157 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 144 | 158 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInheritOverflowChecks; |
| 145 | 159 | } |
| 146 | 160 | |
| ... | ... | @@ -150,6 +164,7 @@ impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser { |
| 150 | 164 | const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access]; |
| 151 | 165 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]); |
| 152 | 166 | const TEMPLATE: AttributeTemplate = template!(Word); |
| 167 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 153 | 168 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 154 | 169 | let arg = cx.expect_single_element_list(args, cx.attr_span)?; |
| 155 | 170 | let lint_message = cx.expect_string_literal(arg)?; |
| ... | ... | @@ -163,6 +178,7 @@ pub(crate) struct RustcLintOptTyParser; |
| 163 | 178 | impl NoArgsAttributeParser for RustcLintOptTyParser { |
| 164 | 179 | const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty]; |
| 165 | 180 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); |
| 181 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 166 | 182 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy; |
| 167 | 183 | } |
| 168 | 184 | |
| ... | ... | @@ -258,6 +274,7 @@ impl AttributeParser for RustcCguTestAttributeParser { |
| 258 | 274 | ( |
| 259 | 275 | &[sym::rustc_partition_reused], |
| 260 | 276 | template!(List: &[r#"cfg = "...", module = "...""#]), |
| 277 | unstable!(rustc_attrs), | |
| 261 | 278 | |this, cx, args| { |
| 262 | 279 | this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| { |
| 263 | 280 | (cx.attr_span, CguFields::PartitionReused { cfg, module }) |
| ... | ... | @@ -267,6 +284,7 @@ impl AttributeParser for RustcCguTestAttributeParser { |
| 267 | 284 | ( |
| 268 | 285 | &[sym::rustc_partition_codegened], |
| 269 | 286 | template!(List: &[r#"cfg = "...", module = "...""#]), |
| 287 | unstable!(rustc_attrs), | |
| 270 | 288 | |this, cx, args| { |
| 271 | 289 | this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| { |
| 272 | 290 | (cx.attr_span, CguFields::PartitionCodegened { cfg, module }) |
| ... | ... | @@ -276,6 +294,7 @@ impl AttributeParser for RustcCguTestAttributeParser { |
| 276 | 294 | ( |
| 277 | 295 | &[sym::rustc_expected_cgu_reuse], |
| 278 | 296 | template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]), |
| 297 | unstable!(rustc_attrs), | |
| 279 | 298 | |this, cx, args| { |
| 280 | 299 | this.items.extend(parse_cgu_fields(cx, args, true).map(|(cfg, module, kind)| { |
| 281 | 300 | // unwrap ok because if not given, we return None in `parse_cgu_fields`. |
| ... | ... | @@ -305,6 +324,7 @@ impl SingleAttributeParser for RustcDeprecatedSafe2024Parser { |
| 305 | 324 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 306 | 325 | ]); |
| 307 | 326 | const TEMPLATE: AttributeTemplate = template!(List: &[r#"audit_that = "...""#]); |
| 327 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 308 | 328 | |
| 309 | 329 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 310 | 330 | let single = cx.expect_single_element_list(args, cx.attr_span)?; |
| ... | ... | @@ -333,6 +353,7 @@ impl NoArgsAttributeParser for RustcConversionSuggestionParser { |
| 333 | 353 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 334 | 354 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 335 | 355 | ]); |
| 356 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 336 | 357 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConversionSuggestion; |
| 337 | 358 | } |
| 338 | 359 | |
| ... | ... | @@ -341,6 +362,7 @@ pub(crate) struct RustcCaptureAnalysisParser; |
| 341 | 362 | impl NoArgsAttributeParser for RustcCaptureAnalysisParser { |
| 342 | 363 | const PATH: &[Symbol] = &[sym::rustc_capture_analysis]; |
| 343 | 364 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); |
| 365 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 344 | 366 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis; |
| 345 | 367 | } |
| 346 | 368 | |
| ... | ... | @@ -353,6 +375,10 @@ impl SingleAttributeParser for RustcNeverTypeOptionsParser { |
| 353 | 375 | r#"fallback = "unit", "never", "no""#, |
| 354 | 376 | r#"diverging_block_default = "unit", "never""#, |
| 355 | 377 | ]); |
| 378 | const STABILITY: AttributeStability = unstable!( | |
| 379 | rustc_attrs, | |
| 380 | "`rustc_never_type_options` is used to experiment with never type fallback and work on never type stabilization" | |
| 381 | ); | |
| 356 | 382 | |
| 357 | 383 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 358 | 384 | let list = cx.expect_list(args, cx.attr_span)?; |
| ... | ... | @@ -418,6 +444,7 @@ pub(crate) struct RustcTrivialFieldReadsParser; |
| 418 | 444 | impl NoArgsAttributeParser for RustcTrivialFieldReadsParser { |
| 419 | 445 | const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads]; |
| 420 | 446 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 447 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 421 | 448 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads; |
| 422 | 449 | } |
| 423 | 450 | |
| ... | ... | @@ -432,6 +459,7 @@ impl NoArgsAttributeParser for RustcNoMirInlineParser { |
| 432 | 459 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 433 | 460 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 434 | 461 | ]); |
| 462 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 435 | 463 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline; |
| 436 | 464 | } |
| 437 | 465 | |
| ... | ... | @@ -447,6 +475,7 @@ impl NoArgsAttributeParser for RustcNoWritableParser { |
| 447 | 475 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 448 | 476 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 449 | 477 | ]); |
| 478 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 450 | 479 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoWritable; |
| 451 | 480 | } |
| 452 | 481 | |
| ... | ... | @@ -461,6 +490,7 @@ impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { |
| 461 | 490 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 462 | 491 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 463 | 492 | ]); |
| 493 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 464 | 494 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability; |
| 465 | 495 | } |
| 466 | 496 | |
| ... | ... | @@ -475,7 +505,7 @@ impl NoArgsAttributeParser for RustcRegionsParser { |
| 475 | 505 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 476 | 506 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 477 | 507 | ]); |
| 478 | ||
| 508 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 479 | 509 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcRegions; |
| 480 | 510 | } |
| 481 | 511 | |
| ... | ... | @@ -490,7 +520,7 @@ impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser { |
| 490 | 520 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 491 | 521 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 492 | 522 | ]); |
| 493 | ||
| 523 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 494 | 524 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation; |
| 495 | 525 | } |
| 496 | 526 | |
| ... | ... | @@ -500,6 +530,7 @@ impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser { |
| 500 | 530 | const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit]; |
| 501 | 531 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); |
| 502 | 532 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); |
| 533 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 503 | 534 | |
| 504 | 535 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 505 | 536 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -513,6 +544,7 @@ impl SingleAttributeParser for RustcScalableVectorParser { |
| 513 | 544 | const PATH: &[Symbol] = &[sym::rustc_scalable_vector]; |
| 514 | 545 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); |
| 515 | 546 | const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]); |
| 547 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 516 | 548 | |
| 517 | 549 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 518 | 550 | if args.as_no_args().is_ok() { |
| ... | ... | @@ -534,6 +566,7 @@ impl SingleAttributeParser for LangParser { |
| 534 | 566 | const PATH: &[Symbol] = &[sym::lang]; |
| 535 | 567 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes` |
| 536 | 568 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); |
| 569 | const STABILITY: AttributeStability = unstable!(lang_items); | |
| 537 | 570 | |
| 538 | 571 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 539 | 572 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -557,6 +590,7 @@ impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParser { |
| 557 | 590 | Allow(Target::Union), |
| 558 | 591 | Allow(Target::ForeignTy), |
| 559 | 592 | ]); |
| 593 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 560 | 594 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls; |
| 561 | 595 | } |
| 562 | 596 | |
| ... | ... | @@ -565,6 +599,7 @@ pub(crate) struct PanicHandlerParser; |
| 565 | 599 | impl NoArgsAttributeParser for PanicHandlerParser { |
| 566 | 600 | const PATH: &[Symbol] = &[sym::panic_handler]; |
| 567 | 601 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes` |
| 602 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 568 | 603 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Lang(LangItem::PanicImpl); |
| 569 | 604 | } |
| 570 | 605 | |
| ... | ... | @@ -579,6 +614,7 @@ impl NoArgsAttributeParser for RustcNounwindParser { |
| 579 | 614 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 580 | 615 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 581 | 616 | ]); |
| 617 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 582 | 618 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNounwind; |
| 583 | 619 | } |
| 584 | 620 | |
| ... | ... | @@ -587,6 +623,7 @@ pub(crate) struct RustcOffloadKernelParser; |
| 587 | 623 | impl NoArgsAttributeParser for RustcOffloadKernelParser { |
| 588 | 624 | const PATH: &[Symbol] = &[sym::rustc_offload_kernel]; |
| 589 | 625 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 626 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 590 | 627 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel; |
| 591 | 628 | } |
| 592 | 629 | |
| ... | ... | @@ -598,7 +635,6 @@ impl CombineAttributeParser for RustcMirParser { |
| 598 | 635 | type Item = RustcMirKind; |
| 599 | 636 | |
| 600 | 637 | const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcMir(items); |
| 601 | ||
| 602 | 638 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 603 | 639 | Allow(Target::Fn), |
| 604 | 640 | Allow(Target::Method(MethodKind::Inherent)), |
| ... | ... | @@ -606,8 +642,8 @@ impl CombineAttributeParser for RustcMirParser { |
| 606 | 642 | Allow(Target::Method(MethodKind::Trait { body: false })), |
| 607 | 643 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 608 | 644 | ]); |
| 609 | ||
| 610 | 645 | const TEMPLATE: AttributeTemplate = template!(List: &["arg1, arg2, ..."]); |
| 646 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 611 | 647 | |
| 612 | 648 | fn extend( |
| 613 | 649 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -679,6 +715,10 @@ impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { |
| 679 | 715 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 680 | 716 | Allow(Target::Method(MethodKind::Trait { body: false })), |
| 681 | 717 | ]); |
| 718 | const STABILITY: AttributeStability = unstable!( | |
| 719 | rustc_attrs, | |
| 720 | "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods as non-const to allow large traits an easier transition to const" | |
| 721 | ); | |
| 682 | 722 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod; |
| 683 | 723 | } |
| 684 | 724 | |
| ... | ... | @@ -690,7 +730,6 @@ impl CombineAttributeParser for RustcCleanParser { |
| 690 | 730 | type Item = RustcCleanAttribute; |
| 691 | 731 | |
| 692 | 732 | const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcClean(items); |
| 693 | ||
| 694 | 733 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 695 | 734 | // tidy-alphabetical-start |
| 696 | 735 | Allow(Target::AssocConst), |
| ... | ... | @@ -715,7 +754,7 @@ impl CombineAttributeParser for RustcCleanParser { |
| 715 | 754 | Allow(Target::Union), |
| 716 | 755 | // tidy-alphabetical-end |
| 717 | 756 | ]); |
| 718 | ||
| 757 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 719 | 758 | const TEMPLATE: AttributeTemplate = |
| 720 | 759 | template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]); |
| 721 | 760 | |
| ... | ... | @@ -784,7 +823,6 @@ pub(crate) struct RustcIfThisChangedParser; |
| 784 | 823 | |
| 785 | 824 | impl SingleAttributeParser for RustcIfThisChangedParser { |
| 786 | 825 | const PATH: &[Symbol] = &[sym::rustc_if_this_changed]; |
| 787 | ||
| 788 | 826 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 789 | 827 | // tidy-alphabetical-start |
| 790 | 828 | Allow(Target::AssocConst), |
| ... | ... | @@ -809,8 +847,8 @@ impl SingleAttributeParser for RustcIfThisChangedParser { |
| 809 | 847 | Allow(Target::Union), |
| 810 | 848 | // tidy-alphabetical-end |
| 811 | 849 | ]); |
| 812 | ||
| 813 | 850 | const TEMPLATE: AttributeTemplate = template!(Word, List: &["DepNode"]); |
| 851 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 814 | 852 | |
| 815 | 853 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 816 | 854 | if !cx.cx.sess.opts.unstable_opts.query_dep_graph { |
| ... | ... | @@ -867,8 +905,8 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { |
| 867 | 905 | Allow(Target::Union), |
| 868 | 906 | // tidy-alphabetical-end |
| 869 | 907 | ]); |
| 870 | ||
| 871 | 908 | const TEMPLATE: AttributeTemplate = template!(List: &["DepNode"]); |
| 909 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 872 | 910 | |
| 873 | 911 | fn extend( |
| 874 | 912 | cx: &mut AcceptContext<'_, '_>, |
| ... | ... | @@ -895,6 +933,7 @@ impl NoArgsAttributeParser for RustcInsignificantDtorParser { |
| 895 | 933 | Allow(Target::Struct), |
| 896 | 934 | Allow(Target::ForeignTy), |
| 897 | 935 | ]); |
| 936 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 898 | 937 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor; |
| 899 | 938 | } |
| 900 | 939 | |
| ... | ... | @@ -933,6 +972,7 @@ impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { |
| 933 | 972 | Allow(Target::PatField), |
| 934 | 973 | Allow(Target::Crate), |
| 935 | 974 | ]); |
| 975 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 936 | 976 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility; |
| 937 | 977 | } |
| 938 | 978 | |
| ... | ... | @@ -959,6 +999,10 @@ impl SingleAttributeParser for RustcDiagnosticItemParser { |
| 959 | 999 | Allow(Target::Crate), |
| 960 | 1000 | ]); |
| 961 | 1001 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); |
| 1002 | const STABILITY: AttributeStability = unstable!( | |
| 1003 | rustc_attrs, | |
| 1004 | "the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types from the standard library for diagnostic purposes" | |
| 1005 | ); | |
| 962 | 1006 | |
| 963 | 1007 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 964 | 1008 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -978,6 +1022,10 @@ impl NoArgsAttributeParser for RustcDoNotConstCheckParser { |
| 978 | 1022 | Allow(Target::Method(MethodKind::Trait { body: false })), |
| 979 | 1023 | Allow(Target::Method(MethodKind::Trait { body: true })), |
| 980 | 1024 | ]); |
| 1025 | const STABILITY: AttributeStability = unstable!( | |
| 1026 | rustc_attrs, | |
| 1027 | "`#[rustc_do_not_const_check]` skips const-check for this function's body" | |
| 1028 | ); | |
| 981 | 1029 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck; |
| 982 | 1030 | } |
| 983 | 1031 | |
| ... | ... | @@ -986,6 +1034,11 @@ pub(crate) struct RustcNonnullOptimizationGuaranteedParser; |
| 986 | 1034 | impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser { |
| 987 | 1035 | const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed]; |
| 988 | 1036 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); |
| 1037 | const STABILITY: AttributeStability = unstable!( | |
| 1038 | rustc_attrs, | |
| 1039 | "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in the standard library", | |
| 1040 | "the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized" | |
| 1041 | ); | |
| 989 | 1042 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed; |
| 990 | 1043 | } |
| 991 | 1044 | |
| ... | ... | @@ -1000,6 +1053,7 @@ impl NoArgsAttributeParser for RustcStrictCoherenceParser { |
| 1000 | 1053 | Allow(Target::Union), |
| 1001 | 1054 | Allow(Target::ForeignTy), |
| 1002 | 1055 | ]); |
| 1056 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 1003 | 1057 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence; |
| 1004 | 1058 | } |
| 1005 | 1059 | |
| ... | ... | @@ -1009,8 +1063,8 @@ impl SingleAttributeParser for RustcReservationImplParser { |
| 1009 | 1063 | const PATH: &[Symbol] = &[sym::rustc_reservation_impl]; |
| 1010 | 1064 | const ALLOWED_TARGETS: AllowedTargets = |
| 1011 | 1065 | AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]); |
| 1012 | ||
| 1013 | 1066 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "reservation message"); |
| 1067 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 1014 | 1068 | |
| 1015 | 1069 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 1016 | 1070 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -1025,6 +1079,7 @@ pub(crate) struct PreludeImportParser; |
| 1025 | 1079 | impl NoArgsAttributeParser for PreludeImportParser { |
| 1026 | 1080 | const PATH: &[Symbol] = &[sym::prelude_import]; |
| 1027 | 1081 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Use)]); |
| 1082 | const STABILITY: AttributeStability = unstable!(prelude_import); | |
| 1028 | 1083 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport; |
| 1029 | 1084 | } |
| 1030 | 1085 | |
| ... | ... | @@ -1034,6 +1089,10 @@ impl SingleAttributeParser for RustcDocPrimitiveParser { |
| 1034 | 1089 | const PATH: &[Symbol] = &[sym::rustc_doc_primitive]; |
| 1035 | 1090 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]); |
| 1036 | 1091 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name"); |
| 1092 | const STABILITY: AttributeStability = unstable!( | |
| 1093 | rustc_attrs, | |
| 1094 | "the `#[rustc_doc_primitive]` attribute is used by the standard library to provide a way to generate documentation for primitive types" | |
| 1095 | ); | |
| 1037 | 1096 | |
| 1038 | 1097 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 1039 | 1098 | let nv = cx.expect_name_value(args, cx.attr_span, None)?; |
| ... | ... | @@ -1048,6 +1107,7 @@ pub(crate) struct RustcIntrinsicParser; |
| 1048 | 1107 | impl NoArgsAttributeParser for RustcIntrinsicParser { |
| 1049 | 1108 | const PATH: &[Symbol] = &[sym::rustc_intrinsic]; |
| 1050 | 1109 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 1110 | const STABILITY: AttributeStability = unstable!(intrinsics); | |
| 1051 | 1111 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic; |
| 1052 | 1112 | } |
| 1053 | 1113 | |
| ... | ... | @@ -1056,6 +1116,7 @@ pub(crate) struct RustcIntrinsicConstStableIndirectParser; |
| 1056 | 1116 | impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser { |
| 1057 | 1117 | const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect]; |
| 1058 | 1118 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 1119 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 1059 | 1120 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect; |
| 1060 | 1121 | } |
| 1061 | 1122 | |
| ... | ... | @@ -1064,5 +1125,6 @@ pub(crate) struct RustcExhaustiveParser; |
| 1064 | 1125 | impl NoArgsAttributeParser for RustcExhaustiveParser { |
| 1065 | 1126 | const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively]; |
| 1066 | 1127 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Enum)]); |
| 1128 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 1067 | 1129 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively; |
| 1068 | 1130 | } |
compiler/rustc_attr_parsing/src/attributes/semantics.rs+3| ... | ... | @@ -1,8 +1,11 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | ||
| 1 | 3 | use super::prelude::*; |
| 2 | 4 | |
| 3 | 5 | pub(crate) struct MayDangleParser; |
| 4 | 6 | impl NoArgsAttributeParser for MayDangleParser { |
| 5 | 7 | const PATH: &[Symbol] = &[sym::may_dangle]; |
| 6 | 8 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` |
| 9 | const STABILITY: AttributeStability = unstable!(dropck_eyepatch); | |
| 7 | 10 | const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle; |
| 8 | 11 | } |
compiler/rustc_attr_parsing/src/attributes/stability.rs+10-25| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | use std::num::NonZero; |
| 2 | 2 | |
| 3 | 3 | use rustc_errors::ErrorGuaranteed; |
| 4 | use rustc_feature::ACCEPTED_LANG_FEATURES; | |
| 4 | use rustc_feature::{ACCEPTED_LANG_FEATURES, AttributeStability}; | |
| 5 | 5 | use rustc_hir::attrs::UnstableRemovedFeature; |
| 6 | 6 | use rustc_hir::target::GenericParamKind; |
| 7 | 7 | use rustc_hir::{ |
| ... | ... | @@ -13,16 +13,6 @@ use super::prelude::*; |
| 13 | 13 | use super::util::parse_version; |
| 14 | 14 | use crate::session_diagnostics; |
| 15 | 15 | |
| 16 | macro_rules! reject_outside_std { | |
| 17 | ($cx: ident) => { | |
| 18 | // Emit errors for non-staged-api crates. | |
| 19 | if !$cx.features().staged_api() { | |
| 20 | $cx.emit_err(session_diagnostics::StabilityOutsideStd { span: $cx.attr_span }); | |
| 21 | return; | |
| 22 | } | |
| 23 | }; | |
| 24 | } | |
| 25 | ||
| 26 | 16 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 27 | 17 | Allow(Target::Fn), |
| 28 | 18 | Allow(Target::Struct), |
| ... | ... | @@ -76,8 +66,8 @@ impl AttributeParser for StabilityParser { |
| 76 | 66 | ( |
| 77 | 67 | &[sym::stable], |
| 78 | 68 | template!(List: &[r#"feature = "name", since = "version""#]), |
| 69 | unstable!(staged_api), | |
| 79 | 70 | |this, cx, args| { |
| 80 | reject_outside_std!(cx); | |
| 81 | 71 | if !this.check_duplicate(cx) |
| 82 | 72 | && let Some((feature, level)) = parse_stability(cx, args) |
| 83 | 73 | { |
| ... | ... | @@ -88,8 +78,8 @@ impl AttributeParser for StabilityParser { |
| 88 | 78 | ( |
| 89 | 79 | &[sym::unstable], |
| 90 | 80 | template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), |
| 81 | unstable!(staged_api), | |
| 91 | 82 | |this, cx, args| { |
| 92 | reject_outside_std!(cx); | |
| 93 | 83 | if !this.check_duplicate(cx) |
| 94 | 84 | && let Some((feature, level)) = parse_unstability(cx, args) |
| 95 | 85 | { |
| ... | ... | @@ -100,8 +90,8 @@ impl AttributeParser for StabilityParser { |
| 100 | 90 | ( |
| 101 | 91 | &[sym::rustc_allowed_through_unstable_modules], |
| 102 | 92 | template!(NameValueStr: "deprecation message"), |
| 93 | unstable!(staged_api), | |
| 103 | 94 | |this, cx, args| { |
| 104 | reject_outside_std!(cx); | |
| 105 | 95 | let Some(nv) = cx.expect_name_value(args, cx.attr_span, None) else { |
| 106 | 96 | return; |
| 107 | 97 | }; |
| ... | ... | @@ -158,8 +148,8 @@ impl AttributeParser for BodyStabilityParser { |
| 158 | 148 | const ATTRIBUTES: AcceptMapping<Self> = &[( |
| 159 | 149 | &[sym::rustc_default_body_unstable], |
| 160 | 150 | template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), |
| 151 | unstable!(staged_api), | |
| 161 | 152 | |this, cx, args| { |
| 162 | reject_outside_std!(cx); | |
| 163 | 153 | if this.stability.is_some() { |
| 164 | 154 | cx.dcx() |
| 165 | 155 | .emit_err(session_diagnostics::MultipleStabilityLevels { span: cx.attr_span }); |
| ... | ... | @@ -185,6 +175,7 @@ impl NoArgsAttributeParser for RustcConstStableIndirectParser { |
| 185 | 175 | Allow(Target::Fn), |
| 186 | 176 | Allow(Target::Method(MethodKind::Inherent)), |
| 187 | 177 | ]); |
| 178 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 188 | 179 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConstStableIndirect; |
| 189 | 180 | } |
| 190 | 181 | |
| ... | ... | @@ -211,9 +202,8 @@ impl AttributeParser for ConstStabilityParser { |
| 211 | 202 | ( |
| 212 | 203 | &[sym::rustc_const_stable], |
| 213 | 204 | template!(List: &[r#"feature = "name""#]), |
| 205 | unstable!(staged_api), | |
| 214 | 206 | |this, cx, args| { |
| 215 | reject_outside_std!(cx); | |
| 216 | ||
| 217 | 207 | if !this.check_duplicate(cx) |
| 218 | 208 | && let Some((feature, level)) = parse_stability(cx, args) |
| 219 | 209 | { |
| ... | ... | @@ -227,8 +217,8 @@ impl AttributeParser for ConstStabilityParser { |
| 227 | 217 | ( |
| 228 | 218 | &[sym::rustc_const_unstable], |
| 229 | 219 | template!(List: &[r#"feature = "name""#]), |
| 220 | unstable!(staged_api), | |
| 230 | 221 | |this, cx, args| { |
| 231 | reject_outside_std!(cx); | |
| 232 | 222 | if !this.check_duplicate(cx) |
| 233 | 223 | && let Some((feature, level)) = parse_unstability(cx, args) |
| 234 | 224 | { |
| ... | ... | @@ -239,8 +229,7 @@ impl AttributeParser for ConstStabilityParser { |
| 239 | 229 | } |
| 240 | 230 | }, |
| 241 | 231 | ), |
| 242 | (&[sym::rustc_promotable], template!(Word), |this, cx, _| { | |
| 243 | reject_outside_std!(cx); | |
| 232 | (&[sym::rustc_promotable], template!(Word), unstable!(staged_api), |this, _cx, _| { | |
| 244 | 233 | this.promotable = true; |
| 245 | 234 | }), |
| 246 | 235 | ]; |
| ... | ... | @@ -474,6 +463,7 @@ impl CombineAttributeParser for UnstableRemovedParser { |
| 474 | 463 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 475 | 464 | const TEMPLATE: AttributeTemplate = |
| 476 | 465 | template!(List: &[r#"feature = "name", reason = "...", link = "...", since = "version""#]); |
| 466 | const STABILITY: AttributeStability = unstable!(staged_api); | |
| 477 | 467 | |
| 478 | 468 | const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableRemoved(items); |
| 479 | 469 | |
| ... | ... | @@ -486,11 +476,6 @@ impl CombineAttributeParser for UnstableRemovedParser { |
| 486 | 476 | let mut link = None; |
| 487 | 477 | let mut since = None; |
| 488 | 478 | |
| 489 | if !cx.features().staged_api() { | |
| 490 | cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span }); | |
| 491 | return None; | |
| 492 | } | |
| 493 | ||
| 494 | 479 | let list = cx.expect_list(args, cx.attr_span)?; |
| 495 | 480 | |
| 496 | 481 | for param in list.mixed() { |
compiler/rustc_attr_parsing/src/attributes/test_attrs.rs+9| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_hir::attrs::RustcAbiAttrKind; |
| 2 | 3 | use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; |
| 3 | 4 | |
| ... | ... | @@ -14,6 +15,7 @@ impl SingleAttributeParser for IgnoreParser { |
| 14 | 15 | Word, NameValueStr: "reason", |
| 15 | 16 | "https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute" |
| 16 | 17 | ); |
| 18 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 17 | 19 | |
| 18 | 20 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 19 | 21 | Some(AttributeKind::Ignore { |
| ... | ... | @@ -55,6 +57,7 @@ impl SingleAttributeParser for ShouldPanicParser { |
| 55 | 57 | Word, List: &[r#"expected = "reason""#], NameValueStr: "reason", |
| 56 | 58 | "https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute" |
| 57 | 59 | ); |
| 60 | const STABILITY: AttributeStability = AttributeStability::Stable; | |
| 58 | 61 | |
| 59 | 62 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 60 | 63 | Some(AttributeKind::ShouldPanic { |
| ... | ... | @@ -82,6 +85,7 @@ impl SingleAttributeParser for ReexportTestHarnessMainParser { |
| 82 | 85 | const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; |
| 83 | 86 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 84 | 87 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); |
| 88 | const STABILITY: AttributeStability = unstable!(custom_test_frameworks); | |
| 85 | 89 | |
| 86 | 90 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 87 | 91 | let nv = cx.expect_name_value( |
| ... | ... | @@ -110,6 +114,7 @@ impl SingleAttributeParser for RustcAbiParser { |
| 110 | 114 | Allow(Target::Method(MethodKind::Trait { body: false })), |
| 111 | 115 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 112 | 116 | ]); |
| 117 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 113 | 118 | |
| 114 | 119 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 115 | 120 | let Some(args) = args.as_list() else { |
| ... | ... | @@ -146,6 +151,7 @@ pub(crate) struct RustcDelayedBugFromInsideQueryParser; |
| 146 | 151 | impl NoArgsAttributeParser for RustcDelayedBugFromInsideQueryParser { |
| 147 | 152 | const PATH: &[Symbol] = &[sym::rustc_delayed_bug_from_inside_query]; |
| 148 | 153 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); |
| 154 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 149 | 155 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDelayedBugFromInsideQuery; |
| 150 | 156 | } |
| 151 | 157 | |
| ... | ... | @@ -160,6 +166,7 @@ impl NoArgsAttributeParser for RustcEvaluateWhereClausesParser { |
| 160 | 166 | Allow(Target::Method(MethodKind::TraitImpl)), |
| 161 | 167 | Allow(Target::Method(MethodKind::Trait { body: false })), |
| 162 | 168 | ]); |
| 169 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 163 | 170 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEvaluateWhereClauses; |
| 164 | 171 | } |
| 165 | 172 | |
| ... | ... | @@ -169,6 +176,7 @@ impl SingleAttributeParser for TestRunnerParser { |
| 169 | 176 | const PATH: &[Symbol] = &[sym::test_runner]; |
| 170 | 177 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 171 | 178 | const TEMPLATE: AttributeTemplate = template!(List: &["path"]); |
| 179 | const STABILITY: AttributeStability = unstable!(custom_test_frameworks); | |
| 172 | 180 | |
| 173 | 181 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 174 | 182 | let single = cx.expect_single_element_list(args, cx.attr_span)?; |
| ... | ... | @@ -191,6 +199,7 @@ impl SingleAttributeParser for RustcTestMarkerParser { |
| 191 | 199 | Allow(Target::Fn), |
| 192 | 200 | Allow(Target::Static), |
| 193 | 201 | ]); |
| 202 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 194 | 203 | const TEMPLATE: AttributeTemplate = template!(NameValueStr: "test_path"); |
| 195 | 204 | |
| 196 | 205 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
compiler/rustc_attr_parsing/src/attributes/traits.rs+12| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | use std::mem; |
| 2 | 2 | |
| 3 | use rustc_feature::AttributeStability; | |
| 4 | ||
| 3 | 5 | use super::prelude::*; |
| 4 | 6 | use crate::attributes::{NoArgsAttributeParser, SingleAttributeParser}; |
| 5 | 7 | use crate::context::AcceptContext; |
| ... | ... | @@ -13,6 +15,7 @@ impl SingleAttributeParser for RustcSkipDuringMethodDispatchParser { |
| 13 | 15 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 14 | 16 | |
| 15 | 17 | const TEMPLATE: AttributeTemplate = template!(List: &["array, boxed_slice"]); |
| 18 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 16 | 19 | |
| 17 | 20 | fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> { |
| 18 | 21 | let mut array = false; |
| ... | ... | @@ -50,6 +53,7 @@ pub(crate) struct RustcParenSugarParser; |
| 50 | 53 | impl NoArgsAttributeParser for RustcParenSugarParser { |
| 51 | 54 | const PATH: &[Symbol] = &[sym::rustc_paren_sugar]; |
| 52 | 55 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 56 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 53 | 57 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcParenSugar; |
| 54 | 58 | } |
| 55 | 59 | |
| ... | ... | @@ -64,6 +68,7 @@ impl NoArgsAttributeParser for MarkerParser { |
| 64 | 68 | Warn(Target::Arm), |
| 65 | 69 | Warn(Target::MacroDef), |
| 66 | 70 | ]); |
| 71 | const STABILITY: AttributeStability = unstable!(marker_trait_attr); | |
| 67 | 72 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Marker; |
| 68 | 73 | } |
| 69 | 74 | |
| ... | ... | @@ -71,6 +76,7 @@ pub(crate) struct RustcDenyExplicitImplParser; |
| 71 | 76 | impl NoArgsAttributeParser for RustcDenyExplicitImplParser { |
| 72 | 77 | const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl]; |
| 73 | 78 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 79 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 74 | 80 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDenyExplicitImpl; |
| 75 | 81 | } |
| 76 | 82 | |
| ... | ... | @@ -78,6 +84,7 @@ pub(crate) struct RustcDynIncompatibleTraitParser; |
| 78 | 84 | impl NoArgsAttributeParser for RustcDynIncompatibleTraitParser { |
| 79 | 85 | const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait]; |
| 80 | 86 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 87 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 81 | 88 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDynIncompatibleTrait; |
| 82 | 89 | } |
| 83 | 90 | |
| ... | ... | @@ -87,6 +94,7 @@ pub(crate) struct RustcSpecializationTraitParser; |
| 87 | 94 | impl NoArgsAttributeParser for RustcSpecializationTraitParser { |
| 88 | 95 | const PATH: &[Symbol] = &[sym::rustc_specialization_trait]; |
| 89 | 96 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 97 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 90 | 98 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcSpecializationTrait; |
| 91 | 99 | } |
| 92 | 100 | |
| ... | ... | @@ -94,6 +102,7 @@ pub(crate) struct RustcUnsafeSpecializationMarkerParser; |
| 94 | 102 | impl NoArgsAttributeParser for RustcUnsafeSpecializationMarkerParser { |
| 95 | 103 | const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker]; |
| 96 | 104 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 105 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 97 | 106 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcUnsafeSpecializationMarker; |
| 98 | 107 | } |
| 99 | 108 | |
| ... | ... | @@ -103,6 +112,7 @@ pub(crate) struct RustcCoinductiveParser; |
| 103 | 112 | impl NoArgsAttributeParser for RustcCoinductiveParser { |
| 104 | 113 | const PATH: &[Symbol] = &[sym::rustc_coinductive]; |
| 105 | 114 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); |
| 115 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 106 | 116 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoinductive; |
| 107 | 117 | } |
| 108 | 118 | |
| ... | ... | @@ -111,6 +121,7 @@ impl NoArgsAttributeParser for RustcAllowIncoherentImplParser { |
| 111 | 121 | const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl]; |
| 112 | 122 | const ALLOWED_TARGETS: AllowedTargets = |
| 113 | 123 | AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]); |
| 124 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 114 | 125 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAllowIncoherentImpl; |
| 115 | 126 | } |
| 116 | 127 | |
| ... | ... | @@ -119,5 +130,6 @@ impl NoArgsAttributeParser for FundamentalParser { |
| 119 | 130 | const PATH: &[Symbol] = &[sym::fundamental]; |
| 120 | 131 | const ALLOWED_TARGETS: AllowedTargets = |
| 121 | 132 | AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]); |
| 133 | const STABILITY: AttributeStability = unstable!(fundamental); | |
| 122 | 134 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental; |
| 123 | 135 | } |
compiler/rustc_attr_parsing/src/attributes/transparency.rs+2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 1 | 2 | use rustc_span::hygiene::Transparency; |
| 2 | 3 | |
| 3 | 4 | use super::prelude::*; |
| ... | ... | @@ -9,6 +10,7 @@ impl SingleAttributeParser for RustcMacroTransparencyParser { |
| 9 | 10 | const ON_DUPLICATE: OnDuplicate = OnDuplicate::Custom(|cx, used, unused| { |
| 10 | 11 | cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes"); |
| 11 | 12 | }); |
| 13 | const STABILITY: AttributeStability = unstable!(rustc_attrs); | |
| 12 | 14 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); |
| 13 | 15 | const TEMPLATE: AttributeTemplate = |
| 14 | 16 | template!(NameValueStr: ["transparent", "semiopaque", "opaque"]); |
compiler/rustc_attr_parsing/src/context.rs+5-3| ... | ... | @@ -10,7 +10,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; |
| 10 | 10 | use rustc_ast::{AttrStyle, MetaItemLit, Safety}; |
| 11 | 11 | use rustc_data_structures::sync::{DynSend, DynSync}; |
| 12 | 12 | use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; |
| 13 | use rustc_feature::{AttrSuggestionStyle, AttributeTemplate}; | |
| 13 | use rustc_feature::{AttrSuggestionStyle, AttributeStability, AttributeTemplate}; | |
| 14 | 14 | use rustc_hir::AttrPath; |
| 15 | 15 | use rustc_hir::attrs::AttributeKind; |
| 16 | 16 | use rustc_parse::parser::Recovery; |
| ... | ... | @@ -83,6 +83,7 @@ pub(super) struct GroupTypeInnerAccept { |
| 83 | 83 | pub(super) accept_fn: AcceptFn, |
| 84 | 84 | pub(super) allowed_targets: AllowedTargets, |
| 85 | 85 | pub(super) safety: AttributeSafety, |
| 86 | pub(super) stability: AttributeStability, | |
| 86 | 87 | pub(super) finalizer: FinalizeFn, |
| 87 | 88 | } |
| 88 | 89 | |
| ... | ... | @@ -102,7 +103,7 @@ macro_rules! attribute_parsers { |
| 102 | 103 | static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default()); |
| 103 | 104 | }; |
| 104 | 105 | |
| 105 | for (path, template, accept_fn) in <$names>::ATTRIBUTES { | |
| 106 | for (path, template, stability, accept_fn) in <$names>::ATTRIBUTES { | |
| 106 | 107 | match accepters.entry(*path) { |
| 107 | 108 | Entry::Vacant(e) => { |
| 108 | 109 | e.insert(GroupTypeInnerAccept { |
| ... | ... | @@ -113,6 +114,7 @@ macro_rules! attribute_parsers { |
| 113 | 114 | }) |
| 114 | 115 | }), |
| 115 | 116 | safety: <$names as crate::attributes::AttributeParser>::SAFETY, |
| 117 | stability: *stability, | |
| 116 | 118 | allowed_targets: <$names as crate::attributes::AttributeParser>::ALLOWED_TARGETS, |
| 117 | 119 | finalizer: |cx| { |
| 118 | 120 | let state = STATE_OBJECT.take(); |
| ... | ... | @@ -154,7 +156,7 @@ attribute_parsers!( |
| 154 | 156 | // tidy-alphabetical-start |
| 155 | 157 | Combine<AllowInternalUnstableParser>, |
| 156 | 158 | Combine<CrateTypeParser>, |
| 157 | Combine<DebuggerViualizerParser>, | |
| 159 | Combine<DebuggerVisualizerParser>, | |
| 158 | 160 | Combine<FeatureParser>, |
| 159 | 161 | Combine<ForceTargetFeatureParser>, |
| 160 | 162 | Combine<LinkParser>, |
compiler/rustc_attr_parsing/src/errors.rs-20| ... | ... | @@ -132,26 +132,6 @@ pub(crate) struct EmptyAttributeList { |
| 132 | 132 | pub valid_without_list: bool, |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | #[derive(Diagnostic)] | |
| 136 | #[diag("`#[{$name}]` attribute cannot be used on {$target}")] | |
| 137 | #[warning( | |
| 138 | "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" | |
| 139 | )] | |
| 140 | #[help("`#[{$name}]` can {$only}be applied to {$applied}")] | |
| 141 | pub(crate) struct InvalidTargetLint { | |
| 142 | pub name: String, | |
| 143 | pub target: &'static str, | |
| 144 | pub applied: DiagArgValue, | |
| 145 | pub only: &'static str, | |
| 146 | #[suggestion( | |
| 147 | "remove the attribute", | |
| 148 | code = "", | |
| 149 | applicability = "machine-applicable", | |
| 150 | style = "tool-only" | |
| 151 | )] | |
| 152 | pub attr_span: Span, | |
| 153 | } | |
| 154 | ||
| 155 | 135 | #[derive(Diagnostic)] |
| 156 | 136 | #[diag( |
| 157 | 137 | "{$is_used_as_inner -> |
compiler/rustc_attr_parsing/src/interface.rs+1| ... | ... | @@ -351,6 +351,7 @@ impl<'sess> AttributeParser<'sess> { |
| 351 | 351 | accept.safety, |
| 352 | 352 | &mut emit_lint, |
| 353 | 353 | ); |
| 354 | self.check_attribute_stability(&attr_path, attr_span, accept.stability); | |
| 354 | 355 | |
| 355 | 356 | let Some(args) = ArgParser::from_attr_args( |
| 356 | 357 | args, |
compiler/rustc_attr_parsing/src/lib.rs+1| ... | ... | @@ -111,6 +111,7 @@ mod early_parsed; |
| 111 | 111 | mod errors; |
| 112 | 112 | mod safety; |
| 113 | 113 | mod session_diagnostics; |
| 114 | mod stability; | |
| 114 | 115 | mod target_checking; |
| 115 | 116 | pub mod validate_attr; |
| 116 | 117 |
compiler/rustc_attr_parsing/src/session_diagnostics.rs+4-7| ... | ... | @@ -323,13 +323,6 @@ pub(crate) struct ObjcSelectorExpectedStringLiteral { |
| 323 | 323 | pub span: Span, |
| 324 | 324 | } |
| 325 | 325 | |
| 326 | #[derive(Diagnostic)] | |
| 327 | #[diag("stability attributes may not be used outside of the standard library", code = E0734)] | |
| 328 | pub(crate) struct StabilityOutsideStd { | |
| 329 | #[primary_span] | |
| 330 | pub span: Span, | |
| 331 | } | |
| 332 | ||
| 333 | 326 | #[derive(Diagnostic)] |
| 334 | 327 | #[diag("expected at least one confusable name")] |
| 335 | 328 | pub(crate) struct EmptyConfusables { |
| ... | ... | @@ -353,6 +346,10 @@ pub(crate) struct InvalidTarget { |
| 353 | 346 | pub target: &'static str, |
| 354 | 347 | pub applied: DiagArgValue, |
| 355 | 348 | pub only: &'static str, |
| 349 | #[warning( | |
| 350 | "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" | |
| 351 | )] | |
| 352 | pub previously_accepted: bool, | |
| 356 | 353 | } |
| 357 | 354 | |
| 358 | 355 | #[derive(Diagnostic)] |
compiler/rustc_attr_parsing/src/stability.rs created+77| ... | ... | @@ -0,0 +1,77 @@ |
| 1 | use rustc_feature::AttributeStability; | |
| 2 | use rustc_hir::AttrPath; | |
| 3 | use rustc_session::errors::feature_err; | |
| 4 | use rustc_span::{Span, sym}; | |
| 5 | ||
| 6 | use crate::{AttributeParser, ShouldEmit}; | |
| 7 | ||
| 8 | #[macro_export] | |
| 9 | macro_rules! unstable { | |
| 10 | ($feat: ident $(, $notes:expr)*) => { | |
| 11 | AttributeStability::Unstable { | |
| 12 | gate_name: rustc_span::sym::$feat, | |
| 13 | gate_check: rustc_feature::Features::$feat, | |
| 14 | notes: &[$($notes),*], | |
| 15 | } | |
| 16 | }; | |
| 17 | } | |
| 18 | ||
| 19 | impl<'sess> AttributeParser<'sess> { | |
| 20 | pub fn check_attribute_stability( | |
| 21 | &mut self, | |
| 22 | attr_path: &AttrPath, | |
| 23 | attr_span: Span, | |
| 24 | expected_stability: AttributeStability, | |
| 25 | ) { | |
| 26 | if matches!(self.should_emit, ShouldEmit::Nothing) { | |
| 27 | return; | |
| 28 | } | |
| 29 | ||
| 30 | let AttributeStability::Unstable { gate_check, gate_name, notes } = expected_stability | |
| 31 | else { | |
| 32 | return; | |
| 33 | }; | |
| 34 | ||
| 35 | if gate_check(self.features()) || attr_span.allows_unstable(gate_name) { | |
| 36 | return; | |
| 37 | } | |
| 38 | ||
| 39 | let (explain, default_notes): (String, &[String]) = match gate_name { | |
| 40 | sym::rustc_attrs => ("use of an internal attribute".to_string(), &[ | |
| 41 | format!("the `#[{attr_path}]` attribute is an internal implementation detail that will never be stable" | |
| 42 | )]), | |
| 43 | sym::staged_api => ("stability attributes may not be used outside of the standard library".to_string(), &[]), | |
| 44 | sym::custom_mir => ("the `#[custom_mir]` attribute is just used for the Rust test suite".to_string(), &[]), | |
| 45 | sym::allow_internal_unsafe => ("allow_internal_unsafe side-steps the unsafe_code lint".to_string(), &[]), | |
| 46 | sym::allow_internal_unstable => ("allow_internal_unstable side-steps feature gating and stability checks".to_string(), &[]), | |
| 47 | sym::compiler_builtins => ("the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable".to_string(), &[]), | |
| 48 | sym::custom_test_frameworks => ("custom test frameworks are an unstable feature".to_string(), &[]), | |
| 49 | sym::linkage => ("the `linkage` attribute is experimental and not portable across platforms".to_string(), &[]), | |
| 50 | sym::dropck_eyepatch => ("`may_dangle` has unstable semantics and may be removed in the future".to_string(), &[]), | |
| 51 | sym::intrinsics => ("the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items".to_string(), &[]), | |
| 52 | sym::lang_items => ("lang items are subject to change".to_string(), &[]), | |
| 53 | sym::prelude_import => ("`#[prelude_import]` is for use by rustc only".to_string(), &[]), | |
| 54 | sym::profiler_runtime => ("the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable".to_string(), &[]), | |
| 55 | sym::thread_local => ("`#[thread_local]` is an experimental feature, and does not currently handle destructors".to_string(), &[]), | |
| 56 | _ => (format!("the `#[{attr_path}]` attribute is an experimental feature"), &[]), | |
| 57 | }; | |
| 58 | ||
| 59 | let mut diag = feature_err(self.sess, gate_name, attr_span, explain); | |
| 60 | ||
| 61 | // Remove the suggestion for `#![feature(staged_api)]` as these attributes are currently | |
| 62 | // not usable outside std. If we do ever expose `#[stable]` etc under a different feature | |
| 63 | // name then it would be unfortunate to have nightlies out there suggesting `staged_api`. | |
| 64 | if gate_name == sym::staged_api { | |
| 65 | diag.children.clear(); | |
| 66 | } | |
| 67 | ||
| 68 | for note in default_notes { | |
| 69 | diag.note(note.clone()); | |
| 70 | } | |
| 71 | for note in notes { | |
| 72 | diag.note(*note); | |
| 73 | } | |
| 74 | ||
| 75 | diag.emit(); | |
| 76 | } | |
| 77 | } |
compiler/rustc_attr_parsing/src/target_checking.rs+24-42| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | use std::borrow::Cow; |
| 2 | 2 | |
| 3 | 3 | use rustc_ast::AttrStyle; |
| 4 | use rustc_errors::{DiagArgValue, Diagnostic, MultiSpan, StashKey}; | |
| 4 | use rustc_errors::{DiagArgValue, MultiSpan, StashKey}; | |
| 5 | 5 | use rustc_feature::Features; |
| 6 | 6 | use rustc_hir::attrs::AttributeKind; |
| 7 | 7 | use rustc_hir::{AttrItem, Attribute, MethodKind, Target}; |
| ... | ... | @@ -9,8 +9,7 @@ use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Span, Symbol, sym} |
| 9 | 9 | |
| 10 | 10 | use crate::context::AcceptContext; |
| 11 | 11 | use crate::errors::{ |
| 12 | InvalidAttrAtCrateLevel, InvalidTargetLint, ItemFollowingInnerAttr, | |
| 13 | UnsupportedAttributesInWhere, | |
| 12 | InvalidAttrAtCrateLevel, ItemFollowingInnerAttr, UnsupportedAttributesInWhere, | |
| 14 | 13 | }; |
| 15 | 14 | use crate::session_diagnostics::InvalidTarget; |
| 16 | 15 | use crate::target_checking::Policy::Allow; |
| ... | ... | @@ -122,15 +121,26 @@ impl<'sess> AttributeParser<'sess> { |
| 122 | 121 | .emit(); |
| 123 | 122 | } |
| 124 | 123 | |
| 125 | match allowed_targets.is_allowed(cx.target) { | |
| 126 | AllowedResult::Allowed => {} | |
| 127 | AllowedResult::Warn => { | |
| 128 | let allowed_targets = allowed_targets.allowed_targets(); | |
| 129 | let (applied, only) = | |
| 130 | allowed_targets_applied(allowed_targets, cx.target, cx.features); | |
| 131 | let name = cx.attr_path.clone(); | |
| 124 | let result = allowed_targets.is_allowed(cx.target); | |
| 125 | if matches!(result, AllowedResult::Allowed) { | |
| 126 | return; | |
| 127 | } | |
| 132 | 128 | |
| 133 | let lint = if name.segments[0] == sym::deprecated | |
| 129 | let allowed_targets = allowed_targets.allowed_targets(); | |
| 130 | let (applied, only) = allowed_targets_applied(allowed_targets, cx.target, cx.features); | |
| 131 | let diag = InvalidTarget { | |
| 132 | span: cx.attr_span.clone(), | |
| 133 | name: cx.attr_path.clone(), | |
| 134 | target: cx.target.plural_name(), | |
| 135 | only: if only { "only " } else { "" }, | |
| 136 | applied: DiagArgValue::StrListSepByAnd(applied.into_iter().map(Cow::Owned).collect()), | |
| 137 | previously_accepted: matches!(result, AllowedResult::Warn), | |
| 138 | }; | |
| 139 | ||
| 140 | match result { | |
| 141 | AllowedResult::Allowed => unreachable!("Should have early returned above"), | |
| 142 | AllowedResult::Warn => { | |
| 143 | let lint = if cx.attr_path.segments[0] == sym::deprecated | |
| 134 | 144 | && ![ |
| 135 | 145 | Target::Closure, |
| 136 | 146 | Target::Expression, |
| ... | ... | @@ -145,39 +155,11 @@ impl<'sess> AttributeParser<'sess> { |
| 145 | 155 | rustc_session::lint::builtin::UNUSED_ATTRIBUTES |
| 146 | 156 | }; |
| 147 | 157 | |
| 148 | let attr_span = cx.attr_span; | |
| 149 | let target = cx.target; | |
| 150 | cx.emit_lint_with_sess( | |
| 151 | lint, | |
| 152 | move |dcx, level, _| { | |
| 153 | InvalidTargetLint { | |
| 154 | name: name.to_string(), | |
| 155 | target: target.plural_name(), | |
| 156 | only: if only { "only " } else { "" }, | |
| 157 | applied: DiagArgValue::StrListSepByAnd( | |
| 158 | applied.iter().map(|i| Cow::Owned(i.to_string())).collect(), | |
| 159 | ), | |
| 160 | attr_span, | |
| 161 | } | |
| 162 | .into_diag(dcx, level) | |
| 163 | }, | |
| 164 | attr_span, | |
| 165 | ); | |
| 158 | let attr_span = cx.attr_span.clone(); | |
| 159 | cx.emit_lint(lint, diag, attr_span); | |
| 166 | 160 | } |
| 167 | 161 | AllowedResult::Error => { |
| 168 | let allowed_targets = allowed_targets.allowed_targets(); | |
| 169 | let (applied, only) = | |
| 170 | allowed_targets_applied(allowed_targets, cx.target, cx.features); | |
| 171 | let name = cx.attr_path.clone(); | |
| 172 | cx.dcx().emit_err(InvalidTarget { | |
| 173 | span: cx.attr_span.clone(), | |
| 174 | name, | |
| 175 | target: cx.target.plural_name(), | |
| 176 | only: if only { "only " } else { "" }, | |
| 177 | applied: DiagArgValue::StrListSepByAnd( | |
| 178 | applied.into_iter().map(Cow::Owned).collect(), | |
| 179 | ), | |
| 180 | }); | |
| 162 | cx.dcx().emit_err(diag); | |
| 181 | 163 | } |
| 182 | 164 | } |
| 183 | 165 | } |
compiler/rustc_attr_parsing/src/validate_attr.rs+2-2| ... | ... | @@ -9,7 +9,7 @@ use rustc_ast::{ |
| 9 | 9 | self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety, |
| 10 | 10 | }; |
| 11 | 11 | use rustc_errors::{Applicability, Diagnostic, PResult}; |
| 12 | use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, template}; | |
| 12 | use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, template}; | |
| 13 | 13 | use rustc_hir::AttrPath; |
| 14 | 14 | use rustc_parse::parse_in; |
| 15 | 15 | use rustc_session::errors::report_lit_error; |
| ... | ... | @@ -29,7 +29,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { |
| 29 | 29 | |
| 30 | 30 | // Check input tokens for built-in and key-value attributes. |
| 31 | 31 | match builtin_attr_info { |
| 32 | Some(BuiltinAttribute { name, .. }) => { | |
| 32 | Some(name) => { | |
| 33 | 33 | if AttributeParser::is_parsed_attribute(slice::from_ref(&name)) { |
| 34 | 34 | return; |
| 35 | 35 | } |
compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs+2-3| ... | ... | @@ -44,9 +44,9 @@ fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiPar |
| 44 | 44 | |
| 45 | 45 | fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[(Size, AbiParam); 2]> { |
| 46 | 46 | if let Some(offset_from_start) = cast.rest_offset { |
| 47 | assert!(cast.prefix[1..].iter().all(|p| p.is_none())); | |
| 47 | assert_eq!(cast.prefix.len(), 1); | |
| 48 | 48 | assert_eq!(cast.rest.unit.size, cast.rest.total); |
| 49 | let first = cast.prefix[0].unwrap(); | |
| 49 | let first = cast.prefix[0]; | |
| 50 | 50 | let second = cast.rest.unit; |
| 51 | 51 | return smallvec![ |
| 52 | 52 | (Size::ZERO, reg_to_abi_param(first)), |
| ... | ... | @@ -71,7 +71,6 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[(Size, AbiParam); 2 |
| 71 | 71 | let args = cast |
| 72 | 72 | .prefix |
| 73 | 73 | .iter() |
| 74 | .flatten() | |
| 75 | 74 | .map(|&reg| reg_to_abi_param(reg)) |
| 76 | 75 | .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))); |
| 77 | 76 |
compiler/rustc_codegen_gcc/src/abi.rs+2-2| ... | ... | @@ -46,7 +46,7 @@ impl GccType for CastTarget { |
| 46 | 46 | ) |
| 47 | 47 | }; |
| 48 | 48 | |
| 49 | if self.prefix.iter().all(|x| x.is_none()) { | |
| 49 | if self.prefix.is_empty() { | |
| 50 | 50 | // Simplify to a single unit when there is no prefix and size <= unit size |
| 51 | 51 | if self.rest.total <= self.rest.unit.size { |
| 52 | 52 | return rest_gcc_unit; |
| ... | ... | @@ -62,7 +62,7 @@ impl GccType for CastTarget { |
| 62 | 62 | let mut args: Vec<_> = self |
| 63 | 63 | .prefix |
| 64 | 64 | .iter() |
| 65 | .flat_map(|option_reg| option_reg.map(|reg| reg.gcc_type(cx))) | |
| 65 | .map(|reg| reg.gcc_type(cx)) | |
| 66 | 66 | .chain((0..rest_count).map(|_| rest_gcc_unit)) |
| 67 | 67 | .collect(); |
| 68 | 68 |
compiler/rustc_codegen_llvm/src/abi.rs+2-3| ... | ... | @@ -187,7 +187,7 @@ impl LlvmType for CastTarget { |
| 187 | 187 | |
| 188 | 188 | // Simplify to a single unit or an array if there's no prefix. |
| 189 | 189 | // This produces the same layout, but using a simpler type. |
| 190 | if self.prefix.iter().all(|x| x.is_none()) { | |
| 190 | if self.prefix.is_empty() { | |
| 191 | 191 | // We can't do this if is_consecutive is set and the unit would get |
| 192 | 192 | // split on the target. Currently, this is only relevant for i128 |
| 193 | 193 | // registers. |
| ... | ... | @@ -199,8 +199,7 @@ impl LlvmType for CastTarget { |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | 201 | // Generate a struct type with the prefix and the "rest" arguments. |
| 202 | let prefix_args = | |
| 203 | self.prefix.iter().flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx))); | |
| 202 | let prefix_args = self.prefix.iter().map(|reg| reg.llvm_type(cx)); | |
| 204 | 203 | let rest_args = (0..rest_count).map(|_| rest_ll_unit); |
| 205 | 204 | let args: Vec<_> = prefix_args.chain(rest_args).collect(); |
| 206 | 205 | cx.type_struct(&args, false) |
compiler/rustc_codegen_llvm/src/consts.rs+1| ... | ... | @@ -206,6 +206,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( |
| 206 | 206 | }) |
| 207 | 207 | }); |
| 208 | 208 | llvm::set_linkage(g2, llvm::Linkage::InternalLinkage); |
| 209 | llvm::set_unnamed_address(g2, llvm::UnnamedAddr::Global); | |
| 209 | 210 | llvm::set_initializer(g2, g1); |
| 210 | 211 | g2 |
| 211 | 212 | } else if cx.tcx.sess.target.arch == Arch::X86 |
compiler/rustc_codegen_ssa/src/mir/block.rs+3-4| ... | ... | @@ -2234,9 +2234,9 @@ fn load_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( |
| 2234 | 2234 | ) -> Bx::Value { |
| 2235 | 2235 | let cast_ty = bx.cast_backend_type(cast); |
| 2236 | 2236 | if let Some(offset_from_start) = cast.rest_offset { |
| 2237 | assert!(cast.prefix[1..].iter().all(|p| p.is_none())); | |
| 2237 | assert_eq!(cast.prefix.len(), 1); | |
| 2238 | 2238 | assert_eq!(cast.rest.unit.size, cast.rest.total); |
| 2239 | let first_ty = bx.reg_backend_type(&cast.prefix[0].unwrap()); | |
| 2239 | let first_ty = bx.reg_backend_type(&cast.prefix[0]); | |
| 2240 | 2240 | let second_ty = bx.reg_backend_type(&cast.rest.unit); |
| 2241 | 2241 | let first = bx.load(first_ty, ptr, align); |
| 2242 | 2242 | let second_ptr = bx.inbounds_ptradd(ptr, bx.const_usize(offset_from_start.bytes())); |
| ... | ... | @@ -2257,9 +2257,8 @@ pub fn store_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( |
| 2257 | 2257 | align: Align, |
| 2258 | 2258 | ) { |
| 2259 | 2259 | if let Some(offset_from_start) = cast.rest_offset { |
| 2260 | assert!(cast.prefix[1..].iter().all(|p| p.is_none())); | |
| 2260 | assert_eq!(cast.prefix.len(), 1); | |
| 2261 | 2261 | assert_eq!(cast.rest.unit.size, cast.rest.total); |
| 2262 | assert!(cast.prefix[0].is_some()); | |
| 2263 | 2262 | let first = bx.extract_value(value, 0); |
| 2264 | 2263 | let second = bx.extract_value(value, 1); |
| 2265 | 2264 | bx.store(first, ptr, align); |
compiler/rustc_codegen_ssa/src/mir/naked_asm.rs+1-1| ... | ... | @@ -451,7 +451,7 @@ fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_t |
| 451 | 451 | PassMode::Cast { pad_i32, ref cast } => { |
| 452 | 452 | // For wasm, Cast is used for single-field primitive wrappers like `struct Wrapper(i64);` |
| 453 | 453 | assert!(!pad_i32, "not currently used by wasm calling convention"); |
| 454 | assert!(cast.prefix[0].is_none(), "no prefix"); | |
| 454 | assert!(cast.prefix.is_empty(), "no prefix"); | |
| 455 | 455 | assert_eq!(cast.rest.total, arg_abi.layout.size, "single item"); |
| 456 | 456 | |
| 457 | 457 | let wrapped_wasm_type = match cast.rest.unit.kind { |
compiler/rustc_error_codes/src/error_codes/E0734.md+5-1| ... | ... | @@ -1,8 +1,12 @@ |
| 1 | #### Note: this error code is no longer emitted by the compiler. | |
| 2 | ||
| 3 | This error code was replaced by the more generic E0658. | |
| 4 | ||
| 1 | 5 | A stability attribute has been used outside of the standard library. |
| 2 | 6 | |
| 3 | 7 | Erroneous code example: |
| 4 | 8 | |
| 5 | ```compile_fail,E0734 | |
| 9 | ```compile_fail,E0658 | |
| 6 | 10 | #[stable(feature = "a", since = "b")] // invalid |
| 7 | 11 | #[unstable(feature = "b", issue = "none")] // invalid |
| 8 | 12 | fn foo(){} |
compiler/rustc_feature/src/builtin_attrs.rs+213-483| ... | ... | @@ -2,9 +2,8 @@ |
| 2 | 2 | |
| 3 | 3 | use std::sync::LazyLock; |
| 4 | 4 | |
| 5 | use AttributeGate::*; | |
| 6 | 5 | use rustc_ast::ast::Safety; |
| 7 | use rustc_data_structures::fx::FxHashMap; | |
| 6 | use rustc_data_structures::fx::FxHashSet; | |
| 8 | 7 | use rustc_hir::AttrStyle; |
| 9 | 8 | use rustc_span::{Symbol, sym}; |
| 10 | 9 | |
| ... | ... | @@ -63,20 +62,18 @@ pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg |
| 63 | 62 | } |
| 64 | 63 | |
| 65 | 64 | #[derive(Clone, Debug, Copy)] |
| 66 | pub enum AttributeGate { | |
| 67 | /// A gated attribute which requires a feature gate to be enabled. | |
| 68 | Gated { | |
| 69 | /// The feature gate, for example `#![feature(rustc_attrs)]` for rustc_* attributes. | |
| 70 | feature: Symbol, | |
| 71 | /// The error message displayed when an attempt is made to use the attribute without its feature gate. | |
| 72 | message: &'static str, | |
| 73 | /// Check function to be called during the `PostExpansionVisitor` pass. | |
| 74 | check: fn(&Features) -> bool, | |
| 65 | pub enum AttributeStability { | |
| 66 | /// An attribute that is unstable behind a specified feature fagte | |
| 67 | Unstable { | |
| 68 | /// The feature gate, for example `rustc_attrs` for rustc_* attributes. | |
| 69 | gate_name: Symbol, | |
| 70 | /// Check function to be called during the `PostExpansionVisitor` pass, which will be one of the `Features::*` functions | |
| 71 | gate_check: fn(&Features) -> bool, | |
| 75 | 72 | /// Notes to be displayed when an attempt is made to use the attribute without its feature gate. |
| 76 | 73 | notes: &'static [&'static str], |
| 77 | 74 | }, |
| 78 | /// Ungated attribute, can be used on all release channels | |
| 79 | Ungated, | |
| 75 | /// A stable attribute, can be used on all release channels | |
| 76 | Stable, | |
| 80 | 77 | } |
| 81 | 78 | |
| 82 | 79 | // FIXME(jdonszelmann): move to rustc_hir::attrs |
| ... | ... | @@ -195,608 +192,341 @@ macro_rules! template { |
| 195 | 192 | } }; |
| 196 | 193 | } |
| 197 | 194 | |
| 198 | macro_rules! ungated { | |
| 199 | ($attr:ident $(,)?) => { | |
| 200 | BuiltinAttribute { name: sym::$attr, gate: Ungated } | |
| 201 | }; | |
| 202 | } | |
| 203 | ||
| 204 | macro_rules! gated { | |
| 205 | ($attr:ident, $gate:ident, $message:expr $(,)?) => { | |
| 206 | BuiltinAttribute { | |
| 207 | name: sym::$attr, | |
| 208 | gate: Gated { | |
| 209 | feature: sym::$gate, | |
| 210 | message: $message, | |
| 211 | check: Features::$gate, | |
| 212 | notes: &[], | |
| 213 | }, | |
| 214 | } | |
| 215 | }; | |
| 216 | ($attr:ident, $message:expr $(,)?) => { | |
| 217 | BuiltinAttribute { | |
| 218 | name: sym::$attr, | |
| 219 | gate: Gated { | |
| 220 | feature: sym::$attr, | |
| 221 | message: $message, | |
| 222 | check: Features::$attr, | |
| 223 | notes: &[], | |
| 224 | }, | |
| 225 | } | |
| 226 | }; | |
| 227 | } | |
| 228 | ||
| 229 | macro_rules! rustc_attr { | |
| 230 | (TEST, $attr:ident $(,)?) => { | |
| 231 | rustc_attr!( | |
| 232 | $attr, | |
| 233 | concat!( | |
| 234 | "the `#[", | |
| 235 | stringify!($attr), | |
| 236 | "]` attribute is used for rustc unit tests" | |
| 237 | ), | |
| 238 | ) | |
| 239 | }; | |
| 240 | ($attr:ident $(, $notes:expr)* $(,)?) => { | |
| 241 | BuiltinAttribute { | |
| 242 | name: sym::$attr, | |
| 243 | gate: Gated { | |
| 244 | feature: sym::rustc_attrs, | |
| 245 | message: "use of an internal attribute", | |
| 246 | check: Features::rustc_attrs, | |
| 247 | notes: &[ | |
| 248 | concat!("the `#[", | |
| 249 | stringify!($attr), | |
| 250 | "]` attribute is an internal implementation detail that will never be stable"), | |
| 251 | $($notes),* | |
| 252 | ] | |
| 253 | }, | |
| 254 | } | |
| 255 | }; | |
| 256 | } | |
| 257 | ||
| 258 | macro_rules! experimental { | |
| 259 | ($attr:ident) => { | |
| 260 | concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature") | |
| 261 | }; | |
| 262 | } | |
| 263 | ||
| 264 | pub struct BuiltinAttribute { | |
| 265 | pub name: Symbol, | |
| 266 | pub gate: AttributeGate, | |
| 267 | } | |
| 268 | ||
| 269 | 195 | /// Attributes that have a special meaning to rustc or rustdoc. |
| 270 | 196 | #[rustfmt::skip] |
| 271 | pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ | |
| 197 | pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[ | |
| 272 | 198 | // ========================================================================== |
| 273 | 199 | // Stable attributes: |
| 274 | 200 | // ========================================================================== |
| 275 | 201 | |
| 276 | 202 | // Conditional compilation: |
| 277 | ungated!(cfg), | |
| 278 | ungated!(cfg_attr), | |
| 203 | sym::cfg, | |
| 204 | sym::cfg_attr, | |
| 279 | 205 | |
| 280 | 206 | // Testing: |
| 281 | ungated!(ignore), | |
| 282 | ungated!(should_panic), | |
| 207 | sym::ignore, | |
| 208 | sym::should_panic, | |
| 283 | 209 | |
| 284 | 210 | // Macros: |
| 285 | ungated!(automatically_derived), | |
| 286 | ungated!(macro_use), | |
| 287 | ungated!(macro_escape), // Deprecated synonym for `macro_use`. | |
| 288 | ungated!(macro_export), | |
| 289 | ungated!(proc_macro), | |
| 290 | ungated!(proc_macro_derive), | |
| 291 | ungated!(proc_macro_attribute), | |
| 211 | sym::automatically_derived, | |
| 212 | sym::macro_use, | |
| 213 | sym::macro_escape, // Deprecated synonym for `macro_use`. | |
| 214 | sym::macro_export, | |
| 215 | sym::proc_macro, | |
| 216 | sym::proc_macro_derive, | |
| 217 | sym::proc_macro_attribute, | |
| 292 | 218 | |
| 293 | 219 | // Lints: |
| 294 | ungated!(warn), | |
| 295 | ungated!(allow), | |
| 296 | ungated!(expect), | |
| 297 | ungated!(forbid), | |
| 298 | ungated!(deny), | |
| 299 | ungated!(must_use), | |
| 300 | gated!(must_not_suspend, experimental!(must_not_suspend)), | |
| 301 | ungated!(deprecated), | |
| 220 | sym::warn, | |
| 221 | sym::allow, | |
| 222 | sym::expect, | |
| 223 | sym::forbid, | |
| 224 | sym::deny, | |
| 225 | sym::must_use, | |
| 226 | sym::must_not_suspend, | |
| 227 | sym::deprecated, | |
| 302 | 228 | |
| 303 | 229 | // Crate properties: |
| 304 | ungated!(crate_name), | |
| 305 | ungated!(crate_type), | |
| 230 | sym::crate_name, | |
| 231 | sym::crate_type, | |
| 306 | 232 | |
| 307 | 233 | // ABI, linking, symbols, and FFI |
| 308 | ungated!(link), | |
| 309 | ungated!(link_name), | |
| 310 | ungated!(no_link), | |
| 311 | ungated!(repr), | |
| 234 | sym::link, | |
| 235 | sym::link_name, | |
| 236 | sym::no_link, | |
| 237 | sym::repr, | |
| 312 | 238 | // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity |
| 313 | gated!(rustc_align, fn_align, experimental!(rustc_align)), | |
| 314 | gated!(rustc_align_static, static_align, experimental!(rustc_align_static)), | |
| 315 | ungated!(export_name), | |
| 316 | ungated!(link_section), | |
| 317 | ungated!(no_mangle), | |
| 318 | ungated!(used), | |
| 319 | ungated!(link_ordinal), | |
| 320 | ungated!(naked), | |
| 239 | sym::rustc_align, | |
| 240 | sym::rustc_align_static, | |
| 241 | sym::export_name, | |
| 242 | sym::link_section, | |
| 243 | sym::no_mangle, | |
| 244 | sym::used, | |
| 245 | sym::link_ordinal, | |
| 246 | sym::naked, | |
| 321 | 247 | // See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details. |
| 322 | rustc_attr!(rustc_pass_indirectly_in_non_rustic_abis, "types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic ABIs"), | |
| 248 | sym::rustc_pass_indirectly_in_non_rustic_abis, | |
| 323 | 249 | |
| 324 | 250 | // Limits: |
| 325 | ungated!(recursion_limit), | |
| 326 | ungated!(type_length_limit), | |
| 327 | gated!(move_size_limit, large_assignments, experimental!(move_size_limit)), | |
| 251 | sym::recursion_limit, | |
| 252 | sym::type_length_limit, | |
| 253 | sym::move_size_limit, | |
| 328 | 254 | |
| 329 | 255 | // Entry point: |
| 330 | ungated!(no_main), | |
| 256 | sym::no_main, | |
| 331 | 257 | |
| 332 | 258 | // Modules, prelude, and resolution: |
| 333 | ungated!(path), | |
| 334 | ungated!(no_std), | |
| 335 | ungated!(no_implicit_prelude), | |
| 336 | ungated!(non_exhaustive), | |
| 259 | sym::path, | |
| 260 | sym::no_std, | |
| 261 | sym::no_implicit_prelude, | |
| 262 | sym::non_exhaustive, | |
| 337 | 263 | |
| 338 | 264 | // Runtime |
| 339 | ungated!(windows_subsystem), | |
| 340 | ungated!(panic_handler), // RFC 2070 | |
| 265 | sym::windows_subsystem, | |
| 266 | sym::panic_handler, // RFC 2070 | |
| 341 | 267 | |
| 342 | 268 | // Code generation: |
| 343 | ungated!(inline), | |
| 344 | ungated!(cold), | |
| 345 | ungated!(no_builtins), | |
| 346 | ungated!(target_feature), | |
| 347 | ungated!(track_caller), | |
| 348 | ungated!(instruction_set), | |
| 349 | gated!(force_target_feature, effective_target_features, experimental!(force_target_feature)), | |
| 350 | gated!(sanitize, sanitize, experimental!(sanitize)), | |
| 351 | gated!(coverage, coverage_attribute, experimental!(coverage)), | |
| 352 | ||
| 353 | ungated!(doc), | |
| 269 | sym::inline, | |
| 270 | sym::cold, | |
| 271 | sym::no_builtins, | |
| 272 | sym::target_feature, | |
| 273 | sym::track_caller, | |
| 274 | sym::instruction_set, | |
| 275 | sym::force_target_feature, | |
| 276 | sym::sanitize, | |
| 277 | sym::coverage, | |
| 278 | ||
| 279 | sym::doc, | |
| 354 | 280 | |
| 355 | 281 | // Debugging |
| 356 | ungated!(debugger_visualizer), | |
| 357 | ungated!(collapse_debuginfo), | |
| 282 | sym::debugger_visualizer, | |
| 283 | sym::collapse_debuginfo, | |
| 358 | 284 | |
| 359 | 285 | // ========================================================================== |
| 360 | 286 | // Unstable attributes: |
| 361 | 287 | // ========================================================================== |
| 362 | 288 | |
| 363 | 289 | // Linking: |
| 364 | gated!(export_stable, experimental!(export_stable)), | |
| 290 | sym::export_stable, | |
| 365 | 291 | |
| 366 | 292 | // Testing: |
| 367 | gated!(test_runner, custom_test_frameworks, "custom test frameworks are an unstable feature"), | |
| 293 | sym::test_runner, | |
| 368 | 294 | |
| 369 | gated!(reexport_test_harness_main, custom_test_frameworks, "custom test frameworks are an unstable feature"), | |
| 295 | sym::reexport_test_harness_main, | |
| 370 | 296 | |
| 371 | 297 | // RFC #1268 |
| 372 | gated!(marker, marker_trait_attr, experimental!(marker)), | |
| 373 | gated!(thread_local, "`#[thread_local]` is an experimental feature, and does not currently handle destructors"), | |
| 374 | gated!(no_core, experimental!(no_core)), | |
| 298 | sym::marker, | |
| 299 | sym::thread_local, | |
| 300 | sym::no_core, | |
| 375 | 301 | // RFC 2412 |
| 376 | gated!(optimize, optimize_attribute, experimental!(optimize)), | |
| 302 | sym::optimize, | |
| 377 | 303 | |
| 378 | gated!(ffi_pure, experimental!(ffi_pure)), | |
| 379 | gated!(ffi_const, experimental!(ffi_const)), | |
| 380 | gated!(register_tool, experimental!(register_tool)), | |
| 304 | sym::ffi_pure, | |
| 305 | sym::ffi_const, | |
| 306 | sym::register_tool, | |
| 381 | 307 | // `#[cfi_encoding = ""]` |
| 382 | gated!(cfi_encoding, experimental!(cfi_encoding)), | |
| 308 | sym::cfi_encoding, | |
| 383 | 309 | |
| 384 | 310 | // `#[coroutine]` attribute to be applied to closures to make them coroutines instead |
| 385 | gated!(coroutine, coroutines, experimental!(coroutine)), | |
| 311 | sym::coroutine, | |
| 386 | 312 | |
| 387 | 313 | // RFC 3543 |
| 388 | 314 | // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` |
| 389 | gated!(patchable_function_entry, experimental!(patchable_function_entry)), | |
| 315 | sym::patchable_function_entry, | |
| 390 | 316 | |
| 391 | 317 | // The `#[loop_match]` and `#[const_continue]` attributes are part of the |
| 392 | 318 | // lang experiment for RFC 3720 tracked in: |
| 393 | 319 | // |
| 394 | 320 | // - https://github.com/rust-lang/rust/issues/132306 |
| 395 | gated!(const_continue, loop_match, experimental!(const_continue)), | |
| 396 | gated!(loop_match, loop_match, experimental!(loop_match)), | |
| 321 | sym::const_continue, | |
| 322 | sym::loop_match, | |
| 397 | 323 | |
| 398 | 324 | // The `#[pin_v2]` attribute is part of the `pin_ergonomics` experiment |
| 399 | 325 | // that allows structurally pinning, tracked in: |
| 400 | 326 | // |
| 401 | 327 | // - https://github.com/rust-lang/rust/issues/130494 |
| 402 | gated!(pin_v2, pin_ergonomics, experimental!(pin_v2)), | |
| 328 | sym::pin_v2, | |
| 403 | 329 | |
| 404 | 330 | // ========================================================================== |
| 405 | 331 | // Internal attributes: Stability, deprecation, and unsafe: |
| 406 | 332 | // ========================================================================== |
| 407 | 333 | |
| 408 | ungated!(feature), | |
| 334 | sym::feature, | |
| 409 | 335 | // DuplicatesOk since it has its own validation |
| 410 | ungated!(stable), | |
| 411 | ungated!(unstable), | |
| 412 | ungated!(unstable_feature_bound), | |
| 413 | ungated!(unstable_removed), | |
| 414 | ungated!(rustc_const_unstable), | |
| 415 | ungated!(rustc_const_stable), | |
| 416 | ungated!(rustc_default_body_unstable), | |
| 417 | gated!( | |
| 418 | allow_internal_unstable, | |
| 419 | "allow_internal_unstable side-steps feature gating and stability checks", | |
| 420 | ), | |
| 421 | gated!( | |
| 422 | allow_internal_unsafe, | |
| 423 | "allow_internal_unsafe side-steps the unsafe_code lint", | |
| 424 | ), | |
| 425 | gated!( | |
| 426 | rustc_eii_foreign_item, | |
| 427 | eii_internals, | |
| 428 | "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", | |
| 429 | ), | |
| 430 | rustc_attr!( | |
| 431 | rustc_allowed_through_unstable_modules, | |
| 432 | "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ | |
| 433 | through unstable paths" | |
| 434 | ), | |
| 435 | rustc_attr!( | |
| 436 | rustc_deprecated_safe_2024, | |
| 437 | "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary", | |
| 438 | ), | |
| 439 | rustc_attr!( | |
| 440 | rustc_pub_transparent, | |
| 441 | "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", | |
| 442 | ), | |
| 336 | sym::stable, | |
| 337 | sym::unstable, | |
| 338 | sym::unstable_feature_bound, | |
| 339 | sym::unstable_removed, | |
| 340 | sym::rustc_const_unstable, | |
| 341 | sym::rustc_const_stable, | |
| 342 | sym::rustc_default_body_unstable, | |
| 343 | sym::allow_internal_unstable, | |
| 344 | sym::allow_internal_unsafe, | |
| 345 | sym::rustc_eii_foreign_item, | |
| 346 | sym::rustc_allowed_through_unstable_modules, | |
| 347 | sym::rustc_deprecated_safe_2024, | |
| 348 | sym::rustc_pub_transparent, | |
| 443 | 349 | |
| 444 | 350 | |
| 445 | 351 | // ========================================================================== |
| 446 | 352 | // Internal attributes: Type system related: |
| 447 | 353 | // ========================================================================== |
| 448 | 354 | |
| 449 | gated!(fundamental, experimental!(fundamental)), | |
| 450 | gated!( | |
| 451 | may_dangle, | |
| 452 | dropck_eyepatch, | |
| 453 | "`may_dangle` has unstable semantics and may be removed in the future", | |
| 454 | ), | |
| 355 | sym::fundamental, | |
| 356 | sym::may_dangle, | |
| 455 | 357 | |
| 456 | rustc_attr!( | |
| 457 | rustc_never_type_options, | |
| 458 | "`rustc_never_type_options` is used to experiment with never type fallback and work on \ | |
| 459 | never type stabilization" | |
| 460 | ), | |
| 358 | sym::rustc_never_type_options, | |
| 461 | 359 | |
| 462 | 360 | // ========================================================================== |
| 463 | 361 | // Internal attributes: Runtime related: |
| 464 | 362 | // ========================================================================== |
| 465 | 363 | |
| 466 | rustc_attr!(rustc_allocator), | |
| 467 | rustc_attr!(rustc_nounwind), | |
| 468 | rustc_attr!(rustc_reallocator), | |
| 469 | rustc_attr!(rustc_deallocator), | |
| 470 | rustc_attr!(rustc_allocator_zeroed), | |
| 471 | rustc_attr!(rustc_allocator_zeroed_variant), | |
| 472 | gated!( | |
| 473 | default_lib_allocator, | |
| 474 | allocator_internals, experimental!(default_lib_allocator), | |
| 475 | ), | |
| 476 | gated!( | |
| 477 | needs_allocator, | |
| 478 | allocator_internals, experimental!(needs_allocator), | |
| 479 | ), | |
| 480 | gated!( | |
| 481 | panic_runtime, | |
| 482 | experimental!(panic_runtime) | |
| 483 | ), | |
| 484 | gated!( | |
| 485 | needs_panic_runtime, | |
| 486 | experimental!(needs_panic_runtime) | |
| 487 | ), | |
| 488 | gated!( | |
| 489 | compiler_builtins, | |
| 490 | "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ | |
| 491 | which contains compiler-rt intrinsics and will never be stable", | |
| 492 | ), | |
| 493 | gated!( | |
| 494 | profiler_runtime, | |
| 495 | "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ | |
| 496 | which contains the profiler runtime and will never be stable", | |
| 497 | ), | |
| 364 | sym::rustc_allocator, | |
| 365 | sym::rustc_nounwind, | |
| 366 | sym::rustc_reallocator, | |
| 367 | sym::rustc_deallocator, | |
| 368 | sym::rustc_allocator_zeroed, | |
| 369 | sym::rustc_allocator_zeroed_variant, | |
| 370 | sym::default_lib_allocator, | |
| 371 | sym::needs_allocator, | |
| 372 | sym::panic_runtime, | |
| 373 | sym::needs_panic_runtime, | |
| 374 | sym::compiler_builtins, | |
| 375 | sym::profiler_runtime, | |
| 498 | 376 | |
| 499 | 377 | // ========================================================================== |
| 500 | 378 | // Internal attributes, Linkage: |
| 501 | 379 | // ========================================================================== |
| 502 | 380 | |
| 503 | gated!( | |
| 504 | linkage, | |
| 505 | "the `linkage` attribute is experimental and not portable across platforms", | |
| 506 | ), | |
| 507 | rustc_attr!(rustc_std_internal_symbol), | |
| 508 | rustc_attr!(rustc_objc_class), | |
| 509 | rustc_attr!(rustc_objc_selector), | |
| 381 | sym::linkage, | |
| 382 | sym::rustc_std_internal_symbol, | |
| 383 | sym::rustc_objc_class, | |
| 384 | sym::rustc_objc_selector, | |
| 510 | 385 | |
| 511 | 386 | // ========================================================================== |
| 512 | 387 | // Internal attributes, Macro related: |
| 513 | 388 | // ========================================================================== |
| 514 | 389 | |
| 515 | rustc_attr!(rustc_builtin_macro), | |
| 516 | rustc_attr!(rustc_proc_macro_decls), | |
| 517 | rustc_attr!( | |
| 518 | rustc_macro_transparency, | |
| 519 | "used internally for testing macro hygiene", | |
| 520 | ), | |
| 521 | rustc_attr!(rustc_autodiff), | |
| 522 | rustc_attr!(rustc_offload_kernel), | |
| 390 | sym::rustc_builtin_macro, | |
| 391 | sym::rustc_proc_macro_decls, | |
| 392 | sym::rustc_macro_transparency, | |
| 393 | sym::rustc_autodiff, | |
| 394 | sym::rustc_offload_kernel, | |
| 523 | 395 | // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. |
| 524 | 396 | // The attributes are not gated, to avoid stability errors, but they cannot be used in stable |
| 525 | 397 | // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they |
| 526 | 398 | // can only be generated by the compiler. |
| 527 | ungated!(cfg_trace), | |
| 528 | ungated!(cfg_attr_trace), | |
| 399 | sym::cfg_trace, | |
| 400 | sym::cfg_attr_trace, | |
| 529 | 401 | |
| 530 | 402 | // ========================================================================== |
| 531 | 403 | // Internal attributes, Diagnostics related: |
| 532 | 404 | // ========================================================================== |
| 533 | 405 | |
| 534 | rustc_attr!( | |
| 535 | rustc_on_unimplemented, | |
| 536 | "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute" | |
| 537 | ), | |
| 538 | rustc_attr!(rustc_confusables), | |
| 406 | sym::rustc_on_unimplemented, | |
| 407 | sym::rustc_confusables, | |
| 539 | 408 | // Enumerates "identity-like" conversion methods to suggest on type mismatch. |
| 540 | rustc_attr!(rustc_conversion_suggestion), | |
| 409 | sym::rustc_conversion_suggestion, | |
| 541 | 410 | // Prevents field reads in the marked trait or method to be considered |
| 542 | 411 | // during dead code analysis. |
| 543 | rustc_attr!(rustc_trivial_field_reads), | |
| 412 | sym::rustc_trivial_field_reads, | |
| 544 | 413 | // Used by the `rustc::potential_query_instability` lint to warn methods which |
| 545 | 414 | // might not be stable during incremental compilation. |
| 546 | rustc_attr!(rustc_lint_query_instability), | |
| 415 | sym::rustc_lint_query_instability, | |
| 547 | 416 | // Used by the `rustc::untracked_query_information` lint to warn methods which |
| 548 | 417 | // might not be stable during incremental compilation. |
| 549 | rustc_attr!(rustc_lint_untracked_query_information), | |
| 418 | sym::rustc_lint_untracked_query_information, | |
| 550 | 419 | // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` |
| 551 | 420 | // types (as well as any others in future). |
| 552 | rustc_attr!(rustc_lint_opt_ty), | |
| 421 | sym::rustc_lint_opt_ty, | |
| 553 | 422 | // Used by the `rustc::bad_opt_access` lint on fields |
| 554 | 423 | // types (as well as any others in future). |
| 555 | rustc_attr!(rustc_lint_opt_deny_field_access), | |
| 424 | sym::rustc_lint_opt_deny_field_access, | |
| 556 | 425 | |
| 557 | 426 | // ========================================================================== |
| 558 | 427 | // Internal attributes, Const related: |
| 559 | 428 | // ========================================================================== |
| 560 | 429 | |
| 561 | rustc_attr!(rustc_promotable), | |
| 562 | rustc_attr!(rustc_legacy_const_generics), | |
| 430 | sym::rustc_promotable, | |
| 431 | sym::rustc_legacy_const_generics, | |
| 563 | 432 | // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. |
| 564 | rustc_attr!( | |
| 565 | rustc_do_not_const_check, | |
| 566 | "`#[rustc_do_not_const_check]` skips const-check for this function's body", | |
| 567 | ), | |
| 568 | rustc_attr!( | |
| 569 | rustc_const_stable_indirect, | |
| 570 | "this is an internal implementation detail", | |
| 571 | ), | |
| 572 | rustc_attr!( | |
| 573 | rustc_intrinsic_const_stable_indirect, | |
| 574 | "this is an internal implementation detail", | |
| 575 | ), | |
| 576 | rustc_attr!( | |
| 577 | rustc_allow_const_fn_unstable, | |
| 578 | "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" | |
| 579 | ), | |
| 433 | sym::rustc_do_not_const_check, | |
| 434 | sym::rustc_const_stable_indirect, | |
| 435 | sym::rustc_intrinsic_const_stable_indirect, | |
| 436 | sym::rustc_allow_const_fn_unstable, | |
| 580 | 437 | |
| 581 | 438 | // ========================================================================== |
| 582 | 439 | // Internal attributes, Layout related: |
| 583 | 440 | // ========================================================================== |
| 584 | 441 | |
| 585 | rustc_attr!( | |
| 586 | rustc_simd_monomorphize_lane_limit, | |
| 587 | "the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \ | |
| 588 | for better error messages", | |
| 589 | ), | |
| 590 | rustc_attr!( | |
| 591 | rustc_nonnull_optimization_guaranteed, | |
| 592 | "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document \ | |
| 593 | guaranteed niche optimizations in the standard library", | |
| 594 | "the compiler does not even check whether the type indeed is being non-null-optimized; \ | |
| 595 | it is your responsibility to ensure that the attribute is only used on types that are optimized", | |
| 596 | ), | |
| 442 | sym::rustc_simd_monomorphize_lane_limit, | |
| 443 | sym::rustc_nonnull_optimization_guaranteed, | |
| 597 | 444 | |
| 598 | 445 | // ========================================================================== |
| 599 | 446 | // Internal attributes, Misc: |
| 600 | 447 | // ========================================================================== |
| 601 | gated!( | |
| 602 | lang, lang_items, | |
| 603 | "lang items are subject to change", | |
| 604 | ), | |
| 605 | rustc_attr!( | |
| 606 | rustc_as_ptr, | |
| 607 | "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations" | |
| 608 | ), | |
| 609 | rustc_attr!( | |
| 610 | rustc_should_not_be_called_on_const_items, | |
| 611 | "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts" | |
| 612 | ), | |
| 613 | rustc_attr!( | |
| 614 | rustc_pass_by_value, | |
| 615 | "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference" | |
| 616 | ), | |
| 617 | rustc_attr!( | |
| 618 | rustc_never_returns_null_ptr, | |
| 619 | "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers" | |
| 620 | ), | |
| 621 | rustc_attr!( | |
| 622 | rustc_no_implicit_autorefs, | |
| 623 | "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument" | |
| 624 | ), | |
| 625 | rustc_attr!( | |
| 626 | rustc_coherence_is_core, | |
| 627 | "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`" | |
| 628 | ), | |
| 629 | rustc_attr!( | |
| 630 | rustc_coinductive, | |
| 631 | "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver" | |
| 632 | ), | |
| 633 | rustc_attr!( | |
| 634 | rustc_allow_incoherent_impl, | |
| 635 | "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl" | |
| 636 | ), | |
| 637 | rustc_attr!( | |
| 638 | rustc_preserve_ub_checks, | |
| 639 | "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR", | |
| 640 | ), | |
| 641 | rustc_attr!( | |
| 642 | rustc_deny_explicit_impl, | |
| 643 | "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls" | |
| 644 | ), | |
| 645 | rustc_attr!( | |
| 646 | rustc_dyn_incompatible_trait, | |
| 647 | "`#[rustc_dyn_incompatible_trait]` marks a trait as dyn-incompatible, \ | |
| 648 | even if it otherwise satisfies the requirements to be dyn-compatible." | |
| 649 | ), | |
| 650 | rustc_attr!( | |
| 651 | rustc_has_incoherent_inherent_impls, | |
| 652 | "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \ | |
| 653 | the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`" | |
| 654 | ), | |
| 655 | rustc_attr!( | |
| 656 | rustc_non_const_trait_method, | |
| 657 | "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ | |
| 658 | as non-const to allow large traits an easier transition to const" | |
| 659 | ), | |
| 660 | ||
| 661 | BuiltinAttribute { | |
| 662 | name: sym::rustc_diagnostic_item, | |
| 663 | gate: Gated { | |
| 664 | feature: sym::rustc_attrs, | |
| 665 | message: "use of an internal attribute", | |
| 666 | check: Features::rustc_attrs, | |
| 667 | notes: &["the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types \ | |
| 668 | from the standard library for diagnostic purposes"], | |
| 669 | }, | |
| 670 | }, | |
| 671 | gated!( | |
| 672 | // Used in resolve: | |
| 673 | prelude_import, | |
| 674 | "`#[prelude_import]` is for use by rustc only", | |
| 675 | ), | |
| 676 | gated!( | |
| 677 | rustc_paren_sugar, | |
| 678 | unboxed_closures, "unboxed_closures are still evolving", | |
| 679 | ), | |
| 680 | rustc_attr!( | |
| 681 | rustc_inherit_overflow_checks, | |
| 682 | "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ | |
| 683 | overflow checking behavior of several functions in the standard library that are inlined \ | |
| 684 | across crates", | |
| 685 | ), | |
| 686 | rustc_attr!( | |
| 687 | rustc_reservation_impl, | |
| 688 | "the `#[rustc_reservation_impl]` attribute is internally used \ | |
| 689 | for reserving `impl<T> From<!> for T` as part of the effort to stabilize `!`" | |
| 690 | ), | |
| 691 | rustc_attr!( | |
| 692 | rustc_test_marker, | |
| 693 | "the `#[rustc_test_marker]` attribute is used internally to track tests", | |
| 694 | ), | |
| 695 | rustc_attr!( | |
| 696 | rustc_unsafe_specialization_marker, | |
| 697 | "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" | |
| 698 | ), | |
| 699 | rustc_attr!( | |
| 700 | rustc_specialization_trait, | |
| 701 | "the `#[rustc_specialization_trait]` attribute is used to check specializations" | |
| 702 | ), | |
| 703 | rustc_attr!( | |
| 704 | rustc_main, | |
| 705 | "the `#[rustc_main]` attribute is used internally to specify test entry point function", | |
| 706 | ), | |
| 707 | rustc_attr!( | |
| 708 | rustc_skip_during_method_dispatch, | |
| 709 | "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ | |
| 710 | from method dispatch when the receiver is of the following type, for compatibility in \ | |
| 711 | editions < 2021 (array) or editions < 2024 (boxed_slice)" | |
| 712 | ), | |
| 713 | rustc_attr!( | |
| 714 | rustc_must_implement_one_of, | |
| 715 | "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ | |
| 716 | definition of a trait. Its syntax and semantics are highly experimental and will be \ | |
| 717 | subject to change before stabilization", | |
| 718 | ), | |
| 719 | rustc_attr!( | |
| 720 | rustc_doc_primitive, | |
| 721 | "the `#[rustc_doc_primitive]` attribute is used by the standard library \ | |
| 722 | to provide a way to generate documentation for primitive types", | |
| 723 | ), | |
| 724 | gated!( | |
| 725 | rustc_intrinsic, intrinsics, | |
| 726 | "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items", | |
| 727 | ), | |
| 728 | rustc_attr!( | |
| 729 | rustc_no_mir_inline, | |
| 730 | "`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen" | |
| 731 | ), | |
| 732 | rustc_attr!( | |
| 733 | rustc_force_inline, | |
| 734 | "`#[rustc_force_inline]` forces a free function to be inlined" | |
| 735 | ), | |
| 736 | rustc_attr!( | |
| 737 | rustc_scalable_vector, | |
| 738 | "`#[rustc_scalable_vector]` defines a scalable vector type" | |
| 739 | ), | |
| 740 | rustc_attr!( | |
| 741 | rustc_must_match_exhaustively, | |
| 742 | "enums with `#[rustc_must_match_exhaustively]` must be matched on with a match block that mentions all variants explicitly" | |
| 743 | ), | |
| 744 | rustc_attr!( | |
| 745 | rustc_no_writable, | |
| 746 | "`#[rustc_no_writable]` stops the compiler from considering mutable reference arguments of this function as implicitly writable" | |
| 747 | ), | |
| 448 | sym::lang, | |
| 449 | sym::rustc_as_ptr, | |
| 450 | sym::rustc_should_not_be_called_on_const_items, | |
| 451 | sym::rustc_pass_by_value, | |
| 452 | sym::rustc_never_returns_null_ptr, | |
| 453 | sym::rustc_no_implicit_autorefs, | |
| 454 | sym::rustc_coherence_is_core, | |
| 455 | sym::rustc_coinductive, | |
| 456 | sym::rustc_allow_incoherent_impl, | |
| 457 | sym::rustc_preserve_ub_checks, | |
| 458 | sym::rustc_deny_explicit_impl, | |
| 459 | sym::rustc_dyn_incompatible_trait, | |
| 460 | sym::rustc_has_incoherent_inherent_impls, | |
| 461 | sym::rustc_non_const_trait_method, | |
| 462 | ||
| 463 | sym::rustc_diagnostic_item, | |
| 464 | sym::prelude_import, | |
| 465 | sym::rustc_paren_sugar, | |
| 466 | sym::rustc_inherit_overflow_checks, | |
| 467 | sym::rustc_reservation_impl, | |
| 468 | sym::rustc_test_marker, | |
| 469 | sym::rustc_unsafe_specialization_marker, | |
| 470 | sym::rustc_specialization_trait, | |
| 471 | sym::rustc_main, | |
| 472 | sym::rustc_skip_during_method_dispatch, | |
| 473 | sym::rustc_must_implement_one_of, | |
| 474 | sym::rustc_doc_primitive, | |
| 475 | sym::rustc_intrinsic, | |
| 476 | sym::rustc_no_mir_inline, | |
| 477 | sym::rustc_force_inline, | |
| 478 | sym::rustc_scalable_vector, | |
| 479 | sym::rustc_must_match_exhaustively, | |
| 480 | sym::rustc_no_writable, | |
| 748 | 481 | |
| 749 | 482 | // ========================================================================== |
| 750 | 483 | // Internal attributes, Testing: |
| 751 | 484 | // ========================================================================== |
| 752 | 485 | |
| 753 | rustc_attr!(TEST, rustc_effective_visibility), | |
| 754 | rustc_attr!(TEST, rustc_dump_inferred_outlives), | |
| 755 | rustc_attr!(TEST, rustc_capture_analysis,), | |
| 756 | rustc_attr!(TEST, rustc_insignificant_dtor), | |
| 757 | rustc_attr!(TEST, rustc_no_implicit_bounds), | |
| 758 | rustc_attr!(TEST, rustc_strict_coherence), | |
| 759 | rustc_attr!(TEST, rustc_dump_variances), | |
| 760 | rustc_attr!(TEST, rustc_dump_variances_of_opaques), | |
| 761 | rustc_attr!(TEST, rustc_dump_hidden_type_of_opaques), | |
| 762 | rustc_attr!(TEST, rustc_dump_layout), | |
| 763 | rustc_attr!(TEST, rustc_abi), | |
| 764 | rustc_attr!(TEST, rustc_regions), | |
| 765 | rustc_attr!(TEST, rustc_delayed_bug_from_inside_query), | |
| 766 | rustc_attr!(TEST, rustc_dump_user_args), | |
| 767 | rustc_attr!(TEST, rustc_evaluate_where_clauses), | |
| 768 | rustc_attr!(TEST, rustc_if_this_changed), | |
| 769 | rustc_attr!(TEST, rustc_then_this_would_need), | |
| 770 | rustc_attr!(TEST, rustc_clean), | |
| 771 | rustc_attr!(TEST, rustc_partition_reused), | |
| 772 | rustc_attr!(TEST, rustc_partition_codegened), | |
| 773 | rustc_attr!(TEST, rustc_expected_cgu_reuse), | |
| 774 | rustc_attr!(TEST, rustc_dump_symbol_name), | |
| 775 | rustc_attr!(TEST, rustc_dump_def_path), | |
| 776 | rustc_attr!(TEST, rustc_mir), | |
| 777 | gated!( | |
| 778 | custom_mir, "the `#[custom_mir]` attribute is just used for the Rust test suite", | |
| 779 | ), | |
| 780 | rustc_attr!(TEST, rustc_dump_item_bounds), | |
| 781 | rustc_attr!(TEST, rustc_dump_predicates), | |
| 782 | rustc_attr!(TEST, rustc_dump_def_parents), | |
| 783 | rustc_attr!(TEST, rustc_dump_object_lifetime_defaults), | |
| 784 | rustc_attr!(TEST, rustc_dump_vtable), | |
| 785 | rustc_attr!(TEST, rustc_dummy), | |
| 786 | rustc_attr!(TEST, pattern_complexity_limit), | |
| 486 | sym::rustc_effective_visibility, | |
| 487 | sym::rustc_dump_inferred_outlives, | |
| 488 | sym::rustc_capture_analysis, | |
| 489 | sym::rustc_insignificant_dtor, | |
| 490 | sym::rustc_no_implicit_bounds, | |
| 491 | sym::rustc_strict_coherence, | |
| 492 | sym::rustc_dump_variances, | |
| 493 | sym::rustc_dump_variances_of_opaques, | |
| 494 | sym::rustc_dump_hidden_type_of_opaques, | |
| 495 | sym::rustc_dump_layout, | |
| 496 | sym::rustc_abi, | |
| 497 | sym::rustc_regions, | |
| 498 | sym::rustc_delayed_bug_from_inside_query, | |
| 499 | sym::rustc_dump_user_args, | |
| 500 | sym::rustc_evaluate_where_clauses, | |
| 501 | sym::rustc_if_this_changed, | |
| 502 | sym::rustc_then_this_would_need, | |
| 503 | sym::rustc_clean, | |
| 504 | sym::rustc_partition_reused, | |
| 505 | sym::rustc_partition_codegened, | |
| 506 | sym::rustc_expected_cgu_reuse, | |
| 507 | sym::rustc_dump_symbol_name, | |
| 508 | sym::rustc_dump_def_path, | |
| 509 | sym::rustc_mir, | |
| 510 | sym::custom_mir, | |
| 511 | sym::rustc_dump_item_bounds, | |
| 512 | sym::rustc_dump_predicates, | |
| 513 | sym::rustc_dump_def_parents, | |
| 514 | sym::rustc_dump_object_lifetime_defaults, | |
| 515 | sym::rustc_dump_vtable, | |
| 516 | sym::rustc_dummy, | |
| 517 | sym::pattern_complexity_limit, | |
| 787 | 518 | ]; |
| 788 | 519 | |
| 789 | 520 | pub fn is_builtin_attr_name(name: Symbol) -> bool { |
| 790 | 521 | BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() |
| 791 | 522 | } |
| 792 | 523 | |
| 793 | pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> = | |
| 794 | LazyLock::new(|| { | |
| 795 | let mut map = FxHashMap::default(); | |
| 796 | for attr in BUILTIN_ATTRIBUTES.iter() { | |
| 797 | if map.insert(attr.name, attr).is_some() { | |
| 798 | panic!("duplicate builtin attribute `{}`", attr.name); | |
| 799 | } | |
| 524 | pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashSet<Symbol>> = LazyLock::new(|| { | |
| 525 | let mut map = FxHashSet::default(); | |
| 526 | for attr in BUILTIN_ATTRIBUTES.iter() { | |
| 527 | if !map.insert(*attr) { | |
| 528 | panic!("duplicate builtin attribute `{}`", attr); | |
| 800 | 529 | } |
| 801 | map | |
| 802 | }); | |
| 530 | } | |
| 531 | map | |
| 532 | }); |
compiler/rustc_feature/src/lib.rs+2-2| ... | ... | @@ -129,8 +129,8 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u |
| 129 | 129 | |
| 130 | 130 | pub use accepted::ACCEPTED_LANG_FEATURES; |
| 131 | 131 | pub use builtin_attrs::{ |
| 132 | AttrSuggestionStyle, AttributeGate, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, | |
| 133 | BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg, find_gated_cfg, is_builtin_attr_name, | |
| 132 | AttrSuggestionStyle, AttributeStability, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, | |
| 133 | BUILTIN_ATTRIBUTES, GatedCfg, find_gated_cfg, is_builtin_attr_name, | |
| 134 | 134 | }; |
| 135 | 135 | pub use removed::REMOVED_LANG_FEATURES; |
| 136 | 136 | pub use unstable::{ |
compiler/rustc_monomorphize/src/mono_checks/abi_check.rs+1-4| ... | ... | @@ -25,10 +25,7 @@ fn passes_vectors_by_value(mode: &PassMode, repr: &BackendRepr) -> UsesVectorReg |
| 25 | 25 | match mode { |
| 26 | 26 | PassMode::Ignore | PassMode::Indirect { .. } => UsesVectorRegisters::No, |
| 27 | 27 | PassMode::Cast { pad_i32: _, cast } |
| 28 | if cast | |
| 29 | .prefix | |
| 30 | .iter() | |
| 31 | .any(|r| r.is_some_and(|x| matches!(x.kind, RegKind::Vector { .. }))) | |
| 28 | if cast.prefix.iter().any(|x| matches!(x.kind, RegKind::Vector { .. })) | |
| 32 | 29 | || matches!(cast.rest.unit.kind, RegKind::Vector { .. }) => |
| 33 | 30 | { |
| 34 | 31 | UsesVectorRegisters::FixedVector |
compiler/rustc_passes/src/eii.rs+1| ... | ... | @@ -141,6 +141,7 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, (): |
| 141 | 141 | decl_crate_name: tcx.crate_name(decl_crate), |
| 142 | 142 | // FIXME: shouldn't call `item_name` |
| 143 | 143 | name: decl.name.name, |
| 144 | kind: tcx.def_kind(decl.foreign_item).descr(decl.foreign_item), | |
| 144 | 145 | span: decl.name.span, |
| 145 | 146 | help: (), |
| 146 | 147 | }); |
compiler/rustc_passes/src/errors.rs+2-1| ... | ... | @@ -1209,12 +1209,13 @@ pub(crate) struct EiiWithTrackCaller { |
| 1209 | 1209 | } |
| 1210 | 1210 | |
| 1211 | 1211 | #[derive(Diagnostic)] |
| 1212 | #[diag("`#[{$name}]` required, but not found")] | |
| 1212 | #[diag("`#[{$name}]` {$kind} required, but not found")] | |
| 1213 | 1213 | pub(crate) struct EiiWithoutImpl { |
| 1214 | 1214 | #[primary_span] |
| 1215 | 1215 | #[label("expected because `#[{$name}]` was declared here in crate `{$decl_crate_name}`")] |
| 1216 | 1216 | pub span: Span, |
| 1217 | 1217 | pub name: Symbol, |
| 1218 | pub kind: &'static str, | |
| 1218 | 1219 | |
| 1219 | 1220 | pub current_crate_name: Symbol, |
| 1220 | 1221 | pub decl_crate_name: Symbol, |
compiler/rustc_resolve/src/check_unused.rs+4-1| ... | ... | @@ -438,7 +438,10 @@ impl Resolver<'_, '_> { |
| 438 | 438 | && !tcx.is_panic_runtime(cnum) |
| 439 | 439 | && !tcx.has_global_allocator(cnum) |
| 440 | 440 | && !tcx.has_panic_handler(cnum) |
| 441 | && tcx.externally_implementable_items(cnum).is_empty() | |
| 441 | && tcx | |
| 442 | .externally_implementable_items(cnum) | |
| 443 | .values() | |
| 444 | .all(|(_, defs)| defs.is_empty()) | |
| 442 | 445 | }) { |
| 443 | 446 | maybe_unused_extern_crates.insert(id, import.span); |
| 444 | 447 | } |
compiler/rustc_resolve/src/diagnostics.rs+2-2| ... | ... | @@ -1282,9 +1282,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 1282 | 1282 | // These trace attributes are compiler-generated and have |
| 1283 | 1283 | // deliberately invalid names. |
| 1284 | 1284 | .filter(|attr| { |
| 1285 | !matches!(attr.name, sym::cfg_trace | sym::cfg_attr_trace) | |
| 1285 | !matches!(**attr, sym::cfg_trace | sym::cfg_attr_trace) | |
| 1286 | 1286 | }) |
| 1287 | .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)), | |
| 1287 | .map(|attr| TypoSuggestion::typo_from_name(*attr, res)), | |
| 1288 | 1288 | ); |
| 1289 | 1289 | } |
| 1290 | 1290 | } |
compiler/rustc_resolve/src/effective_visibilities.rs+3-7| ... | ... | @@ -278,9 +278,8 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { |
| 278 | 278 | // all the parents in the loop below are also guaranteed to be modules. |
| 279 | 279 | let mut module_def_id = macro_module_def_id; |
| 280 | 280 | loop { |
| 281 | let changed_reachability = | |
| 282 | self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev); | |
| 283 | if changed_reachability || module_def_id == CRATE_DEF_ID { | |
| 281 | self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev); | |
| 282 | if module_def_id == CRATE_DEF_ID { | |
| 284 | 283 | break; |
| 285 | 284 | } |
| 286 | 285 | module_def_id = self.r.tcx.local_parent(module_def_id); |
| ... | ... | @@ -294,7 +293,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { |
| 294 | 293 | module_def_id: LocalDefId, |
| 295 | 294 | defining_mod: LocalDefId, |
| 296 | 295 | macro_ev: EffectiveVisibility, |
| 297 | ) -> bool { | |
| 296 | ) { | |
| 298 | 297 | if self.macro_reachable.insert((module_def_id, defining_mod)) { |
| 299 | 298 | let module = self.r.expect_module(module_def_id.to_def_id()); |
| 300 | 299 | for (_, name_resolution) in self.r.resolutions(module).borrow().iter() { |
| ... | ... | @@ -311,9 +310,6 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { |
| 311 | 310 | self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev); |
| 312 | 311 | } |
| 313 | 312 | } |
| 314 | true | |
| 315 | } else { | |
| 316 | false | |
| 317 | 313 | } |
| 318 | 314 | } |
| 319 | 315 |
compiler/rustc_resolve/src/lib.rs+2-2| ... | ... | @@ -1838,9 +1838,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 1838 | 1838 | builtin_attr_decls: BUILTIN_ATTRIBUTES |
| 1839 | 1839 | .iter() |
| 1840 | 1840 | .map(|builtin_attr| { |
| 1841 | let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(builtin_attr.name)); | |
| 1841 | let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(*builtin_attr)); | |
| 1842 | 1842 | let decl = arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT); |
| 1843 | (builtin_attr.name, decl) | |
| 1843 | (*builtin_attr, decl) | |
| 1844 | 1844 | }) |
| 1845 | 1845 | .collect(), |
| 1846 | 1846 | registered_tool_decls: registered_tools |
compiler/rustc_target/Cargo.toml+1| ... | ... | @@ -5,6 +5,7 @@ edition = "2024" |
| 5 | 5 | |
| 6 | 6 | [dependencies] |
| 7 | 7 | # tidy-alphabetical-start |
| 8 | arrayvec = { version = "0.7", default-features = false } | |
| 8 | 9 | bitflags = "2.4.1" |
| 9 | 10 | object = { version = "0.37.0", default-features = false, features = ["elf", "macho"] } |
| 10 | 11 | rustc_abi = { path = "../rustc_abi" } |
compiler/rustc_target/src/callconv/mips64.rs+9-13| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use arrayvec::ArrayVec; | |
| 1 | 2 | use rustc_abi::{ |
| 2 | 3 | BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface, |
| 3 | 4 | }; |
| ... | ... | @@ -81,8 +82,7 @@ where |
| 81 | 82 | { |
| 82 | 83 | let dl = cx.data_layout(); |
| 83 | 84 | let size = arg.layout.size; |
| 84 | let mut prefix = [None; 8]; | |
| 85 | let mut prefix_index = 0; | |
| 85 | let mut prefix = ArrayVec::new(); | |
| 86 | 86 | |
| 87 | 87 | // Detect need for padding |
| 88 | 88 | let align = Ord::clamp(arg.layout.align.abi, dl.i64_align, dl.i128_align); |
| ... | ... | @@ -107,7 +107,7 @@ where |
| 107 | 107 | // doubles not part of another aggregate are passed as floats. |
| 108 | 108 | let mut last_offset = Size::ZERO; |
| 109 | 109 | |
| 110 | for i in 0..arg.layout.fields.count() { | |
| 110 | 'outer: for i in 0..arg.layout.fields.count() { | |
| 111 | 111 | let field = arg.layout.field(cx, i); |
| 112 | 112 | let offset = arg.layout.fields.offset(i); |
| 113 | 113 | |
| ... | ... | @@ -117,19 +117,15 @@ where |
| 117 | 117 | if offset.is_aligned(dl.f64_align) { |
| 118 | 118 | // Insert enough integers to cover [last_offset, offset) |
| 119 | 119 | assert!(last_offset.is_aligned(dl.f64_align)); |
| 120 | for _ in 0..((offset - last_offset).bits() / 64) | |
| 121 | .min((prefix.len() - prefix_index) as u64) | |
| 122 | { | |
| 123 | prefix[prefix_index] = Some(Reg::i64()); | |
| 124 | prefix_index += 1; | |
| 120 | for _ in 0..((offset - last_offset).bits() / 64) { | |
| 121 | if prefix.try_push(Reg::i64()).is_err() { | |
| 122 | break 'outer; | |
| 123 | } | |
| 125 | 124 | } |
| 126 | 125 | |
| 127 | if prefix_index == prefix.len() { | |
| 126 | if prefix.try_push(Reg::f64()).is_err() { | |
| 128 | 127 | break; |
| 129 | 128 | } |
| 130 | ||
| 131 | prefix[prefix_index] = Some(Reg::f64()); | |
| 132 | prefix_index += 1; | |
| 133 | 129 | last_offset = offset + Reg::f64().size; |
| 134 | 130 | } |
| 135 | 131 | } |
| ... | ... | @@ -139,7 +135,7 @@ where |
| 139 | 135 | }; |
| 140 | 136 | |
| 141 | 137 | // Extract first 8 chunks as the prefix |
| 142 | let rest_size = size - Size::from_bytes(8) * prefix_index as u64; | |
| 138 | let rest_size = size - Size::from_bytes(8) * prefix.len() as u64; | |
| 143 | 139 | arg.cast_to_and_pad_i32( |
| 144 | 140 | CastTarget::prefixed(prefix, Uniform::new(Reg::i64(), rest_size)), |
| 145 | 141 | pad_i32, |
compiler/rustc_target/src/callconv/mod.rs+16-10| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | use std::{fmt, iter}; |
| 2 | 2 | |
| 3 | use arrayvec::ArrayVec; | |
| 3 | 4 | use rustc_abi::{ |
| 4 | 5 | AddressSpace, Align, BackendRepr, CanonAbi, ExternAbi, FieldsShape, HasDataLayout, Primitive, |
| 5 | 6 | Reg, RegKind, Scalar, Size, TyAbiInterface, TyAndLayout, Variants, |
| ... | ... | @@ -264,7 +265,11 @@ impl Uniform { |
| 264 | 265 | /// (and all data in the padding between the registers is dropped). |
| 265 | 266 | #[derive(Clone, PartialEq, Eq, Hash, Debug, StableHash)] |
| 266 | 267 | pub struct CastTarget { |
| 267 | pub prefix: [Option<Reg>; 8], | |
| 268 | // Note that this is fixed to 8 elements for now as ABIs currently don't | |
| 269 | // need anything further beyond that, and when this code was originally | |
| 270 | // refactored to use `ArrayVec` it was already using 8, so that stuck | |
| 271 | // around. | |
| 272 | pub prefix: ArrayVec<Reg, 8>, | |
| 268 | 273 | /// The offset of `rest` from the start of the value. Currently only implemented for a `Reg` |
| 269 | 274 | /// pair created by the `offset_pair` method. |
| 270 | 275 | pub rest_offset: Option<Size>, |
| ... | ... | @@ -280,18 +285,20 @@ impl From<Reg> for CastTarget { |
| 280 | 285 | |
| 281 | 286 | impl From<Uniform> for CastTarget { |
| 282 | 287 | fn from(uniform: Uniform) -> CastTarget { |
| 283 | Self::prefixed([None; 8], uniform) | |
| 288 | Self::prefixed(Default::default(), uniform) | |
| 284 | 289 | } |
| 285 | 290 | } |
| 286 | 291 | |
| 287 | 292 | impl CastTarget { |
| 288 | pub fn prefixed(prefix: [Option<Reg>; 8], rest: Uniform) -> Self { | |
| 293 | pub fn prefixed(prefix: ArrayVec<Reg, 8>, rest: Uniform) -> Self { | |
| 289 | 294 | Self { prefix, rest_offset: None, rest, attrs: ArgAttributes::new() } |
| 290 | 295 | } |
| 291 | 296 | |
| 292 | 297 | pub fn offset_pair(a: Reg, offset_from_start: Size, b: Reg) -> Self { |
| 298 | let mut prefix = ArrayVec::new(); | |
| 299 | prefix.push(a); | |
| 293 | 300 | Self { |
| 294 | prefix: [Some(a), None, None, None, None, None, None, None], | |
| 301 | prefix, | |
| 295 | 302 | rest_offset: Some(offset_from_start), |
| 296 | 303 | rest: b.into(), |
| 297 | 304 | attrs: ArgAttributes::new(), |
| ... | ... | @@ -304,7 +311,9 @@ impl CastTarget { |
| 304 | 311 | } |
| 305 | 312 | |
| 306 | 313 | pub fn pair(a: Reg, b: Reg) -> CastTarget { |
| 307 | Self::prefixed([Some(a), None, None, None, None, None, None, None], Uniform::from(b)) | |
| 314 | let mut prefix = ArrayVec::new(); | |
| 315 | prefix.push(a); | |
| 316 | Self::prefixed(prefix, Uniform::from(b)) | |
| 308 | 317 | } |
| 309 | 318 | |
| 310 | 319 | /// When you only access the range containing valid data, you can use this unaligned size; |
| ... | ... | @@ -314,10 +323,7 @@ impl CastTarget { |
| 314 | 323 | let prefix_size = if let Some(offset_from_start) = self.rest_offset { |
| 315 | 324 | offset_from_start |
| 316 | 325 | } else { |
| 317 | self.prefix | |
| 318 | .iter() | |
| 319 | .filter_map(|x| x.map(|reg| reg.size)) | |
| 320 | .fold(Size::ZERO, |acc, size| acc + size) | |
| 326 | self.prefix.iter().map(|reg| reg.size).fold(Size::ZERO, |acc, size| acc + size) | |
| 321 | 327 | }; |
| 322 | 328 | // Remaining arguments are passed in chunks of the unit size |
| 323 | 329 | let rest_size = |
| ... | ... | @@ -333,7 +339,7 @@ impl CastTarget { |
| 333 | 339 | pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align { |
| 334 | 340 | self.prefix |
| 335 | 341 | .iter() |
| 336 | .filter_map(|x| x.map(|reg| reg.align(cx))) | |
| 342 | .map(|reg| reg.align(cx)) | |
| 337 | 343 | .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), |acc, align| { |
| 338 | 344 | acc.max(align) |
| 339 | 345 | }) |
compiler/rustc_target/src/callconv/nvptx64.rs+7-8| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use arrayvec::ArrayVec; | |
| 1 | 2 | use rustc_abi::{HasDataLayout, Reg, Size, TyAbiInterface}; |
| 2 | 3 | |
| 3 | 4 | use super::CastTarget; |
| ... | ... | @@ -41,10 +42,9 @@ fn classify_aggregate<Ty>(arg: &mut ArgAbi<'_, Ty>) { |
| 41 | 42 | }; |
| 42 | 43 | |
| 43 | 44 | if align_bytes == size.bytes() { |
| 44 | arg.cast_to(CastTarget::prefixed( | |
| 45 | [Some(reg), None, None, None, None, None, None, None], | |
| 46 | Uniform::new(Reg::i8(), Size::ZERO), | |
| 47 | )); | |
| 45 | let mut prefix = ArrayVec::new(); | |
| 46 | prefix.push(reg); | |
| 47 | arg.cast_to(CastTarget::prefixed(prefix, Uniform::new(Reg::i8(), Size::ZERO))); | |
| 48 | 48 | } else { |
| 49 | 49 | arg.cast_to(Uniform::new(reg, size)); |
| 50 | 50 | } |
| ... | ... | @@ -79,10 +79,9 @@ where |
| 79 | 79 | }; |
| 80 | 80 | if arg.layout.size.bytes() / align_bytes == 1 { |
| 81 | 81 | // Make sure we pass the struct as array at the LLVM IR level and not as a single integer. |
| 82 | arg.cast_to(CastTarget::prefixed( | |
| 83 | [Some(unit), None, None, None, None, None, None, None], | |
| 84 | Uniform::new(unit, Size::ZERO), | |
| 85 | )); | |
| 82 | let mut prefix = ArrayVec::new(); | |
| 83 | prefix.push(unit); | |
| 84 | arg.cast_to(CastTarget::prefixed(prefix, Uniform::new(unit, Size::ZERO))); | |
| 86 | 85 | } else { |
| 87 | 86 | arg.cast_to(Uniform::new(unit, arg.layout.size)); |
| 88 | 87 | } |
compiler/rustc_target/src/callconv/sparc64.rs+12-19| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use arrayvec::ArrayVec; | |
| 1 | 2 | use rustc_abi::{ |
| 2 | 3 | Align, BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface, |
| 3 | 4 | TyAndLayout, Variants, |
| ... | ... | @@ -147,12 +148,7 @@ fn classify_arg<'a, Ty, C>( |
| 147 | 148 | let mut double_words = [DoubleWord::Words([Word::Integer; 2]); ARGUMENT_REGISTERS / 2]; |
| 148 | 149 | classify(cx, &arg.layout, Size::ZERO, &mut double_words); |
| 149 | 150 | |
| 150 | let mut regs = [None; ARGUMENT_REGISTERS]; | |
| 151 | let mut i = 0; | |
| 152 | let mut push = |reg| { | |
| 153 | regs[i] = Some(reg); | |
| 154 | i += 1; | |
| 155 | }; | |
| 151 | let mut regs = ArrayVec::new(); | |
| 156 | 152 | let mut attrs = ArgAttribute::empty(); |
| 157 | 153 | |
| 158 | 154 | for (index, double_word) in double_words.into_iter().enumerate() { |
| ... | ... | @@ -162,7 +158,7 @@ fn classify_arg<'a, Ty, C>( |
| 162 | 158 | match double_word { |
| 163 | 159 | // `f128` must be aligned to be assigned a float register. |
| 164 | 160 | DoubleWord::F128Start if (start_double_word_count + index).is_multiple_of(2) => { |
| 165 | push(Reg::f128()); | |
| 161 | regs.push(Reg::f128()); | |
| 166 | 162 | } |
| 167 | 163 | DoubleWord::F128Start => { |
| 168 | 164 | // Clang currently handles this case nonsensically, always returning a packed |
| ... | ... | @@ -170,30 +166,27 @@ fn classify_arg<'a, Ty, C>( |
| 170 | 166 | // the `long double` isn't aligned on the stack, which also makes all future |
| 171 | 167 | // arguments get passed in the wrong registers. This passes the `f128` in integer |
| 172 | 168 | // registers when it is unaligned, same as with `f32` and `f64`. |
| 173 | push(Reg::i64()); | |
| 174 | push(Reg::i64()); | |
| 169 | regs.push(Reg::i64()); | |
| 170 | regs.push(Reg::i64()); | |
| 175 | 171 | } |
| 176 | 172 | DoubleWord::F128End => {} // Already handled by `F128Start` |
| 177 | DoubleWord::F64 => push(Reg::f64()), | |
| 178 | DoubleWord::Words([Word::Integer, Word::Integer]) => push(Reg::i64()), | |
| 173 | DoubleWord::F64 => regs.push(Reg::f64()), | |
| 174 | DoubleWord::Words([Word::Integer, Word::Integer]) => regs.push(Reg::i64()), | |
| 179 | 175 | DoubleWord::Words(words) => { |
| 180 | 176 | attrs |= ArgAttribute::InReg; |
| 181 | 177 | for word in words { |
| 182 | 178 | match word { |
| 183 | Word::F32 => push(Reg::f32()), | |
| 184 | Word::Integer => push(Reg::i32()), | |
| 179 | Word::F32 => regs.push(Reg::f32()), | |
| 180 | Word::Integer => regs.push(Reg::i32()), | |
| 185 | 181 | } |
| 186 | 182 | } |
| 187 | 183 | } |
| 188 | 184 | } |
| 189 | 185 | } |
| 190 | 186 | |
| 191 | let cast_target = match regs { | |
| 192 | [Some(reg), None, rest @ ..] => { | |
| 193 | // Just a single register is needed for this value. | |
| 194 | debug_assert!(rest.iter().all(|x| x.is_none())); | |
| 195 | CastTarget::from(reg) | |
| 196 | } | |
| 187 | let cast_target = match regs.as_slice() { | |
| 188 | // Just a single register is needed for this value. | |
| 189 | [reg] => CastTarget::from(*reg), | |
| 197 | 190 | _ => CastTarget::prefixed(regs, Uniform::new(Reg::i8(), Size::ZERO)), |
| 198 | 191 | }; |
| 199 | 192 |
src/ci/github-actions/jobs.yml+1-1| ... | ... | @@ -517,7 +517,7 @@ auto: |
| 517 | 517 | - name: dist-aarch64-apple |
| 518 | 518 | env: |
| 519 | 519 | SCRIPT: >- |
| 520 | ./x.py dist bootstrap | |
| 520 | ./x.py dist bootstrap enzyme | |
| 521 | 521 | --include-default-paths |
| 522 | 522 | --host=aarch64-apple-darwin |
| 523 | 523 | --target=aarch64-apple-darwin |
src/doc/reference+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | Subproject commit ad35aca481751a06afeb23820a672b0f3b11a476 | |
| 1 | Subproject commit 01b0ee707f4571e803c8b2c471d8335a448f5d60 |
src/doc/rust-by-example+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | Subproject commit 898f0ac1479223d332309e0fce88d44b39927d28 | |
| 1 | Subproject commit d3117f6c873acbbf331c1d510371d061dfcc975c |
src/librustdoc/html/render/mod.rs+22-4| ... | ... | @@ -79,6 +79,7 @@ use crate::html::format::{ |
| 79 | 79 | use crate::html::markdown::{ |
| 80 | 80 | HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, short_markdown_summary, |
| 81 | 81 | }; |
| 82 | use crate::html::render::print_item::compare_names; | |
| 82 | 83 | use crate::html::render::search_index::get_function_type_for_search; |
| 83 | 84 | use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD; |
| 84 | 85 | use crate::html::{highlight, sources}; |
| ... | ... | @@ -941,6 +942,16 @@ fn short_item_info( |
| 941 | 942 | extra_info |
| 942 | 943 | } |
| 943 | 944 | |
| 945 | // Prints the polarity and path of an impl's trait, if it has one, e.g. `Send`, `!Sync`. | |
| 946 | fn impl_trait_key(cx: &Context<'_>, i: &Impl) -> Option<String> { | |
| 947 | let trait_ = i.inner_impl().trait_.as_ref()?; | |
| 948 | let prefix = match i.inner_impl().polarity { | |
| 949 | ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", | |
| 950 | ty::ImplPolarity::Negative => "!", | |
| 951 | }; | |
| 952 | Some(format!("{prefix}{:#}", print_path(trait_, cx))) | |
| 953 | } | |
| 954 | ||
| 944 | 955 | // Render the list of items inside one of the sections "Trait Implementations", |
| 945 | 956 | // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). |
| 946 | 957 | fn render_impls( |
| ... | ... | @@ -950,7 +961,9 @@ fn render_impls( |
| 950 | 961 | containing_item: &clean::Item, |
| 951 | 962 | toggle_open_by_default: bool, |
| 952 | 963 | ) -> fmt::Result { |
| 953 | let mut rendered_impls = impls | |
| 964 | // Render each impl alongside its `impl_trait_key`, which is used as the primary sorting key | |
| 965 | // to match the impl order in the sidebar. | |
| 966 | let mut keyed_rendered_impls = impls | |
| 954 | 967 | .iter() |
| 955 | 968 | .map(|i| { |
| 956 | 969 | let did = i.trait_did().unwrap(); |
| ... | ... | @@ -971,11 +984,16 @@ fn render_impls( |
| 971 | 984 | toggle_open_by_default, |
| 972 | 985 | }, |
| 973 | 986 | ); |
| 974 | imp.to_string() | |
| 987 | (impl_trait_key(cx, i).unwrap(), imp.to_string()) | |
| 975 | 988 | }) |
| 976 | 989 | .collect::<Vec<_>>(); |
| 977 | rendered_impls.sort(); | |
| 978 | w.write_str(&rendered_impls.join("")) | |
| 990 | ||
| 991 | // Sort and then remove the `impl_trait_key`s, which are no longer needed after sorting. | |
| 992 | keyed_rendered_impls | |
| 993 | .sort_by(|(k1, h1), (k2, h2)| compare_names(k1, k2).then_with(|| h1.cmp(h2))); | |
| 994 | let joined: String = keyed_rendered_impls.into_iter().map(|a| a.1).collect(); | |
| 995 | ||
| 996 | w.write_str(&joined) | |
| 979 | 997 | } |
| 980 | 998 | |
| 981 | 999 | /// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item. |
src/librustdoc/html/render/sidebar.rs+5-11| ... | ... | @@ -6,10 +6,10 @@ use askama::Template; |
| 6 | 6 | use rustc_data_structures::fx::FxHashSet; |
| 7 | 7 | use rustc_hir::def::CtorKind; |
| 8 | 8 | use rustc_hir::def_id::{DefIdMap, DefIdSet}; |
| 9 | use rustc_middle::ty::{self, TyCtxt}; | |
| 9 | use rustc_middle::ty::TyCtxt; | |
| 10 | 10 | use tracing::debug; |
| 11 | 11 | |
| 12 | use super::{Context, ItemSection, item_ty_to_section}; | |
| 12 | use super::{Context, ItemSection, impl_trait_key, item_ty_to_section}; | |
| 13 | 13 | use crate::clean; |
| 14 | 14 | use crate::formats::Impl; |
| 15 | 15 | use crate::formats::item_type::ItemType; |
| ... | ... | @@ -707,15 +707,9 @@ fn sidebar_render_assoc_items( |
| 707 | 707 | |
| 708 | 708 | let mut ret = impls |
| 709 | 709 | .iter() |
| 710 | .filter_map(|it| { | |
| 711 | let trait_ = it.inner_impl().trait_.as_ref()?; | |
| 712 | let encoded = id_map.derive(super::get_id_for_impl(cx.tcx(), it.impl_item.item_id)); | |
| 713 | ||
| 714 | let prefix = match it.inner_impl().polarity { | |
| 715 | ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", | |
| 716 | ty::ImplPolarity::Negative => "!", | |
| 717 | }; | |
| 718 | let generated = Link::new(encoded, format!("{prefix}{:#}", print_path(trait_, cx))); | |
| 710 | .filter_map(|i| { | |
| 711 | let encoded = id_map.derive(super::get_id_for_impl(cx.tcx(), i.impl_item.item_id)); | |
| 712 | let generated = Link::new(encoded, impl_trait_key(cx, i)?); | |
| 719 | 713 | if links.insert(generated.clone()) { Some(generated) } else { None } |
| 720 | 714 | }) |
| 721 | 715 | .collect::<Vec<Link<'static>>>(); |
src/tools/miri/.github/workflows/ci.yml+14-2| ... | ... | @@ -155,6 +155,18 @@ jobs: |
| 155 | 155 | cd ../rust # ./x does not seem to like being invoked from elsewhere |
| 156 | 156 | ./x check miri |
| 157 | 157 | |
| 158 | # This job is intentionally separate from `test` so that Priroda can be | |
| 159 | # developed as a separate crate inside the Miri repository for now. | |
| 160 | priroda-build: | |
| 161 | name: Priroda | |
| 162 | runs-on: ubuntu-latest | |
| 163 | steps: | |
| 164 | - uses: actions/checkout@v6 | |
| 165 | - uses: ./.github/workflows/setup | |
| 166 | - name: build Priroda | |
| 167 | working-directory: priroda | |
| 168 | run: cargo build --locked | |
| 169 | ||
| 158 | 170 | coverage: |
| 159 | 171 | name: coverage report |
| 160 | 172 | runs-on: ubuntu-latest |
| ... | ... | @@ -168,7 +180,7 @@ jobs: |
| 168 | 180 | # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! |
| 169 | 181 | # And they should be added below in `cron-fail-notify` as well. |
| 170 | 182 | conclusion: |
| 171 | needs: [test, style, bootstrap, coverage] | |
| 183 | needs: [test, style, bootstrap, coverage, priroda-build] | |
| 172 | 184 | # We need to ensure this job does *not* get skipped if its dependencies fail, |
| 173 | 185 | # because a skipped job is considered a success by GitHub. So we have to |
| 174 | 186 | # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run |
| ... | ... | @@ -252,7 +264,7 @@ jobs: |
| 252 | 264 | cron-fail-notify: |
| 253 | 265 | name: cronjob failure notification |
| 254 | 266 | runs-on: ubuntu-latest |
| 255 | needs: [test, style, bootstrap, coverage] | |
| 267 | needs: [test, style, bootstrap, coverage, priroda-build] | |
| 256 | 268 | if: ${{ github.event_name == 'schedule' && failure() }} |
| 257 | 269 | steps: |
| 258 | 270 | # Send a Zulip notification |
src/tools/miri/README.md+4| ... | ... | @@ -517,6 +517,10 @@ to Miri failing to detect cases of undefined behavior in a program. |
| 517 | 517 | track interior mutable data on the level of references instead of on the |
| 518 | 518 | byte-level as is done by default. Therefore, with this flag, Tree |
| 519 | 519 | Borrows will be more permissive. |
| 520 | * `-Zmiri-tree-borrows-relax-custom-allocator-uniqueness` disables uniqueness assumptions for | |
| 521 | `Box<T, A>` where `A` is not `Global`. The exact aliasing rules for such custom allocators are | |
| 522 | still up in the air, and by default Miri is conservative and rejects some allocator | |
| 523 | implementations that incur relevant aliasing between the allocation and the allocator. | |
| 520 | 524 | * `-Zmiri-force-page-size=<num>` overrides the default page size for an architecture, in multiples of 1k. |
| 521 | 525 | `4` is default for most targets. This value should always be a power of 2 and nonzero. |
| 522 | 526 |
src/tools/miri/ci/ci.sh+3-4| ... | ... | @@ -150,11 +150,10 @@ case $HOST_TARGET in |
| 150 | 150 | i686-unknown-linux-gnu) |
| 151 | 151 | # Host |
| 152 | 152 | MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests |
| 153 | # Fully, but not officially, supported tier 2 | |
| 153 | # Not officially supported tier 2 | |
| 154 | 154 | MANY_SEEDS=16 TEST_TARGET=aarch64-linux-android run_tests |
| 155 | # Partially supported targets (tier 2) | |
| 156 | BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator | |
| 157 | UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there | |
| 155 | MANY_SEEDS=16 TEST_TARGET=loongarch64-unknown-linux-gnu run_tests | |
| 156 | # Partially supported targets (no_std, tier 2) | |
| 158 | 157 | TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std |
| 159 | 158 | TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std |
| 160 | 159 | ;; |
src/tools/miri/priroda/Cargo.lock created+1260| ... | ... | @@ -0,0 +1,1260 @@ |
| 1 | # This file is automatically @generated by Cargo. | |
| 2 | # It is not intended for manual editing. | |
| 3 | version = 4 | |
| 4 | ||
| 5 | [[package]] | |
| 6 | name = "aes" | |
| 7 | version = "0.9.0" | |
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 9 | checksum = "66bd29a732b644c0431c6140f370d097879203d79b80c94a6747ba0872adaef8" | |
| 10 | dependencies = [ | |
| 11 | "cipher", | |
| 12 | "cpubits", | |
| 13 | "cpufeatures", | |
| 14 | ] | |
| 15 | ||
| 16 | [[package]] | |
| 17 | name = "anyhow" | |
| 18 | version = "1.0.102" | |
| 19 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 20 | checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" | |
| 21 | ||
| 22 | [[package]] | |
| 23 | name = "autocfg" | |
| 24 | version = "1.5.0" | |
| 25 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 26 | checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" | |
| 27 | ||
| 28 | [[package]] | |
| 29 | name = "bincode" | |
| 30 | version = "1.3.3" | |
| 31 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 32 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" | |
| 33 | dependencies = [ | |
| 34 | "serde", | |
| 35 | ] | |
| 36 | ||
| 37 | [[package]] | |
| 38 | name = "bitflags" | |
| 39 | version = "2.11.1" | |
| 40 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 41 | checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" | |
| 42 | ||
| 43 | [[package]] | |
| 44 | name = "bumpalo" | |
| 45 | version = "3.20.2" | |
| 46 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 47 | checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" | |
| 48 | ||
| 49 | [[package]] | |
| 50 | name = "capstone" | |
| 51 | version = "0.14.0" | |
| 52 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 53 | checksum = "f442ae0f2f3f1b923334b4a5386c95c69c1cfa072bafa23d6fae6d9682eb1dd4" | |
| 54 | dependencies = [ | |
| 55 | "capstone-sys", | |
| 56 | "static_assertions", | |
| 57 | ] | |
| 58 | ||
| 59 | [[package]] | |
| 60 | name = "capstone-sys" | |
| 61 | version = "0.18.0" | |
| 62 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 63 | checksum = "a4e8087cab6731295f5a2a2bd82989ba4f41d3a428aab2e7c98d8f4db38aac05" | |
| 64 | dependencies = [ | |
| 65 | "cc", | |
| 66 | ] | |
| 67 | ||
| 68 | [[package]] | |
| 69 | name = "cc" | |
| 70 | version = "1.2.62" | |
| 71 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 72 | checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" | |
| 73 | dependencies = [ | |
| 74 | "find-msvc-tools", | |
| 75 | "shlex", | |
| 76 | ] | |
| 77 | ||
| 78 | [[package]] | |
| 79 | name = "cfg-if" | |
| 80 | version = "1.0.4" | |
| 81 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 82 | checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" | |
| 83 | ||
| 84 | [[package]] | |
| 85 | name = "cfg_aliases" | |
| 86 | version = "0.2.1" | |
| 87 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 88 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" | |
| 89 | ||
| 90 | [[package]] | |
| 91 | name = "chacha20" | |
| 92 | version = "0.10.0" | |
| 93 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 94 | checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" | |
| 95 | dependencies = [ | |
| 96 | "cfg-if", | |
| 97 | "cpufeatures", | |
| 98 | "rand_core 0.10.1", | |
| 99 | ] | |
| 100 | ||
| 101 | [[package]] | |
| 102 | name = "chrono" | |
| 103 | version = "0.4.44" | |
| 104 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 105 | checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" | |
| 106 | dependencies = [ | |
| 107 | "num-traits", | |
| 108 | ] | |
| 109 | ||
| 110 | [[package]] | |
| 111 | name = "chrono-tz" | |
| 112 | version = "0.10.4" | |
| 113 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 114 | checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" | |
| 115 | dependencies = [ | |
| 116 | "chrono", | |
| 117 | "phf", | |
| 118 | ] | |
| 119 | ||
| 120 | [[package]] | |
| 121 | name = "cipher" | |
| 122 | version = "0.5.1" | |
| 123 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 124 | checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" | |
| 125 | dependencies = [ | |
| 126 | "crypto-common", | |
| 127 | "inout", | |
| 128 | ] | |
| 129 | ||
| 130 | [[package]] | |
| 131 | name = "cpubits" | |
| 132 | version = "0.1.1" | |
| 133 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 134 | checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" | |
| 135 | ||
| 136 | [[package]] | |
| 137 | name = "cpufeatures" | |
| 138 | version = "0.3.0" | |
| 139 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 140 | checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" | |
| 141 | dependencies = [ | |
| 142 | "libc", | |
| 143 | ] | |
| 144 | ||
| 145 | [[package]] | |
| 146 | name = "crossbeam-channel" | |
| 147 | version = "0.5.15" | |
| 148 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 149 | checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" | |
| 150 | dependencies = [ | |
| 151 | "crossbeam-utils", | |
| 152 | ] | |
| 153 | ||
| 154 | [[package]] | |
| 155 | name = "crossbeam-utils" | |
| 156 | version = "0.8.21" | |
| 157 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 158 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" | |
| 159 | ||
| 160 | [[package]] | |
| 161 | name = "crypto-common" | |
| 162 | version = "0.2.1" | |
| 163 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 164 | checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" | |
| 165 | dependencies = [ | |
| 166 | "hybrid-array", | |
| 167 | ] | |
| 168 | ||
| 169 | [[package]] | |
| 170 | name = "directories" | |
| 171 | version = "6.0.0" | |
| 172 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 173 | checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" | |
| 174 | dependencies = [ | |
| 175 | "dirs-sys", | |
| 176 | ] | |
| 177 | ||
| 178 | [[package]] | |
| 179 | name = "dirs-sys" | |
| 180 | version = "0.5.0" | |
| 181 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 182 | checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" | |
| 183 | dependencies = [ | |
| 184 | "libc", | |
| 185 | "option-ext", | |
| 186 | "redox_users", | |
| 187 | "windows-sys", | |
| 188 | ] | |
| 189 | ||
| 190 | [[package]] | |
| 191 | name = "equivalent" | |
| 192 | version = "1.0.2" | |
| 193 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 194 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" | |
| 195 | ||
| 196 | [[package]] | |
| 197 | name = "errno" | |
| 198 | version = "0.3.14" | |
| 199 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 200 | checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" | |
| 201 | dependencies = [ | |
| 202 | "libc", | |
| 203 | "windows-sys", | |
| 204 | ] | |
| 205 | ||
| 206 | [[package]] | |
| 207 | name = "fastrand" | |
| 208 | version = "2.4.1" | |
| 209 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 210 | checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" | |
| 211 | ||
| 212 | [[package]] | |
| 213 | name = "find-msvc-tools" | |
| 214 | version = "0.1.9" | |
| 215 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 216 | checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" | |
| 217 | ||
| 218 | [[package]] | |
| 219 | name = "fnv" | |
| 220 | version = "1.0.7" | |
| 221 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 222 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" | |
| 223 | ||
| 224 | [[package]] | |
| 225 | name = "foldhash" | |
| 226 | version = "0.1.5" | |
| 227 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 228 | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" | |
| 229 | ||
| 230 | [[package]] | |
| 231 | name = "futures-core" | |
| 232 | version = "0.3.32" | |
| 233 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 234 | checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" | |
| 235 | ||
| 236 | [[package]] | |
| 237 | name = "futures-task" | |
| 238 | version = "0.3.32" | |
| 239 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 240 | checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" | |
| 241 | ||
| 242 | [[package]] | |
| 243 | name = "futures-util" | |
| 244 | version = "0.3.32" | |
| 245 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 246 | checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" | |
| 247 | dependencies = [ | |
| 248 | "futures-core", | |
| 249 | "futures-task", | |
| 250 | "pin-project-lite", | |
| 251 | "slab", | |
| 252 | ] | |
| 253 | ||
| 254 | [[package]] | |
| 255 | name = "getrandom" | |
| 256 | version = "0.2.17" | |
| 257 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 258 | checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" | |
| 259 | dependencies = [ | |
| 260 | "cfg-if", | |
| 261 | "libc", | |
| 262 | "wasi", | |
| 263 | ] | |
| 264 | ||
| 265 | [[package]] | |
| 266 | name = "getrandom" | |
| 267 | version = "0.3.4" | |
| 268 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 269 | checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" | |
| 270 | dependencies = [ | |
| 271 | "cfg-if", | |
| 272 | "libc", | |
| 273 | "r-efi 5.3.0", | |
| 274 | "wasip2", | |
| 275 | ] | |
| 276 | ||
| 277 | [[package]] | |
| 278 | name = "getrandom" | |
| 279 | version = "0.4.2" | |
| 280 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 281 | checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" | |
| 282 | dependencies = [ | |
| 283 | "cfg-if", | |
| 284 | "libc", | |
| 285 | "r-efi 6.0.0", | |
| 286 | "rand_core 0.10.1", | |
| 287 | "wasip2", | |
| 288 | "wasip3", | |
| 289 | ] | |
| 290 | ||
| 291 | [[package]] | |
| 292 | name = "hashbrown" | |
| 293 | version = "0.15.5" | |
| 294 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 295 | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" | |
| 296 | dependencies = [ | |
| 297 | "foldhash", | |
| 298 | ] | |
| 299 | ||
| 300 | [[package]] | |
| 301 | name = "hashbrown" | |
| 302 | version = "0.17.1" | |
| 303 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 304 | checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" | |
| 305 | ||
| 306 | [[package]] | |
| 307 | name = "heck" | |
| 308 | version = "0.5.0" | |
| 309 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 310 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" | |
| 311 | ||
| 312 | [[package]] | |
| 313 | name = "hybrid-array" | |
| 314 | version = "0.4.12" | |
| 315 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 316 | checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" | |
| 317 | dependencies = [ | |
| 318 | "typenum", | |
| 319 | ] | |
| 320 | ||
| 321 | [[package]] | |
| 322 | name = "id-arena" | |
| 323 | version = "2.3.0" | |
| 324 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 325 | checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" | |
| 326 | ||
| 327 | [[package]] | |
| 328 | name = "indexmap" | |
| 329 | version = "2.14.0" | |
| 330 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 331 | checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" | |
| 332 | dependencies = [ | |
| 333 | "equivalent", | |
| 334 | "hashbrown 0.17.1", | |
| 335 | "serde", | |
| 336 | "serde_core", | |
| 337 | ] | |
| 338 | ||
| 339 | [[package]] | |
| 340 | name = "inout" | |
| 341 | version = "0.2.2" | |
| 342 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 343 | checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" | |
| 344 | dependencies = [ | |
| 345 | "hybrid-array", | |
| 346 | ] | |
| 347 | ||
| 348 | [[package]] | |
| 349 | name = "ipc-channel" | |
| 350 | version = "0.20.2" | |
| 351 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 352 | checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180" | |
| 353 | dependencies = [ | |
| 354 | "bincode", | |
| 355 | "crossbeam-channel", | |
| 356 | "fnv", | |
| 357 | "libc", | |
| 358 | "mio", | |
| 359 | "rand 0.9.4", | |
| 360 | "serde", | |
| 361 | "tempfile", | |
| 362 | "uuid", | |
| 363 | "windows", | |
| 364 | ] | |
| 365 | ||
| 366 | [[package]] | |
| 367 | name = "itoa" | |
| 368 | version = "1.0.18" | |
| 369 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 370 | checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" | |
| 371 | ||
| 372 | [[package]] | |
| 373 | name = "js-sys" | |
| 374 | version = "0.3.98" | |
| 375 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 376 | checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" | |
| 377 | dependencies = [ | |
| 378 | "cfg-if", | |
| 379 | "futures-util", | |
| 380 | "once_cell", | |
| 381 | "wasm-bindgen", | |
| 382 | ] | |
| 383 | ||
| 384 | [[package]] | |
| 385 | name = "leb128fmt" | |
| 386 | version = "0.1.0" | |
| 387 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 388 | checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" | |
| 389 | ||
| 390 | [[package]] | |
| 391 | name = "libc" | |
| 392 | version = "0.2.186" | |
| 393 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 394 | checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" | |
| 395 | ||
| 396 | [[package]] | |
| 397 | name = "libffi" | |
| 398 | version = "5.1.0" | |
| 399 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 400 | checksum = "0498fe5655f857803e156523e644dcdcdc3b3c7edda42ea2afdae2e09b2db87b" | |
| 401 | dependencies = [ | |
| 402 | "libc", | |
| 403 | "libffi-sys", | |
| 404 | ] | |
| 405 | ||
| 406 | [[package]] | |
| 407 | name = "libffi-sys" | |
| 408 | version = "4.1.0" | |
| 409 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 410 | checksum = "71d4f1d4ce15091955144350b75db16a96d4a63728500122706fb4d29a26afbb" | |
| 411 | dependencies = [ | |
| 412 | "cc", | |
| 413 | ] | |
| 414 | ||
| 415 | [[package]] | |
| 416 | name = "libloading" | |
| 417 | version = "0.9.0" | |
| 418 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 419 | checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" | |
| 420 | dependencies = [ | |
| 421 | "cfg-if", | |
| 422 | "windows-link 0.2.1", | |
| 423 | ] | |
| 424 | ||
| 425 | [[package]] | |
| 426 | name = "libredox" | |
| 427 | version = "0.1.16" | |
| 428 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 429 | checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" | |
| 430 | dependencies = [ | |
| 431 | "libc", | |
| 432 | ] | |
| 433 | ||
| 434 | [[package]] | |
| 435 | name = "linux-raw-sys" | |
| 436 | version = "0.12.1" | |
| 437 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 438 | checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" | |
| 439 | ||
| 440 | [[package]] | |
| 441 | name = "lock_api" | |
| 442 | version = "0.4.14" | |
| 443 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 444 | checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" | |
| 445 | dependencies = [ | |
| 446 | "scopeguard", | |
| 447 | ] | |
| 448 | ||
| 449 | [[package]] | |
| 450 | name = "log" | |
| 451 | version = "0.4.29" | |
| 452 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 453 | checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" | |
| 454 | ||
| 455 | [[package]] | |
| 456 | name = "measureme" | |
| 457 | version = "12.0.3" | |
| 458 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 459 | checksum = "6ebd1ebda747ae161a4a377bf93f87e18d46faad2331cc0c7d25b84b1d445f49" | |
| 460 | dependencies = [ | |
| 461 | "log", | |
| 462 | "memmap2", | |
| 463 | "parking_lot", | |
| 464 | "perf-event-open-sys", | |
| 465 | "rustc-hash", | |
| 466 | "smallvec", | |
| 467 | ] | |
| 468 | ||
| 469 | [[package]] | |
| 470 | name = "memchr" | |
| 471 | version = "2.8.0" | |
| 472 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 473 | checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" | |
| 474 | ||
| 475 | [[package]] | |
| 476 | name = "memmap2" | |
| 477 | version = "0.2.3" | |
| 478 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 479 | checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4" | |
| 480 | dependencies = [ | |
| 481 | "libc", | |
| 482 | ] | |
| 483 | ||
| 484 | [[package]] | |
| 485 | name = "mio" | |
| 486 | version = "1.2.0" | |
| 487 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 488 | checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" | |
| 489 | dependencies = [ | |
| 490 | "libc", | |
| 491 | "log", | |
| 492 | "wasi", | |
| 493 | "windows-sys", | |
| 494 | ] | |
| 495 | ||
| 496 | [[package]] | |
| 497 | name = "miri" | |
| 498 | version = "0.1.0" | |
| 499 | dependencies = [ | |
| 500 | "aes", | |
| 501 | "bitflags", | |
| 502 | "capstone", | |
| 503 | "chrono", | |
| 504 | "chrono-tz", | |
| 505 | "directories", | |
| 506 | "getrandom 0.4.2", | |
| 507 | "ipc-channel", | |
| 508 | "libc", | |
| 509 | "libffi", | |
| 510 | "libloading", | |
| 511 | "measureme", | |
| 512 | "mio", | |
| 513 | "nix", | |
| 514 | "rand 0.10.1", | |
| 515 | "serde", | |
| 516 | "smallvec", | |
| 517 | ] | |
| 518 | ||
| 519 | [[package]] | |
| 520 | name = "nix" | |
| 521 | version = "0.30.1" | |
| 522 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 523 | checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" | |
| 524 | dependencies = [ | |
| 525 | "bitflags", | |
| 526 | "cfg-if", | |
| 527 | "cfg_aliases", | |
| 528 | "libc", | |
| 529 | ] | |
| 530 | ||
| 531 | [[package]] | |
| 532 | name = "num-traits" | |
| 533 | version = "0.2.19" | |
| 534 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 535 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" | |
| 536 | dependencies = [ | |
| 537 | "autocfg", | |
| 538 | ] | |
| 539 | ||
| 540 | [[package]] | |
| 541 | name = "once_cell" | |
| 542 | version = "1.21.4" | |
| 543 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 544 | checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" | |
| 545 | ||
| 546 | [[package]] | |
| 547 | name = "option-ext" | |
| 548 | version = "0.2.0" | |
| 549 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 550 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" | |
| 551 | ||
| 552 | [[package]] | |
| 553 | name = "parking_lot" | |
| 554 | version = "0.12.5" | |
| 555 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 556 | checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" | |
| 557 | dependencies = [ | |
| 558 | "lock_api", | |
| 559 | "parking_lot_core", | |
| 560 | ] | |
| 561 | ||
| 562 | [[package]] | |
| 563 | name = "parking_lot_core" | |
| 564 | version = "0.9.12" | |
| 565 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 566 | checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" | |
| 567 | dependencies = [ | |
| 568 | "cfg-if", | |
| 569 | "libc", | |
| 570 | "redox_syscall", | |
| 571 | "smallvec", | |
| 572 | "windows-link 0.2.1", | |
| 573 | ] | |
| 574 | ||
| 575 | [[package]] | |
| 576 | name = "perf-event-open-sys" | |
| 577 | version = "3.0.0" | |
| 578 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 579 | checksum = "b29be2ba35c12c6939f6bc73187f728bba82c3c062ecdc5fa90ea739282a1f58" | |
| 580 | dependencies = [ | |
| 581 | "libc", | |
| 582 | ] | |
| 583 | ||
| 584 | [[package]] | |
| 585 | name = "phf" | |
| 586 | version = "0.12.1" | |
| 587 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 588 | checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" | |
| 589 | dependencies = [ | |
| 590 | "phf_shared", | |
| 591 | ] | |
| 592 | ||
| 593 | [[package]] | |
| 594 | name = "phf_shared" | |
| 595 | version = "0.12.1" | |
| 596 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 597 | checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" | |
| 598 | dependencies = [ | |
| 599 | "siphasher", | |
| 600 | ] | |
| 601 | ||
| 602 | [[package]] | |
| 603 | name = "pin-project-lite" | |
| 604 | version = "0.2.17" | |
| 605 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 606 | checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" | |
| 607 | ||
| 608 | [[package]] | |
| 609 | name = "ppv-lite86" | |
| 610 | version = "0.2.21" | |
| 611 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 612 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" | |
| 613 | dependencies = [ | |
| 614 | "zerocopy", | |
| 615 | ] | |
| 616 | ||
| 617 | [[package]] | |
| 618 | name = "prettyplease" | |
| 619 | version = "0.2.37" | |
| 620 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 621 | checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" | |
| 622 | dependencies = [ | |
| 623 | "proc-macro2", | |
| 624 | "syn", | |
| 625 | ] | |
| 626 | ||
| 627 | [[package]] | |
| 628 | name = "priroda" | |
| 629 | version = "0.1.0" | |
| 630 | dependencies = [ | |
| 631 | "miri", | |
| 632 | ] | |
| 633 | ||
| 634 | [[package]] | |
| 635 | name = "proc-macro2" | |
| 636 | version = "1.0.106" | |
| 637 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 638 | checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" | |
| 639 | dependencies = [ | |
| 640 | "unicode-ident", | |
| 641 | ] | |
| 642 | ||
| 643 | [[package]] | |
| 644 | name = "quote" | |
| 645 | version = "1.0.45" | |
| 646 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 647 | checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" | |
| 648 | dependencies = [ | |
| 649 | "proc-macro2", | |
| 650 | ] | |
| 651 | ||
| 652 | [[package]] | |
| 653 | name = "r-efi" | |
| 654 | version = "5.3.0" | |
| 655 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 656 | checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" | |
| 657 | ||
| 658 | [[package]] | |
| 659 | name = "r-efi" | |
| 660 | version = "6.0.0" | |
| 661 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 662 | checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" | |
| 663 | ||
| 664 | [[package]] | |
| 665 | name = "rand" | |
| 666 | version = "0.9.4" | |
| 667 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 668 | checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" | |
| 669 | dependencies = [ | |
| 670 | "rand_chacha", | |
| 671 | "rand_core 0.9.5", | |
| 672 | ] | |
| 673 | ||
| 674 | [[package]] | |
| 675 | name = "rand" | |
| 676 | version = "0.10.1" | |
| 677 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 678 | checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" | |
| 679 | dependencies = [ | |
| 680 | "chacha20", | |
| 681 | "getrandom 0.4.2", | |
| 682 | "rand_core 0.10.1", | |
| 683 | ] | |
| 684 | ||
| 685 | [[package]] | |
| 686 | name = "rand_chacha" | |
| 687 | version = "0.9.0" | |
| 688 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 689 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" | |
| 690 | dependencies = [ | |
| 691 | "ppv-lite86", | |
| 692 | "rand_core 0.9.5", | |
| 693 | ] | |
| 694 | ||
| 695 | [[package]] | |
| 696 | name = "rand_core" | |
| 697 | version = "0.9.5" | |
| 698 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 699 | checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" | |
| 700 | dependencies = [ | |
| 701 | "getrandom 0.3.4", | |
| 702 | ] | |
| 703 | ||
| 704 | [[package]] | |
| 705 | name = "rand_core" | |
| 706 | version = "0.10.1" | |
| 707 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 708 | checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" | |
| 709 | ||
| 710 | [[package]] | |
| 711 | name = "redox_syscall" | |
| 712 | version = "0.5.18" | |
| 713 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 714 | checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" | |
| 715 | dependencies = [ | |
| 716 | "bitflags", | |
| 717 | ] | |
| 718 | ||
| 719 | [[package]] | |
| 720 | name = "redox_users" | |
| 721 | version = "0.5.2" | |
| 722 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 723 | checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" | |
| 724 | dependencies = [ | |
| 725 | "getrandom 0.2.17", | |
| 726 | "libredox", | |
| 727 | "thiserror", | |
| 728 | ] | |
| 729 | ||
| 730 | [[package]] | |
| 731 | name = "rustc-hash" | |
| 732 | version = "1.1.0" | |
| 733 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 734 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" | |
| 735 | ||
| 736 | [[package]] | |
| 737 | name = "rustix" | |
| 738 | version = "1.1.4" | |
| 739 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 740 | checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" | |
| 741 | dependencies = [ | |
| 742 | "bitflags", | |
| 743 | "errno", | |
| 744 | "libc", | |
| 745 | "linux-raw-sys", | |
| 746 | "windows-sys", | |
| 747 | ] | |
| 748 | ||
| 749 | [[package]] | |
| 750 | name = "rustversion" | |
| 751 | version = "1.0.22" | |
| 752 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 753 | checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" | |
| 754 | ||
| 755 | [[package]] | |
| 756 | name = "scopeguard" | |
| 757 | version = "1.2.0" | |
| 758 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 759 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" | |
| 760 | ||
| 761 | [[package]] | |
| 762 | name = "semver" | |
| 763 | version = "1.0.28" | |
| 764 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 765 | checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" | |
| 766 | ||
| 767 | [[package]] | |
| 768 | name = "serde" | |
| 769 | version = "1.0.228" | |
| 770 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 771 | checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" | |
| 772 | dependencies = [ | |
| 773 | "serde_core", | |
| 774 | "serde_derive", | |
| 775 | ] | |
| 776 | ||
| 777 | [[package]] | |
| 778 | name = "serde_core" | |
| 779 | version = "1.0.228" | |
| 780 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 781 | checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" | |
| 782 | dependencies = [ | |
| 783 | "serde_derive", | |
| 784 | ] | |
| 785 | ||
| 786 | [[package]] | |
| 787 | name = "serde_derive" | |
| 788 | version = "1.0.228" | |
| 789 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 790 | checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" | |
| 791 | dependencies = [ | |
| 792 | "proc-macro2", | |
| 793 | "quote", | |
| 794 | "syn", | |
| 795 | ] | |
| 796 | ||
| 797 | [[package]] | |
| 798 | name = "serde_json" | |
| 799 | version = "1.0.149" | |
| 800 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 801 | checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" | |
| 802 | dependencies = [ | |
| 803 | "itoa", | |
| 804 | "memchr", | |
| 805 | "serde", | |
| 806 | "serde_core", | |
| 807 | "zmij", | |
| 808 | ] | |
| 809 | ||
| 810 | [[package]] | |
| 811 | name = "shlex" | |
| 812 | version = "1.3.0" | |
| 813 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 814 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" | |
| 815 | ||
| 816 | [[package]] | |
| 817 | name = "siphasher" | |
| 818 | version = "1.0.3" | |
| 819 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 820 | checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" | |
| 821 | ||
| 822 | [[package]] | |
| 823 | name = "slab" | |
| 824 | version = "0.4.12" | |
| 825 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 826 | checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" | |
| 827 | ||
| 828 | [[package]] | |
| 829 | name = "smallvec" | |
| 830 | version = "1.15.1" | |
| 831 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 832 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" | |
| 833 | ||
| 834 | [[package]] | |
| 835 | name = "static_assertions" | |
| 836 | version = "1.1.0" | |
| 837 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 838 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" | |
| 839 | ||
| 840 | [[package]] | |
| 841 | name = "syn" | |
| 842 | version = "2.0.117" | |
| 843 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 844 | checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" | |
| 845 | dependencies = [ | |
| 846 | "proc-macro2", | |
| 847 | "quote", | |
| 848 | "unicode-ident", | |
| 849 | ] | |
| 850 | ||
| 851 | [[package]] | |
| 852 | name = "tempfile" | |
| 853 | version = "3.27.0" | |
| 854 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 855 | checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" | |
| 856 | dependencies = [ | |
| 857 | "fastrand", | |
| 858 | "getrandom 0.4.2", | |
| 859 | "once_cell", | |
| 860 | "rustix", | |
| 861 | "windows-sys", | |
| 862 | ] | |
| 863 | ||
| 864 | [[package]] | |
| 865 | name = "thiserror" | |
| 866 | version = "2.0.18" | |
| 867 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 868 | checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" | |
| 869 | dependencies = [ | |
| 870 | "thiserror-impl", | |
| 871 | ] | |
| 872 | ||
| 873 | [[package]] | |
| 874 | name = "thiserror-impl" | |
| 875 | version = "2.0.18" | |
| 876 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 877 | checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" | |
| 878 | dependencies = [ | |
| 879 | "proc-macro2", | |
| 880 | "quote", | |
| 881 | "syn", | |
| 882 | ] | |
| 883 | ||
| 884 | [[package]] | |
| 885 | name = "typenum" | |
| 886 | version = "1.20.0" | |
| 887 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 888 | checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" | |
| 889 | ||
| 890 | [[package]] | |
| 891 | name = "unicode-ident" | |
| 892 | version = "1.0.24" | |
| 893 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 894 | checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" | |
| 895 | ||
| 896 | [[package]] | |
| 897 | name = "unicode-xid" | |
| 898 | version = "0.2.6" | |
| 899 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 900 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" | |
| 901 | ||
| 902 | [[package]] | |
| 903 | name = "uuid" | |
| 904 | version = "1.23.1" | |
| 905 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 906 | checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" | |
| 907 | dependencies = [ | |
| 908 | "getrandom 0.4.2", | |
| 909 | "js-sys", | |
| 910 | "wasm-bindgen", | |
| 911 | ] | |
| 912 | ||
| 913 | [[package]] | |
| 914 | name = "wasi" | |
| 915 | version = "0.11.1+wasi-snapshot-preview1" | |
| 916 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 917 | checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" | |
| 918 | ||
| 919 | [[package]] | |
| 920 | name = "wasip2" | |
| 921 | version = "1.0.3+wasi-0.2.9" | |
| 922 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 923 | checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" | |
| 924 | dependencies = [ | |
| 925 | "wit-bindgen 0.57.1", | |
| 926 | ] | |
| 927 | ||
| 928 | [[package]] | |
| 929 | name = "wasip3" | |
| 930 | version = "0.4.0+wasi-0.3.0-rc-2026-01-06" | |
| 931 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 932 | checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" | |
| 933 | dependencies = [ | |
| 934 | "wit-bindgen 0.51.0", | |
| 935 | ] | |
| 936 | ||
| 937 | [[package]] | |
| 938 | name = "wasm-bindgen" | |
| 939 | version = "0.2.121" | |
| 940 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 941 | checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" | |
| 942 | dependencies = [ | |
| 943 | "cfg-if", | |
| 944 | "once_cell", | |
| 945 | "rustversion", | |
| 946 | "wasm-bindgen-macro", | |
| 947 | "wasm-bindgen-shared", | |
| 948 | ] | |
| 949 | ||
| 950 | [[package]] | |
| 951 | name = "wasm-bindgen-macro" | |
| 952 | version = "0.2.121" | |
| 953 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 954 | checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" | |
| 955 | dependencies = [ | |
| 956 | "quote", | |
| 957 | "wasm-bindgen-macro-support", | |
| 958 | ] | |
| 959 | ||
| 960 | [[package]] | |
| 961 | name = "wasm-bindgen-macro-support" | |
| 962 | version = "0.2.121" | |
| 963 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 964 | checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" | |
| 965 | dependencies = [ | |
| 966 | "bumpalo", | |
| 967 | "proc-macro2", | |
| 968 | "quote", | |
| 969 | "syn", | |
| 970 | "wasm-bindgen-shared", | |
| 971 | ] | |
| 972 | ||
| 973 | [[package]] | |
| 974 | name = "wasm-bindgen-shared" | |
| 975 | version = "0.2.121" | |
| 976 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 977 | checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" | |
| 978 | dependencies = [ | |
| 979 | "unicode-ident", | |
| 980 | ] | |
| 981 | ||
| 982 | [[package]] | |
| 983 | name = "wasm-encoder" | |
| 984 | version = "0.244.0" | |
| 985 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 986 | checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" | |
| 987 | dependencies = [ | |
| 988 | "leb128fmt", | |
| 989 | "wasmparser", | |
| 990 | ] | |
| 991 | ||
| 992 | [[package]] | |
| 993 | name = "wasm-metadata" | |
| 994 | version = "0.244.0" | |
| 995 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 996 | checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" | |
| 997 | dependencies = [ | |
| 998 | "anyhow", | |
| 999 | "indexmap", | |
| 1000 | "wasm-encoder", | |
| 1001 | "wasmparser", | |
| 1002 | ] | |
| 1003 | ||
| 1004 | [[package]] | |
| 1005 | name = "wasmparser" | |
| 1006 | version = "0.244.0" | |
| 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1008 | checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" | |
| 1009 | dependencies = [ | |
| 1010 | "bitflags", | |
| 1011 | "hashbrown 0.15.5", | |
| 1012 | "indexmap", | |
| 1013 | "semver", | |
| 1014 | ] | |
| 1015 | ||
| 1016 | [[package]] | |
| 1017 | name = "windows" | |
| 1018 | version = "0.61.3" | |
| 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1020 | checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" | |
| 1021 | dependencies = [ | |
| 1022 | "windows-collections", | |
| 1023 | "windows-core", | |
| 1024 | "windows-future", | |
| 1025 | "windows-link 0.1.3", | |
| 1026 | "windows-numerics", | |
| 1027 | ] | |
| 1028 | ||
| 1029 | [[package]] | |
| 1030 | name = "windows-collections" | |
| 1031 | version = "0.2.0" | |
| 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1033 | checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" | |
| 1034 | dependencies = [ | |
| 1035 | "windows-core", | |
| 1036 | ] | |
| 1037 | ||
| 1038 | [[package]] | |
| 1039 | name = "windows-core" | |
| 1040 | version = "0.61.2" | |
| 1041 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1042 | checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" | |
| 1043 | dependencies = [ | |
| 1044 | "windows-implement", | |
| 1045 | "windows-interface", | |
| 1046 | "windows-link 0.1.3", | |
| 1047 | "windows-result", | |
| 1048 | "windows-strings", | |
| 1049 | ] | |
| 1050 | ||
| 1051 | [[package]] | |
| 1052 | name = "windows-future" | |
| 1053 | version = "0.2.1" | |
| 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1055 | checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" | |
| 1056 | dependencies = [ | |
| 1057 | "windows-core", | |
| 1058 | "windows-link 0.1.3", | |
| 1059 | "windows-threading", | |
| 1060 | ] | |
| 1061 | ||
| 1062 | [[package]] | |
| 1063 | name = "windows-implement" | |
| 1064 | version = "0.60.2" | |
| 1065 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1066 | checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" | |
| 1067 | dependencies = [ | |
| 1068 | "proc-macro2", | |
| 1069 | "quote", | |
| 1070 | "syn", | |
| 1071 | ] | |
| 1072 | ||
| 1073 | [[package]] | |
| 1074 | name = "windows-interface" | |
| 1075 | version = "0.59.3" | |
| 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1077 | checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" | |
| 1078 | dependencies = [ | |
| 1079 | "proc-macro2", | |
| 1080 | "quote", | |
| 1081 | "syn", | |
| 1082 | ] | |
| 1083 | ||
| 1084 | [[package]] | |
| 1085 | name = "windows-link" | |
| 1086 | version = "0.1.3" | |
| 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1088 | checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" | |
| 1089 | ||
| 1090 | [[package]] | |
| 1091 | name = "windows-link" | |
| 1092 | version = "0.2.1" | |
| 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1094 | checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" | |
| 1095 | ||
| 1096 | [[package]] | |
| 1097 | name = "windows-numerics" | |
| 1098 | version = "0.2.0" | |
| 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1100 | checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" | |
| 1101 | dependencies = [ | |
| 1102 | "windows-core", | |
| 1103 | "windows-link 0.1.3", | |
| 1104 | ] | |
| 1105 | ||
| 1106 | [[package]] | |
| 1107 | name = "windows-result" | |
| 1108 | version = "0.3.4" | |
| 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1110 | checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" | |
| 1111 | dependencies = [ | |
| 1112 | "windows-link 0.1.3", | |
| 1113 | ] | |
| 1114 | ||
| 1115 | [[package]] | |
| 1116 | name = "windows-strings" | |
| 1117 | version = "0.4.2" | |
| 1118 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1119 | checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" | |
| 1120 | dependencies = [ | |
| 1121 | "windows-link 0.1.3", | |
| 1122 | ] | |
| 1123 | ||
| 1124 | [[package]] | |
| 1125 | name = "windows-sys" | |
| 1126 | version = "0.61.2" | |
| 1127 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1128 | checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" | |
| 1129 | dependencies = [ | |
| 1130 | "windows-link 0.2.1", | |
| 1131 | ] | |
| 1132 | ||
| 1133 | [[package]] | |
| 1134 | name = "windows-threading" | |
| 1135 | version = "0.1.0" | |
| 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1137 | checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" | |
| 1138 | dependencies = [ | |
| 1139 | "windows-link 0.1.3", | |
| 1140 | ] | |
| 1141 | ||
| 1142 | [[package]] | |
| 1143 | name = "wit-bindgen" | |
| 1144 | version = "0.51.0" | |
| 1145 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1146 | checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" | |
| 1147 | dependencies = [ | |
| 1148 | "wit-bindgen-rust-macro", | |
| 1149 | ] | |
| 1150 | ||
| 1151 | [[package]] | |
| 1152 | name = "wit-bindgen" | |
| 1153 | version = "0.57.1" | |
| 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1155 | checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" | |
| 1156 | ||
| 1157 | [[package]] | |
| 1158 | name = "wit-bindgen-core" | |
| 1159 | version = "0.51.0" | |
| 1160 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1161 | checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" | |
| 1162 | dependencies = [ | |
| 1163 | "anyhow", | |
| 1164 | "heck", | |
| 1165 | "wit-parser", | |
| 1166 | ] | |
| 1167 | ||
| 1168 | [[package]] | |
| 1169 | name = "wit-bindgen-rust" | |
| 1170 | version = "0.51.0" | |
| 1171 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1172 | checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" | |
| 1173 | dependencies = [ | |
| 1174 | "anyhow", | |
| 1175 | "heck", | |
| 1176 | "indexmap", | |
| 1177 | "prettyplease", | |
| 1178 | "syn", | |
| 1179 | "wasm-metadata", | |
| 1180 | "wit-bindgen-core", | |
| 1181 | "wit-component", | |
| 1182 | ] | |
| 1183 | ||
| 1184 | [[package]] | |
| 1185 | name = "wit-bindgen-rust-macro" | |
| 1186 | version = "0.51.0" | |
| 1187 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1188 | checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" | |
| 1189 | dependencies = [ | |
| 1190 | "anyhow", | |
| 1191 | "prettyplease", | |
| 1192 | "proc-macro2", | |
| 1193 | "quote", | |
| 1194 | "syn", | |
| 1195 | "wit-bindgen-core", | |
| 1196 | "wit-bindgen-rust", | |
| 1197 | ] | |
| 1198 | ||
| 1199 | [[package]] | |
| 1200 | name = "wit-component" | |
| 1201 | version = "0.244.0" | |
| 1202 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1203 | checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" | |
| 1204 | dependencies = [ | |
| 1205 | "anyhow", | |
| 1206 | "bitflags", | |
| 1207 | "indexmap", | |
| 1208 | "log", | |
| 1209 | "serde", | |
| 1210 | "serde_derive", | |
| 1211 | "serde_json", | |
| 1212 | "wasm-encoder", | |
| 1213 | "wasm-metadata", | |
| 1214 | "wasmparser", | |
| 1215 | "wit-parser", | |
| 1216 | ] | |
| 1217 | ||
| 1218 | [[package]] | |
| 1219 | name = "wit-parser" | |
| 1220 | version = "0.244.0" | |
| 1221 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1222 | checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" | |
| 1223 | dependencies = [ | |
| 1224 | "anyhow", | |
| 1225 | "id-arena", | |
| 1226 | "indexmap", | |
| 1227 | "log", | |
| 1228 | "semver", | |
| 1229 | "serde", | |
| 1230 | "serde_derive", | |
| 1231 | "serde_json", | |
| 1232 | "unicode-xid", | |
| 1233 | "wasmparser", | |
| 1234 | ] | |
| 1235 | ||
| 1236 | [[package]] | |
| 1237 | name = "zerocopy" | |
| 1238 | version = "0.8.48" | |
| 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1240 | checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" | |
| 1241 | dependencies = [ | |
| 1242 | "zerocopy-derive", | |
| 1243 | ] | |
| 1244 | ||
| 1245 | [[package]] | |
| 1246 | name = "zerocopy-derive" | |
| 1247 | version = "0.8.48" | |
| 1248 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1249 | checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" | |
| 1250 | dependencies = [ | |
| 1251 | "proc-macro2", | |
| 1252 | "quote", | |
| 1253 | "syn", | |
| 1254 | ] | |
| 1255 | ||
| 1256 | [[package]] | |
| 1257 | name = "zmij" | |
| 1258 | version = "1.0.21" | |
| 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1260 | checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" |
src/tools/miri/priroda/Cargo.toml created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | [package] | |
| 2 | description = "Debugger for Rust MIR." | |
| 3 | license = "MIT OR Apache-2.0" | |
| 4 | name = "priroda" | |
| 5 | repository = "https://github.com/rust-lang/miri" | |
| 6 | version = "0.1.0" | |
| 7 | edition = "2024" | |
| 8 | ||
| 9 | ||
| 10 | [[bin]] | |
| 11 | name = "priroda" | |
| 12 | path = "src/main.rs" | |
| 13 | doctest = false # and no doc tests | |
| 14 | ||
| 15 | [dependencies] | |
| 16 | miri = { path = ".." } | |
| 17 | ||
| 18 | [package.metadata.rust-analyzer] | |
| 19 | rustc_private = true |
src/tools/miri/priroda/README.md created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | # Priroda | |
| 2 | ||
| 3 | Priroda is a step-through debugger for Rust programs running under | |
| 4 | Miri. | |
| 5 | ||
| 6 | Current focus: | |
| 7 | ||
| 8 | - simple CLI prototype | |
| 9 | - single-threaded stepping with Miri's interpreter | |
| 10 | - commands: empty Enter, `s`, or `step` | |
| 11 | ||
| 12 | ## Setup | |
| 13 | ||
| 14 | From `miri/`, install the pinned toolchain and the local `cargo-miri` | |
| 15 | command: | |
| 16 | ||
| 17 | ```sh | |
| 18 | ./miri toolchain | |
| 19 | ./miri install | |
| 20 | ``` | |
| 21 | ||
| 22 | Then build the Miri sysroot and export it for Priroda: | |
| 23 | ||
| 24 | ```sh | |
| 25 | cargo +miri miri setup | |
| 26 | export MIRI_SYSROOT="$(cargo +miri miri setup --print-sysroot)" | |
| 27 | ``` | |
| 28 | ||
| 29 | ## Run | |
| 30 | ||
| 31 | Priroda currently reads `MIRI_SYSROOT` directly. After setup: | |
| 32 | ||
| 33 | ```sh | |
| 34 | cargo run -p priroda -- tests/pass/empty_main.rs | |
| 35 | ``` | |
| 36 | ||
| 37 | At the prompt, press Enter or type `s` / `step`. |
src/tools/miri/priroda/rust-toolchain.toml created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | [toolchain] | |
| 2 | channel = "miri" |
src/tools/miri/priroda/src/main.rs created+147| ... | ... | @@ -0,0 +1,147 @@ |
| 1 | #![feature(rustc_private)] | |
| 2 | ||
| 3 | extern crate miri; | |
| 4 | extern crate rustc_codegen_ssa; | |
| 5 | extern crate rustc_data_structures; | |
| 6 | extern crate rustc_driver; | |
| 7 | extern crate rustc_hir; | |
| 8 | extern crate rustc_hir_analysis; | |
| 9 | extern crate rustc_interface; | |
| 10 | extern crate rustc_log; | |
| 11 | extern crate rustc_middle; | |
| 12 | extern crate rustc_session; | |
| 13 | ||
| 14 | use std::io::{self, Write}; | |
| 15 | ||
| 16 | use miri::*; | |
| 17 | use rustc_driver::Compilation; | |
| 18 | use rustc_hir::attrs::CrateType; | |
| 19 | use rustc_interface::interface; | |
| 20 | use rustc_middle::ty::TyCtxt; | |
| 21 | use rustc_session::EarlyDiagCtxt; | |
| 22 | use rustc_session::config::ErrorOutputType; | |
| 23 | fn find_sysroot() -> String { | |
| 24 | std::env::var("MIRI_SYSROOT") | |
| 25 | .expect("set MIRI_SYSROOT to the path from `cargo miri setup --print-sysroot`") | |
| 26 | } | |
| 27 | ||
| 28 | fn main() { | |
| 29 | let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); | |
| 30 | rustc_driver::init_rustc_env_logger(&early_dcx); | |
| 31 | ||
| 32 | let mut args: Vec<String> = std::env::args().collect(); | |
| 33 | ||
| 34 | args.splice(1..1, miri::MIRI_DEFAULT_ARGS.iter().map(ToString::to_string)); | |
| 35 | ||
| 36 | let sysroot_flag = String::from("--sysroot"); | |
| 37 | if !args.contains(&sysroot_flag) { | |
| 38 | args.push(sysroot_flag); | |
| 39 | args.push(find_sysroot()); | |
| 40 | } | |
| 41 | //TODO: handle the same `-Z` flags that Miri accepts. | |
| 42 | rustc_driver::run_compiler(&args, &mut PrirodaCompilerCalls::new()); | |
| 43 | } | |
| 44 | ||
| 45 | struct PrirodaCompilerCalls; | |
| 46 | ||
| 47 | impl PrirodaCompilerCalls { | |
| 48 | fn new() -> Self { | |
| 49 | Self | |
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | impl rustc_driver::Callbacks for PrirodaCompilerCalls { | |
| 54 | fn after_analysis<'tcx>(&mut self, _: &interface::Compiler, tcx: TyCtxt<'tcx>) -> Compilation { | |
| 55 | tcx.dcx().emit_stashed_diagnostics(); | |
| 56 | tcx.dcx().abort_if_errors(); | |
| 57 | ||
| 58 | if !tcx.crate_types().contains(&CrateType::Executable) { | |
| 59 | //TODO: support non-bin crates by listing functions and letting users call them with manually entered arguments. | |
| 60 | tcx.dcx().fatal("priroda only makes sense on bin crates"); | |
| 61 | } | |
| 62 | ||
| 63 | let ecx = create_ecx(tcx); | |
| 64 | ||
| 65 | let mut session = PrirodaContext::new(ecx); | |
| 66 | let result = run_cli_loop(&mut session); | |
| 67 | ||
| 68 | match result.report_err() { | |
| 69 | Ok(()) => {} | |
| 70 | Err(err) => | |
| 71 | if let Some((return_code, _leak_check)) = report_result(&session.ecx, err) { | |
| 72 | //TODO: print the evaluated program's exit code and return to the debugger prompt instead of exiting Priroda. | |
| 73 | if return_code != 0 { | |
| 74 | std::process::exit(return_code); | |
| 75 | } | |
| 76 | }, | |
| 77 | } | |
| 78 | ||
| 79 | Compilation::Stop | |
| 80 | } | |
| 81 | } | |
| 82 | ||
| 83 | fn create_ecx<'tcx>(tcx: TyCtxt<'tcx>) -> MiriInterpCx<'tcx> { | |
| 84 | let (entry_id, entry_type) = miri::entry_fn(tcx); | |
| 85 | let config = MiriConfig::default(); | |
| 86 | miri::create_ecx(tcx, entry_id, entry_type, &config, None).unwrap() | |
| 87 | } | |
| 88 | ||
| 89 | pub struct PrirodaContext<'tcx> { | |
| 90 | ecx: MiriInterpCx<'tcx>, | |
| 91 | } | |
| 92 | ||
| 93 | impl<'tcx> PrirodaContext<'tcx> { | |
| 94 | fn new(ecx: MiriInterpCx<'tcx>) -> Self { | |
| 95 | Self { ecx } | |
| 96 | } | |
| 97 | ||
| 98 | // TODO: return a StepResult enum once we distinguish breakpoint stops, | |
| 99 | // program exit, and other debugger states. | |
| 100 | pub fn step(&mut self) -> InterpResult<'tcx> { | |
| 101 | self.ecx.miri_step() | |
| 102 | } | |
| 103 | ||
| 104 | pub fn print_location(&self) { | |
| 105 | let span = self.ecx.machine.current_user_relevant_span(); | |
| 106 | let location = self.ecx.tcx.sess.source_map().span_to_diagnostic_string(span); | |
| 107 | // TODO: skip noisy std/runtime spans and avoid printing `no-location` | |
| 108 | // once the basic command loop is solid. | |
| 109 | println!("{location}"); | |
| 110 | io::stdout().flush().unwrap(); | |
| 111 | } | |
| 112 | fn run_command(&mut self, command: SessionCommand) -> InterpResult<'tcx> { | |
| 113 | match command { | |
| 114 | SessionCommand::Step => self.step(), | |
| 115 | } | |
| 116 | } | |
| 117 | } | |
| 118 | ||
| 119 | enum SessionCommand { | |
| 120 | Step, | |
| 121 | } | |
| 122 | ||
| 123 | fn parse_command(input: &str) -> Option<SessionCommand> { | |
| 124 | match input.trim() { | |
| 125 | "" | "s" | "step" => Some(SessionCommand::Step), | |
| 126 | _ => None, | |
| 127 | } | |
| 128 | } | |
| 129 | ||
| 130 | fn run_cli_loop<'tcx>(session: &mut PrirodaContext<'tcx>) -> InterpResult<'tcx> { | |
| 131 | loop { | |
| 132 | print!("(priroda) "); | |
| 133 | io::stdout().flush().unwrap(); | |
| 134 | ||
| 135 | let mut input = String::new(); | |
| 136 | // TODO: handle EOF explicitly so scripted input can stop the CLI instead | |
| 137 | // of being treated like an empty Enter step. | |
| 138 | io::stdin().read_line(&mut input).unwrap(); | |
| 139 | ||
| 140 | if let Some(command) = parse_command(&input) { | |
| 141 | session.run_command(command)?; | |
| 142 | session.print_location(); | |
| 143 | } else { | |
| 144 | println!("no command"); | |
| 145 | } | |
| 146 | } | |
| 147 | } |
src/tools/miri/rust-version+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | 1f8e04d34ab0c1fd9574840aa6db670e41593bfb | |
| 1 | bef8e620f19adbfd1530e916ab8caa296ef9c3ee |
src/tools/miri/src/bin/miri.rs+15-56| ... | ... | @@ -12,12 +12,10 @@ extern crate rustc_codegen_ssa; |
| 12 | 12 | extern crate rustc_data_structures; |
| 13 | 13 | extern crate rustc_driver; |
| 14 | 14 | extern crate rustc_hir; |
| 15 | extern crate rustc_hir_analysis; | |
| 16 | 15 | extern crate rustc_interface; |
| 17 | 16 | extern crate rustc_log; |
| 18 | 17 | extern crate rustc_middle; |
| 19 | 18 | extern crate rustc_session; |
| 20 | extern crate rustc_span; | |
| 21 | 19 | |
| 22 | 20 | /// See docs in https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc/src/main.rs |
| 23 | 21 | /// and https://github.com/rust-lang/rust/pull/146627 for why we need this. |
| ... | ... | @@ -44,15 +42,13 @@ use std::str::FromStr; |
| 44 | 42 | use std::sync::atomic::{AtomicU32, Ordering}; |
| 45 | 43 | |
| 46 | 44 | use miri::{ |
| 47 | BacktraceStyle, BorrowTrackerMethod, GenmcConfig, GenmcCtx, MiriConfig, MiriEntryFnType, | |
| 48 | ProvenanceMode, TreeBorrowsParams, ValidationMode, run_genmc_mode, | |
| 45 | BacktraceStyle, BorrowTrackerMethod, GenmcConfig, GenmcCtx, MiriConfig, ProvenanceMode, | |
| 46 | TreeBorrowsParams, ValidationMode, entry_fn, run_genmc_mode, | |
| 49 | 47 | }; |
| 50 | 48 | use rustc_codegen_ssa::traits::CodegenBackend; |
| 51 | 49 | use rustc_data_structures::sync::{self, DynSync}; |
| 52 | 50 | use rustc_driver::Compilation; |
| 53 | use rustc_hir::def_id::LOCAL_CRATE; | |
| 54 | 51 | use rustc_hir::{self as hir, Node}; |
| 55 | use rustc_hir_analysis::check::check_function_signature; | |
| 56 | 52 | use rustc_interface::interface::Config; |
| 57 | 53 | use rustc_interface::util::DummyCodegenBackend; |
| 58 | 54 | use rustc_log::tracing::debug; |
| ... | ... | @@ -61,11 +57,9 @@ use rustc_middle::middle::exported_symbols::{ |
| 61 | 57 | ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, |
| 62 | 58 | }; |
| 63 | 59 | use rustc_middle::query::LocalCrate; |
| 64 | use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; | |
| 65 | use rustc_middle::ty::{self, Ty, TyCtxt}; | |
| 60 | use rustc_middle::ty::TyCtxt; | |
| 66 | 61 | use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; |
| 67 | 62 | use rustc_session::{EarlyDiagCtxt, Session}; |
| 68 | use rustc_span::def_id::DefId; | |
| 69 | 63 | |
| 70 | 64 | use crate::log::setup::{deinit_loggers, init_early_loggers, init_late_loggers}; |
| 71 | 65 | |
| ... | ... | @@ -85,53 +79,6 @@ impl MiriCompilerCalls { |
| 85 | 79 | } |
| 86 | 80 | } |
| 87 | 81 | |
| 88 | fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) { | |
| 89 | if let Some((def_id, entry_type)) = tcx.entry_fn(()) { | |
| 90 | return (def_id, MiriEntryFnType::Rustc(entry_type)); | |
| 91 | } | |
| 92 | // Look for a symbol in the local crate named `miri_start`, and treat that as the entry point. | |
| 93 | let sym = tcx.exported_non_generic_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| { | |
| 94 | if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None } | |
| 95 | }); | |
| 96 | if let Some(ExportedSymbol::NonGeneric(id)) = sym { | |
| 97 | let start_def_id = id.expect_local(); | |
| 98 | let start_span = tcx.def_span(start_def_id); | |
| 99 | ||
| 100 | let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi( | |
| 101 | [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))], | |
| 102 | tcx.types.isize, | |
| 103 | )); | |
| 104 | ||
| 105 | let correct_func_sig = check_function_signature( | |
| 106 | tcx, | |
| 107 | ObligationCause::new(start_span, start_def_id, ObligationCauseCode::Misc), | |
| 108 | *id, | |
| 109 | expected_sig, | |
| 110 | ) | |
| 111 | .is_ok(); | |
| 112 | ||
| 113 | if correct_func_sig { | |
| 114 | (*id, MiriEntryFnType::MiriStart) | |
| 115 | } else { | |
| 116 | tcx.dcx().fatal( | |
| 117 | "`miri_start` must have the following signature:\n\ | |
| 118 | fn miri_start(argc: isize, argv: *const *const u8) -> isize", | |
| 119 | ); | |
| 120 | } | |
| 121 | } else { | |
| 122 | tcx.dcx().fatal( | |
| 123 | "Miri can only run programs that have a main function.\n\ | |
| 124 | Alternatively, you can export a `miri_start` function:\n\ | |
| 125 | \n\ | |
| 126 | #[cfg(miri)]\n\ | |
| 127 | #[unsafe(no_mangle)]\n\ | |
| 128 | fn miri_start(argc: isize, argv: *const *const u8) -> isize {\ | |
| 129 | \n // Call the actual start function that your project implements, based on your target's conventions.\n\ | |
| 130 | }" | |
| 131 | ); | |
| 132 | } | |
| 133 | } | |
| 134 | ||
| 135 | 82 | fn run_many_seeds( |
| 136 | 83 | many_seeds: ManySeedsConfig, |
| 137 | 84 | eval_entry_once: impl Fn(u64) -> Result<(), NonZeroI32> + DynSync, |
| ... | ... | @@ -526,6 +473,8 @@ fn main() -> ExitCode { |
| 526 | 473 | Some(BorrowTrackerMethod::TreeBorrows(TreeBorrowsParams { |
| 527 | 474 | precise_interior_mut: true, |
| 528 | 475 | implicit_writes: false, |
| 476 | // We default this to "unique" for now to keep the design space open. | |
| 477 | box_custom_allocator_unique: true, | |
| 529 | 478 | })); |
| 530 | 479 | } else if arg == "-Zmiri-tree-borrows-no-precise-interior-mut" { |
| 531 | 480 | match &mut miri_config.borrow_tracker { |
| ... | ... | @@ -547,6 +496,16 @@ fn main() -> ExitCode { |
| 547 | 496 | "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-implicit-writes`" |
| 548 | 497 | ), |
| 549 | 498 | }; |
| 499 | } else if arg == "-Zmiri-tree-borrows-relax-custom-allocator-uniqueness" { | |
| 500 | match &mut miri_config.borrow_tracker { | |
| 501 | Some(BorrowTrackerMethod::TreeBorrows(params)) => { | |
| 502 | params.box_custom_allocator_unique = false; | |
| 503 | } | |
| 504 | _ => | |
| 505 | fatal_error!( | |
| 506 | "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-relax-custom-allocator-uniqueness`" | |
| 507 | ), | |
| 508 | }; | |
| 550 | 509 | } else if arg == "-Zmiri-disable-data-race-detector" { |
| 551 | 510 | miri_config.data_race_detector = false; |
| 552 | 511 | miri_config.weak_memory_emulation = false; |
src/tools/miri/src/borrow_tracker/mod.rs+4| ... | ... | @@ -226,9 +226,12 @@ pub enum BorrowTrackerMethod { |
| 226 | 226 | /// Parameters that Tree Borrows can take. |
| 227 | 227 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 228 | 228 | pub struct TreeBorrowsParams { |
| 229 | /// Controls whether we track `UnsafeCell` with byte precision. | |
| 229 | 230 | pub precise_interior_mut: bool, |
| 230 | 231 | /// Controls whether `&mut` function arguments are immediately activated with an implicit write. |
| 231 | 232 | pub implicit_writes: bool, |
| 233 | /// Controls whether `Box` with custom allocator is considered unique. | |
| 234 | pub box_custom_allocator_unique: bool, | |
| 232 | 235 | } |
| 233 | 236 | |
| 234 | 237 | impl BorrowTrackerMethod { |
| ... | ... | @@ -236,6 +239,7 @@ impl BorrowTrackerMethod { |
| 236 | 239 | RefCell::new(GlobalStateInner::new(self, config.tracked_pointer_tags.clone())) |
| 237 | 240 | } |
| 238 | 241 | |
| 242 | #[track_caller] | |
| 239 | 243 | pub fn get_tree_borrows_params(self) -> TreeBorrowsParams { |
| 240 | 244 | match self { |
| 241 | 245 | BorrowTrackerMethod::TreeBorrows(params) => params, |
src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs+1-6| ... | ... | @@ -869,12 +869,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 869 | 869 | RetagMode::None => return interp_ok(None), // no retagging |
| 870 | 870 | }; |
| 871 | 871 | let new_perm = if ty.is_box() { |
| 872 | if ty.is_box_global(*this.tcx) { | |
| 873 | NewPermission::from_box_ty(val.layout.ty, mode, this) | |
| 874 | } else { | |
| 875 | // Boxes with local allocator are not retagged. | |
| 876 | return interp_ok(None); | |
| 877 | } | |
| 872 | NewPermission::from_box_ty(val.layout.ty, mode, this) | |
| 878 | 873 | } else { |
| 879 | 874 | NewPermission::from_ref_ty(val.layout.ty, mode, this) |
| 880 | 875 | }; |
src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs+22-27| ... | ... | @@ -127,7 +127,7 @@ impl<'tcx> NewPermission { |
| 127 | 127 | pointee: Ty<'tcx>, |
| 128 | 128 | ref_mutability: Option<Mutability>, |
| 129 | 129 | mode: RetagMode, |
| 130 | cx: &crate::MiriInterpCx<'tcx>, | |
| 130 | cx: &MiriInterpCx<'tcx>, | |
| 131 | 131 | ) -> Option<Self> { |
| 132 | 132 | if mode == RetagMode::None { |
| 133 | 133 | return None; |
| ... | ... | @@ -143,15 +143,7 @@ impl<'tcx> NewPermission { |
| 143 | 143 | // `#[rustc_no_writable]` attribute. For performance reasons, only performs the lookup if |
| 144 | 144 | // is_protected is true as implicit writes are only performed for protected references. |
| 145 | 145 | let implicit_writes_enabled = is_protected && { |
| 146 | let implicit_writes = cx | |
| 147 | .machine | |
| 148 | .borrow_tracker | |
| 149 | .as_ref() | |
| 150 | .unwrap() | |
| 151 | .borrow() | |
| 152 | .borrow_tracker_method | |
| 153 | .get_tree_borrows_params() | |
| 154 | .implicit_writes; | |
| 146 | let implicit_writes = cx.get_tree_borrows_params().implicit_writes; | |
| 155 | 147 | let def_id = cx.frame().instance().def_id(); |
| 156 | 148 | implicit_writes && !find_attr!(cx.tcx, def_id, RustcNoWritable) |
| 157 | 149 | }; |
| ... | ... | @@ -234,6 +226,14 @@ impl<'tcx> NewPermission { |
| 234 | 226 | /// the implementation of NewPermission. |
| 235 | 227 | impl<'tcx> EvalContextPrivExt<'tcx> for crate::MiriInterpCx<'tcx> {} |
| 236 | 228 | trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 229 | #[track_caller] | |
| 230 | #[inline] | |
| 231 | fn get_tree_borrows_params(&self) -> TreeBorrowsParams { | |
| 232 | let this = self.eval_context_ref(); | |
| 233 | let borrow_tracker = this.machine.borrow_tracker.as_ref().unwrap().borrow(); | |
| 234 | borrow_tracker.borrow_tracker_method.get_tree_borrows_params() | |
| 235 | } | |
| 236 | ||
| 237 | 237 | /// Returns the provenance that should be used henceforth. |
| 238 | 238 | fn tb_reborrow( |
| 239 | 239 | &mut self, |
| ... | ... | @@ -326,15 +326,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 326 | 326 | } |
| 327 | 327 | |
| 328 | 328 | let protected = new_perm.protector.is_some(); |
| 329 | let precise_interior_mut = this | |
| 330 | .machine | |
| 331 | .borrow_tracker | |
| 332 | .as_mut() | |
| 333 | .unwrap() | |
| 334 | .get_mut() | |
| 335 | .borrow_tracker_method | |
| 336 | .get_tree_borrows_params() | |
| 337 | .precise_interior_mut; | |
| 329 | let precise_interior_mut = this.get_tree_borrows_params().precise_interior_mut; | |
| 338 | 330 | |
| 339 | 331 | // Compute initial "inside" permissions. |
| 340 | 332 | let loc_state = |frozen: bool| -> LocationState { |
| ... | ... | @@ -487,22 +479,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 487 | 479 | ) -> InterpResult<'tcx, Option<ImmTy<'tcx>>> { |
| 488 | 480 | let this = self.eval_context_mut(); |
| 489 | 481 | let new_perm = match *ty.kind() { |
| 490 | _ if ty.is_box_global(*this.tcx) => { | |
| 491 | // The `None` marks this as a Box. | |
| 492 | NewPermission::new(ty.builtin_deref(true).unwrap(), None, mode, this) | |
| 493 | } | |
| 494 | 482 | ty::Ref(_, pointee, mutability) => |
| 495 | 483 | NewPermission::new(pointee, Some(mutability), mode, this), |
| 484 | _ if ty.is_box() => { | |
| 485 | let box_custom_allocator_unique = | |
| 486 | this.get_tree_borrows_params().box_custom_allocator_unique; | |
| 487 | if box_custom_allocator_unique || ty.is_box_global(*this.tcx) { | |
| 488 | // The `None` marks this as a Box. | |
| 489 | NewPermission::new(ty.builtin_deref(true).unwrap(), None, mode, this) | |
| 490 | } else { | |
| 491 | // No retagging for boxes with custom allocators. | |
| 492 | None | |
| 493 | } | |
| 494 | } | |
| 496 | 495 | |
| 497 | 496 | ty::RawPtr(..) => { |
| 498 | 497 | assert!(mode == RetagMode::Raw); |
| 499 | 498 | // We don't give new tags to raw pointers. |
| 500 | 499 | None |
| 501 | 500 | } |
| 502 | _ if ty.is_box() => { | |
| 503 | // No retagging for boxes with local allocators. | |
| 504 | None | |
| 505 | } | |
| 506 | 501 | _ => panic!("tb_retag_ptr_value: invalid type {ty}"), |
| 507 | 502 | }; |
| 508 | 503 | if let Some(new_perm) = new_perm { |
src/tools/miri/src/concurrency/thread.rs+18-8| ... | ... | @@ -856,6 +856,23 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { |
| 856 | 856 | // Public interface to thread management. |
| 857 | 857 | impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} |
| 858 | 858 | pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 859 | /// Public because this is used by Priroda. | |
| 860 | fn miri_step(&mut self) -> InterpResult<'tcx> { | |
| 861 | let this = self.eval_context_mut(); | |
| 862 | ||
| 863 | if !this.step()? { | |
| 864 | // See if this thread can do something else. | |
| 865 | match this.run_on_stack_empty()? { | |
| 866 | Poll::Pending => {} //keep going | |
| 867 | Poll::Ready(()) => { | |
| 868 | this.terminate_active_thread(TlsAllocAction::Deallocate)?; | |
| 869 | } | |
| 870 | } | |
| 871 | } | |
| 872 | ||
| 873 | interp_ok(()) | |
| 874 | } | |
| 875 | ||
| 859 | 876 | #[inline] |
| 860 | 877 | fn thread_id_try_from(&self, id: impl TryInto<u32>) -> Result<ThreadId, ThreadLookupError> { |
| 861 | 878 | self.eval_context_ref().machine.threads.thread_id_try_from(id) |
| ... | ... | @@ -1289,14 +1306,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1289 | 1306 | } |
| 1290 | 1307 | match this.schedule()? { |
| 1291 | 1308 | SchedulingAction::ExecuteStep => { |
| 1292 | if !this.step()? { | |
| 1293 | // See if this thread can do something else. | |
| 1294 | match this.run_on_stack_empty()? { | |
| 1295 | Poll::Pending => {} // keep going | |
| 1296 | Poll::Ready(()) => | |
| 1297 | this.terminate_active_thread(TlsAllocAction::Deallocate)?, | |
| 1298 | } | |
| 1299 | } | |
| 1309 | this.miri_step()?; | |
| 1300 | 1310 | } |
| 1301 | 1311 | SchedulingAction::SleepAndWaitForIo(duration) => { |
| 1302 | 1312 | if this.machine.communicate() { |
src/tools/miri/src/eval.rs+54-1| ... | ... | @@ -12,7 +12,10 @@ use rustc_abi::ExternAbi; |
| 12 | 12 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
| 13 | 13 | use rustc_errors::FatalErrorMarker; |
| 14 | 14 | use rustc_hir::def::Namespace; |
| 15 | use rustc_hir::def_id::DefId; | |
| 15 | use rustc_hir::def_id::{DefId, LOCAL_CRATE}; | |
| 16 | use rustc_hir_analysis::check::check_function_signature; | |
| 17 | use rustc_middle::middle::exported_symbols::ExportedSymbol; | |
| 18 | use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; | |
| 16 | 19 | use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutCx}; |
| 17 | 20 | use rustc_middle::ty::{self, Ty, TyCtxt}; |
| 18 | 21 | use rustc_session::config::EntryFnType; |
| ... | ... | @@ -31,6 +34,56 @@ pub enum MiriEntryFnType { |
| 31 | 34 | Rustc(EntryFnType), |
| 32 | 35 | } |
| 33 | 36 | |
| 37 | /// Finds the entry point Miri should execute. | |
| 38 | /// | |
| 39 | /// Public because this is used by Priroda. | |
| 40 | pub fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) { | |
| 41 | if let Some((def_id, entry_type)) = tcx.entry_fn(()) { | |
| 42 | return (def_id, MiriEntryFnType::Rustc(entry_type)); | |
| 43 | } | |
| 44 | // Look for a symbol in the local crate named `miri_start`, and treat that as the entry point. | |
| 45 | let sym = tcx.exported_non_generic_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| { | |
| 46 | if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None } | |
| 47 | }); | |
| 48 | if let Some(ExportedSymbol::NonGeneric(id)) = sym { | |
| 49 | let start_def_id = id.expect_local(); | |
| 50 | let start_span = tcx.def_span(start_def_id); | |
| 51 | ||
| 52 | let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi( | |
| 53 | [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))], | |
| 54 | tcx.types.isize, | |
| 55 | )); | |
| 56 | ||
| 57 | let correct_func_sig = check_function_signature( | |
| 58 | tcx, | |
| 59 | ObligationCause::new(start_span, start_def_id, ObligationCauseCode::Misc), | |
| 60 | *id, | |
| 61 | expected_sig, | |
| 62 | ) | |
| 63 | .is_ok(); | |
| 64 | ||
| 65 | if correct_func_sig { | |
| 66 | (*id, MiriEntryFnType::MiriStart) | |
| 67 | } else { | |
| 68 | tcx.dcx().fatal( | |
| 69 | "`miri_start` must have the following signature:\n\ | |
| 70 | fn miri_start(argc: isize, argv: *const *const u8) -> isize", | |
| 71 | ); | |
| 72 | } | |
| 73 | } else { | |
| 74 | tcx.dcx().fatal( | |
| 75 | "Miri can only run programs that have a main function.\n\ | |
| 76 | Alternatively, you can export a `miri_start` function:\n\ | |
| 77 | \n\ | |
| 78 | #[cfg(miri)]\n\ | |
| 79 | #[unsafe(no_mangle)]\n\ | |
| 80 | fn miri_start(argc: isize, argv: *const *const u8) -> isize {\ | |
| 81 | \n // Call the actual start function that your project implements, based on your target's conventions.\n\ | |
| 82 | }" | |
| 83 | ); | |
| 84 | } | |
| 85 | } | |
| 86 | ||
| 34 | 87 | /// When the main thread would exit, we will yield to any other thread that is ready to execute. |
| 35 | 88 | /// But we must only do that a finite number of times, or a background thread running `loop {}` |
| 36 | 89 | /// will hang the program. |
src/tools/miri/src/lib.rs+4-2| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | feature(abort_unwind) |
| 10 | 10 | )] |
| 11 | 11 | #![feature(rustc_private)] |
| 12 | #![feature(dirfd)] | |
| 12 | 13 | #![feature(f16)] |
| 13 | 14 | #![feature(float_gamma)] |
| 14 | 15 | #![feature(float_erf)] |
| ... | ... | @@ -69,6 +70,7 @@ extern crate rustc_const_eval; |
| 69 | 70 | extern crate rustc_data_structures; |
| 70 | 71 | extern crate rustc_errors; |
| 71 | 72 | extern crate rustc_hir; |
| 73 | extern crate rustc_hir_analysis; | |
| 72 | 74 | extern crate rustc_index; |
| 73 | 75 | extern crate rustc_log; |
| 74 | 76 | extern crate rustc_middle; |
| ... | ... | @@ -146,7 +148,7 @@ pub use crate::concurrency::init_once::{EvalContextExt as _, InitOnceRef}; |
| 146 | 148 | pub use crate::concurrency::sync::{CondvarRef, EvalContextExt as _, MutexRef, RwLockRef}; |
| 147 | 149 | pub use crate::concurrency::thread::{ |
| 148 | 150 | BlockReason, DynUnblockCallback, EvalContextExt as _, StackEmptyCallback, ThreadId, |
| 149 | ThreadManager, UnblockKind, | |
| 151 | ThreadManager, TlsAllocAction, UnblockKind, | |
| 150 | 152 | }; |
| 151 | 153 | pub use crate::concurrency::{GenmcConfig, GenmcCtx, run_genmc_mode}; |
| 152 | 154 | pub use crate::data_structures::dedup_range_map::DedupRangeMap; |
| ... | ... | @@ -154,7 +156,7 @@ pub use crate::data_structures::mono_hash_map::MonoHashMap; |
| 154 | 156 | pub use crate::diagnostics::{ |
| 155 | 157 | EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo, report_result, |
| 156 | 158 | }; |
| 157 | pub use crate::eval::{MiriConfig, MiriEntryFnType, create_ecx, eval_entry}; | |
| 159 | pub use crate::eval::{MiriConfig, MiriEntryFnType, create_ecx, entry_fn, eval_entry}; | |
| 158 | 160 | pub use crate::helpers::{EvalContextExt as _, ToU64 as _, ToUsize as _}; |
| 159 | 161 | pub use crate::intrinsics::EvalContextExt as _; |
| 160 | 162 | pub use crate::machine::{ |
src/tools/miri/src/shims/aarch64.rs+29-7| ... | ... | @@ -196,10 +196,9 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 196 | 196 | _ => unreachable!(), |
| 197 | 197 | }; |
| 198 | 198 | |
| 199 | let [left, right] = | |
| 200 | this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; | |
| 201 | let left = this.read_scalar(left)?; | |
| 202 | let right = this.read_scalar(right)?; | |
| 199 | let [crc, data] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; | |
| 200 | let crc = this.read_scalar(crc)?; | |
| 201 | let data = this.read_scalar(data)?; | |
| 203 | 202 | |
| 204 | 203 | // The CRC accumulator is always u32. The data argument is u32 for |
| 205 | 204 | // b/h/w variants and u64 for the x variant, per the LLVM intrinsic |
| ... | ... | @@ -207,13 +206,36 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 207 | 206 | // https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/IntrinsicsAArch64.td |
| 208 | 207 | // If the higher bits are non-zero, `compute_crc32` will panic. We should probably |
| 209 | 208 | // raise a proper error instead, but outside stdarch nobody can trigger this anyway. |
| 210 | let crc = left.to_u32()?; | |
| 211 | let data = | |
| 212 | if bit_size == 64 { right.to_u64()? } else { u64::from(right.to_u32()?) }; | |
| 209 | let crc = crc.to_u32()?; | |
| 210 | let data = if bit_size == 64 { data.to_u64()? } else { u64::from(data.to_u32()?) }; | |
| 213 | 211 | |
| 214 | 212 | let result = compute_crc32(crc, data, bit_size, polynomial); |
| 215 | 213 | this.write_scalar(Scalar::from_u32(result), dest)?; |
| 216 | 214 | } |
| 215 | // Polynomial multiply long (64-bit x 64-bit -> 128-bit). | |
| 216 | // | |
| 217 | // This is the same as "carryless" multiplication, see | |
| 218 | // <https://en.wikipedia.org/wiki/Carry-less_product#Multiplication_of_polynomials>. | |
| 219 | // | |
| 220 | // Used to implement the vmull_p64 and vmull_high_p64 functions. | |
| 221 | // https://developer.arm.com/architectures/instruction-sets/intrinsics/vmull_p64 | |
| 222 | "neon.pmull64" => { | |
| 223 | // LLVM and GCC group pmull with the AES intrinsics. | |
| 224 | // Also see <https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612088.html>. | |
| 225 | this.expect_target_feature_for_intrinsic(link_name, "aes")?; | |
| 226 | ||
| 227 | let [left, right] = | |
| 228 | this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; | |
| 229 | let left = this.read_scalar(left)?.to_u64()?; | |
| 230 | let right = this.read_scalar(right)?.to_u64()?; | |
| 231 | ||
| 232 | let result = left.widening_carryless_mul(right); | |
| 233 | ||
| 234 | // dest is int8x16_t, transmute to u128 for the write. | |
| 235 | let dest = dest.transmute(this.machine.layouts.u128, this)?; | |
| 236 | this.write_scalar(Scalar::from_u128(result), &dest)?; | |
| 237 | } | |
| 238 | ||
| 217 | 239 | _ => return interp_ok(EmulateItemResult::NotSupported), |
| 218 | 240 | } |
| 219 | 241 | interp_ok(EmulateItemResult::NeedsReturn) |
src/tools/miri/src/shims/files.rs+40-1| ... | ... | @@ -1,9 +1,10 @@ |
| 1 | 1 | use std::any::Any; |
| 2 | 2 | use std::collections::BTreeMap; |
| 3 | use std::fs::File; | |
| 3 | use std::fs::{Dir, File}; | |
| 4 | 4 | use std::io::{ErrorKind, IsTerminal, Read, Seek, SeekFrom, Write}; |
| 5 | 5 | use std::marker::CoercePointee; |
| 6 | 6 | use std::ops::Deref; |
| 7 | use std::path::PathBuf; | |
| 7 | 8 | use std::rc::{Rc, Weak}; |
| 8 | 9 | use std::{fs, io}; |
| 9 | 10 | |
| ... | ... | @@ -362,6 +363,7 @@ impl FileDescription for io::Stderr { |
| 362 | 363 | #[derive(Debug)] |
| 363 | 364 | pub struct FileHandle { |
| 364 | 365 | pub(crate) file: File, |
| 366 | pub(crate) readable: bool, | |
| 365 | 367 | pub(crate) writable: bool, |
| 366 | 368 | } |
| 367 | 369 | |
| ... | ... | @@ -380,6 +382,10 @@ impl FileDescription for FileHandle { |
| 380 | 382 | ) -> InterpResult<'tcx> { |
| 381 | 383 | assert!(communicate_allowed, "isolation should have prevented even opening a file"); |
| 382 | 384 | |
| 385 | if !self.readable { | |
| 386 | return finish.call(ecx, Err(ErrorKind::PermissionDenied.into())); | |
| 387 | } | |
| 388 | ||
| 383 | 389 | let mut file = &self.file; |
| 384 | 390 | let result = ecx.read_from_host(|buf| file.read(buf), len, ptr)?; |
| 385 | 391 | finish.call(ecx, result) |
| ... | ... | @@ -468,6 +474,39 @@ impl FileDescription for FileHandle { |
| 468 | 474 | } |
| 469 | 475 | } |
| 470 | 476 | |
| 477 | #[derive(Debug)] | |
| 478 | pub struct DirHandle { | |
| 479 | #[cfg_attr(bootstrap, allow(unused))] | |
| 480 | pub(crate) dir: Dir, | |
| 481 | /// Fallback used under `cfg(bootstrap)`. | |
| 482 | #[cfg_attr(not(bootstrap), allow(unused))] | |
| 483 | pub(crate) path: PathBuf, | |
| 484 | } | |
| 485 | ||
| 486 | impl FileDescription for DirHandle { | |
| 487 | fn name(&self) -> &'static str { | |
| 488 | "directory" | |
| 489 | } | |
| 490 | ||
| 491 | fn metadata<'tcx>( | |
| 492 | &self, | |
| 493 | ) -> InterpResult<'tcx, Either<io::Result<std::fs::Metadata>, &'static str>> { | |
| 494 | #[cfg(not(bootstrap))] | |
| 495 | return interp_ok(Either::Left(self.dir.metadata())); | |
| 496 | #[cfg(bootstrap)] | |
| 497 | return interp_ok(Either::Left(std::fs::metadata(&self.path))); | |
| 498 | } | |
| 499 | ||
| 500 | fn destroy<'tcx>( | |
| 501 | self, | |
| 502 | _self_id: FdId, | |
| 503 | _communicate_allowed: bool, | |
| 504 | _ecx: &mut MiriInterpCx<'tcx>, | |
| 505 | ) -> InterpResult<'tcx, io::Result<()>> { | |
| 506 | interp_ok(Ok(())) | |
| 507 | } | |
| 508 | } | |
| 509 | ||
| 471 | 510 | /// Like /dev/null |
| 472 | 511 | #[derive(Debug)] |
| 473 | 512 | pub struct NullOutput; |
src/tools/miri/src/shims/foreign_items.rs+8| ... | ... | @@ -857,6 +857,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 857 | 857 | this, link_name, abi, args, dest, |
| 858 | 858 | ); |
| 859 | 859 | } |
| 860 | name if name.starts_with("llvm.loongarch.") | |
| 861 | && matches!(this.tcx.sess.target.arch, Arch::LoongArch32 | Arch::LoongArch64) | |
| 862 | && this.tcx.sess.target.endian == Endian::Little => | |
| 863 | { | |
| 864 | return shims::loongarch::EvalContextExt::emulate_loongarch_intrinsic( | |
| 865 | this, link_name, abi, args, dest, | |
| 866 | ); | |
| 867 | } | |
| 860 | 868 | |
| 861 | 869 | // Fallback to shims in submodules. |
| 862 | 870 | _ => { |
src/tools/miri/src/shims/loongarch.rs created+70| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | use rustc_abi::CanonAbi; | |
| 2 | use rustc_middle::ty::Ty; | |
| 3 | use rustc_span::Symbol; | |
| 4 | use rustc_target::callconv::FnAbi; | |
| 5 | ||
| 6 | use crate::shims::math::compute_crc32; | |
| 7 | use crate::*; | |
| 8 | ||
| 9 | impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} | |
| 10 | pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | |
| 11 | fn emulate_loongarch_intrinsic( | |
| 12 | &mut self, | |
| 13 | link_name: Symbol, | |
| 14 | abi: &FnAbi<'tcx, Ty<'tcx>>, | |
| 15 | args: &[OpTy<'tcx>], | |
| 16 | dest: &MPlaceTy<'tcx>, | |
| 17 | ) -> InterpResult<'tcx, EmulateItemResult> { | |
| 18 | let this = self.eval_context_mut(); | |
| 19 | // Prefix should have already been checked. | |
| 20 | let unprefixed_name = link_name.as_str().strip_prefix("llvm.loongarch.").unwrap(); | |
| 21 | match unprefixed_name { | |
| 22 | // Used to implement the crc.w.{b,h,w,d}.w and crcc.w.{b,h,w,d}.w functions. | |
| 23 | // https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#crc-check-instructions | |
| 24 | // These are only available on LA64, not on LA32, and are part of | |
| 25 | // the LA64 1.0 baseline and therefore always available and don't | |
| 26 | // require a target feature to be enabled. | |
| 27 | "crc.w.b.w" | "crc.w.h.w" | "crc.w.w.w" | "crc.w.d.w" | "crcc.w.b.w" | "crcc.w.h.w" | |
| 28 | | "crcc.w.w.w" | "crcc.w.d.w" | |
| 29 | if this.tcx.pointer_size().bits() == 64 => | |
| 30 | { | |
| 31 | // The polynomial constants below include the leading 1 bit | |
| 32 | // (e.g. 0x104C11DB7 instead of 0x04C11DB7) which the the | |
| 33 | // polynomial division algorithm requires. | |
| 34 | // Note that Loongson's documentation mentions the numbers | |
| 35 | // 0xEDB88320 for IEEE802.3 and 0x82F63B78 for Castagnoli, | |
| 36 | // which is because their docs put the least significant bit | |
| 37 | // first. | |
| 38 | let (bit_size, polynomial): (u32, u128) = match unprefixed_name { | |
| 39 | "crc.w.b.w" => (8, 0x104C11DB7), | |
| 40 | "crc.w.h.w" => (16, 0x104C11DB7), | |
| 41 | "crc.w.w.w" => (32, 0x104C11DB7), | |
| 42 | "crc.w.d.w" => (64, 0x104C11DB7), | |
| 43 | "crcc.w.b.w" => (8, 0x11EDC6F41), | |
| 44 | "crcc.w.h.w" => (16, 0x11EDC6F41), | |
| 45 | "crcc.w.w.w" => (32, 0x11EDC6F41), | |
| 46 | "crcc.w.d.w" => (64, 0x11EDC6F41), | |
| 47 | _ => unreachable!(), | |
| 48 | }; | |
| 49 | ||
| 50 | let [data, crc] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; | |
| 51 | let data = this.read_scalar(data)?; | |
| 52 | let crc = this.read_scalar(crc)?; | |
| 53 | ||
| 54 | // The CRC accumulator is always i32. The data argument is i32 for | |
| 55 | // b/h/w variants and i64 for the d variant, per the LLVM intrinsic | |
| 56 | // definitions. | |
| 57 | // https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/IntrinsicsLoongArch.td | |
| 58 | // If the higher bits are non-zero, `compute_crc32` will panic. We should probably | |
| 59 | // raise a proper error instead, but outside stdarch nobody can trigger this anyway. | |
| 60 | let crc = crc.to_u32()?; | |
| 61 | let data = if bit_size == 64 { data.to_u64()? } else { u64::from(data.to_u32()?) }; | |
| 62 | ||
| 63 | let result = compute_crc32(crc, data, bit_size, polynomial); | |
| 64 | this.write_scalar(Scalar::from_u32(result), dest)?; | |
| 65 | } | |
| 66 | _ => return interp_ok(EmulateItemResult::NotSupported), | |
| 67 | } | |
| 68 | interp_ok(EmulateItemResult::NeedsReturn) | |
| 69 | } | |
| 70 | } |
src/tools/miri/src/shims/mod.rs+1| ... | ... | @@ -4,6 +4,7 @@ mod aarch64; |
| 4 | 4 | mod alloc; |
| 5 | 5 | mod backtrace; |
| 6 | 6 | mod files; |
| 7 | mod loongarch; | |
| 7 | 8 | mod math; |
| 8 | 9 | #[cfg(all(feature = "native-lib", unix))] |
| 9 | 10 | pub mod native_lib; |
src/tools/miri/src/shims/unix/android/foreign_items.rs+1-13| ... | ... | @@ -3,11 +3,11 @@ use rustc_middle::ty::Ty; |
| 3 | 3 | use rustc_span::Symbol; |
| 4 | 4 | use rustc_target::callconv::FnAbi; |
| 5 | 5 | |
| 6 | use crate::shims::unix::android::thread::prctl; | |
| 7 | 6 | use crate::shims::unix::env::EvalContextExt as _; |
| 8 | 7 | use crate::shims::unix::linux_like::epoll::EvalContextExt as _; |
| 9 | 8 | use crate::shims::unix::linux_like::eventfd::EvalContextExt as _; |
| 10 | 9 | use crate::shims::unix::linux_like::syscall::syscall; |
| 10 | use crate::shims::unix::linux_like::thread::prctl; | |
| 11 | 11 | use crate::shims::unix::*; |
| 12 | 12 | use crate::*; |
| 13 | 13 | |
| ... | ... | @@ -27,18 +27,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 27 | 27 | let this = self.eval_context_mut(); |
| 28 | 28 | match link_name.as_str() { |
| 29 | 29 | // File related shims |
| 30 | "stat" => { | |
| 31 | // FIXME: This does not have a direct test (#3179). | |
| 32 | let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; | |
| 33 | let result = this.stat(path, buf)?; | |
| 34 | this.write_scalar(result, dest)?; | |
| 35 | } | |
| 36 | "lstat" => { | |
| 37 | // FIXME: This does not have a direct test (#3179). | |
| 38 | let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; | |
| 39 | let result = this.lstat(path, buf)?; | |
| 40 | this.write_scalar(result, dest)?; | |
| 41 | } | |
| 42 | 30 | "pread64" => { |
| 43 | 31 | // FIXME: This does not have a direct test (#3179). |
| 44 | 32 | let [fd, buf, count, offset] = this.check_shim_sig( |
src/tools/miri/src/shims/unix/android/mod.rs-1| ... | ... | @@ -1,2 +1 @@ |
| 1 | 1 | pub mod foreign_items; |
| 2 | pub mod thread; |
src/tools/miri/src/shims/unix/android/thread.rs deleted-55| ... | ... | @@ -1,55 +0,0 @@ |
| 1 | use rustc_abi::{CanonAbi, Size}; | |
| 2 | use rustc_middle::ty::Ty; | |
| 3 | use rustc_span::Symbol; | |
| 4 | use rustc_target::callconv::FnAbi; | |
| 5 | ||
| 6 | use crate::shims::sig::check_min_vararg_count; | |
| 7 | use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult}; | |
| 8 | use crate::*; | |
| 9 | ||
| 10 | const TASK_COMM_LEN: u64 = 16; | |
| 11 | ||
| 12 | pub fn prctl<'tcx>( | |
| 13 | ecx: &mut MiriInterpCx<'tcx>, | |
| 14 | link_name: Symbol, | |
| 15 | abi: &FnAbi<'tcx, Ty<'tcx>>, | |
| 16 | args: &[OpTy<'tcx>], | |
| 17 | dest: &MPlaceTy<'tcx>, | |
| 18 | ) -> InterpResult<'tcx> { | |
| 19 | let ([op], varargs) = ecx.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?; | |
| 20 | ||
| 21 | // FIXME: Use constants once https://github.com/rust-lang/libc/pull/3941 backported to the 0.2 branch. | |
| 22 | let pr_set_name = 15; | |
| 23 | let pr_get_name = 16; | |
| 24 | ||
| 25 | let res = match ecx.read_scalar(op)?.to_i32()? { | |
| 26 | op if op == pr_set_name => { | |
| 27 | let [name] = check_min_vararg_count("prctl(PR_SET_NAME, ...)", varargs)?; | |
| 28 | let name = ecx.read_scalar(name)?; | |
| 29 | let thread = ecx.pthread_self()?; | |
| 30 | // The Linux kernel silently truncates long names. | |
| 31 | // https://www.man7.org/linux/man-pages/man2/PR_SET_NAME.2const.html | |
| 32 | let res = | |
| 33 | ecx.pthread_setname_np(thread, name, TASK_COMM_LEN, /* truncate */ true)?; | |
| 34 | assert_eq!(res, ThreadNameResult::Ok); | |
| 35 | Scalar::from_u32(0) | |
| 36 | } | |
| 37 | op if op == pr_get_name => { | |
| 38 | let [name] = check_min_vararg_count("prctl(PR_GET_NAME, ...)", varargs)?; | |
| 39 | let name = ecx.read_scalar(name)?; | |
| 40 | let thread = ecx.pthread_self()?; | |
| 41 | let len = Scalar::from_target_usize(TASK_COMM_LEN, ecx); | |
| 42 | ecx.check_ptr_access( | |
| 43 | name.to_pointer(ecx)?, | |
| 44 | Size::from_bytes(TASK_COMM_LEN), | |
| 45 | CheckInAllocMsg::MemoryAccess, | |
| 46 | )?; | |
| 47 | let res = ecx.pthread_getname_np(thread, name, len, /* truncate*/ false)?; | |
| 48 | assert_eq!(res, ThreadNameResult::Ok); | |
| 49 | Scalar::from_u32(0) | |
| 50 | } | |
| 51 | op => throw_unsup_format!("Miri does not support `prctl` syscall with op={}", op), | |
| 52 | }; | |
| 53 | ecx.write_scalar(res, dest)?; | |
| 54 | interp_ok(()) | |
| 55 | } |
src/tools/miri/src/shims/unix/foreign_items.rs+14-1| ... | ... | @@ -342,7 +342,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 342 | 342 | } |
| 343 | 343 | "flock" => { |
| 344 | 344 | // Currently this function does not exist on all Unixes, e.g. on Solaris. |
| 345 | this.check_target_os(&[Os::Linux, Os::Android, Os::FreeBsd, Os::MacOs, Os::Illumos], link_name)?; | |
| 345 | this.check_target_os( | |
| 346 | &[Os::Linux, Os::Android, Os::FreeBsd, Os::MacOs, Os::Illumos], | |
| 347 | link_name, | |
| 348 | )?; | |
| 346 | 349 | |
| 347 | 350 | let [fd, op] = this.check_shim_sig( |
| 348 | 351 | shim_sig!(extern "C" fn(i32, i32) -> i32), |
| ... | ... | @@ -393,6 +396,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 393 | 396 | let result = this.symlink(target, linkpath)?; |
| 394 | 397 | this.write_scalar(result, dest)?; |
| 395 | 398 | } |
| 399 | "linkat" => { | |
| 400 | let [oldfd, oldpath, newfd, newpath, flags] = this.check_shim_sig( | |
| 401 | shim_sig!(extern "C" fn(i32, *const _, i32, *const _, i32) -> i32), | |
| 402 | link_name, | |
| 403 | abi, | |
| 404 | args, | |
| 405 | )?; | |
| 406 | let result = this.linkat(oldfd, oldpath, newfd, newpath, flags)?; | |
| 407 | this.write_scalar(result, dest)?; | |
| 408 | } | |
| 396 | 409 | "fstat" => { |
| 397 | 410 | let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; |
| 398 | 411 | let result = this.fstat(fd, buf)?; |
src/tools/miri/src/shims/unix/fs.rs+90-46| ... | ... | @@ -64,6 +64,10 @@ impl UnixFileDescription for FileHandle { |
| 64 | 64 | finish: DynMachineCallback<'tcx, Result<usize, IoError>>, |
| 65 | 65 | ) -> InterpResult<'tcx> { |
| 66 | 66 | assert!(communicate_allowed, "isolation should have prevented even opening a file"); |
| 67 | if !self.readable { | |
| 68 | return finish.call(ecx, Err(LibcError("EBADF"))); | |
| 69 | } | |
| 70 | ||
| 67 | 71 | let mut bytes = vec![0; len]; |
| 68 | 72 | // Emulates pread using seek + read + seek to restore cursor position. |
| 69 | 73 | // Correctness of this emulation relies on sequential nature of Miri execution. |
| ... | ... | @@ -101,6 +105,10 @@ impl UnixFileDescription for FileHandle { |
| 101 | 105 | finish: DynMachineCallback<'tcx, Result<usize, IoError>>, |
| 102 | 106 | ) -> InterpResult<'tcx> { |
| 103 | 107 | assert!(communicate_allowed, "isolation should have prevented even opening a file"); |
| 108 | if !self.writable { | |
| 109 | return finish.call(ecx, Err(LibcError("EBADF"))); | |
| 110 | } | |
| 111 | ||
| 104 | 112 | // Emulates pwrite using seek + write + seek to restore cursor position. |
| 105 | 113 | // Correctness of this emulation relies on sequential nature of Miri execution. |
| 106 | 114 | // The closure is used to emulate `try` block, since we "bubble" `io::Error` using `?`. |
| ... | ... | @@ -387,6 +395,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 387 | 395 | throw_unsup_format!("access mode flags on this target are unsupported"); |
| 388 | 396 | } |
| 389 | 397 | let mut writable = true; |
| 398 | let mut readable = true; | |
| 390 | 399 | |
| 391 | 400 | // Now we check the access mode |
| 392 | 401 | let access_mode = flag & 0b11; |
| ... | ... | @@ -396,6 +405,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 396 | 405 | writable = false; |
| 397 | 406 | options.read(true); |
| 398 | 407 | } else if access_mode == o_wronly { |
| 408 | readable = false; | |
| 399 | 409 | options.write(true); |
| 400 | 410 | } else if access_mode == o_rdwr { |
| 401 | 411 | options.read(true).write(true); |
| ... | ... | @@ -495,7 +505,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 495 | 505 | |
| 496 | 506 | let fd = options |
| 497 | 507 | .open(path) |
| 498 | .map(|file| this.machine.fds.insert_new(FileHandle { file, writable })); | |
| 508 | .map(|file| this.machine.fds.insert_new(FileHandle { file, writable, readable })); | |
| 499 | 509 | |
| 500 | 510 | interp_ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?)) |
| 501 | 511 | } |
| ... | ... | @@ -584,6 +594,59 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 584 | 594 | interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) |
| 585 | 595 | } |
| 586 | 596 | |
| 597 | fn linkat( | |
| 598 | &mut self, | |
| 599 | oldfd_op: &OpTy<'tcx>, | |
| 600 | oldpath_op: &OpTy<'tcx>, | |
| 601 | newfd_op: &OpTy<'tcx>, | |
| 602 | newpath_op: &OpTy<'tcx>, | |
| 603 | flags_op: &OpTy<'tcx>, | |
| 604 | ) -> InterpResult<'tcx, Scalar> { | |
| 605 | let this = self.eval_context_mut(); | |
| 606 | ||
| 607 | // Load all arguments | |
| 608 | let flags = this.read_scalar(flags_op)?.to_i32()?; | |
| 609 | let oldfd = this.read_scalar(oldfd_op)?.to_i32()?; | |
| 610 | let newfd = this.read_scalar(newfd_op)?.to_i32()?; | |
| 611 | let oldpath_ptr = this.read_pointer(oldpath_op)?; | |
| 612 | let newpath_ptr = this.read_pointer(newpath_op)?; | |
| 613 | ||
| 614 | // Relevant libc constants | |
| 615 | let at_fdcwd = this.eval_libc_i32("AT_FDCWD"); | |
| 616 | ||
| 617 | // Reject if isolation is enabled. | |
| 618 | if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { | |
| 619 | this.reject_in_isolation("`linkat`", reject_with)?; | |
| 620 | return this.set_errno_and_return_neg1_i32(ErrorKind::PermissionDenied); | |
| 621 | } | |
| 622 | ||
| 623 | // Read flags - only support 0. | |
| 624 | if flags != 0 { | |
| 625 | throw_unsup_format!("unsupported linkat flags {:#x}", flags); | |
| 626 | } | |
| 627 | ||
| 628 | // Resolve oldpath | |
| 629 | if oldfd != at_fdcwd { | |
| 630 | throw_unsup_format!("linkat with `olddirfd` not equal to `AT_FDCWD` is not supported"); | |
| 631 | } | |
| 632 | if oldpath_ptr == Pointer::null() { | |
| 633 | return this.set_errno_and_return_neg1_i32(LibcError("EFAULT")); | |
| 634 | } | |
| 635 | let oldpath = this.read_path_from_c_str(oldpath_ptr)?.into_owned(); | |
| 636 | ||
| 637 | // Resolve newpath | |
| 638 | if newfd != at_fdcwd { | |
| 639 | throw_unsup_format!("linkat with `newdirfd` not equal to `AT_FDCWD` is not supported"); | |
| 640 | } | |
| 641 | if newpath_ptr == Pointer::null() { | |
| 642 | return this.set_errno_and_return_neg1_i32(LibcError("EFAULT")); | |
| 643 | } | |
| 644 | let newpath = this.read_path_from_c_str(newpath_ptr)?.into_owned(); | |
| 645 | ||
| 646 | let result = fs::hard_link(&oldpath, &newpath).map(|()| 0); | |
| 647 | interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) | |
| 648 | } | |
| 649 | ||
| 587 | 650 | fn stat(&mut self, path_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { |
| 588 | 651 | let this = self.eval_context_mut(); |
| 589 | 652 | |
| ... | ... | @@ -892,12 +955,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 892 | 955 | // The docs don't talk about what happens for non-regular files... |
| 893 | 956 | throw_unsup_format!("`fchmod` is only supported on regular files") |
| 894 | 957 | }; |
| 895 | ||
| 896 | // Reject if isolation is enabled. | |
| 897 | if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { | |
| 898 | this.reject_in_isolation("`fchmod`", reject_with)?; | |
| 899 | return this.set_errno_and_return_neg1_i32(LibcError("EACCES")); | |
| 958 | if !file.writable && !file.readable { | |
| 959 | // Apparently, `fchmod` on a read-only file is fine. But let's not allow it on a | |
| 960 | // path-only file. | |
| 961 | return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); | |
| 900 | 962 | } |
| 963 | assert!(this.machine.communicate(), "isolation should have prevented even opening a file"); | |
| 901 | 964 | |
| 902 | 965 | let permissions = this.host_permissions_from_mode(mode.try_into().unwrap())?; |
| 903 | 966 | if let Err(err) = file.file.set_permissions(permissions) { |
| ... | ... | @@ -1253,33 +1316,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1253 | 1316 | fn ftruncate64(&mut self, fd_num: i32, length: i128) -> InterpResult<'tcx, Scalar> { |
| 1254 | 1317 | let this = self.eval_context_mut(); |
| 1255 | 1318 | |
| 1256 | // Reject if isolation is enabled. | |
| 1257 | if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { | |
| 1258 | this.reject_in_isolation("`ftruncate64`", reject_with)?; | |
| 1259 | // Set error code as "EBADF" (bad fd) | |
| 1260 | return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); | |
| 1261 | } | |
| 1262 | ||
| 1263 | 1319 | let Some(fd) = this.machine.fds.get(fd_num) else { |
| 1264 | 1320 | return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); |
| 1265 | 1321 | }; |
| 1266 | ||
| 1267 | 1322 | let Some(file) = fd.downcast::<FileHandle>() else { |
| 1268 | 1323 | // The docs say that EINVAL is returned when the FD "does not reference a regular file |
| 1269 | 1324 | // or a POSIX shared memory object" (and we don't support shmem objects). |
| 1270 | return interp_ok(this.eval_libc("EINVAL")); | |
| 1325 | return this.set_errno_and_return_neg1_i32(LibcError("EINVAL")); | |
| 1271 | 1326 | }; |
| 1327 | if !file.writable { | |
| 1328 | // man page says "EBADF or EINVAL", Linux seems to use EINVAL. | |
| 1329 | return this.set_errno_and_return_neg1_i32(LibcError("EINVAL")); | |
| 1330 | } | |
| 1331 | assert!(this.machine.communicate(), "isolation should have prevented even opening a file"); | |
| 1272 | 1332 | |
| 1273 | if file.writable { | |
| 1274 | if let Ok(length) = length.try_into() { | |
| 1275 | let result = file.file.set_len(length); | |
| 1276 | let result = this.try_unwrap_io_result(result.map(|_| 0i32))?; | |
| 1277 | interp_ok(Scalar::from_i32(result)) | |
| 1278 | } else { | |
| 1279 | this.set_errno_and_return_neg1_i32(LibcError("EINVAL")) | |
| 1280 | } | |
| 1333 | if let Ok(length) = length.try_into() { | |
| 1334 | let result = file.file.set_len(length); | |
| 1335 | let result = this.try_unwrap_io_result(result.map(|_| 0i32))?; | |
| 1336 | interp_ok(Scalar::from_i32(result)) | |
| 1281 | 1337 | } else { |
| 1282 | // The file is not writable | |
| 1283 | 1338 | this.set_errno_and_return_neg1_i32(LibcError("EINVAL")) |
| 1284 | 1339 | } |
| 1285 | 1340 | } |
| ... | ... | @@ -1352,13 +1407,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1352 | 1407 | |
| 1353 | 1408 | let fd = this.read_scalar(fd_op)?.to_i32()?; |
| 1354 | 1409 | |
| 1355 | // Reject if isolation is enabled. | |
| 1356 | if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { | |
| 1357 | this.reject_in_isolation("`fsync`", reject_with)?; | |
| 1358 | // Set error code as "EBADF" (bad fd) | |
| 1359 | return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); | |
| 1360 | } | |
| 1361 | ||
| 1362 | 1410 | self.ffullsync_fd(fd) |
| 1363 | 1411 | } |
| 1364 | 1412 | |
| ... | ... | @@ -1371,6 +1419,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1371 | 1419 | let file = fd.downcast::<FileHandle>().ok_or_else(|| { |
| 1372 | 1420 | err_unsup_format!("`fsync` is only supported on file-backed file descriptors") |
| 1373 | 1421 | })?; |
| 1422 | assert!(this.machine.communicate(), "isolation should have prevented even opening a file"); | |
| 1423 | ||
| 1374 | 1424 | let io_result = maybe_sync_file(&file.file, file.writable, File::sync_all); |
| 1375 | 1425 | interp_ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) |
| 1376 | 1426 | } |
| ... | ... | @@ -1380,13 +1430,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1380 | 1430 | |
| 1381 | 1431 | let fd = this.read_scalar(fd_op)?.to_i32()?; |
| 1382 | 1432 | |
| 1383 | // Reject if isolation is enabled. | |
| 1384 | if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { | |
| 1385 | this.reject_in_isolation("`fdatasync`", reject_with)?; | |
| 1386 | // Set error code as "EBADF" (bad fd) | |
| 1387 | return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); | |
| 1388 | } | |
| 1389 | ||
| 1390 | 1433 | let Some(fd) = this.machine.fds.get(fd) else { |
| 1391 | 1434 | return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); |
| 1392 | 1435 | }; |
| ... | ... | @@ -1394,6 +1437,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1394 | 1437 | let file = fd.downcast::<FileHandle>().ok_or_else(|| { |
| 1395 | 1438 | err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors") |
| 1396 | 1439 | })?; |
| 1440 | assert!(this.machine.communicate(), "isolation should have prevented even opening a file"); | |
| 1441 | ||
| 1397 | 1442 | let io_result = maybe_sync_file(&file.file, file.writable, File::sync_data); |
| 1398 | 1443 | interp_ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) |
| 1399 | 1444 | } |
| ... | ... | @@ -1422,13 +1467,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1422 | 1467 | return this.set_errno_and_return_neg1_i32(LibcError("EINVAL")); |
| 1423 | 1468 | } |
| 1424 | 1469 | |
| 1425 | // Reject if isolation is enabled. | |
| 1426 | if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { | |
| 1427 | this.reject_in_isolation("`sync_file_range`", reject_with)?; | |
| 1428 | // Set error code as "EBADF" (bad fd) | |
| 1429 | return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); | |
| 1430 | } | |
| 1431 | ||
| 1432 | 1470 | let Some(fd) = this.machine.fds.get(fd) else { |
| 1433 | 1471 | return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); |
| 1434 | 1472 | }; |
| ... | ... | @@ -1436,6 +1474,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1436 | 1474 | let file = fd.downcast::<FileHandle>().ok_or_else(|| { |
| 1437 | 1475 | err_unsup_format!("`sync_data_range` is only supported on file-backed file descriptors") |
| 1438 | 1476 | })?; |
| 1477 | assert!(this.machine.communicate(), "isolation should have prevented even opening a file"); | |
| 1478 | ||
| 1439 | 1479 | let io_result = maybe_sync_file(&file.file, file.writable, File::sync_data); |
| 1440 | 1480 | interp_ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) |
| 1441 | 1481 | } |
| ... | ... | @@ -1661,7 +1701,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 1661 | 1701 | let file = fopts.open(bytes_to_os_str(template_bytes)?); |
| 1662 | 1702 | match file { |
| 1663 | 1703 | Ok(f) => { |
| 1664 | let fd = this.machine.fds.insert_new(FileHandle { file: f, writable: true }); | |
| 1704 | let fd = this.machine.fds.insert_new(FileHandle { | |
| 1705 | file: f, | |
| 1706 | writable: true, | |
| 1707 | readable: true, | |
| 1708 | }); | |
| 1665 | 1709 | return interp_ok(Scalar::from_i32(fd)); |
| 1666 | 1710 | } |
| 1667 | 1711 | Err(e) => |
src/tools/miri/src/shims/unix/linux/foreign_items.rs+2| ... | ... | @@ -8,6 +8,7 @@ use self::shims::unix::linux_like::eventfd::EvalContextExt as _; |
| 8 | 8 | use self::shims::unix::linux_like::syscall::syscall; |
| 9 | 9 | use crate::machine::{SIGRTMAX, SIGRTMIN}; |
| 10 | 10 | use crate::shims::unix::foreign_items::EvalContextExt as _; |
| 11 | use crate::shims::unix::linux_like::thread::prctl; | |
| 11 | 12 | use crate::shims::unix::*; |
| 12 | 13 | use crate::*; |
| 13 | 14 | |
| ... | ... | @@ -197,6 +198,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 197 | 198 | let result = this.unix_gettid(link_name.as_str())?; |
| 198 | 199 | this.write_scalar(result, dest)?; |
| 199 | 200 | } |
| 201 | "prctl" => prctl(this, link_name, abi, args, dest)?, | |
| 200 | 202 | |
| 201 | 203 | // Dynamically invoked syscalls |
| 202 | 204 | "syscall" => { |
src/tools/miri/src/shims/unix/linux_like/epoll.rs+58-38| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | use std::cell::RefCell; |
| 2 | use std::collections::{BTreeMap, BTreeSet, VecDeque}; | |
| 2 | use std::collections::{BTreeMap, VecDeque}; | |
| 3 | 3 | use std::io; |
| 4 | use std::ops::Bound; | |
| 5 | 4 | use std::time::Duration; |
| 6 | 5 | |
| 7 | 6 | use rustc_abi::FieldIdx; |
| ... | ... | @@ -23,7 +22,9 @@ pub struct Epoll { |
| 23 | 22 | interest_list: RefCell<BTreeMap<EpollEventKey, EpollEventInterest>>, |
| 24 | 23 | /// The subset of interests that is currently considered "ready". Stored separately so we |
| 25 | 24 | /// can access it more efficiently. |
| 26 | ready_set: RefCell<BTreeSet<EpollEventKey>>, | |
| 25 | /// This is implemented as a queue so that for level-triggered epoll, all events eventually | |
| 26 | /// get returned from `epoll_wait`. The queue does not contain any duplicates. | |
| 27 | ready_events: RefCell<VecDeque<EpollEventKey>>, | |
| 27 | 28 | /// The queue of threads blocked on this epoll instance. |
| 28 | 29 | queue: RefCell<VecDeque<ThreadId>>, |
| 29 | 30 | } |
| ... | ... | @@ -46,6 +47,9 @@ pub struct EpollEventInterest { |
| 46 | 47 | relevant_events: u32, |
| 47 | 48 | /// The currently active events for this file descriptor. |
| 48 | 49 | active_events: u32, |
| 50 | /// Boolean whether this is an edge-triggered interest. | |
| 51 | /// When [`false`] it's a level-triggered interest instead. | |
| 52 | is_edge_triggered: bool, | |
| 49 | 53 | /// The vector clock for wakeups. |
| 50 | 54 | clock: VClock, |
| 51 | 55 | /// User-defined data associated with this interest. |
| ... | ... | @@ -203,12 +207,8 @@ impl EpollInterestTable { |
| 203 | 207 | .extract_if(range_for_id(id), |_, _| true) |
| 204 | 208 | // Consume the iterator. |
| 205 | 209 | .for_each(drop); |
| 206 | epoll | |
| 207 | .ready_set | |
| 208 | .borrow_mut() | |
| 209 | .extract_if(range_for_id(id), |_| true) | |
| 210 | // Consume the iterator. | |
| 211 | .for_each(drop); | |
| 210 | // Remove the ready events for this file description. | |
| 211 | epoll.ready_events.borrow_mut().retain(|(fd_id, _)| fd_id != &id); | |
| 212 | 212 | } |
| 213 | 213 | } |
| 214 | 214 | } |
| ... | ... | @@ -303,6 +303,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 303 | 303 | this.read_scalar(&this.project_field(&event, FieldIdx::ZERO)?)?.to_u32()?; |
| 304 | 304 | let data = this.read_scalar(&this.project_field(&event, FieldIdx::ONE)?)?.to_u64()?; |
| 305 | 305 | |
| 306 | let is_edge_triggered = if events & epollet == epollet { | |
| 307 | events &= !epollet; | |
| 308 | true | |
| 309 | } else { | |
| 310 | false | |
| 311 | }; | |
| 312 | ||
| 306 | 313 | // Unset the flag we support to discover if any unsupported flags are used. |
| 307 | 314 | let mut flags = events; |
| 308 | 315 | // epoll_wait(2) will always wait for epollhup and epollerr; it is not |
| ... | ... | @@ -311,12 +318,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 311 | 318 | events |= epollhup; |
| 312 | 319 | events |= epollerr; |
| 313 | 320 | |
| 314 | if events & epollet != epollet { | |
| 315 | // We only support edge-triggered notification for now. | |
| 316 | throw_unsup_format!("epoll_ctl: epollet flag must be included."); | |
| 317 | } else { | |
| 318 | flags &= !epollet; | |
| 319 | } | |
| 320 | 321 | if flags & epollin == epollin { |
| 321 | 322 | flags &= !epollin; |
| 322 | 323 | } |
| ... | ... | @@ -350,6 +351,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 350 | 351 | } |
| 351 | 352 | let new_interest = EpollEventInterest { |
| 352 | 353 | relevant_events: events, |
| 354 | is_edge_triggered, | |
| 353 | 355 | data, |
| 354 | 356 | active_events: 0, |
| 355 | 357 | clock: VClock::default(), |
| ... | ... | @@ -364,6 +366,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 364 | 366 | return this.set_errno_and_return_neg1_i32(LibcError("ENOENT")); |
| 365 | 367 | }; |
| 366 | 368 | interest.relevant_events = events; |
| 369 | interest.is_edge_triggered = is_edge_triggered; | |
| 367 | 370 | interest.data = data; |
| 368 | 371 | } |
| 369 | 372 | |
| ... | ... | @@ -391,7 +394,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 391 | 394 | // We did not have interest in this. |
| 392 | 395 | return this.set_errno_and_return_neg1_i32(LibcError("ENOENT")); |
| 393 | 396 | }; |
| 394 | epfd.ready_set.borrow_mut().remove(&epoll_key); | |
| 397 | // Remove the ready event for this key, should one exist. | |
| 398 | let mut ready_events = epfd.ready_events.borrow_mut(); | |
| 399 | if let Some(idx) = ready_events.iter().position(|k| k == &epoll_key) { | |
| 400 | ready_events.remove(idx); | |
| 401 | } | |
| 395 | 402 | // If this was the last interest in this FD, remove us from the global list |
| 396 | 403 | // of who is interested in this FD. |
| 397 | 404 | if interest_list.range(range_for_id(id)).next().is_none() { |
| ... | ... | @@ -469,7 +476,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 469 | 476 | return this.set_errno_and_return_neg1(LibcError("EBADF"), dest); |
| 470 | 477 | }; |
| 471 | 478 | |
| 472 | if timeout == 0 || !epfd.ready_set.borrow().is_empty() { | |
| 479 | if timeout == 0 || !epfd.ready_events.borrow().is_empty() { | |
| 473 | 480 | // If the timeout is 0 or there is a ready event, we can return immediately. |
| 474 | 481 | return_ready_list(&epfd, dest, &event, this)?; |
| 475 | 482 | } else { |
| ... | ... | @@ -590,18 +597,29 @@ fn update_readiness<'tcx>( |
| 590 | 597 | &mut dyn FnMut(EpollEventKey, &mut EpollEventInterest) -> InterpResult<'tcx>, |
| 591 | 598 | ) -> InterpResult<'tcx>, |
| 592 | 599 | ) -> InterpResult<'tcx> { |
| 593 | let mut ready_set = epoll.ready_set.borrow_mut(); | |
| 600 | let mut ready_events = epoll.ready_events.borrow_mut(); | |
| 594 | 601 | for_each_interest(&mut |key, interest| { |
| 595 | 602 | // Update the ready events tracked in this interest. |
| 596 | 603 | let new_readiness = interest.relevant_events & active_events; |
| 597 | 604 | let prev_readiness = std::mem::replace(&mut interest.active_events, new_readiness); |
| 598 | 605 | if new_readiness == 0 { |
| 599 | 606 | // Un-trigger this, there's nothing left to report here. |
| 600 | ready_set.remove(&key); | |
| 607 | if let Some(idx) = ready_events.iter().position(|k| k == &key) { | |
| 608 | ready_events.remove(idx); | |
| 609 | } | |
| 601 | 610 | } else if force_edge || new_readiness != prev_readiness & new_readiness { |
| 602 | // Either we force an "edge" to be detected, or there's a bit set in `new` | |
| 603 | // that was not set in `prev`. In both cases, this is ready now. | |
| 604 | ready_set.insert(key); | |
| 611 | // Either we force an "edge" to be detected or there's a bit set in `new_readiness` | |
| 612 | // that was not set in `prev_readiness`. In both cases, this is ready now. | |
| 613 | ||
| 614 | // We need to ensure that this event is not already part of the | |
| 615 | // `ready_events` queue before enqueueing: | |
| 616 | // <https://github.com/torvalds/linux/blob/HEAD/fs/eventpoll.c#L1292-L1296> | |
| 617 | if !ready_events.contains(&key) { | |
| 618 | ready_events.push_back(key); | |
| 619 | } | |
| 620 | ||
| 621 | // No matter whether this is newly ready or just re-triggered, | |
| 622 | // the `epoll_wait` fetching this event should sync with the current thread. | |
| 605 | 623 | ecx.release_clock(|clock| { |
| 606 | 624 | interest.clock.join(clock); |
| 607 | 625 | })?; |
| ... | ... | @@ -609,12 +627,12 @@ fn update_readiness<'tcx>( |
| 609 | 627 | interp_ok(()) |
| 610 | 628 | })?; |
| 611 | 629 | // While there are events ready to be delivered, wake up a thread to receive them. |
| 612 | while !ready_set.is_empty() | |
| 630 | while !ready_events.is_empty() | |
| 613 | 631 | && let Some(thread_id) = epoll.queue.borrow_mut().pop_front() |
| 614 | 632 | { |
| 615 | drop(ready_set); // release the "lock" so the unblocked thread can have it | |
| 633 | drop(ready_events); // release the "lock" so the unblocked thread can have it | |
| 616 | 634 | ecx.unblock_thread(thread_id, BlockReason::Epoll { epfd: epoll.clone() })?; |
| 617 | ready_set = epoll.ready_set.borrow_mut(); | |
| 635 | ready_events = epoll.ready_events.borrow_mut(); | |
| 618 | 636 | } |
| 619 | 637 | |
| 620 | 638 | interp_ok(()) |
| ... | ... | @@ -629,7 +647,7 @@ fn return_ready_list<'tcx>( |
| 629 | 647 | ecx: &mut MiriInterpCx<'tcx>, |
| 630 | 648 | ) -> InterpResult<'tcx, i32> { |
| 631 | 649 | let mut interest_list = epfd.interest_list.borrow_mut(); |
| 632 | let mut ready_set = epfd.ready_set.borrow_mut(); | |
| 650 | let mut ready_events = epfd.ready_events.borrow_mut(); | |
| 633 | 651 | let mut num_of_events: i32 = 0; |
| 634 | 652 | let mut array_iter = ecx.project_array_fields(events)?; |
| 635 | 653 | |
| ... | ... | @@ -644,27 +662,29 @@ fn return_ready_list<'tcx>( |
| 644 | 662 | } |
| 645 | 663 | } |
| 646 | 664 | |
| 647 | // While there is a slot to store another event, and an event to store, deliver that event. | |
| 648 | // We can't use an iterator over `ready_set` as we want to remove elements as we go, | |
| 649 | // so we track the most recently delivered event to find the next one. We track it as a lower | |
| 650 | // bound that we can pass to `BTreeSet::range`. | |
| 651 | let mut event_lower_bound = Bound::Unbounded; | |
| 652 | while let Some(slot) = array_iter.next(ecx)? | |
| 653 | && let Some(&key) = ready_set.range((event_lower_bound, Bound::Unbounded)).next() | |
| 665 | // We will fill at most the first `ready_events_len` slots of the array. | |
| 666 | // Bounding the iterator this way ensures that we can re-add events | |
| 667 | // to the end of the queue during the loop without having them show up in the array. | |
| 668 | let ready_events_len = u64::try_from(ready_events.len()).unwrap(); | |
| 669 | while let Some((idx, slot)) = array_iter.next(ecx)? | |
| 670 | && idx < ready_events_len | |
| 671 | && let Some(key) = ready_events.pop_front() | |
| 654 | 672 | { |
| 655 | 673 | let interest = interest_list.get_mut(&key).expect("non-existent event in ready set"); |
| 656 | 674 | // Deliver event to caller. |
| 657 | 675 | ecx.write_int_fields_named( |
| 658 | 676 | &[("events", interest.active_events.into()), ("u64", interest.data.into())], |
| 659 | &slot.1, | |
| 677 | &slot, | |
| 660 | 678 | )?; |
| 661 | 679 | num_of_events = num_of_events.strict_add(1); |
| 662 | 680 | // Synchronize receiving thread with the event of interest. |
| 663 | 681 | ecx.acquire_clock(&interest.clock)?; |
| 664 | // This was an edge-triggered event, so remove it from the ready set. | |
| 665 | ready_set.remove(&key); | |
| 666 | // Go find the next event. | |
| 667 | event_lower_bound = Bound::Excluded(key); | |
| 682 | if !interest.is_edge_triggered { | |
| 683 | // This is a level-triggered interest, so we need to re-add the event | |
| 684 | // at the end of the ready queue: | |
| 685 | // <https://github.com/torvalds/linux/blob/HEAD/fs/eventpoll.c#L1835-L1847> | |
| 686 | ready_events.push_back(key); | |
| 687 | } | |
| 668 | 688 | } |
| 669 | 689 | ecx.write_int(num_of_events, dest)?; |
| 670 | 690 | interp_ok(num_of_events) |
src/tools/miri/src/shims/unix/linux_like/mod.rs+1| ... | ... | @@ -2,3 +2,4 @@ pub mod epoll; |
| 2 | 2 | pub mod eventfd; |
| 3 | 3 | pub mod sync; |
| 4 | 4 | pub mod syscall; |
| 5 | pub mod thread; |
src/tools/miri/src/shims/unix/linux_like/thread.rs created+54| ... | ... | @@ -0,0 +1,54 @@ |
| 1 | use rustc_abi::{CanonAbi, Size}; | |
| 2 | use rustc_middle::ty::Ty; | |
| 3 | use rustc_span::Symbol; | |
| 4 | use rustc_target::callconv::FnAbi; | |
| 5 | ||
| 6 | use crate::shims::sig::check_min_vararg_count; | |
| 7 | use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult}; | |
| 8 | use crate::*; | |
| 9 | ||
| 10 | const TASK_COMM_LEN: u64 = 16; | |
| 11 | ||
| 12 | pub fn prctl<'tcx>( | |
| 13 | ecx: &mut MiriInterpCx<'tcx>, | |
| 14 | link_name: Symbol, | |
| 15 | abi: &FnAbi<'tcx, Ty<'tcx>>, | |
| 16 | args: &[OpTy<'tcx>], | |
| 17 | dest: &MPlaceTy<'tcx>, | |
| 18 | ) -> InterpResult<'tcx> { | |
| 19 | let ([op], varargs) = ecx.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?; | |
| 20 | ||
| 21 | let pr_set_name = ecx.eval_libc_i32("PR_SET_NAME"); | |
| 22 | let pr_get_name = ecx.eval_libc_i32("PR_GET_NAME"); | |
| 23 | ||
| 24 | let res = match ecx.read_scalar(op)?.to_i32()? { | |
| 25 | op if op == pr_set_name => { | |
| 26 | let [name] = check_min_vararg_count("prctl(PR_SET_NAME, ...)", varargs)?; | |
| 27 | let name = ecx.read_scalar(name)?; | |
| 28 | let thread = ecx.pthread_self()?; | |
| 29 | // The Linux kernel silently truncates long names. | |
| 30 | // https://www.man7.org/linux/man-pages/man2/PR_SET_NAME.2const.html | |
| 31 | let res = | |
| 32 | ecx.pthread_setname_np(thread, name, TASK_COMM_LEN, /* truncate */ true)?; | |
| 33 | assert_eq!(res, ThreadNameResult::Ok); | |
| 34 | Scalar::from_u32(0) | |
| 35 | } | |
| 36 | op if op == pr_get_name => { | |
| 37 | let [name] = check_min_vararg_count("prctl(PR_GET_NAME, ...)", varargs)?; | |
| 38 | let name = ecx.read_scalar(name)?; | |
| 39 | let thread = ecx.pthread_self()?; | |
| 40 | let len = Scalar::from_target_usize(TASK_COMM_LEN, ecx); | |
| 41 | ecx.check_ptr_access( | |
| 42 | name.to_pointer(ecx)?, | |
| 43 | Size::from_bytes(TASK_COMM_LEN), | |
| 44 | CheckInAllocMsg::MemoryAccess, | |
| 45 | )?; | |
| 46 | let res = ecx.pthread_getname_np(thread, name, len, /* truncate*/ false)?; | |
| 47 | assert_eq!(res, ThreadNameResult::Ok); | |
| 48 | Scalar::from_u32(0) | |
| 49 | } | |
| 50 | op => throw_unsup_format!("Miri does not support `prctl` syscall with op={}", op), | |
| 51 | }; | |
| 52 | ecx.write_scalar(res, dest)?; | |
| 53 | interp_ok(()) | |
| 54 | } |
src/tools/miri/src/shims/windows/fs.rs+38-72| ... | ... | @@ -1,72 +1,16 @@ |
| 1 | use std::fs::{Metadata, OpenOptions}; | |
| 1 | use std::fs::{self, Dir}; | |
| 2 | 2 | use std::io; |
| 3 | 3 | use std::io::SeekFrom; |
| 4 | use std::path::PathBuf; | |
| 5 | 4 | use std::time::SystemTime; |
| 6 | 5 | |
| 7 | 6 | use bitflags::bitflags; |
| 8 | 7 | use rustc_abi::Size; |
| 9 | 8 | use rustc_target::spec::Os; |
| 10 | 9 | |
| 11 | use crate::shims::files::{FdId, FileDescription, FileHandle}; | |
| 10 | use crate::shims::files::{DirHandle, FileHandle}; | |
| 12 | 11 | use crate::shims::windows::handle::{EvalContextExt as _, Handle}; |
| 13 | 12 | use crate::*; |
| 14 | 13 | |
| 15 | #[derive(Debug)] | |
| 16 | pub struct DirHandle { | |
| 17 | pub(crate) path: PathBuf, | |
| 18 | } | |
| 19 | ||
| 20 | impl FileDescription for DirHandle { | |
| 21 | fn name(&self) -> &'static str { | |
| 22 | "directory" | |
| 23 | } | |
| 24 | ||
| 25 | fn metadata<'tcx>( | |
| 26 | &self, | |
| 27 | ) -> InterpResult<'tcx, Either<io::Result<std::fs::Metadata>, &'static str>> { | |
| 28 | interp_ok(Either::Left(self.path.metadata())) | |
| 29 | } | |
| 30 | ||
| 31 | fn destroy<'tcx>( | |
| 32 | self, | |
| 33 | _self_id: FdId, | |
| 34 | _communicate_allowed: bool, | |
| 35 | _ecx: &mut MiriInterpCx<'tcx>, | |
| 36 | ) -> InterpResult<'tcx, io::Result<()>> { | |
| 37 | interp_ok(Ok(())) | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | /// Windows supports handles without any read/write/delete permissions - these handles can get | |
| 42 | /// metadata, but little else. We represent that by storing the metadata from the time the handle | |
| 43 | /// was opened. | |
| 44 | #[derive(Debug)] | |
| 45 | pub struct MetadataHandle { | |
| 46 | pub(crate) meta: Metadata, | |
| 47 | } | |
| 48 | ||
| 49 | impl FileDescription for MetadataHandle { | |
| 50 | fn name(&self) -> &'static str { | |
| 51 | "metadata-only" | |
| 52 | } | |
| 53 | ||
| 54 | fn metadata<'tcx>( | |
| 55 | &self, | |
| 56 | ) -> InterpResult<'tcx, Either<io::Result<std::fs::Metadata>, &'static str>> { | |
| 57 | interp_ok(Either::Left(Ok(self.meta.clone()))) | |
| 58 | } | |
| 59 | ||
| 60 | fn destroy<'tcx>( | |
| 61 | self, | |
| 62 | _self_id: FdId, | |
| 63 | _communicate_allowed: bool, | |
| 64 | _ecx: &mut MiriInterpCx<'tcx>, | |
| 65 | ) -> InterpResult<'tcx, io::Result<()>> { | |
| 66 | interp_ok(Ok(())) | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | 14 | #[derive(Copy, Clone, Debug, PartialEq)] |
| 71 | 15 | enum CreationDisposition { |
| 72 | 16 | CreateAlways, |
| ... | ... | @@ -213,8 +157,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 213 | 157 | throw_unsup_format!("CreateFileW: Template files are not supported"); |
| 214 | 158 | } |
| 215 | 159 | |
| 216 | // We need to know if the file is a directory to correctly open directory handles. | |
| 217 | // This is racy, but currently the stdlib doesn't appear to offer a better solution. | |
| 160 | // We need to know if the file is a directory to correctly open directory handles. This is | |
| 161 | // racy, but currently the stdlib doesn't appear to offer a better solution. We do later | |
| 162 | // verify that our guess was correct so worst-case, Miri ICEs here. | |
| 163 | // FIXME: retry in a loop if we get an error indicating we got the wrong file type? | |
| 218 | 164 | let is_dir = file_name.is_dir(); |
| 219 | 165 | |
| 220 | 166 | // BACKUP_SEMANTICS is how Windows calls the act of opening a directory handle. |
| ... | ... | @@ -226,7 +172,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 226 | 172 | let desired_read = desired_access & generic_read != 0; |
| 227 | 173 | let desired_write = desired_access & generic_write != 0; |
| 228 | 174 | |
| 229 | let mut options = OpenOptions::new(); | |
| 175 | let mut options = fs::OpenOptions::new(); | |
| 230 | 176 | if desired_read { |
| 231 | 177 | desired_access &= !generic_read; |
| 232 | 178 | options.read(true); |
| ... | ... | @@ -261,17 +207,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 261 | 207 | |
| 262 | 208 | let handle = if is_dir { |
| 263 | 209 | // Open this as a directory. |
| 264 | let fd_num = this.machine.fds.insert_new(DirHandle { path: file_name }); | |
| 265 | Ok(Handle::File(fd_num)) | |
| 266 | } else if creation_disposition == OpenExisting && !(desired_read || desired_write) { | |
| 267 | // Windows supports handles with no permissions. These allow things such as reading | |
| 268 | // metadata, but not file content. | |
| 269 | file_name.metadata().map(|meta| { | |
| 270 | let fd_num = this.machine.fds.insert_new(MetadataHandle { meta }); | |
| 210 | // FIXME: shouldn't we check `creation_disposition` here? | |
| 211 | Dir::open(&file_name).map(|dir| { | |
| 212 | #[cfg(not(bootstrap))] | |
| 213 | assert!( | |
| 214 | dir.metadata().unwrap().is_dir(), | |
| 215 | "we tried to open a directory and got a file" | |
| 216 | ); | |
| 217 | let fd_num = this.machine.fds.insert_new(DirHandle { dir, path: file_name }); | |
| 271 | 218 | Handle::File(fd_num) |
| 272 | 219 | }) |
| 273 | 220 | } else { |
| 274 | // Open this as a standard file. | |
| 221 | // Open this as a standard file. We already set the `read`/`write` flags above, | |
| 222 | // but we still need to represent the `creation_disposition`. | |
| 275 | 223 | match creation_disposition { |
| 276 | 224 | CreateAlways | OpenAlways => { |
| 277 | 225 | options.create(true); |
| ... | ... | @@ -288,15 +236,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 288 | 236 | options.append(true); |
| 289 | 237 | } |
| 290 | 238 | } |
| 291 | OpenExisting => {} // Default options | |
| 239 | OpenExisting => { | |
| 240 | if !desired_read && !desired_write { | |
| 241 | // Windows supports handles with no permissions. These allow things such as | |
| 242 | // reading metadata, but not file content. This is used by `Path::metadata`. | |
| 243 | // `std` does not support this. To ensure we behave correctly as often as | |
| 244 | // possible, we open the file for reading and live with the fact that this | |
| 245 | // might incorrectly return `PermissionDenied`. | |
| 246 | // FIXME: We could probably use `OpenOptionsExt`? On a Unix host, | |
| 247 | // `O_PATH` apparently can open files for metadata use only. | |
| 248 | options.read(true); | |
| 249 | } | |
| 250 | } | |
| 292 | 251 | TruncateExisting => { |
| 293 | 252 | options.truncate(true); |
| 294 | 253 | } |
| 295 | 254 | } |
| 296 | 255 | |
| 297 | 256 | options.open(file_name).map(|file| { |
| 298 | let fd_num = | |
| 299 | this.machine.fds.insert_new(FileHandle { file, writable: desired_write }); | |
| 257 | assert!( | |
| 258 | !file.metadata().unwrap().is_dir(), | |
| 259 | "we tried to open a file and got a directory" | |
| 260 | ); | |
| 261 | let fd_num = this.machine.fds.insert_new(FileHandle { | |
| 262 | file, | |
| 263 | writable: desired_write, | |
| 264 | readable: desired_read, | |
| 265 | }); | |
| 300 | 266 | Handle::File(fd_num) |
| 301 | 267 | }) |
| 302 | 268 | }; |
src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs+11-43| ... | ... | @@ -6,33 +6,13 @@ |
| 6 | 6 | // ensure deterministic schedule |
| 7 | 7 | //@compile-flags: -Zmiri-deterministic-concurrency |
| 8 | 8 | |
| 9 | use std::convert::TryInto; | |
| 10 | 9 | use std::thread; |
| 11 | 10 | use std::thread::spawn; |
| 12 | 11 | |
| 13 | 12 | #[path = "../../utils/libc.rs"] |
| 14 | 13 | mod libc_utils; |
| 15 | ||
| 16 | #[track_caller] | |
| 17 | fn check_epoll_wait<const N: usize>(epfd: i32, expected_notifications: &[(u32, u64)]) { | |
| 18 | let epoll_event = libc::epoll_event { events: 0, u64: 0 }; | |
| 19 | let mut array: [libc::epoll_event; N] = [epoll_event; N]; | |
| 20 | let maxsize = N; | |
| 21 | let array_ptr = array.as_mut_ptr(); | |
| 22 | let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), 0) }; | |
| 23 | if res < 0 { | |
| 24 | panic!("epoll_wait failed: {}", std::io::Error::last_os_error()); | |
| 25 | } | |
| 26 | assert_eq!( | |
| 27 | res, | |
| 28 | expected_notifications.len().try_into().unwrap(), | |
| 29 | "got wrong number of notifications" | |
| 30 | ); | |
| 31 | let got_notifications = | |
| 32 | unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) }; | |
| 33 | let got_notifications = got_notifications.iter().map(|e| (e.events, e.u64)).collect::<Vec<_>>(); | |
| 34 | assert_eq!(got_notifications, expected_notifications, "got wrong notifications"); | |
| 35 | } | |
| 14 | use libc_utils::epoll::*; | |
| 15 | use libc_utils::*; | |
| 36 | 16 | |
| 37 | 17 | fn main() { |
| 38 | 18 | // Create an epoll instance. |
| ... | ... | @@ -41,27 +21,17 @@ fn main() { |
| 41 | 21 | |
| 42 | 22 | // Create two socketpair instances. |
| 43 | 23 | let mut fds_a = [-1, -1]; |
| 44 | let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_a.as_mut_ptr()) }; | |
| 45 | assert_eq!(res, 0); | |
| 46 | ||
| 24 | unsafe { | |
| 25 | errno_check(libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_a.as_mut_ptr())) | |
| 26 | }; | |
| 47 | 27 | let mut fds_b = [-1, -1]; |
| 48 | let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_b.as_mut_ptr()) }; | |
| 49 | assert_eq!(res, 0); | |
| 50 | ||
| 51 | // Register both pipe read ends. | |
| 52 | let mut ev = libc::epoll_event { | |
| 53 | events: (libc::EPOLLIN | libc::EPOLLET) as _, | |
| 54 | u64: u64::try_from(fds_a[1]).unwrap(), | |
| 28 | unsafe { | |
| 29 | errno_check(libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds_b.as_mut_ptr())) | |
| 55 | 30 | }; |
| 56 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds_a[1], &mut ev) }; | |
| 57 | assert_eq!(res, 0); | |
| 58 | 31 | |
| 59 | let mut ev = libc::epoll_event { | |
| 60 | events: (libc::EPOLLIN | libc::EPOLLET) as _, | |
| 61 | u64: u64::try_from(fds_b[1]).unwrap(), | |
| 62 | }; | |
| 63 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds_b[1], &mut ev) }; | |
| 64 | assert_eq!(res, 0); | |
| 32 | // Register both pipe read ends. | |
| 33 | epoll_ctl_add(epfd, fds_a[1], EPOLLIN | EPOLLET).unwrap(); | |
| 34 | epoll_ctl_add(epfd, fds_b[1], EPOLLIN | EPOLLET).unwrap(); | |
| 65 | 35 | |
| 66 | 36 | static mut VAL_ONE: u8 = 40; // This one will be read soundly. |
| 67 | 37 | static mut VAL_TWO: u8 = 50; // This one will be read unsoundly. |
| ... | ... | @@ -78,9 +48,7 @@ fn main() { |
| 78 | 48 | thread::yield_now(); |
| 79 | 49 | |
| 80 | 50 | // With room for one event: check result from epoll_wait. |
| 81 | let expected_event = u32::try_from(libc::EPOLLIN).unwrap(); | |
| 82 | let expected_value = u64::try_from(fds_a[1]).unwrap(); | |
| 83 | check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)]); | |
| 51 | check_epoll_wait_partial(epfd, &[Ev { events: EPOLLIN, data: fds_a[1] }], 1, -1); | |
| 84 | 52 | |
| 85 | 53 | // Since we only received one event, we have synchronized with |
| 86 | 54 | // the write to VAL_ONE but not with the one to VAL_TWO. |
src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs+19-43| ... | ... | @@ -2,42 +2,11 @@ |
| 2 | 2 | //@only-target: linux android illumos |
| 3 | 3 | //@error-in-other-file: deadlock |
| 4 | 4 | |
| 5 | use std::convert::TryInto; | |
| 6 | 5 | use std::thread; |
| 7 | 6 | |
| 8 | 7 | #[path = "../../utils/libc.rs"] |
| 9 | 8 | mod libc_utils; |
| 10 | ||
| 11 | // Using `as` cast since `EPOLLET` wraps around | |
| 12 | const EPOLL_IN_OUT_ET: u32 = (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _; | |
| 13 | ||
| 14 | #[track_caller] | |
| 15 | fn check_epoll_wait<const N: usize>( | |
| 16 | epfd: i32, | |
| 17 | expected_notifications: &[(u32, u64)], | |
| 18 | timeout: i32, | |
| 19 | ) { | |
| 20 | let epoll_event = libc::epoll_event { events: 0, u64: 0 }; | |
| 21 | let mut array: [libc::epoll_event; N] = [epoll_event; N]; | |
| 22 | let maxsize = N; | |
| 23 | let array_ptr = array.as_mut_ptr(); | |
| 24 | let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), timeout) }; | |
| 25 | if res < 0 { | |
| 26 | panic!("epoll_wait failed: {}", std::io::Error::last_os_error()); | |
| 27 | } | |
| 28 | assert_eq!( | |
| 29 | res, | |
| 30 | expected_notifications.len().try_into().unwrap(), | |
| 31 | "got wrong number of notifications" | |
| 32 | ); | |
| 33 | let slice = unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) }; | |
| 34 | for (return_event, expected_event) in slice.iter().zip(expected_notifications.iter()) { | |
| 35 | let event = return_event.events; | |
| 36 | let data = return_event.u64; | |
| 37 | assert_eq!(event, expected_event.0, "got wrong events"); | |
| 38 | assert_eq!(data, expected_event.1, "got wrong data"); | |
| 39 | } | |
| 40 | } | |
| 9 | use libc_utils::epoll::*; | |
| 41 | 10 | |
| 42 | 11 | // Test if only one thread is unblocked if multiple threads blocked on same epfd. |
| 43 | 12 | // Expected execution: |
| ... | ... | @@ -57,23 +26,30 @@ fn main() { |
| 57 | 26 | let fd2 = unsafe { libc::dup(fd1) }; |
| 58 | 27 | |
| 59 | 28 | // Register both with epoll. |
| 60 | let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fd1 as u64 }; | |
| 61 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd1, &mut ev) }; | |
| 62 | assert_eq!(res, 0); | |
| 63 | let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fd2 as u64 }; | |
| 64 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd2, &mut ev) }; | |
| 65 | assert_eq!(res, 0); | |
| 29 | epoll_ctl_add(epfd, fd1, EPOLLIN | EPOLLOUT | EPOLLET).unwrap(); | |
| 30 | epoll_ctl_add(epfd, fd2, EPOLLIN | EPOLLOUT | EPOLLET).unwrap(); | |
| 66 | 31 | |
| 67 | 32 | // Consume the initial events. |
| 68 | let expected = [(libc::EPOLLOUT as u32, fd1 as u64), (libc::EPOLLOUT as u32, fd2 as u64)]; | |
| 69 | check_epoll_wait::<8>(epfd, &expected, -1); | |
| 33 | check_epoll_wait( | |
| 34 | epfd, | |
| 35 | &[Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }], | |
| 36 | -1, | |
| 37 | ); | |
| 70 | 38 | |
| 71 | 39 | let thread1 = thread::spawn(move || { |
| 72 | check_epoll_wait::<2>(epfd, &expected, -1); | |
| 40 | check_epoll_wait( | |
| 41 | epfd, | |
| 42 | &[Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }], | |
| 43 | -1, | |
| 44 | ); | |
| 73 | 45 | }); |
| 74 | 46 | let thread2 = thread::spawn(move || { |
| 75 | check_epoll_wait::<2>(epfd, &expected, -1); | |
| 76 | //~^ERROR: deadlocked | |
| 47 | //~vERROR: deadlocked | |
| 48 | check_epoll_wait( | |
| 49 | epfd, | |
| 50 | &[Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }], | |
| 51 | -1, | |
| 52 | ); | |
| 77 | 53 | }); |
| 78 | 54 | // Yield so the threads are both blocked. |
| 79 | 55 | thread::yield_now(); |
src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr+10-3| ... | ... | @@ -18,8 +18,12 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; |
| 18 | 18 | error: the evaluated program deadlocked |
| 19 | 19 | --> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC |
| 20 | 20 | | |
| 21 | LL | check_epoll_wait::<TAG>(epfd, &expected, -1); | |
| 22 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ thread got stuck here | |
| 21 | LL | / check_epoll_wait( | |
| 22 | LL | | epfd, | |
| 23 | LL | | &[Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }], | |
| 24 | LL | | -1, | |
| 25 | LL | | ); | |
| 26 | | |_________^ thread got stuck here | |
| 23 | 27 | | |
| 24 | 28 | = note: this is on thread `unnamed-ID` |
| 25 | 29 | note: the current function got called indirectly due to this code |
| ... | ... | @@ -27,8 +31,11 @@ note: the current function got called indirectly due to this code |
| 27 | 31 | | |
| 28 | 32 | LL | let thread2 = thread::spawn(move || { |
| 29 | 33 | | ___________________^ |
| 30 | LL | | check_epoll_wait::<TAG>(epfd, &expected, -1); | |
| 31 | 34 | LL | | |
| 35 | LL | | check_epoll_wait( | |
| 36 | LL | | epfd, | |
| 37 | ... | | |
| 38 | LL | | ); | |
| 32 | 39 | LL | | }); |
| 33 | 40 | | |______^ |
| 34 | 41 |
src/tools/miri/tests/fail-dep/libc/socket-connect-after-failed-connection.rs+1-1| ... | ... | @@ -41,7 +41,7 @@ fn main() { |
| 41 | 41 | epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | libc::EPOLLERR).unwrap(); |
| 42 | 42 | |
| 43 | 43 | // Wait until the socket has an error. |
| 44 | check_epoll_wait::<8>( | |
| 44 | check_epoll_wait( | |
| 45 | 45 | epfd, |
| 46 | 46 | &[Ev { events: libc::EPOLLERR | EPOLLOUT | EPOLLHUP, data: client_sockfd }], |
| 47 | 47 | -1, |
src/tools/miri/tests/fail/async-shared-mutable.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | //! `UnsafePinned` must include the effects of `UnsafeCell`. |
| 4 | 4 | //@revisions: stack tree |
| 5 | 5 | //@[tree]compile-flags: -Zmiri-tree-borrows |
| 6 | //@normalize-stderr-test: "\[0x[a-fx\d.]+\]" -> "[OFFSET]" | |
| 6 | //@normalize-stderr-test: "\[0x[a-fx\d.]+\]" -> "[RANGE]" | |
| 7 | 7 | |
| 8 | 8 | use core::future::Future; |
| 9 | 9 | use core::pin::{Pin, pin}; |
src/tools/miri/tests/fail/async-shared-mutable.stack.stderr+4-4| ... | ... | @@ -1,12 +1,12 @@ |
| 1 | error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[OFFSET], but that tag does not exist in the borrow stack for this location | |
| 1 | error: Undefined Behavior: attempting a write access using <TAG> at ALLOC[RANGE], but that tag does not exist in the borrow stack for this location | |
| 2 | 2 | --> tests/fail/async-shared-mutable.rs:LL:CC |
| 3 | 3 | | |
| 4 | 4 | LL | *x = 1; |
| 5 | | ^^^^^^ this error occurs as part of an access at ALLOC[OFFSET] | |
| 5 | | ^^^^^^ this error occurs as part of an access at ALLOC[RANGE] | |
| 6 | 6 | | |
| 7 | 7 | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental |
| 8 | 8 | = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information |
| 9 | help: <TAG> was created by a Unique retag at offsets [OFFSET] | |
| 9 | help: <TAG> was created by a Unique retag at offsets [RANGE] | |
| 10 | 10 | --> tests/fail/async-shared-mutable.rs:LL:CC |
| 11 | 11 | | |
| 12 | 12 | LL | / core::future::poll_fn(move |_| { |
| ... | ... | @@ -15,7 +15,7 @@ LL | | Poll::<()>::Pending |
| 15 | 15 | LL | | }) |
| 16 | 16 | LL | | .await |
| 17 | 17 | | |______________^ |
| 18 | help: <TAG> was later invalidated at offsets [OFFSET] by a SharedReadOnly retag | |
| 18 | help: <TAG> was later invalidated at offsets [RANGE] by a SharedReadOnly retag | |
| 19 | 19 | --> tests/fail/async-shared-mutable.rs:LL:CC |
| 20 | 20 | | |
| 21 | 21 | LL | let _: Pin<&_> = f.as_ref(); // Or: `f.as_mut().into_ref()`. |
src/tools/miri/tests/fail/async-shared-mutable.tree.stderr+3-3| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: Undefined Behavior: write access through <TAG> at ALLOC[OFFSET] is forbidden | |
| 1 | error: Undefined Behavior: write access through <TAG> at ALLOC[RANGE] is forbidden | |
| 2 | 2 | --> tests/fail/async-shared-mutable.rs:LL:CC |
| 3 | 3 | | |
| 4 | 4 | LL | *x = 1; |
| ... | ... | @@ -16,13 +16,13 @@ LL | | Poll::<()>::Pending |
| 16 | 16 | LL | | }) |
| 17 | 17 | LL | | .await |
| 18 | 18 | | |______________^ |
| 19 | help: the accessed tag <TAG> later transitioned to Unique due to a child write access at offsets [OFFSET] | |
| 19 | help: the accessed tag <TAG> later transitioned to Unique due to a child write access at offsets [RANGE] | |
| 20 | 20 | --> tests/fail/async-shared-mutable.rs:LL:CC |
| 21 | 21 | | |
| 22 | 22 | LL | *x = 1; |
| 23 | 23 | | ^^^^^^ |
| 24 | 24 | = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference |
| 25 | help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [OFFSET] | |
| 25 | help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [RANGE] | |
| 26 | 26 | --> tests/fail/async-shared-mutable.rs:LL:CC |
| 27 | 27 | | |
| 28 | 28 | LL | let _: Pin<&_> = f.as_ref(); // Or: `f.as_mut().into_ref()`. |
src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.rs created+131| ... | ... | @@ -0,0 +1,131 @@ |
| 1 | //! Test related to <https://github.com/rust-lang/miri/issues/3341>: | |
| 2 | //! `Box` with custom allocators are still `noalias`, leading to UB. | |
| 3 | ||
| 4 | //@revisions: stack tree | |
| 5 | //@[tree]compile-flags: -Zmiri-tree-borrows | |
| 6 | //@normalize-stderr-test: "\[0x[a-fx\d.]+\]" -> "[RANGE]" | |
| 7 | #![feature(allocator_api)] | |
| 8 | ||
| 9 | use std::alloc::{AllocError, Allocator, Layout}; | |
| 10 | use std::cell::{Cell, UnsafeCell}; | |
| 11 | use std::mem; | |
| 12 | use std::ptr::{self, NonNull, addr_of}; | |
| 13 | use std::thread::{self, ThreadId}; | |
| 14 | ||
| 15 | const BIN_SIZE: usize = 8; | |
| 16 | ||
| 17 | // A bin represents a collection of blocks of a specific layout. | |
| 18 | #[repr(align(128))] | |
| 19 | struct MyBin { | |
| 20 | top: Cell<usize>, | |
| 21 | thread_id: ThreadId, | |
| 22 | memory: UnsafeCell<[usize; BIN_SIZE]>, | |
| 23 | } | |
| 24 | ||
| 25 | impl MyBin { | |
| 26 | fn pop(&self) -> Option<NonNull<u8>> { | |
| 27 | let top = self.top.get(); | |
| 28 | if top == BIN_SIZE { | |
| 29 | return None; | |
| 30 | } | |
| 31 | // Cast the *entire* thing to a raw pointer to not restrict its provenance. | |
| 32 | let bin = self as *const MyBin; | |
| 33 | let base_ptr = UnsafeCell::raw_get(unsafe { addr_of!((*bin).memory) }).cast::<usize>(); | |
| 34 | let ptr = unsafe { NonNull::new_unchecked(base_ptr.add(top)) }; | |
| 35 | self.top.set(top + 1); | |
| 36 | Some(ptr.cast()) | |
| 37 | } | |
| 38 | ||
| 39 | // Pretends to not be a throwaway allocation method like this. A more realistic | |
| 40 | // substitute is using intrusive linked lists, which requires access to the | |
| 41 | // metadata of this bin as well. | |
| 42 | unsafe fn push(&self, ptr: NonNull<u8>) { | |
| 43 | // For now just check that this really is in this bin. | |
| 44 | let start = self.memory.get().addr(); | |
| 45 | let end = start + BIN_SIZE * mem::size_of::<usize>(); | |
| 46 | let addr = ptr.addr().get(); | |
| 47 | assert!((start..end).contains(&addr)); | |
| 48 | ||
| 49 | // We can't update `top` as this may not be the last bin, but we can pretend to do so | |
| 50 | // such that the aliasing model checks things. | |
| 51 | // We access this via raw pointers so that the error span is in this file. | |
| 52 | let top_ptr = (&raw const self.top) as *mut usize; | |
| 53 | let top = top_ptr.read(); | |
| 54 | //~[tree]^ERROR: /read access .* is forbidden/ | |
| 55 | top_ptr.write(top); | |
| 56 | } | |
| 57 | } | |
| 58 | ||
| 59 | // A collection of bins. | |
| 60 | struct MyAllocator { | |
| 61 | thread_id: ThreadId, | |
| 62 | // Pretends to be some complex collection of bins, such as an array of linked lists. | |
| 63 | bins: Box<[MyBin; 1]>, | |
| 64 | } | |
| 65 | ||
| 66 | impl MyAllocator { | |
| 67 | fn new() -> Self { | |
| 68 | let thread_id = thread::current().id(); | |
| 69 | MyAllocator { | |
| 70 | thread_id, | |
| 71 | bins: Box::new( | |
| 72 | [MyBin { top: Cell::new(0), thread_id, memory: UnsafeCell::default() }; 1], | |
| 73 | ), | |
| 74 | } | |
| 75 | } | |
| 76 | ||
| 77 | // Pretends to be expensive finding a suitable bin for the layout. | |
| 78 | fn find_bin(&self, layout: Layout) -> Option<&MyBin> { | |
| 79 | if layout == Layout::new::<usize>() { Some(&self.bins[0]) } else { None } | |
| 80 | } | |
| 81 | } | |
| 82 | ||
| 83 | unsafe impl Allocator for MyAllocator { | |
| 84 | fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { | |
| 85 | // Expensive bin search. | |
| 86 | let bin = self.find_bin(layout).ok_or(AllocError)?; | |
| 87 | let ptr = bin.pop().ok_or(AllocError)?; | |
| 88 | Ok(NonNull::slice_from_raw_parts(ptr, layout.size())) | |
| 89 | } | |
| 90 | ||
| 91 | unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) { | |
| 92 | // Make sure accesses via `self` don't disturb anything. | |
| 93 | let _val = self.bins[0].top.get(); | |
| 94 | // Since manually finding the corresponding bin of `ptr` is very expensive, | |
| 95 | // doing pointer arithmetics is preferred. | |
| 96 | // But this means we access `top` via `ptr` rather than `self`! | |
| 97 | // That is fundamentally the source of the aliasing trouble in this example. | |
| 98 | let their_bin = ptr.as_ptr().map_addr(|addr| addr & !127).cast::<MyBin>(); | |
| 99 | let thread_id = ptr::read(ptr::addr_of!((*their_bin).thread_id)); | |
| 100 | //~[stack]^ERROR: tag does not exist in the borrow stack | |
| 101 | if self.thread_id == thread_id { | |
| 102 | unsafe { (*their_bin).push(ptr) }; | |
| 103 | } else { | |
| 104 | todo!("Deallocating from another thread"); | |
| 105 | } | |
| 106 | // Make sure we can also still access this via `self` after the rest is done. | |
| 107 | let _val = self.bins[0].top.get(); | |
| 108 | } | |
| 109 | } | |
| 110 | ||
| 111 | // Make sure to involve `Box` in allocating these, | |
| 112 | // as that's where `noalias` may come from. | |
| 113 | fn v1<T, A: Allocator>(t: T, a: A) -> Vec<T, A> { | |
| 114 | (Box::new_in([t], a) as Box<[T], A>).into_vec() | |
| 115 | } | |
| 116 | fn v2<T, A: Allocator>(t: T, a: A) -> Vec<T, A> { | |
| 117 | let v = v1(t, a); | |
| 118 | // There was a bug in `into_boxed_slice` that caused aliasing issues, | |
| 119 | // so round-trip through that as well. | |
| 120 | v.into_boxed_slice().into_vec() | |
| 121 | } | |
| 122 | ||
| 123 | fn main() { | |
| 124 | assert!(mem::size_of::<MyBin>() <= 128); // if it grows bigger, the trick to access the "header" no longer works | |
| 125 | let my_alloc = MyAllocator::new(); | |
| 126 | let a = v1(1usize, &my_alloc); | |
| 127 | let b = v2(2usize, &my_alloc); | |
| 128 | assert_eq!(a[0] + 1, b[0]); | |
| 129 | assert_eq!(addr_of!(a[0]).wrapping_add(1), addr_of!(b[0])); | |
| 130 | drop((a, b)); | |
| 131 | } |
src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.stack.stderr created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | error: Undefined Behavior: attempting a read access using <TAG> at ALLOC[RANGE], but that tag does not exist in the borrow stack for this location | |
| 2 | --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 3 | | | |
| 4 | LL | let thread_id = ptr::read(ptr::addr_of!((*their_bin).thread_id)); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of an access at ALLOC[RANGE] | |
| 6 | | | |
| 7 | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental | |
| 8 | = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information | |
| 9 | help: <TAG> was created by a Unique retag at offsets [RANGE] | |
| 10 | --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 11 | | | |
| 12 | LL | (Box::new_in([t], a) as Box<[T], A>).into_vec() | |
| 13 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 14 | = note: stack backtrace: | |
| 15 | 0: <MyAllocator as std::alloc::Allocator>::deallocate | |
| 16 | at tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 17 | 1: <&MyAllocator as std::alloc::Allocator>::deallocate | |
| 18 | at RUSTLIB/core/src/alloc/mod.rs:LL:CC | |
| 19 | 2: alloc::raw_vec::RawVecInner::<&MyAllocator>::deallocate | |
| 20 | at RUSTLIB/alloc/src/raw_vec/mod.rs:LL:CC | |
| 21 | 3: <alloc::raw_vec::RawVec<usize, &MyAllocator> as std::ops::Drop>::drop | |
| 22 | at RUSTLIB/alloc/src/raw_vec/mod.rs:LL:CC | |
| 23 | 4: std::ptr::drop_glue::<alloc::raw_vec::RawVec<usize, &MyAllocator>> - shim(Some(alloc::raw_vec::RawVec<usize, &MyAllocator>)) | |
| 24 | at RUSTLIB/core/src/ptr/mod.rs:LL:CC | |
| 25 | 5: std::ptr::drop_glue::<std::vec::Vec<usize, &MyAllocator>> - shim(Some(std::vec::Vec<usize, &MyAllocator>)) | |
| 26 | at RUSTLIB/core/src/ptr/mod.rs:LL:CC | |
| 27 | 6: std::ptr::drop_glue::<(std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)> - shim(Some((std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>))) | |
| 28 | at RUSTLIB/core/src/ptr/mod.rs:LL:CC | |
| 29 | 7: std::mem::drop::<(std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)> | |
| 30 | at RUSTLIB/core/src/mem/mod.rs:LL:CC | |
| 31 | 8: main | |
| 32 | at tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 33 | ||
| 34 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 35 | ||
| 36 | error: aborting due to 1 previous error | |
| 37 |
src/tools/miri/tests/fail/both_borrows/box-custom-alloc-aliasing.tree.stderr created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | error: Undefined Behavior: read access through <TAG> at ALLOC[RANGE] is forbidden | |
| 2 | --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 3 | | | |
| 4 | LL | let top = top_ptr.read(); | |
| 5 | | ^^^^^^^^^^^^^^ Undefined Behavior occurred here | |
| 6 | | | |
| 7 | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental | |
| 8 | = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information | |
| 9 | = help: the accessed tag <TAG> is a child of the conflicting tag <TAG> | |
| 10 | = help: the conflicting tag <TAG> has state Disabled which forbids this child read access | |
| 11 | help: the accessed tag <TAG> was created here | |
| 12 | --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 13 | | | |
| 14 | LL | unsafe fn push(&self, ptr: NonNull<u8>) { | |
| 15 | | ^^^^^ | |
| 16 | help: the conflicting tag <TAG> was created here, in the initial state Reserved | |
| 17 | --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 18 | | | |
| 19 | LL | (Box::new_in([t], a) as Box<[T], A>).into_vec() | |
| 20 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 21 | help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [RANGE] | |
| 22 | --> tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 23 | | | |
| 24 | LL | self.top.set(top + 1); | |
| 25 | | ^^^^^^^^^^^^^^^^^^^^^ | |
| 26 | = help: this transition corresponds to a loss of read and write permissions | |
| 27 | = note: stack backtrace: | |
| 28 | 0: MyBin::push | |
| 29 | at tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 30 | 1: <MyAllocator as std::alloc::Allocator>::deallocate | |
| 31 | at tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 32 | 2: <&MyAllocator as std::alloc::Allocator>::deallocate | |
| 33 | at RUSTLIB/core/src/alloc/mod.rs:LL:CC | |
| 34 | 3: alloc::raw_vec::RawVecInner::<&MyAllocator>::deallocate | |
| 35 | at RUSTLIB/alloc/src/raw_vec/mod.rs:LL:CC | |
| 36 | 4: <alloc::raw_vec::RawVec<usize, &MyAllocator> as std::ops::Drop>::drop | |
| 37 | at RUSTLIB/alloc/src/raw_vec/mod.rs:LL:CC | |
| 38 | 5: std::ptr::drop_glue::<alloc::raw_vec::RawVec<usize, &MyAllocator>> - shim(Some(alloc::raw_vec::RawVec<usize, &MyAllocator>)) | |
| 39 | at RUSTLIB/core/src/ptr/mod.rs:LL:CC | |
| 40 | 6: std::ptr::drop_glue::<std::vec::Vec<usize, &MyAllocator>> - shim(Some(std::vec::Vec<usize, &MyAllocator>)) | |
| 41 | at RUSTLIB/core/src/ptr/mod.rs:LL:CC | |
| 42 | 7: std::ptr::drop_glue::<(std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)> - shim(Some((std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>))) | |
| 43 | at RUSTLIB/core/src/ptr/mod.rs:LL:CC | |
| 44 | 8: std::mem::drop::<(std::vec::Vec<usize, &MyAllocator>, std::vec::Vec<usize, &MyAllocator>)> | |
| 45 | at RUSTLIB/core/src/mem/mod.rs:LL:CC | |
| 46 | 9: main | |
| 47 | at tests/fail/both_borrows/box-custom-alloc-aliasing.rs:LL:CC | |
| 48 | ||
| 49 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 50 | ||
| 51 | error: aborting due to 1 previous error | |
| 52 |
src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs+1-1| ... | ... | @@ -25,7 +25,7 @@ fn main() { |
| 25 | 25 | |
| 26 | 26 | // Detach the thread and sleep until it terminates |
| 27 | 27 | mem::drop(join); |
| 28 | sleep(Duration::from_millis(200)); | |
| 28 | sleep(Duration::from_millis(100)); | |
| 29 | 29 | |
| 30 | 30 | // Spawn and immediately join a thread |
| 31 | 31 | // to execute the join code-path |
src/tools/miri/tests/fail/data_race/dangling_thread_race.rs+1-1| ... | ... | @@ -25,7 +25,7 @@ fn main() { |
| 25 | 25 | |
| 26 | 26 | // Detach the thread and sleep until it terminates |
| 27 | 27 | mem::drop(join); |
| 28 | sleep(Duration::from_millis(200)); | |
| 28 | sleep(Duration::from_millis(100)); | |
| 29 | 29 | |
| 30 | 30 | // Spawn and immediately join a thread |
| 31 | 31 | // to execute the join code-path |
src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs+1-1| ... | ... | @@ -34,7 +34,7 @@ fn main() { |
| 34 | 34 | |
| 35 | 35 | pointer.store(&mut stack_var as *mut _, Ordering::Release); |
| 36 | 36 | |
| 37 | sleep(Duration::from_millis(200)); | |
| 37 | sleep(Duration::from_millis(100)); | |
| 38 | 38 | |
| 39 | 39 | // Now `stack_var` gets deallocated. |
| 40 | 40 | } //~ ERROR: Data race detected between (1) non-atomic read on thread `unnamed-2` and (2) deallocation on thread `unnamed-1` |
src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs+1-1| ... | ... | @@ -34,7 +34,7 @@ fn main() { |
| 34 | 34 | |
| 35 | 35 | pointer.store(&mut stack_var as *mut _, Ordering::Release); |
| 36 | 36 | |
| 37 | sleep(Duration::from_millis(200)); | |
| 37 | sleep(Duration::from_millis(100)); | |
| 38 | 38 | |
| 39 | 39 | // Now `stack_var` gets deallocated. |
| 40 | 40 | } //~ ERROR: Data race detected between (1) non-atomic write on thread `unnamed-2` and (2) deallocation on thread `unnamed-1` |
src/tools/miri/tests/fail/data_race/read_write_race_stack.rs+1-1| ... | ... | @@ -39,7 +39,7 @@ fn main() { |
| 39 | 39 | |
| 40 | 40 | pointer.store(&mut stack_var as *mut _, Ordering::Release); |
| 41 | 41 | |
| 42 | sleep(Duration::from_millis(200)); | |
| 42 | sleep(Duration::from_millis(100)); | |
| 43 | 43 | |
| 44 | 44 | stack_var //~ ERROR: Data race detected between (1) non-atomic write on thread `unnamed-2` and (2) non-atomic read on thread `unnamed-1` |
| 45 | 45 | }); |
src/tools/miri/tests/fail/data_race/release_seq_race.rs+1-1| ... | ... | @@ -31,7 +31,7 @@ fn main() { |
| 31 | 31 | let c = c; // avoid field capturing |
| 32 | 32 | *c.0 = 1; |
| 33 | 33 | SYNC.store(1, Ordering::Release); |
| 34 | sleep(Duration::from_millis(200)); | |
| 34 | sleep(Duration::from_millis(100)); | |
| 35 | 35 | SYNC.store(3, Ordering::Relaxed); |
| 36 | 36 | }); |
| 37 | 37 |
src/tools/miri/tests/fail/data_race/write_write_race_stack.rs+1-1| ... | ... | @@ -39,7 +39,7 @@ fn main() { |
| 39 | 39 | |
| 40 | 40 | pointer.store(&mut stack_var as *mut _, Ordering::Release); |
| 41 | 41 | |
| 42 | sleep(Duration::from_millis(200)); | |
| 42 | sleep(Duration::from_millis(100)); | |
| 43 | 43 | |
| 44 | 44 | stack_var = 1usize; //~ ERROR: Data race detected between (1) non-atomic write on thread `unnamed-2` and (2) non-atomic write on thread `unnamed-1` |
| 45 | 45 |
src/tools/miri/tests/pass-dep/concurrency/apple-futex.rs+11-13| ... | ... | @@ -62,7 +62,7 @@ fn wait_timeout() { |
| 62 | 62 | |
| 63 | 63 | let futex: i32 = 123; |
| 64 | 64 | |
| 65 | // Wait for 200ms, with nobody waking us up early. | |
| 65 | // Wait for 100ms, with nobody waking us up early. | |
| 66 | 66 | unsafe { |
| 67 | 67 | assert_eq!( |
| 68 | 68 | libc::os_sync_wait_on_address_with_timeout( |
| ... | ... | @@ -71,14 +71,14 @@ fn wait_timeout() { |
| 71 | 71 | size_of::<i32>(), |
| 72 | 72 | libc::OS_SYNC_WAIT_ON_ADDRESS_NONE, |
| 73 | 73 | libc::OS_CLOCK_MACH_ABSOLUTE_TIME, |
| 74 | 200_000_000, | |
| 74 | 100_000_000, | |
| 75 | 75 | ), |
| 76 | 76 | -1, |
| 77 | 77 | ); |
| 78 | 78 | assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | assert!((200..1000).contains(&start.elapsed().as_millis())); | |
| 81 | assert!((100..1000).contains(&start.elapsed().as_millis())); | |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | fn wait_absolute_timeout() { |
| ... | ... | @@ -88,15 +88,15 @@ fn wait_absolute_timeout() { |
| 88 | 88 | #[allow(deprecated)] |
| 89 | 89 | let mut deadline = unsafe { libc::mach_absolute_time() }; |
| 90 | 90 | |
| 91 | // Add 200ms. | |
| 91 | // Add 100ms. | |
| 92 | 92 | // What we should be doing here is call `mach_timebase_info` to determine the |
| 93 | 93 | // unit used for `deadline`, but we know what Miri returns for that function: |
| 94 | 94 | // the unit is nanoseconds. |
| 95 | deadline += 200_000_000; | |
| 95 | deadline += 100_000_000; | |
| 96 | 96 | |
| 97 | 97 | let futex: i32 = 123; |
| 98 | 98 | |
| 99 | // Wait for 200ms from now, with nobody waking us up early. | |
| 99 | // Wait for 100ms from now, with nobody waking us up early. | |
| 100 | 100 | unsafe { |
| 101 | 101 | assert_eq!( |
| 102 | 102 | libc::os_sync_wait_on_address_with_deadline( |
| ... | ... | @@ -112,16 +112,14 @@ fn wait_absolute_timeout() { |
| 112 | 112 | assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | assert!((200..1000).contains(&start.elapsed().as_millis())); | |
| 115 | assert!((100..1000).contains(&start.elapsed().as_millis())); | |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | fn wait_wake() { |
| 119 | let start = Instant::now(); | |
| 120 | ||
| 121 | 119 | static mut FUTEX: i32 = 0; |
| 122 | 120 | |
| 123 | 121 | let t = thread::spawn(move || { |
| 124 | thread::sleep(Duration::from_millis(200)); | |
| 122 | thread::sleep(Duration::from_millis(100)); | |
| 125 | 123 | unsafe { |
| 126 | 124 | assert_eq!( |
| 127 | 125 | libc::os_sync_wake_by_address_any( |
| ... | ... | @@ -134,6 +132,8 @@ fn wait_wake() { |
| 134 | 132 | } |
| 135 | 133 | }); |
| 136 | 134 | |
| 135 | let start = Instant::now(); | |
| 136 | ||
| 137 | 137 | unsafe { |
| 138 | 138 | assert_eq!( |
| 139 | 139 | libc::os_sync_wait_on_address( |
| ... | ... | @@ -146,9 +146,7 @@ fn wait_wake() { |
| 146 | 146 | ); |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | // When running this in stress-gc mode, things can take quite long. | |
| 150 | // So the timeout is 3000 ms. | |
| 151 | assert!((200..3000).contains(&start.elapsed().as_millis())); | |
| 149 | assert!((100..1000).contains(&start.elapsed().as_millis())); | |
| 152 | 150 | t.join().unwrap(); |
| 153 | 151 | } |
| 154 | 152 |
src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs+19-21| ... | ... | @@ -78,7 +78,7 @@ fn wait_timeout() { |
| 78 | 78 | |
| 79 | 79 | let futex: i32 = 123; |
| 80 | 80 | |
| 81 | // Wait for 200ms, with nobody waking us up early. | |
| 81 | // Wait for 100ms, with nobody waking us up early. | |
| 82 | 82 | unsafe { |
| 83 | 83 | assert_eq!( |
| 84 | 84 | libc::syscall( |
| ... | ... | @@ -86,17 +86,19 @@ fn wait_timeout() { |
| 86 | 86 | addr_of!(futex), |
| 87 | 87 | libc::FUTEX_WAIT, |
| 88 | 88 | 123, |
| 89 | &libc::timespec { tv_sec: 0, tv_nsec: 200_000_000 }, | |
| 89 | &libc::timespec { tv_sec: 0, tv_nsec: 100_000_000 }, | |
| 90 | 90 | ), |
| 91 | 91 | -1, |
| 92 | 92 | ); |
| 93 | 93 | assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | assert!((200..1000).contains(&start.elapsed().as_millis())); | |
| 96 | assert!((100..1000).contains(&start.elapsed().as_millis())); | |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | fn wait_absolute_timeout() { |
| 100 | static mut FUTEX: i32 = 123; | |
| 101 | ||
| 100 | 102 | let start = Instant::now(); |
| 101 | 103 | |
| 102 | 104 | // Get the current monotonic timestamp as timespec. |
| ... | ... | @@ -106,21 +108,19 @@ fn wait_absolute_timeout() { |
| 106 | 108 | now.assume_init() |
| 107 | 109 | }; |
| 108 | 110 | |
| 109 | // Add 200ms. | |
| 110 | timeout.tv_nsec += 200_000_000; | |
| 111 | // Add 100ms. | |
| 112 | timeout.tv_nsec += 100_000_000; | |
| 111 | 113 | if timeout.tv_nsec > 1_000_000_000 { |
| 112 | 114 | timeout.tv_nsec -= 1_000_000_000; |
| 113 | 115 | timeout.tv_sec += 1; |
| 114 | 116 | } |
| 115 | 117 | |
| 116 | let futex: i32 = 123; | |
| 117 | ||
| 118 | // Wait for 200ms from now, with nobody waking us up early. | |
| 118 | // Wait for 100ms from now, with nobody waking us up early. | |
| 119 | 119 | unsafe { |
| 120 | 120 | assert_eq!( |
| 121 | 121 | libc::syscall( |
| 122 | 122 | libc::SYS_futex, |
| 123 | addr_of!(futex), | |
| 123 | addr_of!(FUTEX), | |
| 124 | 124 | libc::FUTEX_WAIT_BITSET, |
| 125 | 125 | 123, |
| 126 | 126 | &timeout, |
| ... | ... | @@ -132,16 +132,14 @@ fn wait_absolute_timeout() { |
| 132 | 132 | assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | assert!((200..1000).contains(&start.elapsed().as_millis())); | |
| 135 | assert!((100..1000).contains(&start.elapsed().as_millis())); | |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | 138 | fn wait_wake() { |
| 139 | let start = Instant::now(); | |
| 140 | ||
| 141 | 139 | static mut FUTEX: i32 = 0; |
| 142 | 140 | |
| 143 | 141 | let t = thread::spawn(move || { |
| 144 | thread::sleep(Duration::from_millis(200)); | |
| 142 | thread::sleep(Duration::from_millis(100)); | |
| 145 | 143 | unsafe { |
| 146 | 144 | assert_eq!( |
| 147 | 145 | libc::syscall( |
| ... | ... | @@ -155,6 +153,8 @@ fn wait_wake() { |
| 155 | 153 | } |
| 156 | 154 | }); |
| 157 | 155 | |
| 156 | let start = Instant::now(); | |
| 157 | ||
| 158 | 158 | unsafe { |
| 159 | 159 | assert_eq!( |
| 160 | 160 | libc::syscall( |
| ... | ... | @@ -168,19 +168,15 @@ fn wait_wake() { |
| 168 | 168 | ); |
| 169 | 169 | } |
| 170 | 170 | |
| 171 | // When running this in stress-gc mode, things can take quite long. | |
| 172 | // So the timeout is 3000 ms. | |
| 173 | assert!((200..3000).contains(&start.elapsed().as_millis())); | |
| 171 | assert!((100..1000).contains(&start.elapsed().as_millis())); | |
| 174 | 172 | t.join().unwrap(); |
| 175 | 173 | } |
| 176 | 174 | |
| 177 | 175 | fn wait_wake_bitset() { |
| 178 | let start = Instant::now(); | |
| 179 | ||
| 180 | 176 | static mut FUTEX: i32 = 0; |
| 181 | 177 | |
| 182 | 178 | let t = thread::spawn(move || { |
| 183 | thread::sleep(Duration::from_millis(200)); | |
| 179 | thread::sleep(Duration::from_millis(100)); | |
| 184 | 180 | unsafe { |
| 185 | 181 | assert_eq!( |
| 186 | 182 | libc::syscall( |
| ... | ... | @@ -195,7 +191,7 @@ fn wait_wake_bitset() { |
| 195 | 191 | 0, // Didn't match any thread. |
| 196 | 192 | ); |
| 197 | 193 | } |
| 198 | thread::sleep(Duration::from_millis(200)); | |
| 194 | thread::sleep(Duration::from_millis(100)); | |
| 199 | 195 | unsafe { |
| 200 | 196 | assert_eq!( |
| 201 | 197 | libc::syscall( |
| ... | ... | @@ -212,6 +208,8 @@ fn wait_wake_bitset() { |
| 212 | 208 | } |
| 213 | 209 | }); |
| 214 | 210 | |
| 211 | let start = Instant::now(); | |
| 212 | ||
| 215 | 213 | unsafe { |
| 216 | 214 | assert_eq!( |
| 217 | 215 | libc::syscall( |
| ... | ... | @@ -227,7 +225,7 @@ fn wait_wake_bitset() { |
| 227 | 225 | ); |
| 228 | 226 | } |
| 229 | 227 | |
| 230 | assert!((400..1000).contains(&start.elapsed().as_millis())); | |
| 228 | assert!((200..1000).contains(&start.elapsed().as_millis())); | |
| 231 | 229 | t.join().unwrap(); |
| 232 | 230 | } |
| 233 | 231 |
src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs+64-34| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | //@only-target: linux android illumos |
| 2 | 2 | // test_epoll_block_then_unblock and test_epoll_race depend on a deterministic schedule. |
| 3 | 3 | //@compile-flags: -Zmiri-deterministic-concurrency |
| 4 | //@revisions: edge_triggered level_triggered | |
| 4 | 5 | |
| 5 | 6 | use std::convert::TryInto; |
| 6 | 7 | use std::thread; |
| ... | ... | @@ -10,6 +11,10 @@ mod libc_utils; |
| 10 | 11 | use libc_utils::epoll::*; |
| 11 | 12 | use libc_utils::*; |
| 12 | 13 | |
| 14 | /// When the `edge_triggered` revision is active, this is EPOLLET, otherwise | |
| 15 | /// it's zero which means we perform level-triggered epolls. | |
| 16 | const EPOLLET_OR_ZERO: libc::c_int = if cfg!(edge_triggered) { EPOLLET } else { 0 }; | |
| 17 | ||
| 13 | 18 | // This is a set of testcases for blocking epoll. |
| 14 | 19 | |
| 15 | 20 | fn main() { |
| ... | ... | @@ -21,7 +26,9 @@ fn main() { |
| 21 | 26 | multiple_events_wake_multiple_threads(); |
| 22 | 27 | } |
| 23 | 28 | |
| 24 | // This test allows epoll_wait to block, then unblock without notification. | |
| 29 | // This test allows edge-triggered epoll_wait to block and then unblock | |
| 30 | // without notification because the timeout expired. | |
| 31 | // The level-triggered epoll_wait should not block. | |
| 25 | 32 | fn test_epoll_block_without_notification() { |
| 26 | 33 | // Create an epoll instance. |
| 27 | 34 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| ... | ... | @@ -31,16 +38,24 @@ fn test_epoll_block_without_notification() { |
| 31 | 38 | let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap(); |
| 32 | 39 | |
| 33 | 40 | // Register eventfd with epoll. |
| 34 | epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 41 | epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 35 | 42 | |
| 36 | 43 | // epoll_wait to clear notification. |
| 37 | check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLOUT, data: fd }], 0); | |
| 38 | ||
| 39 | // This epoll wait blocks, and timeout without notification. | |
| 40 | check_epoll_wait::<1>(epfd, &[], 5); | |
| 44 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fd }], -1); | |
| 45 | ||
| 46 | if cfg!(edge_triggered) { | |
| 47 | // This epoll wait blocks, and timeout without notification. | |
| 48 | check_epoll_wait(epfd, &[], 5); | |
| 49 | } else { | |
| 50 | // In level-triggered mode we should receive the same events | |
| 51 | // as before without timing out. | |
| 52 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fd }], -1); | |
| 53 | } | |
| 41 | 54 | } |
| 42 | 55 | |
| 43 | // This test triggers notification and unblocks the epoll_wait before timeout. | |
| 56 | // This test triggers notification and unblocks the edge-triggered epoll_wait | |
| 57 | // before the timeout exceeds. | |
| 58 | // The level-triggered epoll_wait should not block. | |
| 44 | 59 | fn test_epoll_block_then_unblock() { |
| 45 | 60 | // Create an epoll instance. |
| 46 | 61 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| ... | ... | @@ -50,21 +65,33 @@ fn test_epoll_block_then_unblock() { |
| 50 | 65 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); |
| 51 | 66 | |
| 52 | 67 | // Register one side of the socketpair with epoll. |
| 53 | epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 68 | epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 54 | 69 | |
| 55 | 70 | // epoll_wait to clear notification. |
| 56 | check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLOUT, data: fds[0] }], 0); | |
| 71 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], -1); | |
| 57 | 72 | |
| 58 | // epoll_wait before triggering notification so it will block then get unblocked before timeout. | |
| 59 | 73 | let thread1 = thread::spawn(move || { |
| 60 | 74 | thread::yield_now(); |
| 75 | // Due to deterministic concurrency, we'll only get here when the other thread blocks. | |
| 61 | 76 | write_all(fds[1], b"abcde").unwrap(); |
| 62 | 77 | }); |
| 63 | check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLIN | libc::EPOLLOUT, data: fds[0] }], 10); | |
| 78 | ||
| 79 | if cfg!(edge_triggered) { | |
| 80 | // Edge-triggered epoll will block until the write succeeds and the buffer | |
| 81 | // becomes readable. This is because we already read the writable edge | |
| 82 | // before so at the time of calling `epoll_wait` there is no active readiness. | |
| 83 | check_epoll_wait(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }], 10); | |
| 84 | } else { | |
| 85 | // Level-triggered epoll won't wait for the write to succeed because | |
| 86 | // _some_ readiness is already set (in this case the EPOLLOUT). | |
| 87 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], -1); | |
| 88 | } | |
| 89 | ||
| 64 | 90 | thread1.join().unwrap(); |
| 65 | 91 | } |
| 66 | 92 | |
| 67 | // This test triggers a notification after epoll_wait times out. | |
| 93 | // This test triggers a notification after epoll_wait times out in edge-triggered mode. | |
| 94 | // In level-triggered the epoll_wait should not time out. | |
| 68 | 95 | fn test_notification_after_timeout() { |
| 69 | 96 | // Create an epoll instance. |
| 70 | 97 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| ... | ... | @@ -74,19 +101,26 @@ fn test_notification_after_timeout() { |
| 74 | 101 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); |
| 75 | 102 | |
| 76 | 103 | // Register one side of the socketpair with epoll. |
| 77 | epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 104 | epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 78 | 105 | |
| 79 | 106 | // epoll_wait to clear notification. |
| 80 | check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLOUT, data: fds[0] }], 0); | |
| 81 | ||
| 82 | // epoll_wait timeouts without notification. | |
| 83 | check_epoll_wait::<1>(epfd, &[], 10); | |
| 107 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], -1); | |
| 108 | ||
| 109 | if cfg!(edge_triggered) { | |
| 110 | // Edge-triggered epoll wait times out without notification because | |
| 111 | // we just processed the edge. | |
| 112 | check_epoll_wait(epfd, &[], 10); | |
| 113 | } else { | |
| 114 | // Level-triggered epoll just returns the same events as before | |
| 115 | // without blocking. | |
| 116 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], -1); | |
| 117 | } | |
| 84 | 118 | |
| 85 | 119 | // Trigger epoll notification after timeout. |
| 86 | 120 | write_all(fds[1], b"abcde").unwrap(); |
| 87 | 121 | |
| 88 | 122 | // Check the result of the notification. |
| 89 | check_epoll_wait::<1>(epfd, &[Ev { events: libc::EPOLLIN | libc::EPOLLOUT, data: fds[0] }], 10); | |
| 123 | check_epoll_wait(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }], 10); | |
| 90 | 124 | } |
| 91 | 125 | |
| 92 | 126 | // This test shows a data race before epoll had vector clocks added. |
| ... | ... | @@ -99,7 +133,7 @@ fn test_epoll_race() { |
| 99 | 133 | let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap(); |
| 100 | 134 | |
| 101 | 135 | // Register eventfd with the epoll instance. |
| 102 | epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLET).unwrap(); | |
| 136 | epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLET_OR_ZERO).unwrap(); | |
| 103 | 137 | |
| 104 | 138 | static mut VAL: u8 = 0; |
| 105 | 139 | let thread1 = thread::spawn(move || { |
| ... | ... | @@ -110,7 +144,7 @@ fn test_epoll_race() { |
| 110 | 144 | }); |
| 111 | 145 | thread::yield_now(); |
| 112 | 146 | // epoll_wait for EPOLLIN. |
| 113 | check_epoll_wait::<8>(epfd, &[Ev { events: libc::EPOLLIN, data: fd }], -1); | |
| 147 | check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: fd }], -1); | |
| 114 | 148 | // Read from the static mut variable. |
| 115 | 149 | assert_eq!(unsafe { VAL }, 1); |
| 116 | 150 | thread1.join().unwrap(); |
| ... | ... | @@ -131,18 +165,14 @@ fn wakeup_on_new_interest() { |
| 131 | 165 | |
| 132 | 166 | // Block a thread on the epoll instance. |
| 133 | 167 | let t = std::thread::spawn(move || { |
| 134 | check_epoll_wait::<8>( | |
| 135 | epfd, | |
| 136 | &[Ev { events: libc::EPOLLIN | libc::EPOLLOUT, data: fds[1] }], | |
| 137 | -1, | |
| 138 | ); | |
| 168 | check_epoll_wait(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[1] }], -1); | |
| 139 | 169 | }); |
| 140 | 170 | // Ensure the thread is blocked. |
| 141 | 171 | std::thread::yield_now(); |
| 142 | 172 | |
| 143 | // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP | |
| 144 | epoll_ctl_add(epfd, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP) | |
| 145 | .unwrap(); | |
| 173 | // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLRDHUP (and EPOLLET if we're in the | |
| 174 | // `edge_triggered` revision). | |
| 175 | epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET_OR_ZERO).unwrap(); | |
| 146 | 176 | |
| 147 | 177 | // This should wake up the thread. |
| 148 | 178 | t.join().unwrap(); |
| ... | ... | @@ -161,13 +191,12 @@ fn multiple_events_wake_multiple_threads() { |
| 161 | 191 | let fd2 = errno_result(unsafe { libc::dup(fd1) }).unwrap(); |
| 162 | 192 | |
| 163 | 193 | // Register both with epoll. |
| 164 | epoll_ctl_add(epfd, fd1, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 165 | epoll_ctl_add(epfd, fd2, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 194 | epoll_ctl_add(epfd, fd1, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 195 | epoll_ctl_add(epfd, fd2, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 166 | 196 | |
| 167 | 197 | // Consume the initial events. |
| 168 | let expected = | |
| 169 | [Ev { events: libc::EPOLLOUT, data: fd1 }, Ev { events: libc::EPOLLOUT, data: fd2 }]; | |
| 170 | check_epoll_wait::<8>(epfd, &expected, -1); | |
| 198 | let expected = [Ev { events: EPOLLOUT, data: fd1 }, Ev { events: EPOLLOUT, data: fd2 }]; | |
| 199 | check_epoll_wait(epfd, &expected, -1); | |
| 171 | 200 | |
| 172 | 201 | // Block two threads on the epoll, both wanting to get just one event. |
| 173 | 202 | let t1 = thread::spawn(move || { |
| ... | ... | @@ -191,6 +220,7 @@ fn multiple_events_wake_multiple_threads() { |
| 191 | 220 | // Both threads should have been woken up so that both events can be consumed. |
| 192 | 221 | let e1 = t1.join().unwrap(); |
| 193 | 222 | let e2 = t2.join().unwrap(); |
| 194 | // Ensure that across the two threads we got both events. | |
| 223 | ||
| 224 | // In both modes we should get both events across the two threads. | |
| 195 | 225 | assert!(expected == [e1, e2] || expected == [e2, e1]); |
| 196 | 226 | } |
src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs+229-185| ... | ... | @@ -1,12 +1,15 @@ |
| 1 | 1 | //@only-target: linux android illumos |
| 2 | ||
| 3 | use std::convert::TryInto; | |
| 2 | //@revisions: edge_triggered level_triggered | |
| 4 | 3 | |
| 5 | 4 | #[path = "../../utils/libc.rs"] |
| 6 | 5 | mod libc_utils; |
| 7 | 6 | use libc_utils::epoll::*; |
| 8 | 7 | use libc_utils::*; |
| 9 | 8 | |
| 9 | /// When the `edge_triggered` revision is active, this is EPOLLET, otherwise | |
| 10 | /// it's zero which means we perform level-triggered epolls. | |
| 11 | const EPOLLET_OR_ZERO: libc::c_int = if cfg!(edge_triggered) { EPOLLET } else { 0 }; | |
| 12 | ||
| 10 | 13 | fn main() { |
| 11 | 14 | test_epoll_socketpair(); |
| 12 | 15 | test_epoll_socketpair_both_sides(); |
| ... | ... | @@ -27,27 +30,13 @@ fn main() { |
| 27 | 30 | test_ready_list_fetching_logic(); |
| 28 | 31 | test_epoll_ctl_epfd_equal_fd(); |
| 29 | 32 | test_epoll_ctl_notification(); |
| 33 | test_epoll_mixed_modes(); | |
| 34 | test_epoll_registered_mode_switch(); | |
| 30 | 35 | test_issue_3858(); |
| 31 | 36 | test_issue_4374(); |
| 32 | 37 | test_issue_4374_reads(); |
| 33 | 38 | } |
| 34 | 39 | |
| 35 | #[track_caller] | |
| 36 | fn check_epoll_wait<const N: usize>(epfd: i32, expected_notifications: &[(u32, u64)]) { | |
| 37 | let epoll_event = libc::epoll_event { events: 0, u64: 0 }; | |
| 38 | let mut array: [libc::epoll_event; N] = [epoll_event; N]; | |
| 39 | let maxsize = N; | |
| 40 | let array_ptr = array.as_mut_ptr(); | |
| 41 | let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), 0) }; | |
| 42 | if res < 0 { | |
| 43 | panic!("epoll_wait failed: {}", std::io::Error::last_os_error()); | |
| 44 | } | |
| 45 | let got_notifications = | |
| 46 | unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) }; | |
| 47 | let got_notifications = got_notifications.iter().map(|e| (e.events, e.u64)).collect::<Vec<_>>(); | |
| 48 | assert_eq!(got_notifications, expected_notifications, "got wrong notifications"); | |
| 49 | } | |
| 50 | ||
| 51 | 40 | fn test_epoll_socketpair() { |
| 52 | 41 | // Create an epoll instance. |
| 53 | 42 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| ... | ... | @@ -59,14 +48,22 @@ fn test_epoll_socketpair() { |
| 59 | 48 | // Write to fds[0] |
| 60 | 49 | write_all(fds[0], b"abcde").unwrap(); |
| 61 | 50 | |
| 62 | // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP | |
| 63 | epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET | EPOLLRDHUP).unwrap(); | |
| 51 | // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLRDHUP (and EPOLLET if we're | |
| 52 | // in the `edge_triggered` revision). | |
| 53 | epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET_OR_ZERO).unwrap(); | |
| 64 | 54 | |
| 65 | 55 | // Check result from epoll_wait. |
| 66 | check_epoll_wait_noblock::<8>(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]); | |
| 67 | ||
| 68 | // Check that this is indeed using "ET" (edge-trigger) semantics: a second epoll should return nothing. | |
| 69 | check_epoll_wait_noblock::<8>(epfd, &[]); | |
| 56 | check_epoll_wait_noblock(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]); | |
| 57 | ||
| 58 | if cfg!(edge_triggered) { | |
| 59 | // Check that this is indeed using "ET" (edge-trigger) semantics: a second wait | |
| 60 | // should return nothing. | |
| 61 | check_epoll_wait_noblock(epfd, &[]); | |
| 62 | } else { | |
| 63 | // Check that this is indeed using "LT" (level-trigger) semantics: a second wait | |
| 64 | // should return the same readiness. | |
| 65 | check_epoll_wait_noblock(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]); | |
| 66 | } | |
| 70 | 67 | |
| 71 | 68 | // Write some more to fds[0]. |
| 72 | 69 | write_all(fds[0], b"abcde").unwrap(); |
| ... | ... | @@ -74,14 +71,14 @@ fn test_epoll_socketpair() { |
| 74 | 71 | // This did not change the readiness of fds[1], so we should get no event. |
| 75 | 72 | // However, Linux seems to always deliver spurious events to the peer on each write, |
| 76 | 73 | // so we match that. |
| 77 | check_epoll_wait_noblock::<8>(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]); | |
| 74 | check_epoll_wait_noblock(epfd, &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT }]); | |
| 78 | 75 | |
| 79 | 76 | // Close the peer socketpair. |
| 80 | 77 | errno_check(unsafe { libc::close(fds[0]) }); |
| 81 | 78 | |
| 82 | 79 | // Check result from epoll_wait. We expect to get a read, write, HUP notification from the close |
| 83 | 80 | // since closing an FD always unblocks reads and writes on its peer. |
| 84 | check_epoll_wait_noblock::<8>( | |
| 81 | check_epoll_wait_noblock( | |
| 85 | 82 | epfd, |
| 86 | 83 | &[Ev { data: fds[1], events: EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLRDHUP }], |
| 87 | 84 | ); |
| ... | ... | @@ -98,17 +95,19 @@ fn test_epoll_ctl_mod() { |
| 98 | 95 | let mut fds = [-1, -1]; |
| 99 | 96 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); |
| 100 | 97 | |
| 101 | // Register fds[1] with EPOLLIN|EPOLLET, and data of "0". | |
| 102 | epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], Ev { events: EPOLLIN | EPOLLET, data: 0 }).unwrap(); | |
| 98 | // Register fds[1] with EPOLLIN (and EPOLLET if we're in the `edge_triggered` revision), and data of "0". | |
| 99 | epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], Ev { events: EPOLLIN | EPOLLET_OR_ZERO, data: 0 }) | |
| 100 | .unwrap(); | |
| 103 | 101 | |
| 104 | 102 | // Check result from epoll_wait. No notification would be returned. |
| 105 | check_epoll_wait_noblock::<8>(epfd, &[]); | |
| 103 | check_epoll_wait_noblock(epfd, &[]); | |
| 106 | 104 | |
| 107 | 105 | // Use EPOLL_CTL_MOD to change to EPOLLOUT flag and data. |
| 108 | epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET, data: 1 }).unwrap(); | |
| 106 | epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET_OR_ZERO, data: 1 }) | |
| 107 | .unwrap(); | |
| 109 | 108 | |
| 110 | 109 | // Check result from epoll_wait. EPOLLOUT notification and new data is expected. |
| 111 | check_epoll_wait_noblock::<8>(epfd, &[Ev { events: EPOLLOUT, data: 1 }]); | |
| 110 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: 1 }]); | |
| 112 | 111 | |
| 113 | 112 | // Write to fds[1] and read from fds[0] to make the notification ready again |
| 114 | 113 | // (relying on there always being an event when the buffer gets emptied). |
| ... | ... | @@ -116,16 +115,18 @@ fn test_epoll_ctl_mod() { |
| 116 | 115 | read_exact_array::<3>(fds[0]).unwrap(); |
| 117 | 116 | |
| 118 | 117 | // Now that the event is already ready, change the "data" value. |
| 119 | epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET, data: 2 }).unwrap(); | |
| 118 | epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET_OR_ZERO, data: 2 }) | |
| 119 | .unwrap(); | |
| 120 | 120 | |
| 121 | 121 | // Receive event, with latest data value. |
| 122 | check_epoll_wait_noblock::<8>(epfd, &[Ev { events: EPOLLOUT, data: 2 }]); | |
| 122 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: 2 }]); | |
| 123 | 123 | |
| 124 | 124 | // Do another update that changes nothing. |
| 125 | epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET, data: 2 }).unwrap(); | |
| 125 | epoll_ctl(epfd, EPOLL_CTL_MOD, fds[1], Ev { events: EPOLLOUT | EPOLLET_OR_ZERO, data: 2 }) | |
| 126 | .unwrap(); | |
| 126 | 127 | |
| 127 | 128 | // This re-triggers the event, even if it's the same flags as before. |
| 128 | check_epoll_wait_noblock::<8>(epfd, &[Ev { events: EPOLLOUT, data: 2 }]); | |
| 129 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: 2 }]); | |
| 129 | 130 | } |
| 130 | 131 | |
| 131 | 132 | fn test_epoll_ctl_del() { |
| ... | ... | @@ -139,18 +140,18 @@ fn test_epoll_ctl_del() { |
| 139 | 140 | // Write to fds[0] |
| 140 | 141 | libc_utils::write_all(fds[0], b"abcde").unwrap(); |
| 141 | 142 | |
| 142 | // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLET | |
| 143 | // Register fds[1] with EPOLLIN|EPOLLOUT (and EPOLLET if we're in the `edge_triggered` revision). | |
| 143 | 144 | let mut ev = libc::epoll_event { |
| 144 | events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as u32, | |
| 145 | events: (EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO) as u32, | |
| 145 | 146 | u64: u64::try_from(fds[1]).unwrap(), |
| 146 | 147 | }; |
| 147 | 148 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; |
| 148 | 149 | assert_eq!(res, 0); |
| 149 | 150 | |
| 150 | 151 | // Test EPOLL_CTL_DEL. |
| 151 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_DEL, fds[1], &mut ev) }; | |
| 152 | let res = unsafe { libc::epoll_ctl(epfd, EPOLL_CTL_DEL, fds[1], &mut ev) }; | |
| 152 | 153 | assert_eq!(res, 0); |
| 153 | check_epoll_wait::<8>(epfd, &[]); | |
| 154 | check_epoll_wait_noblock(epfd, &[]); | |
| 154 | 155 | } |
| 155 | 156 | |
| 156 | 157 | // This test is for one fd registered under two different epoll instance. |
| ... | ... | @@ -168,15 +169,14 @@ fn test_two_epoll_instance() { |
| 168 | 169 | // Write to the socketpair. |
| 169 | 170 | libc_utils::write_all(fds[0], b"abcde").unwrap(); |
| 170 | 171 | |
| 171 | // Register one side of the socketpair with EPOLLIN | EPOLLOUT | EPOLLET. | |
| 172 | epoll_ctl_add(epfd1, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 173 | epoll_ctl_add(epfd2, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 172 | // Register one side of the socketpair with EPOLLIN | EPOLLOUT (and EPOLLET | |
| 173 | // if we're in the `edge_triggered` revision). | |
| 174 | epoll_ctl_add(epfd1, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 175 | epoll_ctl_add(epfd2, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 174 | 176 | |
| 175 | 177 | // Notification should be received from both instance of epoll. |
| 176 | let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); | |
| 177 | let expected_value = u64::try_from(fds[1]).unwrap(); | |
| 178 | check_epoll_wait::<8>(epfd1, &[(expected_event, expected_value)]); | |
| 179 | check_epoll_wait::<8>(epfd2, &[(expected_event, expected_value)]); | |
| 178 | check_epoll_wait_noblock(epfd1, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[1] }]); | |
| 179 | check_epoll_wait_noblock(epfd2, &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[1] }]); | |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | 182 | // This test is for two same file description registered under the same epoll instance through dup. |
| ... | ... | @@ -194,24 +194,19 @@ fn test_two_same_fd_in_same_epoll_instance() { |
| 194 | 194 | assert_ne!(newfd, -1); |
| 195 | 195 | |
| 196 | 196 | // Register both fd to the same epoll instance. |
| 197 | let mut ev = libc::epoll_event { | |
| 198 | events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(), | |
| 199 | u64: 5u64, | |
| 200 | }; | |
| 201 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; | |
| 202 | assert_eq!(res, 0); | |
| 203 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, newfd, &mut ev) }; | |
| 204 | assert_eq!(res, 0); | |
| 197 | epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 198 | epoll_ctl_add(epfd, newfd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 205 | 199 | |
| 206 | 200 | // Write to the socketpair. |
| 207 | 201 | libc_utils::write_all(fds[0], b"abcde").unwrap(); |
| 208 | 202 | |
| 209 | 203 | // Two notification should be received. |
| 210 | let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); | |
| 211 | let expected_value = 5u64; | |
| 212 | check_epoll_wait::<8>( | |
| 204 | check_epoll_wait_noblock( | |
| 213 | 205 | epfd, |
| 214 | &[(expected_event, expected_value), (expected_event, expected_value)], | |
| 206 | &[ | |
| 207 | Ev { events: EPOLLIN | EPOLLOUT, data: fds[1] }, | |
| 208 | Ev { events: EPOLLIN | EPOLLOUT, data: newfd }, | |
| 209 | ], | |
| 215 | 210 | ); |
| 216 | 211 | } |
| 217 | 212 | |
| ... | ... | @@ -226,20 +221,19 @@ fn test_epoll_eventfd() { |
| 226 | 221 | // Create an epoll instance. |
| 227 | 222 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| 228 | 223 | |
| 229 | // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET | |
| 230 | epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 224 | // Register eventfd with EPOLLIN | EPOLLOUT (and EPOLLET if we're in the `edge_triggered` | |
| 225 | // revision). | |
| 226 | epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 231 | 227 | |
| 232 | 228 | // Check result from epoll_wait. |
| 233 | let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); | |
| 234 | let expected_value = u64::try_from(fd).unwrap(); | |
| 235 | check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); | |
| 229 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fd }]); | |
| 236 | 230 | |
| 237 | 231 | // Write 0 to the eventfd. |
| 238 | 232 | libc_utils::write_all(fd, &0_u64.to_ne_bytes()).unwrap(); |
| 239 | 233 | |
| 240 | 234 | // This does not change the status, so we should get no event. |
| 241 | 235 | // However, Linux performs a spurious wakeup. |
| 242 | check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); | |
| 236 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fd }]); | |
| 243 | 237 | |
| 244 | 238 | // Read from the eventfd. |
| 245 | 239 | libc_utils::read_exact_array::<8>(fd).unwrap(); |
| ... | ... | @@ -247,15 +241,13 @@ fn test_epoll_eventfd() { |
| 247 | 241 | // This consumes the event, so the read status is gone. However, deactivation |
| 248 | 242 | // does not trigger an event. |
| 249 | 243 | // Still, we see a spurious wakeup. |
| 250 | let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 251 | check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); | |
| 244 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fd }]); | |
| 252 | 245 | |
| 253 | 246 | // Write the maximum possible value. |
| 254 | 247 | libc_utils::write_all(fd, &(u64::MAX - 1).to_ne_bytes()).unwrap(); |
| 255 | 248 | |
| 256 | 249 | // This reactivates reads, therefore triggering an event. Writing is no longer possible. |
| 257 | let expected_event = u32::try_from(libc::EPOLLIN).unwrap(); | |
| 258 | check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); | |
| 250 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN, data: fd }]); | |
| 259 | 251 | } |
| 260 | 252 | |
| 261 | 253 | // When read/write happened on one side of the socketpair, only the other side will be notified. |
| ... | ... | @@ -268,8 +260,8 @@ fn test_epoll_socketpair_both_sides() { |
| 268 | 260 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); |
| 269 | 261 | |
| 270 | 262 | // Register both fd to the same epoll instance. |
| 271 | epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 272 | epoll_ctl_add(epfd, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 263 | epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 264 | epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 273 | 265 | |
| 274 | 266 | // Write to fds[1]. |
| 275 | 267 | // (We do the write after the register here, unlike in `test_epoll_socketpair`, to ensure |
| ... | ... | @@ -277,23 +269,28 @@ fn test_epoll_socketpair_both_sides() { |
| 277 | 269 | libc_utils::write_all(fds[1], b"abcde").unwrap(); |
| 278 | 270 | |
| 279 | 271 | // Two notification should be received. |
| 280 | let expected_event0 = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); | |
| 281 | let expected_value0 = fds[0] as u64; | |
| 282 | let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 283 | let expected_value1 = fds[1] as u64; | |
| 284 | check_epoll_wait::<8>( | |
| 272 | check_epoll_wait_noblock( | |
| 285 | 273 | epfd, |
| 286 | &[(expected_event0, expected_value0), (expected_event1, expected_value1)], | |
| 274 | &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }], | |
| 287 | 275 | ); |
| 288 | 276 | |
| 289 | 277 | // Read from fds[0]. |
| 290 | 278 | let buf = libc_utils::read_exact_array::<5>(fds[0]).unwrap(); |
| 291 | 279 | assert_eq!(buf, *b"abcde"); |
| 292 | 280 | |
| 293 | // The state of fds[1] does not change (was writable, is writable). | |
| 294 | // However, we force a spurious wakeup as the read buffer just got emptied. | |
| 295 | // fds[0] lost its readability, but becoming less active is not considered an "edge". | |
| 296 | check_epoll_wait::<8>(epfd, &[(expected_event1, expected_value1)]); | |
| 281 | if cfg!(edge_triggered) { | |
| 282 | // The state of fds[1] does not change (was writable, is writable). | |
| 283 | // However, we force a spurious wakeup as the read buffer just got emptied. | |
| 284 | // fds[0] lost its readability, but becoming less active is not considered an "edge". | |
| 285 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[1] }]) | |
| 286 | } else { | |
| 287 | // With level-triggered epoll, only the readable readiness for fds[0] should | |
| 288 | // no longer be reported. The rest stays the same. | |
| 289 | check_epoll_wait_noblock( | |
| 290 | epfd, | |
| 291 | &[Ev { events: EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }], | |
| 292 | ); | |
| 293 | } | |
| 297 | 294 | } |
| 298 | 295 | |
| 299 | 296 | // When file description is fully closed, epoll_wait should not provide any notification for |
| ... | ... | @@ -306,8 +303,8 @@ fn test_closed_fd() { |
| 306 | 303 | let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; |
| 307 | 304 | let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap(); |
| 308 | 305 | |
| 309 | // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET | |
| 310 | epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 306 | // Register eventfd with EPOLLIN | EPOLLOUT (and EPOLLET if we're in the `edge_triggered` revision). | |
| 307 | epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 311 | 308 | |
| 312 | 309 | // Write to the eventfd instance. |
| 313 | 310 | libc_utils::write_all(fd, &1_u64.to_ne_bytes()).unwrap(); |
| ... | ... | @@ -316,7 +313,7 @@ fn test_closed_fd() { |
| 316 | 313 | errno_check(unsafe { libc::close(fd) }); |
| 317 | 314 | |
| 318 | 315 | // No notification should be provided because the file description is closed. |
| 319 | check_epoll_wait::<8>(epfd, &[]); | |
| 316 | check_epoll_wait_noblock(epfd, &[]); | |
| 320 | 317 | } |
| 321 | 318 | |
| 322 | 319 | // When a certain file descriptor registered with epoll is closed, but the underlying file description |
| ... | ... | @@ -336,16 +333,14 @@ fn test_not_fully_closed_fd() { |
| 336 | 333 | // Dup the fd. |
| 337 | 334 | let newfd = errno_result(unsafe { libc::dup(fd) }).unwrap(); |
| 338 | 335 | |
| 339 | // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET | |
| 340 | epoll_ctl_add(epfd, fd, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 336 | // Register eventfd with EPOLLIN | EPOLLOUT (and EPOLLET if we're in the `edge_triggered` revision). | |
| 337 | epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 341 | 338 | |
| 342 | 339 | // Close the original fd that being used to register with epoll. |
| 343 | 340 | errno_check(unsafe { libc::close(fd) }); |
| 344 | 341 | |
| 345 | 342 | // Notification should still be provided because the file description is not closed. |
| 346 | let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 347 | let expected_value = fd as u64; | |
| 348 | check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)]); | |
| 343 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fd }]); | |
| 349 | 344 | |
| 350 | 345 | // Write to the eventfd instance to produce notification. |
| 351 | 346 | libc_utils::write_all(newfd, &1_u64.to_ne_bytes()).unwrap(); |
| ... | ... | @@ -354,7 +349,7 @@ fn test_not_fully_closed_fd() { |
| 354 | 349 | errno_check(unsafe { libc::close(newfd) }); |
| 355 | 350 | |
| 356 | 351 | // No notification should be provided. |
| 357 | check_epoll_wait::<1>(epfd, &[]); | |
| 352 | check_epoll_wait_noblock(epfd, &[]); | |
| 358 | 353 | } |
| 359 | 354 | |
| 360 | 355 | // Each time a notification is provided, it should reflect the file description's readiness |
| ... | ... | @@ -370,13 +365,8 @@ fn test_event_overwrite() { |
| 370 | 365 | // Create an epoll instance. |
| 371 | 366 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| 372 | 367 | |
| 373 | // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET | |
| 374 | let mut ev = libc::epoll_event { | |
| 375 | events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(), | |
| 376 | u64: u64::try_from(fd).unwrap(), | |
| 377 | }; | |
| 378 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; | |
| 379 | assert_eq!(res, 0); | |
| 368 | // Register eventfd with EPOLLIN | EPOLLOUT (and EPOLLET if we're in the `edge_triggered` revision). | |
| 369 | epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 380 | 370 | |
| 381 | 371 | // Read from the eventfd instance. |
| 382 | 372 | let mut buf: [u8; 8] = [0; 8]; |
| ... | ... | @@ -384,9 +374,7 @@ fn test_event_overwrite() { |
| 384 | 374 | assert_eq!(res, 8); |
| 385 | 375 | |
| 386 | 376 | // Check result from epoll_wait. |
| 387 | let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 388 | let expected_value = u64::try_from(fd).unwrap(); | |
| 389 | check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); | |
| 377 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fd }]); | |
| 390 | 378 | } |
| 391 | 379 | |
| 392 | 380 | // An epoll notification will be provided for every succesful read in a socketpair. |
| ... | ... | @@ -400,53 +388,58 @@ fn test_socketpair_read() { |
| 400 | 388 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); |
| 401 | 389 | |
| 402 | 390 | // Register both fd to the same epoll instance. |
| 403 | let mut ev = libc::epoll_event { | |
| 404 | events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(), | |
| 405 | u64: fds[0] as u64, | |
| 406 | }; | |
| 407 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; | |
| 408 | assert_eq!(res, 0); | |
| 409 | let mut ev = libc::epoll_event { | |
| 410 | events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(), | |
| 411 | u64: fds[1] as u64, | |
| 412 | }; | |
| 413 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; | |
| 414 | assert_eq!(res, 0); | |
| 391 | epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 392 | epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 415 | 393 | |
| 416 | 394 | // Write a bunch of data bytes to fds[1]. |
| 417 | 395 | let data = [42u8; 1024]; |
| 418 | 396 | libc_utils::write_all(fds[1], &data).unwrap(); |
| 419 | 397 | |
| 420 | 398 | // Two notification should be received. |
| 421 | let expected_event0 = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); | |
| 422 | let expected_value0 = fds[0] as u64; | |
| 423 | let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 424 | let expected_value1 = fds[1] as u64; | |
| 425 | check_epoll_wait::<8>( | |
| 399 | check_epoll_wait_noblock( | |
| 426 | 400 | epfd, |
| 427 | &[(expected_event0, expected_value0), (expected_event1, expected_value1)], | |
| 401 | &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }], | |
| 428 | 402 | ); |
| 429 | 403 | |
| 430 | 404 | // Read some of the data from fds[0]. |
| 431 | 405 | let mut buf = [0; 512]; |
| 432 | 406 | libc_utils::read_exact(fds[0], &mut buf).unwrap(); |
| 433 | ||
| 434 | // fds[1] did not change, it is still writable, so we get no event. | |
| 435 | let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 436 | let expected_value = fds[1] as u64; | |
| 437 | check_epoll_wait::<8>(epfd, &[]); | |
| 407 | if cfg!(edge_triggered) { | |
| 408 | // fds[1] did not change, it is still writable, so we get no event | |
| 409 | // in edge-triggered mode. | |
| 410 | check_epoll_wait_noblock(epfd, &[]); | |
| 411 | } else { | |
| 412 | // In level-triggered mode we expect the same events as before because | |
| 413 | // we didn't read everything in the buffer. | |
| 414 | check_epoll_wait_noblock( | |
| 415 | epfd, | |
| 416 | &[ | |
| 417 | Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }, | |
| 418 | Ev { events: EPOLLOUT, data: fds[1] }, | |
| 419 | ], | |
| 420 | ); | |
| 421 | } | |
| 438 | 422 | |
| 439 | 423 | // Read until the buffer is empty. |
| 440 | 424 | let rest = data.len() - buf.len(); |
| 441 | 425 | libc_utils::read_exact(fds[0], &mut buf[..rest]).unwrap(); |
| 442 | 426 | |
| 443 | // Now we get a notification that fds[1] can be written. This is spurious since it | |
| 444 | // could already be written before, but Linux seems to always emit a notification for | |
| 445 | // the writer when a read empties the buffer. | |
| 446 | check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); | |
| 427 | if cfg!(edge_triggered) { | |
| 428 | // Now we get a notification that fds[1] can be written. This is spurious since it | |
| 429 | // could already be written before, but Linux seems to always emit a notification for | |
| 430 | // the writer when a read empties the buffer. | |
| 431 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[1] }]); | |
| 432 | } else { | |
| 433 | // In level-triggered mode we expect the same events as before just without | |
| 434 | // the readable readiness of fds[0] because we now read everything. | |
| 435 | check_epoll_wait_noblock( | |
| 436 | epfd, | |
| 437 | &[Ev { events: EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }], | |
| 438 | ); | |
| 439 | } | |
| 447 | 440 | } |
| 448 | 441 | |
| 449 | // This is to test whether flag that we don't register won't trigger notification. | |
| 442 | // This is to test whether a flag that we don't register won't trigger notification. | |
| 450 | 443 | fn test_no_notification_for_unregister_flag() { |
| 451 | 444 | // Create an epoll instance. |
| 452 | 445 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| ... | ... | @@ -455,22 +448,15 @@ fn test_no_notification_for_unregister_flag() { |
| 455 | 448 | let mut fds = [-1, -1]; |
| 456 | 449 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); |
| 457 | 450 | |
| 458 | // Register fds[0] with EPOLLOUT|EPOLLET. | |
| 459 | let mut ev = libc::epoll_event { | |
| 460 | events: (libc::EPOLLOUT | libc::EPOLLET).cast_unsigned(), | |
| 461 | u64: u64::try_from(fds[0]).unwrap(), | |
| 462 | }; | |
| 463 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; | |
| 464 | assert_eq!(res, 0); | |
| 451 | // Register fds[0] with EPOLLOUT (and EPOLLET when we're in the `edge_triggered` revision). | |
| 452 | epoll_ctl_add(epfd, fds[0], EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 465 | 453 | |
| 466 | 454 | // Write to fds[1]. |
| 467 | 455 | libc_utils::write_all(fds[1], b"abcde").unwrap(); |
| 468 | 456 | |
| 469 | 457 | // Check result from epoll_wait. Since we didn't register EPOLLIN flag, the notification won't |
| 470 | 458 | // contain EPOLLIN even though fds[0] is now readable. |
| 471 | let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 472 | let expected_value = u64::try_from(fds[0]).unwrap(); | |
| 473 | check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); | |
| 459 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }]); | |
| 474 | 460 | } |
| 475 | 461 | |
| 476 | 462 | fn test_epoll_wait_maxevent_zero() { |
| ... | ... | @@ -500,17 +486,15 @@ fn test_socketpair_epollerr() { |
| 500 | 486 | // EPOLLERR will be triggered if we close peer fd that still has data in its read buffer. |
| 501 | 487 | errno_check(unsafe { libc::close(fds[1]) }); |
| 502 | 488 | |
| 503 | // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP | |
| 504 | epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP) | |
| 505 | .unwrap(); | |
| 489 | // Register fds[1] with EPOLLIN|EPOLLOUT|EPOLLRDHUP (and EPOLLET when we're in the | |
| 490 | // `edge_triggered` revision). | |
| 491 | epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET_OR_ZERO).unwrap(); | |
| 506 | 492 | |
| 507 | 493 | // Check result from epoll_wait. |
| 508 | let expected_event = u32::try_from( | |
| 509 | libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLHUP | libc::EPOLLRDHUP | libc::EPOLLERR, | |
| 510 | ) | |
| 511 | .unwrap(); | |
| 512 | let expected_value = u64::try_from(fds[0]).unwrap(); | |
| 513 | check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); | |
| 494 | check_epoll_wait_noblock( | |
| 495 | epfd, | |
| 496 | &[Ev { events: EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLRDHUP | EPOLLERR, data: fds[0] }], | |
| 497 | ); | |
| 514 | 498 | } |
| 515 | 499 | |
| 516 | 500 | // This is a test for https://github.com/rust-lang/miri/issues/3812, |
| ... | ... | @@ -524,18 +508,24 @@ fn test_epoll_lost_events() { |
| 524 | 508 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); |
| 525 | 509 | |
| 526 | 510 | // Register both fd to the same epoll instance. |
| 527 | epoll_ctl_add(epfd, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 528 | epoll_ctl_add(epfd, fds[1], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 511 | epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 512 | epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 529 | 513 | |
| 530 | 514 | // Two notification should be received. But we only provide buffer for one event. |
| 531 | let expected_event0 = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 532 | let expected_value0 = fds[0] as u64; | |
| 533 | check_epoll_wait::<1>(epfd, &[(expected_event0, expected_value0)]); | |
| 534 | ||
| 535 | // Previous event should be returned for the second epoll_wait. | |
| 536 | let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 537 | let expected_value1 = fds[1] as u64; | |
| 538 | check_epoll_wait::<1>(epfd, &[(expected_event1, expected_value1)]); | |
| 515 | check_epoll_wait_partial(epfd, &[Ev { events: EPOLLOUT, data: fds[0] }], 1, 0); | |
| 516 | ||
| 517 | if cfg!(edge_triggered) { | |
| 518 | // Previous event should be returned for the second epoll_wait but because we're | |
| 519 | // edge-triggered the first event should no longer be returned. | |
| 520 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[1] }]); | |
| 521 | } else { | |
| 522 | // Both events should be returned in level-triggered mode when | |
| 523 | // we provide a big enough buffer. | |
| 524 | check_epoll_wait_noblock( | |
| 525 | epfd, | |
| 526 | &[Ev { events: EPOLLOUT, data: fds[1] }, Ev { events: EPOLLOUT, data: fds[0] }], | |
| 527 | ); | |
| 528 | } | |
| 539 | 529 | } |
| 540 | 530 | |
| 541 | 531 | // This is testing if closing an fd that is already in ready list will cause an empty entry in |
| ... | ... | @@ -551,16 +541,14 @@ fn test_ready_list_fetching_logic() { |
| 551 | 541 | let fd1 = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap(); |
| 552 | 542 | |
| 553 | 543 | // Register both fd to the same epoll instance. At this point, both of them are on the ready list. |
| 554 | epoll_ctl_add(epfd, fd0, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 555 | epoll_ctl_add(epfd, fd1, libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 544 | epoll_ctl_add(epfd, fd0, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 545 | epoll_ctl_add(epfd, fd1, EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 556 | 546 | |
| 557 | 547 | // Close fd0 so the first entry in the ready list will be empty. |
| 558 | 548 | errno_check(unsafe { libc::close(fd0) }); |
| 559 | 549 | |
| 560 | 550 | // Notification for fd1 should be returned. |
| 561 | let expected_event1 = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 562 | let expected_value1 = fd1 as u64; | |
| 563 | check_epoll_wait::<1>(epfd, &[(expected_event1, expected_value1)]); | |
| 551 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fd1 }]); | |
| 564 | 552 | } |
| 565 | 553 | |
| 566 | 554 | // In epoll_ctl, if the value of epfd equals to fd, EFAULT should be returned. |
| ... | ... | @@ -570,7 +558,7 @@ fn test_epoll_ctl_epfd_equal_fd() { |
| 570 | 558 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| 571 | 559 | |
| 572 | 560 | let array_ptr = std::ptr::without_provenance_mut::<libc::epoll_event>(0x100); |
| 573 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, epfd, array_ptr) }; | |
| 561 | let res = unsafe { libc::epoll_ctl(epfd, EPOLL_CTL_ADD, epfd, array_ptr) }; | |
| 574 | 562 | let e = std::io::Error::last_os_error(); |
| 575 | 563 | assert_eq!(e.raw_os_error(), Some(libc::EFAULT)); |
| 576 | 564 | assert_eq!(res, -1); |
| ... | ... | @@ -578,7 +566,7 @@ fn test_epoll_ctl_epfd_equal_fd() { |
| 578 | 566 | |
| 579 | 567 | // We previously used check_and_update_readiness the moment a file description is registered in an |
| 580 | 568 | // epoll instance. But this has an unfortunate side effect of returning notification to another |
| 581 | // epfd that shouldn't receive notification. | |
| 569 | // epfd that shouldn't receive a notification in edge-triggered mode. | |
| 582 | 570 | fn test_epoll_ctl_notification() { |
| 583 | 571 | // Create an epoll instance. |
| 584 | 572 | let epfd0 = unsafe { libc::epoll_create1(0) }; |
| ... | ... | @@ -589,24 +577,87 @@ fn test_epoll_ctl_notification() { |
| 589 | 577 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); |
| 590 | 578 | |
| 591 | 579 | // Register one side of the socketpair with epoll. |
| 592 | epoll_ctl_add(epfd0, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 580 | epoll_ctl_add(epfd0, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 593 | 581 | |
| 594 | 582 | // epoll_wait to clear notification for epfd0. |
| 595 | let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 596 | let expected_value = fds[0] as u64; | |
| 597 | check_epoll_wait::<1>(epfd0, &[(expected_event, expected_value)]); | |
| 583 | check_epoll_wait_noblock(epfd0, &[Ev { events: EPOLLOUT, data: fds[0] }]); | |
| 598 | 584 | |
| 599 | 585 | // Create another epoll instance. |
| 600 | 586 | let epfd1 = unsafe { libc::epoll_create1(0) }; |
| 601 | 587 | assert_ne!(epfd1, -1); |
| 602 | 588 | |
| 603 | 589 | // Register the same file description for epfd1. |
| 604 | epoll_ctl_add(epfd1, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 605 | check_epoll_wait::<1>(epfd1, &[(expected_event, expected_value)]); | |
| 590 | epoll_ctl_add(epfd1, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 591 | check_epoll_wait_noblock(epfd1, &[Ev { events: EPOLLOUT, data: fds[0] }]); | |
| 592 | ||
| 593 | if cfg!(edge_triggered) { | |
| 594 | // Previously this epoll_wait will receive a notification, but we shouldn't return notification | |
| 595 | // for this epfd, because there is no I/O event between the two epoll_wait. | |
| 596 | check_epoll_wait_noblock(epfd0, &[]); | |
| 597 | } else { | |
| 598 | // We should still get the same events in level-triggered mode. | |
| 599 | check_epoll_wait_noblock(epfd0, &[Ev { events: EPOLLOUT, data: fds[0] }]); | |
| 600 | } | |
| 601 | } | |
| 602 | ||
| 603 | /// Test storing a level-triggered and an edge-triggered file descriptor | |
| 604 | /// in the same epoll instance and calling `epoll_wait` multiple times. | |
| 605 | fn test_epoll_mixed_modes() { | |
| 606 | // Create an epoll instance. | |
| 607 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); | |
| 608 | ||
| 609 | // Create a socketpair instance. | |
| 610 | let mut fds = [-1, -1]; | |
| 611 | errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); | |
| 612 | ||
| 613 | // Register both fd to the same epoll instance. | |
| 614 | // `fds[0]` is added in edge-triggered mode whilst `fds[1]` is added in level-triggered mode. | |
| 615 | epoll_ctl_add(epfd, fds[0], EPOLLIN | EPOLLOUT | EPOLLET).unwrap(); | |
| 616 | epoll_ctl_add(epfd, fds[1], EPOLLIN | EPOLLOUT | 0).unwrap(); | |
| 617 | ||
| 618 | // Write to `fds[1]`. | |
| 619 | libc_utils::write_all(fds[1], b"abcde").unwrap(); | |
| 620 | ||
| 621 | // Two events should be received. | |
| 622 | check_epoll_wait_noblock( | |
| 623 | epfd, | |
| 624 | &[Ev { events: EPOLLIN | EPOLLOUT, data: fds[0] }, Ev { events: EPOLLOUT, data: fds[1] }], | |
| 625 | ); | |
| 626 | ||
| 627 | // If we call epoll_wait again immediately, only the level-triggered interests should be received again. | |
| 628 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLOUT, data: fds[1] }]); | |
| 629 | } | |
| 630 | ||
| 631 | /// Test first registering a file descriptor in edge-triggered mode, | |
| 632 | /// then consuming it's readiness and then changing it to level-triggered | |
| 633 | /// mode. | |
| 634 | fn test_epoll_registered_mode_switch() { | |
| 635 | // Create an eventfd instance. | |
| 636 | let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; | |
| 637 | let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap(); | |
| 638 | ||
| 639 | // Write 1 to the eventfd instance. | |
| 640 | libc_utils::write_all(fd, &1_u64.to_ne_bytes()).unwrap(); | |
| 641 | ||
| 642 | // Create an epoll instance. | |
| 643 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); | |
| 644 | ||
| 645 | // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET. | |
| 646 | epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLOUT | EPOLLET).unwrap(); | |
| 647 | ||
| 648 | // Check result from `epoll_wait`. | |
| 649 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fd }]); | |
| 650 | ||
| 651 | // Because `fd` is registered in edge-triggered mode, the next `epoll_wait` shouldn't | |
| 652 | // return any events. | |
| 653 | check_epoll_wait_noblock(epfd, &[]); | |
| 606 | 654 | |
| 607 | // Previously this epoll_wait will receive a notification, but we shouldn't return notification | |
| 608 | // for this epfd, because there is no I/O event between the two epoll_wait. | |
| 609 | check_epoll_wait::<1>(epfd0, &[]); | |
| 655 | // Update the registration for `fd` to switch to level-triggered mode. | |
| 656 | epoll_ctl(epfd, EPOLL_CTL_MOD, fd, Ev { events: EPOLLIN | EPOLLOUT, data: fd }).unwrap(); | |
| 657 | ||
| 658 | // Because `fd` is now registered in level-triggered mode, we should see | |
| 659 | // the same events as from the first `epoll_wait`. | |
| 660 | check_epoll_wait_noblock(epfd, &[Ev { events: EPOLLIN | EPOLLOUT, data: fd }]); | |
| 610 | 661 | } |
| 611 | 662 | |
| 612 | 663 | // Test for ICE caused by weak epoll interest upgrade succeed, but the attempt to retrieve |
| ... | ... | @@ -623,13 +674,8 @@ fn test_issue_3858() { |
| 623 | 674 | // Create an epoll instance. |
| 624 | 675 | let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); |
| 625 | 676 | |
| 626 | // Register eventfd with EPOLLIN | EPOLLET. | |
| 627 | let mut ev = libc::epoll_event { | |
| 628 | events: (libc::EPOLLIN | libc::EPOLLET).cast_unsigned(), | |
| 629 | u64: u64::try_from(fd).unwrap(), | |
| 630 | }; | |
| 631 | let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; | |
| 632 | assert_eq!(res, 0); | |
| 677 | // Register eventfd with EPOLLIN (and EPOLLET if we're in the `edge_triggered` revision). | |
| 678 | epoll_ctl_add(epfd, fd, EPOLLIN | EPOLLET_OR_ZERO).unwrap(); | |
| 633 | 679 | |
| 634 | 680 | // Dup the epoll instance. |
| 635 | 681 | let newfd = unsafe { libc::dup(epfd) }; |
| ... | ... | @@ -655,7 +701,7 @@ fn test_issue_4374() { |
| 655 | 701 | assert_eq!(unsafe { libc::fcntl(fds[1], libc::F_SETFL, libc::O_NONBLOCK) }, 0); |
| 656 | 702 | |
| 657 | 703 | // Register fds[0] with epoll while it is writable (but not readable). |
| 658 | epoll_ctl_add(epfd0, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 704 | epoll_ctl_add(epfd0, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 659 | 705 | |
| 660 | 706 | // Fill up fds[0] so that it is not writable any more. |
| 661 | 707 | let zeros = [0u8; 512]; |
| ... | ... | @@ -668,7 +714,7 @@ fn test_issue_4374() { |
| 668 | 714 | } |
| 669 | 715 | |
| 670 | 716 | // This should have canceled the previous readiness, so now we get nothing. |
| 671 | check_epoll_wait::<1>(epfd0, &[]); | |
| 717 | check_epoll_wait_noblock(epfd0, &[]); | |
| 672 | 718 | } |
| 673 | 719 | |
| 674 | 720 | /// Same as above, but for becoming un-readable. |
| ... | ... | @@ -687,13 +733,11 @@ fn test_issue_4374_reads() { |
| 687 | 733 | libc_utils::write_all(fds[1], b"abcde").unwrap(); |
| 688 | 734 | |
| 689 | 735 | // Register fds[0] with epoll while it is readable. |
| 690 | epoll_ctl_add(epfd0, fds[0], libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET).unwrap(); | |
| 736 | epoll_ctl_add(epfd0, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); | |
| 691 | 737 | |
| 692 | 738 | // Read fds[0] so it is no longer readable. |
| 693 | 739 | libc_utils::read_exact_array::<5>(fds[0]).unwrap(); |
| 694 | 740 | |
| 695 | 741 | // We should now still see a notification, but only about it being writable. |
| 696 | let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); | |
| 697 | let expected_value = fds[0] as u64; | |
| 698 | check_epoll_wait::<1>(epfd0, &[(expected_event, expected_value)]); | |
| 742 | check_epoll_wait_noblock(epfd0, &[Ev { events: EPOLLOUT, data: fds[0] }]); | |
| 699 | 743 | } |
src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs+40-6| ... | ... | @@ -2,6 +2,10 @@ |
| 2 | 2 | //@ignore-target: solaris # Does not have flock |
| 3 | 3 | //@compile-flags: -Zmiri-disable-isolation |
| 4 | 4 | |
| 5 | //@revisions: windows_host unix_host | |
| 6 | //@[unix_host] ignore-host: windows | |
| 7 | //@[windows_host] only-host: windows | |
| 8 | ||
| 5 | 9 | use std::fs::File; |
| 6 | 10 | use std::os::fd::AsRawFd; |
| 7 | 11 | |
| ... | ... | @@ -17,12 +21,12 @@ fn main() { |
| 17 | 21 | |
| 18 | 22 | let files: Vec<File> = (0..3).map(|_| File::open(&path).unwrap()).collect(); |
| 19 | 23 | |
| 20 | // Test that we can apply many shared locks | |
| 24 | // Test that we can apply many shared locks. | |
| 21 | 25 | for file in files.iter() { |
| 22 | 26 | errno_check(unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_SH) }); |
| 23 | 27 | } |
| 24 | 28 | |
| 25 | // Test that shared lock prevents exclusive lock | |
| 29 | // Test that shared lock prevents exclusive lock. | |
| 26 | 30 | { |
| 27 | 31 | let fd = files[0].as_raw_fd(); |
| 28 | 32 | let err = |
| ... | ... | @@ -30,18 +34,18 @@ fn main() { |
| 30 | 34 | assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK); |
| 31 | 35 | } |
| 32 | 36 | |
| 33 | // Unlock shared lock | |
| 37 | // Unlock shared lock. | |
| 34 | 38 | for file in files.iter() { |
| 35 | 39 | errno_check(unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_UN) }); |
| 36 | 40 | } |
| 37 | 41 | |
| 38 | // Take exclusive lock | |
| 42 | // Take exclusive lock. | |
| 39 | 43 | { |
| 40 | 44 | let fd = files[0].as_raw_fd(); |
| 41 | 45 | errno_check(unsafe { libc::flock(fd, libc::LOCK_EX) }); |
| 42 | 46 | } |
| 43 | 47 | |
| 44 | // Test that shared lock prevents exclusive and shared locks | |
| 48 | // Test that exclusive lock prevents exclusive and shared locks. | |
| 45 | 49 | { |
| 46 | 50 | let fd = files[1].as_raw_fd(); |
| 47 | 51 | let err = |
| ... | ... | @@ -54,9 +58,39 @@ fn main() { |
| 54 | 58 | assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK); |
| 55 | 59 | } |
| 56 | 60 | |
| 57 | // Unlock exclusive lock | |
| 61 | // Unlock exclusive lock. | |
| 58 | 62 | { |
| 59 | 63 | let fd = files[0].as_raw_fd(); |
| 60 | 64 | errno_check(unsafe { libc::flock(fd, libc::LOCK_UN) }); |
| 65 | // Redundant unlock also works. | |
| 66 | // FIXME(#miri/5074): except on Windows hosts... | |
| 67 | if !cfg!(windows_host) { | |
| 68 | errno_check(unsafe { libc::flock(fd, libc::LOCK_UN) }); | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 72 | // Test behavior when we acquire multiple locks on the same FD. | |
| 73 | // FIXME(#miri/5074): this does not behave correctly on Windows hosts. | |
| 74 | if !cfg!(windows_host) { | |
| 75 | let fd1 = files[1].as_raw_fd(); | |
| 76 | let fd2 = files[2].as_raw_fd(); | |
| 77 | ||
| 78 | errno_check(unsafe { libc::flock(fd1, libc::LOCK_EX | libc::LOCK_NB) }); | |
| 79 | // This converts the exclusive lock to a shared lock. | |
| 80 | errno_check(unsafe { libc::flock(fd1, libc::LOCK_SH | libc::LOCK_NB) }); | |
| 81 | // Now the other fd can have the shared lock as well. | |
| 82 | errno_check(unsafe { libc::flock(fd2, libc::LOCK_SH | libc::LOCK_NB) }); | |
| 83 | ||
| 84 | // Reset. | |
| 85 | errno_check(unsafe { libc::flock(fd1, libc::LOCK_UN) }); | |
| 86 | errno_check(unsafe { libc::flock(fd2, libc::LOCK_UN) }); | |
| 87 | ||
| 88 | // Getting first a shared lock and then upgrading to exclusive should also work. | |
| 89 | errno_check(unsafe { libc::flock(fd1, libc::LOCK_SH | libc::LOCK_NB) }); | |
| 90 | errno_check(unsafe { libc::flock(fd1, libc::LOCK_EX | libc::LOCK_NB) }); | |
| 91 | // This is truly exclusive: fd2 is locked out. | |
| 92 | let err = | |
| 93 | errno_result(unsafe { libc::flock(fd2, libc::LOCK_SH | libc::LOCK_NB) }).unwrap_err(); | |
| 94 | assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK); | |
| 61 | 95 | } |
| 62 | 96 | } |
src/tools/miri/tests/pass-dep/libc/libc-fs.rs+62-6| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | //@compile-flags: -Zmiri-disable-isolation |
| 3 | 3 | |
| 4 | 4 | use std::ffi::{CStr, CString, OsString}; |
| 5 | use std::fs::{File, canonicalize, create_dir, remove_dir, remove_file}; | |
| 5 | use std::fs::{self, File, canonicalize, create_dir, remove_dir, remove_file}; | |
| 6 | 6 | use std::io::{Error, ErrorKind, Write}; |
| 7 | 7 | use std::os::unix::ffi::OsStrExt; |
| 8 | 8 | use std::os::unix::io::AsRawFd; |
| ... | ... | @@ -28,6 +28,7 @@ fn main() { |
| 28 | 28 | test_file_open_unix_allow_two_args(); |
| 29 | 29 | test_file_open_unix_needs_three_args(); |
| 30 | 30 | test_file_open_unix_extra_third_arg(); |
| 31 | test_file_open_dir(); | |
| 31 | 32 | #[cfg(target_os = "linux")] |
| 32 | 33 | test_o_tmpfile_flag(); |
| 33 | 34 | test_posix_mkstemp(); |
| ... | ... | @@ -68,11 +69,12 @@ fn main() { |
| 68 | 69 | #[cfg(not(target_os = "solaris"))] |
| 69 | 70 | test_pwritev(); |
| 70 | 71 | test_pwrite(); |
| 72 | test_linkat(); | |
| 71 | 73 | } |
| 72 | 74 | |
| 73 | 75 | #[cfg(target_os = "linux")] |
| 74 | 76 | #[track_caller] |
| 75 | fn assert_statx_matches_metadata(stx: &libc::statx, meta: &std::fs::Metadata, expected_size: u64) { | |
| 77 | fn assert_statx_matches_metadata(stx: &libc::statx, meta: &fs::Metadata, expected_size: u64) { | |
| 76 | 78 | use std::os::unix::fs::MetadataExt; |
| 77 | 79 | let mask = stx.stx_mask; |
| 78 | 80 | |
| ... | ... | @@ -152,7 +154,7 @@ fn test_statx_on_file_path() { |
| 152 | 154 | assert_eq!(ret, 0, "statx failed: {}", std::io::Error::last_os_error()); |
| 153 | 155 | |
| 154 | 156 | let stx = stx.assume_init(); |
| 155 | let meta = std::fs::metadata(&path).unwrap(); | |
| 157 | let meta = fs::metadata(&path).unwrap(); | |
| 156 | 158 | assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); |
| 157 | 159 | } |
| 158 | 160 | |
| ... | ... | @@ -211,21 +213,46 @@ fn test_file_open_unix_allow_two_args() { |
| 211 | 213 | let path = utils::prepare_with_content("test_file_open_unix_allow_two_args.txt", &[]); |
| 212 | 214 | let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); |
| 213 | 215 | |
| 214 | let _fd = unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) }; | |
| 216 | let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) }).unwrap(); | |
| 215 | 217 | } |
| 216 | 218 | |
| 217 | 219 | fn test_file_open_unix_needs_three_args() { |
| 218 | 220 | let path = utils::prepare_with_content("test_file_open_unix_needs_three_args.txt", &[]); |
| 219 | 221 | let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); |
| 220 | 222 | |
| 221 | let _fd = unsafe { libc::open(name.as_ptr(), libc::O_CREAT, 0o666) }; | |
| 223 | let _fd = | |
| 224 | errno_result(unsafe { libc::open(name.as_ptr(), libc::O_CREAT | libc::O_RDWR, 0o666) }) | |
| 225 | .unwrap(); | |
| 222 | 226 | } |
| 223 | 227 | |
| 224 | 228 | fn test_file_open_unix_extra_third_arg() { |
| 225 | 229 | let path = utils::prepare_with_content("test_file_open_unix_extra_third_arg.txt", &[]); |
| 226 | 230 | let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); |
| 227 | 231 | |
| 228 | let _fd = unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) }; | |
| 232 | let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) }).unwrap(); | |
| 233 | } | |
| 234 | ||
| 235 | fn test_file_open_dir() { | |
| 236 | let dir_path = utils::prepare_dir("miri_test_fs_dir"); | |
| 237 | create_dir(&dir_path).unwrap(); | |
| 238 | let dir_name = CString::new(dir_path.into_os_string().into_encoded_bytes()).unwrap(); | |
| 239 | ||
| 240 | // Opening it for read-write fails. The error code differs between Unix and Windows hosts. | |
| 241 | let err = errno_result(unsafe { libc::open(dir_name.as_ptr(), libc::O_RDWR) }).unwrap_err(); | |
| 242 | assert!( | |
| 243 | [libc::EISDIR, libc::EPERM].contains(&err.raw_os_error().unwrap()), | |
| 244 | "unexpected errno: {err}" | |
| 245 | ); | |
| 246 | ||
| 247 | // Opening it for reading succeeds, but then reading fails. | |
| 248 | // FIXME: currently does not behave as expected on Windows hosts. | |
| 249 | // See <https://github.com/rust-lang/miri/issues/5084>. | |
| 250 | // let fd = errno_result(unsafe { libc::open(dir_name.as_ptr(), libc::O_RDONLY) }).unwrap(); | |
| 251 | // let mut buf = [0u8; 4]; | |
| 252 | // let err = | |
| 253 | // errno_result(unsafe { libc::read(fd, buf.as_mut_ptr().cast(), buf.len()) }).unwrap_err(); | |
| 254 | // assert_eq!(err.raw_os_error().unwrap(), libc::EISDIR, "unexpected errno: {err}"); | |
| 255 | // libc_utils::errno_check(unsafe { libc::close(fd) }); | |
| 229 | 256 | } |
| 230 | 257 | |
| 231 | 258 | fn test_dup_stdout_stderr() { |
| ... | ... | @@ -1147,3 +1174,32 @@ fn test_pwrite() { |
| 1147 | 1174 | // The write should start at the provided byte offset. |
| 1148 | 1175 | assert_eq!(&write_buffer[0..bytes_written], &read_buffer[OFFSET..(bytes_written + OFFSET)]); |
| 1149 | 1176 | } |
| 1177 | ||
| 1178 | fn test_linkat() { | |
| 1179 | let source = utils::prepare_with_content("miri_test_libc_linkat_source.txt", b"hello"); | |
| 1180 | let link = utils::prepare("miri_test_libc_linkat_link.txt"); | |
| 1181 | ||
| 1182 | let c_source = CString::new(source.as_os_str().as_bytes()).expect("CString::new failed"); | |
| 1183 | let c_link = CString::new(link.as_os_str().as_bytes()).expect("CString::new failed"); | |
| 1184 | ||
| 1185 | // Call linkat | |
| 1186 | unsafe { | |
| 1187 | libc_utils::errno_check(libc::linkat( | |
| 1188 | libc::AT_FDCWD, | |
| 1189 | c_source.as_ptr(), | |
| 1190 | libc::AT_FDCWD, | |
| 1191 | c_link.as_ptr(), | |
| 1192 | 0, | |
| 1193 | )); | |
| 1194 | } | |
| 1195 | ||
| 1196 | // Verify that the hard link works: | |
| 1197 | // Modifications to one are visible through the other. | |
| 1198 | fs::write(&source, b"hello world").unwrap(); | |
| 1199 | let contents = fs::read(&link).unwrap(); | |
| 1200 | assert_eq!(contents, b"hello world"); | |
| 1201 | ||
| 1202 | // Cleanup | |
| 1203 | remove_file(&source).unwrap(); | |
| 1204 | remove_file(&link).unwrap(); | |
| 1205 | } |
src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs+12-12| ... | ... | @@ -61,7 +61,7 @@ fn test_connect_nonblock() { |
| 61 | 61 | epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | EPOLLERR).unwrap(); |
| 62 | 62 | |
| 63 | 63 | // Wait until we are done connecting. |
| 64 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); | |
| 64 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); | |
| 65 | 65 | |
| 66 | 66 | // There should be no error during async connection. |
| 67 | 67 | let errno = |
| ... | ... | @@ -95,7 +95,7 @@ fn test_accept_nonblock() { |
| 95 | 95 | epoll_ctl_add(epfd, server_sockfd, EPOLLIN | EPOLLET | EPOLLERR).unwrap(); |
| 96 | 96 | |
| 97 | 97 | // Wait until we get a readable event on the server socket. |
| 98 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLIN, data: server_sockfd }], -1); | |
| 98 | check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: server_sockfd }], -1); | |
| 99 | 99 | |
| 100 | 100 | // Accepting should now be possible. |
| 101 | 101 | net::accept_ipv4(server_sockfd).unwrap(); |
| ... | ... | @@ -149,7 +149,7 @@ fn test_connect_nonblock_err() { |
| 149 | 149 | epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | libc::EPOLLERR).unwrap(); |
| 150 | 150 | |
| 151 | 151 | // Wait until the socket has an error. |
| 152 | check_epoll_wait::<8>( | |
| 152 | check_epoll_wait( | |
| 153 | 153 | epfd, |
| 154 | 154 | &[Ev { events: libc::EPOLLERR | EPOLLOUT | EPOLLHUP, data: client_sockfd }], |
| 155 | 155 | -1, |
| ... | ... | @@ -229,7 +229,7 @@ fn test_recv_nonblock() { |
| 229 | 229 | Ok(received) => bytes_received += received as usize, |
| 230 | 230 | Err(err) if err.kind() == ErrorKind::WouldBlock => { |
| 231 | 231 | // Use epoll to block until there's data available again. |
| 232 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1); | |
| 232 | check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1); | |
| 233 | 233 | } |
| 234 | 234 | Err(err) => panic!("unexpected error whilst receiving: {err}"), |
| 235 | 235 | } |
| ... | ... | @@ -339,7 +339,7 @@ fn test_send_nonblock() { |
| 339 | 339 | }); |
| 340 | 340 | |
| 341 | 341 | // Wait until the socket is again writable. |
| 342 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); | |
| 342 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); | |
| 343 | 343 | |
| 344 | 344 | let fill_buf = [1u8; 100]; |
| 345 | 345 | // We should be able to write again without blocking because we just received |
| ... | ... | @@ -371,7 +371,7 @@ fn test_shutdown_read_write() { |
| 371 | 371 | unsafe { libc::shutdown(client_sockfd, libc::SHUT_RDWR) }; |
| 372 | 372 | |
| 373 | 373 | // Ensure that the "read end closed", "write end closed", and "readable" readiness are set. |
| 374 | check_epoll_wait::<8>( | |
| 374 | check_epoll_wait( | |
| 375 | 375 | epfd, |
| 376 | 376 | &[Ev { events: EPOLLRDHUP | EPOLLHUP | EPOLLIN, data: client_sockfd }], |
| 377 | 377 | -1, |
| ... | ... | @@ -399,7 +399,7 @@ fn test_shutdown_read() { |
| 399 | 399 | unsafe { libc::shutdown(client_sockfd, libc::SHUT_RD) }; |
| 400 | 400 | |
| 401 | 401 | // Ensure that the "read end closed" readiness is set. |
| 402 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLRDHUP, data: client_sockfd }], -1); | |
| 402 | check_epoll_wait(epfd, &[Ev { events: EPOLLRDHUP, data: client_sockfd }], -1); | |
| 403 | 403 | |
| 404 | 404 | server_thread.join().unwrap(); |
| 405 | 405 | } |
| ... | ... | @@ -425,7 +425,7 @@ fn test_shutdown_write() { |
| 425 | 425 | |
| 426 | 426 | // Ensure that the "read end closed" readiness is set when |
| 427 | 427 | // the write end of the peer is closed. |
| 428 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLRDHUP, data: client_sockfd }], -1); | |
| 428 | check_epoll_wait(epfd, &[Ev { events: EPOLLRDHUP, data: client_sockfd }], -1); | |
| 429 | 429 | |
| 430 | 430 | server_thread.join().unwrap(); |
| 431 | 431 | } |
| ... | ... | @@ -460,7 +460,7 @@ fn test_readiness_after_short_read() { |
| 460 | 460 | epoll_ctl_add(epfd, client_sockfd, EPOLLET | EPOLLIN).unwrap(); |
| 461 | 461 | |
| 462 | 462 | // Wait until the socket becomes readable. |
| 463 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1); | |
| 463 | check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1); | |
| 464 | 464 | |
| 465 | 465 | let mut buffer = [0u8; 1024]; |
| 466 | 466 | |
| ... | ... | @@ -499,7 +499,7 @@ fn test_readiness_after_short_read() { |
| 499 | 499 | |
| 500 | 500 | // Wait until the client socket becomes readable again. |
| 501 | 501 | // If this blocks indefinitely, Miri lost track of the proper status of this socket. |
| 502 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1); | |
| 502 | check_epoll_wait(epfd, &[Ev { events: EPOLLIN, data: client_sockfd }], -1); | |
| 503 | 503 | |
| 504 | 504 | // Now we can read the 2nd chunk of data. |
| 505 | 505 | unsafe { |
| ... | ... | @@ -583,7 +583,7 @@ fn test_readiness_after_short_write() { |
| 583 | 583 | epoll_ctl_add(epfd, client_sockfd, EPOLLET | EPOLLOUT).unwrap(); |
| 584 | 584 | |
| 585 | 585 | // Wait until the socket becomes writable. |
| 586 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); | |
| 586 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); | |
| 587 | 587 | |
| 588 | 588 | // We now want to fill the write buffer of the socket by repeatedly writing |
| 589 | 589 | // `buffer` into it. The last write should then be a short write. |
| ... | ... | @@ -630,7 +630,7 @@ fn test_readiness_after_short_write() { |
| 630 | 630 | |
| 631 | 631 | // Wait until the socket becomes writable again. |
| 632 | 632 | // If this blocks indefinitely, Miri lost track of the proper status of this socket. |
| 633 | check_epoll_wait::<8>(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); | |
| 633 | check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); | |
| 634 | 634 | |
| 635 | 635 | // We should again be able to write into the socket. |
| 636 | 636 | libc_utils::write_all(client_sockfd, &buffer).unwrap(); |
src/tools/miri/tests/pass-dep/libc/prctl-threadname.rs+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | //@only-target: android # Miri supports prctl for Android only | |
| 1 | //@only-target: linux android # Linux-specific API | |
| 2 | 2 | use std::ffi::{CStr, CString}; |
| 3 | 3 | use std::thread; |
| 4 | 4 |
src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | //@ignore-target: windows # No pthreads on Windows |
| 2 | //@ignore-target: android # No pthread_{get,set}_name on Android | |
| 2 | //@ignore-target: android # No pthread_{get,set}name_np on Android | |
| 3 | 3 | use std::ffi::{CStr, CString}; |
| 4 | 4 | use std::thread; |
| 5 | 5 |
src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs+10-3| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | 1 | //! Regression test for <https://github.com/rust-lang/miri/issues/3341>: |
| 2 | 2 | //! If `Box` has a local allocator, then it can't be `noalias` as the allocator |
| 3 | 3 | //! may want to access allocator state based on the data pointer. |
| 4 | //! Ensure that the `-Zmiri-tree-borrows-relax-custom-allocator-uniqueness` flag makes us | |
| 5 | //! accept such code. | |
| 4 | 6 | |
| 5 | //@revisions: stack tree tree_implicit_writes | |
| 6 | //@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes | |
| 7 | //@[tree]compile-flags: -Zmiri-tree-borrows | |
| 7 | //@compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-relax-custom-allocator-uniqueness -Zmiri-tree-borrows-implicit-writes | |
| 8 | 8 | #![feature(allocator_api)] |
| 9 | 9 | |
| 10 | 10 | use std::alloc::{AllocError, Allocator, Layout}; |
| ... | ... | @@ -46,6 +46,13 @@ impl MyBin { |
| 46 | 46 | let end = start + BIN_SIZE * mem::size_of::<usize>(); |
| 47 | 47 | let addr = ptr.addr().get(); |
| 48 | 48 | assert!((start..end).contains(&addr)); |
| 49 | ||
| 50 | // We can't update `top` as this may not be the last bin, but we can pretend to do so | |
| 51 | // such that the aliasing model checks things. | |
| 52 | // We access this via raw pointers so that the error span is in this file. | |
| 53 | let top_ptr = (&raw const self.top) as *mut usize; | |
| 54 | let top = top_ptr.read(); | |
| 55 | top_ptr.write(top); | |
| 49 | 56 | } |
| 50 | 57 | } |
| 51 | 58 |
src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs+3-3| ... | ... | @@ -5,8 +5,8 @@ use std::time::{Duration, Instant}; |
| 5 | 5 | fn main() { |
| 6 | 6 | let start = Instant::now(); |
| 7 | 7 | |
| 8 | thread::park_timeout(Duration::from_millis(200)); | |
| 8 | thread::park_timeout(Duration::from_millis(100)); | |
| 9 | 9 | |
| 10 | // Thanks to deterministic execution, this will wait *exactly* 200ms, plus the time for the surrounding code. | |
| 11 | assert!((200..210).contains(&start.elapsed().as_millis()), "{}", start.elapsed().as_millis()); | |
| 10 | // Thanks to deterministic execution, this will wait *exactly* 100ms, plus the time for the surrounding code. | |
| 11 | assert!((100..110).contains(&start.elapsed().as_millis()), "{}", start.elapsed().as_millis()); | |
| 12 | 12 | } |
src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | // We're testing aarch64 AES target specific features. | |
| 2 | //@only-target: aarch64 | |
| 3 | //@compile-flags: -C target-feature=+neon,+aes | |
| 4 | ||
| 5 | use std::arch::aarch64::*; | |
| 6 | use std::arch::is_aarch64_feature_detected; | |
| 7 | ||
| 8 | fn main() { | |
| 9 | assert!(is_aarch64_feature_detected!("neon")); | |
| 10 | assert!(is_aarch64_feature_detected!("aes")); | |
| 11 | ||
| 12 | unsafe { | |
| 13 | test_vmull_p64(); | |
| 14 | test_vmull_high_p64(); | |
| 15 | } | |
| 16 | } | |
| 17 | ||
| 18 | #[target_feature(enable = "neon,aes")] | |
| 19 | unsafe fn test_vmull_p64() { | |
| 20 | assert_eq!(vmull_p64(0, 0), 0); | |
| 21 | assert_eq!(vmull_p64(0, 0xffffffffffffffff), 0); | |
| 22 | assert_eq!(vmull_p64(1, 1), 1); | |
| 23 | assert_eq!(vmull_p64(1, 0x8000000000000000), 0x8000000000000000); | |
| 24 | ||
| 25 | assert_eq!(vmull_p64(0b11, 0b11), 0b101); | |
| 26 | ||
| 27 | // Check with the same inputs that are used in the x86_64 pclmulqdq test. | |
| 28 | assert_eq!( | |
| 29 | vmull_p64(0x7fffffffffffffff, 0xdd358416f52ecd34), | |
| 30 | (2704901987789626761u128 << 64) | 13036940098130298092u128, | |
| 31 | ); | |
| 32 | } | |
| 33 | ||
| 34 | #[target_feature(enable = "neon,aes")] | |
| 35 | unsafe fn test_vmull_high_p64() { | |
| 36 | // The lower (first) element is ignored. | |
| 37 | let a = vcombine_p64(vcreate_p64(123), vcreate_p64(0b11)); | |
| 38 | let b = vcombine_p64(vcreate_p64(456), vcreate_p64(0b11)); | |
| 39 | assert_eq!(vmull_high_p64(a, b), 0b101); | |
| 40 | ||
| 41 | // Check with the same inputs that are used in the x86_64 pclmulqdq test. | |
| 42 | let a = vcombine_p64(vcreate_p64(0), vcreate_p64(0x7fffffffffffffff)); | |
| 43 | let b = vcombine_p64(vcreate_p64(0), vcreate_p64(0xdd358416f52ecd34)); | |
| 44 | assert_eq!(vmull_high_p64(a, b), (2704901987789626761u128 << 64) | 13036940098130298092u128); | |
| 45 | } |
src/tools/miri/tests/pass/shims/fs.rs+46-10| ... | ... | @@ -38,11 +38,14 @@ fn main() { |
| 38 | 38 | if cfg!(not(windows)) { |
| 39 | 39 | test_directory(); |
| 40 | 40 | test_canonicalize(); |
| 41 | #[cfg(unix)] | |
| 42 | test_pread_pwrite(); | |
| 43 | 41 | #[cfg(not(target_os = "solaris"))] |
| 44 | 42 | test_flock(); |
| 43 | #[cfg(not(target_os = "android"))] | |
| 44 | test_hard_link(); | |
| 45 | ||
| 45 | 46 | test_readv_writev(); |
| 47 | #[cfg(unix)] | |
| 48 | test_pread_pwrite(); | |
| 46 | 49 | #[cfg(all(unix, not(any(target_os = "solaris", target_os = "android"))))] |
| 47 | 50 | test_preadv_pwritev(); |
| 48 | 51 | } |
| ... | ... | @@ -221,9 +224,10 @@ fn test_file_set_len() { |
| 221 | 224 | let file = OpenOptions::new().read(true).open(&path).unwrap(); |
| 222 | 225 | // Due to https://github.com/rust-lang/miri/issues/4457, we have to assume the failure could |
| 223 | 226 | // be either of the Windows or Unix kind, no matter which platform we're on. |
| 227 | let err = file.set_len(14).unwrap_err(); | |
| 224 | 228 | assert!( |
| 225 | [ErrorKind::PermissionDenied, ErrorKind::InvalidInput] | |
| 226 | .contains(&file.set_len(14).unwrap_err().kind()) | |
| 229 | [ErrorKind::PermissionDenied, ErrorKind::InvalidInput].contains(&err.kind()), | |
| 230 | "unexpected error: {err}" | |
| 227 | 231 | ); |
| 228 | 232 | |
| 229 | 233 | remove_file(&path).unwrap(); |
| ... | ... | @@ -415,20 +419,21 @@ fn test_flock() { |
| 415 | 419 | let file1 = OpenOptions::new().read(true).write(true).open(&path).unwrap(); |
| 416 | 420 | let file2 = OpenOptions::new().read(true).write(true).open(&path).unwrap(); |
| 417 | 421 | |
| 418 | // Test that we can apply many shared locks | |
| 422 | // Test that we can apply many shared locks. | |
| 419 | 423 | file1.lock_shared().unwrap(); |
| 420 | 424 | file2.lock_shared().unwrap(); |
| 421 | // Test that shared lock prevents exclusive lock | |
| 425 | // Test that shared lock prevents exclusive lock. | |
| 422 | 426 | assert!(matches!(file1.try_lock().unwrap_err(), fs::TryLockError::WouldBlock)); |
| 423 | // Unlock shared lock | |
| 427 | // Unlock both files. | |
| 424 | 428 | file1.unlock().unwrap(); |
| 425 | 429 | file2.unlock().unwrap(); |
| 426 | // Take exclusive lock | |
| 430 | ||
| 431 | // Take exclusive lock. | |
| 427 | 432 | file1.lock().unwrap(); |
| 428 | // Test that shared lock prevents exclusive and shared locks | |
| 433 | // Test that shared lock prevents exclusive and shared locks. | |
| 429 | 434 | assert!(matches!(file2.try_lock().unwrap_err(), fs::TryLockError::WouldBlock)); |
| 430 | 435 | assert!(matches!(file2.try_lock_shared().unwrap_err(), fs::TryLockError::WouldBlock)); |
| 431 | // Unlock exclusive lock | |
| 436 | // Unlock exclusive lock. | |
| 432 | 437 | file1.unlock().unwrap(); |
| 433 | 438 | } |
| 434 | 439 | |
| ... | ... | @@ -510,3 +515,34 @@ fn test_preadv_pwritev() { |
| 510 | 515 | f.read_exact(&mut written_bytes).unwrap(); |
| 511 | 516 | assert_eq!(written_bytes.as_slice(), &write_buffer[0..bytes_written]); |
| 512 | 517 | } |
| 518 | ||
| 519 | // std uses `libc::link` on Android which we do not support. | |
| 520 | #[cfg(not(target_os = "android"))] | |
| 521 | fn test_hard_link() { | |
| 522 | let source = utils::prepare_with_content("miri_test_fs_hard_link_source.txt", b"hello"); | |
| 523 | let link = utils::prepare("miri_test_fs_hard_link_link.txt"); | |
| 524 | ||
| 525 | fs::hard_link(&source, &link).unwrap(); | |
| 526 | ||
| 527 | // Verify that the hard link works: | |
| 528 | // Modifications to one are visible through the other. | |
| 529 | fs::write(&source, b"hello world").unwrap(); | |
| 530 | let contents = fs::read(&link).unwrap(); | |
| 531 | assert_eq!(contents, b"hello world"); | |
| 532 | ||
| 533 | // Only on Unix: verify both files have same inode | |
| 534 | #[cfg(unix)] | |
| 535 | { | |
| 536 | use std::os::unix::fs::MetadataExt; | |
| 537 | let source_meta = std::fs::metadata(&source).unwrap(); | |
| 538 | let link_meta = std::fs::metadata(&link).unwrap(); | |
| 539 | assert_eq!(source_meta.ino(), link_meta.ino()); | |
| 540 | } | |
| 541 | ||
| 542 | // Test error: link already exists | |
| 543 | assert_eq!(ErrorKind::AlreadyExists, fs::hard_link(&source, &link).unwrap_err().kind()); | |
| 544 | ||
| 545 | // Cleanup after test | |
| 546 | remove_file(&source).unwrap(); | |
| 547 | remove_file(&link).unwrap(); | |
| 548 | } |
src/tools/miri/tests/pass/shims/loongarch/intrinsics-loongarch64-crc.rs created+54| ... | ... | @@ -0,0 +1,54 @@ |
| 1 | // We're testing loongarch64-specific intrinsics | |
| 2 | //@only-target: loongarch64 | |
| 3 | #![feature(stdarch_loongarch)] | |
| 4 | ||
| 5 | use std::arch::loongarch64::*; | |
| 6 | ||
| 7 | fn main() { | |
| 8 | test_crc_ieee(); | |
| 9 | test_crc_castagnoli(); | |
| 10 | } | |
| 11 | ||
| 12 | fn test_crc_ieee() { | |
| 13 | // crc.w.b.w: 8-bit input | |
| 14 | assert_eq!(crc_w_b_w(0x01, 0x00000000), 0x77073096); | |
| 15 | assert_eq!(crc_w_b_w(0x61, 0xffffffff_u32 as i32), 0x174841bc); | |
| 16 | assert_eq!(crc_w_b_w(0x2a, 0x2aa1e72b), 0x772d9171); | |
| 17 | ||
| 18 | // crc.w.h.w: 16-bit input | |
| 19 | assert_eq!(crc_w_h_w(0x0001, 0x00000000), 0x191b3141); | |
| 20 | assert_eq!(crc_w_h_w(0x1234, 0xffffffff_u32 as i32), 0xf6b56fbf_u32 as i32); | |
| 21 | assert_eq!(crc_w_h_w(0x022b, 0x8ecec3b5_u32 as i32), 0x03a1db7c); | |
| 22 | ||
| 23 | // crc.w.w.w: 32-bit input | |
| 24 | assert_eq!(crc_w_w_w(0x00000001, 0x00000000), 0xb8bc6765_u32 as i32); | |
| 25 | assert_eq!(crc_w_w_w(0x12345678, 0xffffffff_u32 as i32), 0x5092782d); | |
| 26 | assert_eq!(crc_w_w_w(0x00845fed, 0xae2912c8_u32 as i32), 0xc5690dd4_u32 as i32); | |
| 27 | ||
| 28 | // crc.w.d.w: 64-bit input | |
| 29 | assert_eq!(crc_w_d_w(0x0000000000000001, 0x00000000), 0xccaa009e_u32 as i32); | |
| 30 | assert_eq!(crc_w_d_w(0x123456789abcdef0, 0xffffffff_u32 as i32), 0xe6ddf8b5_u32 as i32); | |
| 31 | assert_eq!(crc_w_d_w(0xc0febeefdadafefe_u64 as i64, 0x0badeafe), 0x61a45fba); | |
| 32 | } | |
| 33 | ||
| 34 | fn test_crc_castagnoli() { | |
| 35 | // crcc.w.b.w: 8-bit input | |
| 36 | assert_eq!(crcc_w_b_w(0x01, 0x00000000), 0xf26b8303_u32 as i32); | |
| 37 | assert_eq!(crcc_w_b_w(0x61, 0xffffffff_u32 as i32), 0x3e2fbccf); | |
| 38 | assert_eq!(crcc_w_b_w(0x2a, 0x2aa1e72b), 0xf24122e4_u32 as i32); | |
| 39 | ||
| 40 | // crcc.w.h.w: 16-bit input | |
| 41 | assert_eq!(crcc_w_h_w(0x0001, 0x00000000), 0x13a29877); | |
| 42 | assert_eq!(crcc_w_h_w(0x1234, 0xffffffff_u32 as i32), 0xf13f4cea_u32 as i32); | |
| 43 | assert_eq!(crcc_w_h_w(0x022b, 0x8ecec3b5_u32 as i32), 0x013bb2fb); | |
| 44 | ||
| 45 | // crcc.w.w.w: 32-bit input | |
| 46 | assert_eq!(crcc_w_w_w(0x00000001, 0x00000000), 0xdd45aab8_u32 as i32); | |
| 47 | assert_eq!(crcc_w_w_w(0x12345678, 0xffffffff_u32 as i32), 0x4dece20c); | |
| 48 | assert_eq!(crcc_w_w_w(0x00845fed, 0xae2912c8_u32 as i32), 0xffae2ed1_u32 as i32); | |
| 49 | ||
| 50 | // crcc.w.d.w: 64-bit input | |
| 51 | assert_eq!(crcc_w_d_w(0x0000000000000001, 0x00000000), 0x493c7d27); | |
| 52 | assert_eq!(crcc_w_d_w(0x123456789abcdef0, 0xffffffff_u32 as i32), 0xd95b664b_u32 as i32); | |
| 53 | assert_eq!(crcc_w_d_w(0xc0febeefdadafefe_u64 as i64, 0x0badeafe), 0x5b44f54f); | |
| 54 | } |
src/tools/miri/tests/utils/libc.rs+21-8| ... | ... | @@ -164,24 +164,37 @@ pub mod epoll { |
| 164 | 164 | epoll_ctl(epfd, EPOLL_CTL_ADD, fd, Ev { events, data: fd }) |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | /// Call `epoll_wait` on `epfd` with the provided `timeout`. | |
| 168 | /// It fetches at most `max_events` events from `epfd` and | |
| 169 | /// ensures that the returned events match the `expected` events. | |
| 167 | 170 | #[track_caller] |
| 168 | pub fn check_epoll_wait<const N: usize>(epfd: i32, expected: &[Ev], timeout: i32) { | |
| 169 | let mut array: [libc::epoll_event; N] = [libc::epoll_event { events: 0, u64: 0 }; N]; | |
| 171 | pub fn check_epoll_wait_partial(epfd: i32, expected: &[Ev], max_events: usize, timeout: i32) { | |
| 172 | let mut events = vec![libc::epoll_event { events: 0, u64: 0 }; max_events]; | |
| 170 | 173 | let num = errno_result(unsafe { |
| 171 | libc::epoll_wait(epfd, array.as_mut_ptr(), N.try_into().unwrap(), timeout) | |
| 174 | libc::epoll_wait(epfd, events.as_mut_ptr(), i32::try_from(max_events).unwrap(), timeout) | |
| 172 | 175 | }) |
| 173 | 176 | .expect("epoll_wait returned an error"); |
| 174 | let got = &mut array[..num.try_into().unwrap()]; | |
| 175 | let got = got | |
| 177 | let got = events | |
| 176 | 178 | .iter() |
| 179 | .take(num as usize) | |
| 177 | 180 | .map(|e| Ev { events: e.events.cast_signed(), data: e.u64.try_into().unwrap() }) |
| 178 | 181 | .collect::<Vec<_>>(); |
| 179 | assert_eq!(got, expected, "got wrong notifications"); | |
| 182 | assert_eq!(got, expected, "got wrong ready events"); | |
| 183 | } | |
| 184 | ||
| 185 | /// Call `epoll_wait` on `epfd` with the provided `timeout` and ensure | |
| 186 | /// that the set of *all* ready events matches `expected`. | |
| 187 | #[track_caller] | |
| 188 | pub fn check_epoll_wait(epfd: i32, expected: &[Ev], timeout: i32) { | |
| 189 | // We set `max_events` to `expected.len() + 1` to ensure that there are no additional ready | |
| 190 | // events besides those which are contained in `expected`. | |
| 191 | check_epoll_wait_partial(epfd, &expected, expected.len() + 1, timeout); | |
| 180 | 192 | } |
| 181 | 193 | |
| 194 | /// This does the same as [`check_epoll_wait`] just without blocking (zero `timeout`). | |
| 182 | 195 | #[track_caller] |
| 183 | pub fn check_epoll_wait_noblock<const N: usize>(epfd: i32, expected: &[Ev]) { | |
| 184 | check_epoll_wait::<N>(epfd, expected, 0); | |
| 196 | pub fn check_epoll_wait_noblock(epfd: i32, expected: &[Ev]) { | |
| 197 | check_epoll_wait(epfd, expected, 0); | |
| 185 | 198 | } |
| 186 | 199 | |
| 187 | 200 | /// Query the current epoll readiness of a file descriptor. |
tests/assembly-llvm/simd-bitmask.rs+18-5| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | //@ add-minicore |
| 2 | //@ revisions: x86 x86-avx2 x86-avx512 aarch64 | |
| 2 | //@ revisions: x86 x86-avx2 x86-avx512 aarch64-llvm-pre-23 aarch64 | |
| 3 | 3 | //@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel |
| 4 | 4 | //@ [x86] needs-llvm-components: x86 |
| 5 | 5 | //@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel |
| ... | ... | @@ -8,8 +8,12 @@ |
| 8 | 8 | //@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel |
| 9 | 9 | //@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq |
| 10 | 10 | //@ [x86-avx512] needs-llvm-components: x86 |
| 11 | //@ [aarch64] min-llvm-version: 23 | |
| 11 | 12 | //@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu |
| 12 | 13 | //@ [aarch64] needs-llvm-components: aarch64 |
| 14 | //@ [aarch64-llvm-pre-23] ignore-llvm-version: 23 - 99 | |
| 15 | //@ [aarch64-llvm-pre-23] compile-flags: --target=aarch64-unknown-linux-gnu | |
| 16 | //@ [aarch64-llvm-pre-23] needs-llvm-components: aarch64 | |
| 13 | 17 | //@ assembly-output: emit-asm |
| 14 | 18 | //@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort |
| 15 | 19 | |
| ... | ... | @@ -54,14 +58,23 @@ pub unsafe extern "C" fn bitmask_m8x16(mask: m8x16) -> u16 { |
| 54 | 58 | // x86-avx512-NOT: vpsllw xmm0 |
| 55 | 59 | // x86-avx512: vpmovmskb eax, xmm0 |
| 56 | 60 | // |
| 61 | // aarch64-pre-llvm-23: adrp | |
| 62 | // aarch64-pre-llvm-23-NEXT: cmlt | |
| 63 | // aarch64-pre-llvm-23-NEXT: ldr | |
| 64 | // aarch64-pre-llvm-23-NEXT: and | |
| 65 | // aarch64-pre-llvm-23-NEXT: ext | |
| 66 | // aarch64-pre-llvm-23-NEXT: zip1 | |
| 67 | // aarch64-pre-llvm-23-NEXT: addv | |
| 68 | // aarch64-pre-llvm-23-NEXT: fmov | |
| 69 | // | |
| 57 | 70 | // aarch64: adrp |
| 58 | 71 | // aarch64-NEXT: cmlt |
| 59 | 72 | // aarch64-NEXT: ldr |
| 60 | 73 | // aarch64-NEXT: and |
| 61 | // aarch64-NEXT: ext | |
| 62 | // aarch64-NEXT: zip1 | |
| 63 | // aarch64-NEXT: addv | |
| 64 | // aarch64-NEXT: fmov | |
| 74 | // aarch64-NEXT: addp | |
| 75 | // aarch64-NEXT: addp | |
| 76 | // aarch64-NEXT: addp | |
| 77 | // aarch64-NEXT: umov | |
| 65 | 78 | simd_bitmask(mask) |
| 66 | 79 | } |
| 67 | 80 |
tests/codegen-llvm/sanitizer/cfi/external_weak_symbols.rs+1-1| ... | ... | @@ -10,7 +10,7 @@ unsafe extern "C" { |
| 10 | 10 | #[linkage = "extern_weak"] |
| 11 | 11 | static FOO: Option<unsafe extern "C" fn(f64) -> ()>; |
| 12 | 12 | } |
| 13 | // CHECK: @_rust_extern_with_linkage_{{.*}}_FOO = internal global ptr @FOO | |
| 13 | // CHECK: @_rust_extern_with_linkage_{{.*}}_FOO = internal unnamed_addr global ptr @FOO | |
| 14 | 14 | |
| 15 | 15 | fn main() { |
| 16 | 16 | unsafe { |
tests/rustdoc-gui/search-tab.goml+1-1| ... | ... | @@ -81,7 +81,7 @@ set-window-size: (851, 600) |
| 81 | 81 | // Check the size and count in tabs |
| 82 | 82 | assert-text: ("#search-tabs > button:nth-child(1) > .count", " (25) ") |
| 83 | 83 | assert-text: ("#search-tabs > button:nth-child(2) > .count", " (7)  ") |
| 84 | assert-text: ("#search-tabs > button:nth-child(3) > .count", " (0)  ") | |
| 84 | assert-text: ("#search-tabs > button:nth-child(3) > .count", " (1)  ") | |
| 85 | 85 | store-property: ("#search-tabs > button:nth-child(1)", {"offsetWidth": buttonWidth}) |
| 86 | 86 | assert-property: ("#search-tabs > button:nth-child(2)", {"offsetWidth": |buttonWidth|}) |
| 87 | 87 | assert-property: ("#search-tabs > button:nth-child(3)", {"offsetWidth": |buttonWidth|}) |
tests/rustdoc-gui/sidebar-foreign-impl-sort.goml+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | // Checks sidebar resizing close the Settings popover | |
| 1 | // Checks sidebar foreign impl ordering | |
| 2 | 2 | go-to: "file://" + |DOC_PATH| + "/test_docs/SidebarSort/trait.Sort.html#foreign-impls" |
| 3 | 3 | |
| 4 | 4 | // Check that the sidebar contains the expected foreign implementations |
tests/rustdoc-gui/src/test_docs/lib.rs+14| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | #![feature(associated_type_defaults)] |
| 11 | 11 | #![feature(macro_attr)] |
| 12 | 12 | #![feature(macro_derive)] |
| 13 | #![feature(negative_impls)] | |
| 13 | 14 | |
| 14 | 15 | /*! |
| 15 | 16 | Enable the feature <span class="stab portability"><code>some-feature</code></span> to enjoy |
| ... | ... | @@ -89,6 +90,19 @@ impl AsRef<str> for Foo { |
| 89 | 90 | } |
| 90 | 91 | } |
| 91 | 92 | |
| 93 | unsafe impl Send for Foo {} | |
| 94 | impl !Sync for Foo {} | |
| 95 | ||
| 96 | impl From<u8> for Foo { | |
| 97 | fn from(value: u8) -> Self { todo!(); } | |
| 98 | } | |
| 99 | impl From<u16> for Foo { | |
| 100 | fn from(value: u16) -> Self { todo!(); } | |
| 101 | } | |
| 102 | impl From<u32> for Foo { | |
| 103 | fn from(value: u32) -> Self { todo!(); } | |
| 104 | } | |
| 105 | ||
| 92 | 106 | /// <div id="doc-warning-0" class="warning">I have warnings!</div> |
| 93 | 107 | pub struct WarningStruct; |
| 94 | 108 |
tests/rustdoc-gui/trait-impl-sort.goml created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | // Check that trait impls in the sidebar and the main section have the same | |
| 2 | // ordering. | |
| 3 | ||
| 4 | go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" | |
| 5 | ||
| 6 | // .sidebar .trait-implementation li:nth-child(3) a | |
| 7 | assert-text: (".sidebar-elems .trait-implementation li:nth-child(1) a", "!Sync") | |
| 8 | assert-text: (".sidebar-elems .trait-implementation li:nth-child(2) a", "AsRef<str>") | |
| 9 | assert-text: (".sidebar-elems .trait-implementation li:nth-child(3) a", "From<u8>") | |
| 10 | assert-text: (".sidebar-elems .trait-implementation li:nth-child(4) a", "From<u16>") | |
| 11 | assert-text: (".sidebar-elems .trait-implementation li:nth-child(5) a", "From<u32>") | |
| 12 | assert-text: (".sidebar-elems .trait-implementation li:nth-child(6) a", "Send") | |
| 13 | ||
| 14 | assert-text: ("#trait-implementations-list section:nth-child(1) .code-header", "impl !Sync for Foo") | |
| 15 | assert-text: ("#trait-implementations-list details:nth-child(2) .code-header", "impl AsRef<str> for Foo") | |
| 16 | assert-text: ("#trait-implementations-list details:nth-child(3) .code-header", "impl From<u8> for Foo") | |
| 17 | assert-text: ("#trait-implementations-list details:nth-child(4) .code-header", "impl From<u16> for Foo") | |
| 18 | assert-text: ("#trait-implementations-list details:nth-child(5) .code-header", "impl From<u32> for Foo") | |
| 19 | assert-text: ("#trait-implementations-list section:nth-child(6) .code-header", "impl Send for Foo") |
tests/ui/abi/pass-indirectly-attr.stderr+1-10| ... | ... | @@ -123,16 +123,7 @@ error: fn_abi_of(extern_rust) = FnAbi { |
| 123 | 123 | mode: Cast { |
| 124 | 124 | pad_i32: false, |
| 125 | 125 | cast: CastTarget { |
| 126 | prefix: [ | |
| 127 | None, | |
| 128 | None, | |
| 129 | None, | |
| 130 | None, | |
| 131 | None, | |
| 132 | None, | |
| 133 | None, | |
| 134 | None, | |
| 135 | ], | |
| 126 | prefix: [], | |
| 136 | 127 | rest_offset: None, |
| 137 | 128 | rest: Uniform { |
| 138 | 129 | unit: Reg { |
tests/ui/attributes/attr-on-mac-call.stderr+22-22| ... | ... | @@ -4,8 +4,8 @@ warning: `#[export_name]` attribute cannot be used on macro calls |
| 4 | 4 | LL | #[export_name = "x"] |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[export_name]` can be applied to functions and statics |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | note: the lint level is defined here |
| 10 | 10 | --> $DIR/attr-on-mac-call.rs:3:9 |
| 11 | 11 | | |
| ... | ... | @@ -18,8 +18,8 @@ warning: `#[naked]` attribute cannot be used on macro calls |
| 18 | 18 | LL | #[unsafe(naked)] |
| 19 | 19 | | ^^^^^^^^^^^^^^^^ |
| 20 | 20 | | |
| 21 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 22 | 21 | = help: `#[naked]` can only be applied to functions |
| 22 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 23 | 23 | |
| 24 | 24 | warning: `#[track_caller]` attribute cannot be used on macro calls |
| 25 | 25 | --> $DIR/attr-on-mac-call.rs:12:5 |
| ... | ... | @@ -27,8 +27,8 @@ warning: `#[track_caller]` attribute cannot be used on macro calls |
| 27 | 27 | LL | #[track_caller] |
| 28 | 28 | | ^^^^^^^^^^^^^^^ |
| 29 | 29 | | |
| 30 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 31 | 30 | = help: `#[track_caller]` can only be applied to functions |
| 31 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 32 | 32 | |
| 33 | 33 | warning: `#[used]` attribute cannot be used on macro calls |
| 34 | 34 | --> $DIR/attr-on-mac-call.rs:15:5 |
| ... | ... | @@ -36,8 +36,8 @@ warning: `#[used]` attribute cannot be used on macro calls |
| 36 | 36 | LL | #[used] |
| 37 | 37 | | ^^^^^^^ |
| 38 | 38 | | |
| 39 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 40 | 39 | = help: `#[used]` can only be applied to statics |
| 40 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 41 | 41 | |
| 42 | 42 | warning: `#[target_feature]` attribute cannot be used on macro calls |
| 43 | 43 | --> $DIR/attr-on-mac-call.rs:18:5 |
| ... | ... | @@ -45,8 +45,8 @@ warning: `#[target_feature]` attribute cannot be used on macro calls |
| 45 | 45 | LL | #[target_feature(enable = "x")] |
| 46 | 46 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 47 | 47 | | |
| 48 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 49 | 48 | = help: `#[target_feature]` can only be applied to functions |
| 49 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 50 | 50 | |
| 51 | 51 | warning: `#[deprecated]` attribute cannot be used on macro calls |
| 52 | 52 | --> $DIR/attr-on-mac-call.rs:21:5 |
| ... | ... | @@ -54,8 +54,8 @@ warning: `#[deprecated]` attribute cannot be used on macro calls |
| 54 | 54 | LL | #[deprecated] |
| 55 | 55 | | ^^^^^^^^^^^^^ |
| 56 | 56 | | |
| 57 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 58 | 57 | = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements |
| 58 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 59 | 59 | |
| 60 | 60 | warning: `#[inline]` attribute cannot be used on macro calls |
| 61 | 61 | --> $DIR/attr-on-mac-call.rs:24:5 |
| ... | ... | @@ -63,8 +63,8 @@ warning: `#[inline]` attribute cannot be used on macro calls |
| 63 | 63 | LL | #[inline] |
| 64 | 64 | | ^^^^^^^^^ |
| 65 | 65 | | |
| 66 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 67 | 66 | = help: `#[inline]` can only be applied to functions |
| 67 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 68 | 68 | |
| 69 | 69 | warning: `#[link_name]` attribute cannot be used on macro calls |
| 70 | 70 | --> $DIR/attr-on-mac-call.rs:27:5 |
| ... | ... | @@ -72,8 +72,8 @@ warning: `#[link_name]` attribute cannot be used on macro calls |
| 72 | 72 | LL | #[link_name = "x"] |
| 73 | 73 | | ^^^^^^^^^^^^^^^^^^ |
| 74 | 74 | | |
| 75 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 76 | 75 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 76 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 77 | 77 | |
| 78 | 78 | warning: `#[link_section]` attribute cannot be used on macro calls |
| 79 | 79 | --> $DIR/attr-on-mac-call.rs:30:5 |
| ... | ... | @@ -81,8 +81,8 @@ warning: `#[link_section]` attribute cannot be used on macro calls |
| 81 | 81 | LL | #[link_section = "__TEXT,__text"] |
| 82 | 82 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 83 | 83 | | |
| 84 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 85 | 84 | = help: `#[link_section]` can be applied to functions and statics |
| 85 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 86 | 86 | |
| 87 | 87 | warning: `#[link_ordinal]` attribute cannot be used on macro calls |
| 88 | 88 | --> $DIR/attr-on-mac-call.rs:33:5 |
| ... | ... | @@ -90,8 +90,8 @@ warning: `#[link_ordinal]` attribute cannot be used on macro calls |
| 90 | 90 | LL | #[link_ordinal(42)] |
| 91 | 91 | | ^^^^^^^^^^^^^^^^^^^ |
| 92 | 92 | | |
| 93 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 94 | 93 | = help: `#[link_ordinal]` can be applied to foreign functions and foreign statics |
| 94 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 95 | 95 | |
| 96 | 96 | warning: `#[non_exhaustive]` attribute cannot be used on macro calls |
| 97 | 97 | --> $DIR/attr-on-mac-call.rs:36:5 |
| ... | ... | @@ -99,8 +99,8 @@ warning: `#[non_exhaustive]` attribute cannot be used on macro calls |
| 99 | 99 | LL | #[non_exhaustive] |
| 100 | 100 | | ^^^^^^^^^^^^^^^^^ |
| 101 | 101 | | |
| 102 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 103 | 102 | = help: `#[non_exhaustive]` can be applied to data types and enum variants |
| 103 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 104 | 104 | |
| 105 | 105 | warning: `#[proc_macro]` attribute cannot be used on macro calls |
| 106 | 106 | --> $DIR/attr-on-mac-call.rs:39:5 |
| ... | ... | @@ -108,8 +108,8 @@ warning: `#[proc_macro]` attribute cannot be used on macro calls |
| 108 | 108 | LL | #[proc_macro] |
| 109 | 109 | | ^^^^^^^^^^^^^ |
| 110 | 110 | | |
| 111 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 112 | 111 | = help: `#[proc_macro]` can only be applied to functions |
| 112 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 113 | 113 | |
| 114 | 114 | warning: `#[cold]` attribute cannot be used on macro calls |
| 115 | 115 | --> $DIR/attr-on-mac-call.rs:42:5 |
| ... | ... | @@ -117,8 +117,8 @@ warning: `#[cold]` attribute cannot be used on macro calls |
| 117 | 117 | LL | #[cold] |
| 118 | 118 | | ^^^^^^^ |
| 119 | 119 | | |
| 120 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 121 | 120 | = help: `#[cold]` can only be applied to functions |
| 121 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 122 | 122 | |
| 123 | 123 | warning: `#[no_mangle]` attribute cannot be used on macro calls |
| 124 | 124 | --> $DIR/attr-on-mac-call.rs:45:5 |
| ... | ... | @@ -126,8 +126,8 @@ warning: `#[no_mangle]` attribute cannot be used on macro calls |
| 126 | 126 | LL | #[no_mangle] |
| 127 | 127 | | ^^^^^^^^^^^^ |
| 128 | 128 | | |
| 129 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 130 | 129 | = help: `#[no_mangle]` can be applied to functions and statics |
| 130 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 131 | 131 | |
| 132 | 132 | warning: `#[deprecated]` attribute cannot be used on macro calls |
| 133 | 133 | --> $DIR/attr-on-mac-call.rs:48:5 |
| ... | ... | @@ -135,8 +135,8 @@ warning: `#[deprecated]` attribute cannot be used on macro calls |
| 135 | 135 | LL | #[deprecated] |
| 136 | 136 | | ^^^^^^^^^^^^^ |
| 137 | 137 | | |
| 138 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 139 | 138 | = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements |
| 139 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 140 | 140 | |
| 141 | 141 | warning: `#[automatically_derived]` attribute cannot be used on macro calls |
| 142 | 142 | --> $DIR/attr-on-mac-call.rs:51:5 |
| ... | ... | @@ -144,8 +144,8 @@ warning: `#[automatically_derived]` attribute cannot be used on macro calls |
| 144 | 144 | LL | #[automatically_derived] |
| 145 | 145 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 146 | 146 | | |
| 147 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 148 | 147 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 148 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 149 | 149 | |
| 150 | 150 | warning: `#[macro_use]` attribute cannot be used on macro calls |
| 151 | 151 | --> $DIR/attr-on-mac-call.rs:54:5 |
| ... | ... | @@ -153,8 +153,8 @@ warning: `#[macro_use]` attribute cannot be used on macro calls |
| 153 | 153 | LL | #[macro_use] |
| 154 | 154 | | ^^^^^^^^^^^^ |
| 155 | 155 | | |
| 156 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 157 | 156 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 157 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 158 | 158 | |
| 159 | 159 | warning: `#[must_use]` attribute cannot be used on macro calls |
| 160 | 160 | --> $DIR/attr-on-mac-call.rs:57:5 |
| ... | ... | @@ -162,8 +162,8 @@ warning: `#[must_use]` attribute cannot be used on macro calls |
| 162 | 162 | LL | #[must_use] |
| 163 | 163 | | ^^^^^^^^^^^ |
| 164 | 164 | | |
| 165 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 166 | 165 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 166 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 167 | 167 | |
| 168 | 168 | warning: `#[no_implicit_prelude]` attribute cannot be used on macro calls |
| 169 | 169 | --> $DIR/attr-on-mac-call.rs:60:5 |
| ... | ... | @@ -171,8 +171,8 @@ warning: `#[no_implicit_prelude]` attribute cannot be used on macro calls |
| 171 | 171 | LL | #[no_implicit_prelude] |
| 172 | 172 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 173 | 173 | | |
| 174 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 175 | 174 | = help: `#[no_implicit_prelude]` can be applied to crates and modules |
| 175 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 176 | 176 | |
| 177 | 177 | warning: `#[path]` attribute cannot be used on macro calls |
| 178 | 178 | --> $DIR/attr-on-mac-call.rs:63:5 |
| ... | ... | @@ -180,8 +180,8 @@ warning: `#[path]` attribute cannot be used on macro calls |
| 180 | 180 | LL | #[path = ""] |
| 181 | 181 | | ^^^^^^^^^^^^ |
| 182 | 182 | | |
| 183 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 184 | 183 | = help: `#[path]` can only be applied to modules |
| 184 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 185 | 185 | |
| 186 | 186 | warning: `#[ignore]` attribute cannot be used on macro calls |
| 187 | 187 | --> $DIR/attr-on-mac-call.rs:66:5 |
| ... | ... | @@ -189,8 +189,8 @@ warning: `#[ignore]` attribute cannot be used on macro calls |
| 189 | 189 | LL | #[ignore] |
| 190 | 190 | | ^^^^^^^^^ |
| 191 | 191 | | |
| 192 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 193 | 192 | = help: `#[ignore]` can only be applied to functions |
| 193 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 194 | 194 | |
| 195 | 195 | warning: `#[should_panic]` attribute cannot be used on macro calls |
| 196 | 196 | --> $DIR/attr-on-mac-call.rs:69:5 |
| ... | ... | @@ -198,8 +198,8 @@ warning: `#[should_panic]` attribute cannot be used on macro calls |
| 198 | 198 | LL | #[should_panic] |
| 199 | 199 | | ^^^^^^^^^^^^^^^ |
| 200 | 200 | | |
| 201 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 202 | 201 | = help: `#[should_panic]` can only be applied to functions |
| 202 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 203 | 203 | |
| 204 | 204 | warning: 22 warnings emitted |
| 205 | 205 |
tests/ui/attributes/codegen_attr_on_required_trait_method.stderr+3-3| ... | ... | @@ -4,8 +4,8 @@ error: `#[cold]` attribute cannot be used on required trait methods |
| 4 | 4 | LL | #[cold] |
| 5 | 5 | | ^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[cold]` can be applied to closures, foreign functions, functions, inherent methods, provided trait methods, and trait methods in impl blocks |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | note: the lint level is defined here |
| 10 | 10 | --> $DIR/codegen_attr_on_required_trait_method.rs:1:9 |
| 11 | 11 | | |
| ... | ... | @@ -18,8 +18,8 @@ error: `#[link_section]` attribute cannot be used on required trait methods |
| 18 | 18 | LL | #[link_section = "__TEXT,__text"] |
| 19 | 19 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 20 | 20 | | |
| 21 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 22 | 21 | = help: `#[link_section]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks |
| 22 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 23 | 23 | |
| 24 | 24 | error: `#[linkage]` attribute cannot be used on required trait methods |
| 25 | 25 | --> $DIR/codegen_attr_on_required_trait_method.rs:14:5 |
| ... | ... | @@ -27,8 +27,8 @@ error: `#[linkage]` attribute cannot be used on required trait methods |
| 27 | 27 | LL | #[linkage = "common"] |
| 28 | 28 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 29 | 29 | | |
| 30 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 31 | 30 | = help: `#[linkage]` can be applied to foreign functions, foreign statics, functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks |
| 31 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 32 | 32 | |
| 33 | 33 | error: aborting due to 3 previous errors |
| 34 | 34 |
tests/ui/attributes/cold-attribute-application-54044.stderr+2-2| ... | ... | @@ -4,8 +4,8 @@ error: `#[cold]` attribute cannot be used on structs |
| 4 | 4 | LL | #[cold] |
| 5 | 5 | | ^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[cold]` can only be applied to functions |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | note: the lint level is defined here |
| 10 | 10 | --> $DIR/cold-attribute-application-54044.rs:2:9 |
| 11 | 11 | | |
| ... | ... | @@ -18,8 +18,8 @@ error: `#[cold]` attribute cannot be used on expressions |
| 18 | 18 | LL | #[cold] |
| 19 | 19 | | ^^^^^^^ |
| 20 | 20 | | |
| 21 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 22 | 21 | = help: `#[cold]` can only be applied to functions |
| 22 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 23 | 23 | |
| 24 | 24 | error: aborting due to 2 previous errors |
| 25 | 25 |
tests/ui/attributes/inline/attr-usage-inline.stderr+3-3| ... | ... | @@ -18,8 +18,8 @@ warning: `#[inline]` attribute cannot be used on struct fields |
| 18 | 18 | LL | #[inline] |
| 19 | 19 | | ^^^^^^^^^ |
| 20 | 20 | | |
| 21 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 22 | 21 | = help: `#[inline]` can only be applied to functions |
| 22 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 23 | 23 | = note: requested on the command line with `-W unused-attributes` |
| 24 | 24 | |
| 25 | 25 | warning: `#[inline]` attribute cannot be used on macro defs |
| ... | ... | @@ -28,8 +28,8 @@ warning: `#[inline]` attribute cannot be used on macro defs |
| 28 | 28 | LL | #[inline] |
| 29 | 29 | | ^^^^^^^^^ |
| 30 | 30 | | |
| 31 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 32 | 31 | = help: `#[inline]` can only be applied to functions |
| 32 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 33 | 33 | |
| 34 | 34 | warning: `#[inline]` attribute cannot be used on macro defs |
| 35 | 35 | --> $DIR/attr-usage-inline.rs:25:1 |
| ... | ... | @@ -37,8 +37,8 @@ warning: `#[inline]` attribute cannot be used on macro defs |
| 37 | 37 | LL | #[inline] |
| 38 | 38 | | ^^^^^^^^^ |
| 39 | 39 | | |
| 40 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 41 | 40 | = help: `#[inline]` can only be applied to functions |
| 41 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 42 | 42 | |
| 43 | 43 | error: aborting due to 2 previous errors; 3 warnings emitted |
| 44 | 44 |
tests/ui/attributes/malformed-attrs.stderr+12-12| ... | ... | @@ -126,15 +126,6 @@ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `p |
| 126 | 126 | LL | #[proc_macro_derive] |
| 127 | 127 | | ^^^^^^^^^^^^^^^^^^^^ |
| 128 | 128 | |
| 129 | error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint | |
| 130 | --> $DIR/malformed-attrs.rs:215:1 | |
| 131 | | | |
| 132 | LL | #[allow_internal_unsafe = 1] | |
| 133 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 134 | | | |
| 135 | = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable | |
| 136 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 137 | ||
| 138 | 129 | error[E0539]: malformed `windows_subsystem` attribute input |
| 139 | 130 | --> $DIR/malformed-attrs.rs:26:1 |
| 140 | 131 | | |
| ... | ... | @@ -788,6 +779,15 @@ LL - #[macro_export = 18] |
| 788 | 779 | LL + #[macro_export] |
| 789 | 780 | | |
| 790 | 781 | |
| 782 | error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint | |
| 783 | --> $DIR/malformed-attrs.rs:215:1 | |
| 784 | | | |
| 785 | LL | #[allow_internal_unsafe = 1] | |
| 786 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 787 | | | |
| 788 | = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable | |
| 789 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 790 | ||
| 791 | 791 | error[E0565]: malformed `allow_internal_unsafe` attribute input |
| 792 | 792 | --> $DIR/malformed-attrs.rs:215:1 |
| 793 | 793 | | |
| ... | ... | @@ -890,8 +890,8 @@ warning: `#[link_name]` attribute cannot be used on functions |
| 890 | 890 | LL | #[link_name] |
| 891 | 891 | | ^^^^^^^^^^^^ |
| 892 | 892 | | |
| 893 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 894 | 893 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 894 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 895 | 895 | |
| 896 | 896 | error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` |
| 897 | 897 | --> $DIR/malformed-attrs.rs:96:1 |
| ... | ... | @@ -908,8 +908,8 @@ warning: `#[no_implicit_prelude]` attribute cannot be used on functions |
| 908 | 908 | LL | #[no_implicit_prelude = 23] |
| 909 | 909 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 910 | 910 | | |
| 911 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 912 | 911 | = help: `#[no_implicit_prelude]` can be applied to crates and modules |
| 912 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 913 | 913 | |
| 914 | 914 | warning: missing options for `diagnostic::on_unimplemented` attribute |
| 915 | 915 | --> $DIR/malformed-attrs.rs:138:1 |
| ... | ... | @@ -940,8 +940,8 @@ warning: `#[automatically_derived]` attribute cannot be used on modules |
| 940 | 940 | LL | #[automatically_derived = 18] |
| 941 | 941 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 942 | 942 | | |
| 943 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 944 | 943 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 944 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 945 | 945 | |
| 946 | 946 | error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` |
| 947 | 947 | --> $DIR/malformed-attrs.rs:222:1 |
tests/ui/attributes/unstable_removed.stderr+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/unstable_removed.rs:9:1 |
| 3 | 3 | | |
| 4 | 4 | LL | / #![unstable_removed( |
| ... | ... | @@ -30,5 +30,5 @@ LL | #![feature(concat_idents)] |
| 30 | 30 | |
| 31 | 31 | error: aborting due to 3 previous errors |
| 32 | 32 | |
| 33 | Some errors have detailed explanations: E0557, E0734. | |
| 33 | Some errors have detailed explanations: E0557, E0658. | |
| 34 | 34 | For more information about an error, try `rustc --explain E0557`. |
tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr+1-1| ... | ... | @@ -171,8 +171,8 @@ warning: `#[link_section]` attribute cannot be used on structs |
| 171 | 171 | LL | #[cfg_attr(true, link_section)] |
| 172 | 172 | | ^^^^^^^^^^^^ |
| 173 | 173 | | |
| 174 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 175 | 174 | = help: `#[link_section]` can be applied to functions and statics |
| 175 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 176 | 176 | = note: requested on the command line with `-W unused-attributes` |
| 177 | 177 | |
| 178 | 178 | error: aborting due to 13 previous errors; 1 warning emitted |
tests/ui/const-generics/invalid-attributes-on-const-params-78957.stderr+3-3| ... | ... | @@ -46,8 +46,8 @@ error: `#[cold]` attribute cannot be used on const parameters |
| 46 | 46 | LL | pub struct Bar<#[cold] const N: usize>; |
| 47 | 47 | | ^^^^^^^ |
| 48 | 48 | | |
| 49 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 50 | 49 | = help: `#[cold]` can only be applied to functions |
| 50 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 51 | 51 | note: the lint level is defined here |
| 52 | 52 | --> $DIR/invalid-attributes-on-const-params-78957.rs:2:9 |
| 53 | 53 | | |
| ... | ... | @@ -60,8 +60,8 @@ error: `#[cold]` attribute cannot be used on lifetime parameters |
| 60 | 60 | LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>); |
| 61 | 61 | | ^^^^^^^ |
| 62 | 62 | | |
| 63 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 64 | 63 | = help: `#[cold]` can only be applied to functions |
| 64 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 65 | 65 | |
| 66 | 66 | error: `#[cold]` attribute cannot be used on type parameters |
| 67 | 67 | --> $DIR/invalid-attributes-on-const-params-78957.rs:24:17 |
| ... | ... | @@ -69,8 +69,8 @@ error: `#[cold]` attribute cannot be used on type parameters |
| 69 | 69 | LL | pub struct Bar3<#[cold] T>(PhantomData<T>); |
| 70 | 70 | | ^^^^^^^ |
| 71 | 71 | | |
| 72 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 73 | 72 | = help: `#[cold]` can only be applied to functions |
| 73 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 74 | 74 | |
| 75 | 75 | error: aborting due to 9 previous errors |
| 76 | 76 |
tests/ui/coroutine/gen_block.e2024.stderr+11-11| ... | ... | @@ -1,3 +1,14 @@ |
| 1 | error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks | |
| 2 | --> $DIR/gen_block.rs:16:16 | |
| 3 | | | |
| 4 | LL | let _ = || yield true; | |
| 5 | | ^^^^^^^^^^ | |
| 6 | | | |
| 7 | help: use `#[coroutine]` to make this closure a coroutine | |
| 8 | | | |
| 9 | LL | let _ = #[coroutine] || yield true; | |
| 10 | | ++++++++++++ | |
| 11 | ||
| 1 | 12 | error[E0658]: the `#[coroutine]` attribute is an experimental feature |
| 2 | 13 | --> $DIR/gen_block.rs:20:13 |
| 3 | 14 | | |
| ... | ... | @@ -18,17 +29,6 @@ LL | let _ = #[coroutine] || {}; |
| 18 | 29 | = help: add `#![feature(coroutines)]` to the crate attributes to enable |
| 19 | 30 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 20 | 31 | |
| 21 | error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks | |
| 22 | --> $DIR/gen_block.rs:16:16 | |
| 23 | | | |
| 24 | LL | let _ = || yield true; | |
| 25 | | ^^^^^^^^^^ | |
| 26 | | | |
| 27 | help: use `#[coroutine]` to make this closure a coroutine | |
| 28 | | | |
| 29 | LL | let _ = #[coroutine] || yield true; | |
| 30 | | ++++++++++++ | |
| 31 | ||
| 32 | 32 | error[E0282]: type annotations needed |
| 33 | 33 | --> $DIR/gen_block.rs:7:13 |
| 34 | 34 | | |
tests/ui/coroutine/gen_block.none.stderr+20-20| ... | ... | @@ -44,26 +44,6 @@ LL | let _ = #[coroutine] || yield true; |
| 44 | 44 | = help: add `#![feature(yield_expr)]` to the crate attributes to enable |
| 45 | 45 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 46 | 46 | |
| 47 | error[E0658]: the `#[coroutine]` attribute is an experimental feature | |
| 48 | --> $DIR/gen_block.rs:20:13 | |
| 49 | | | |
| 50 | LL | let _ = #[coroutine] || yield true; | |
| 51 | | ^^^^^^^^^^^^ | |
| 52 | | | |
| 53 | = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information | |
| 54 | = help: add `#![feature(coroutines)]` to the crate attributes to enable | |
| 55 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 56 | ||
| 57 | error[E0658]: the `#[coroutine]` attribute is an experimental feature | |
| 58 | --> $DIR/gen_block.rs:24:13 | |
| 59 | | | |
| 60 | LL | let _ = #[coroutine] || {}; | |
| 61 | | ^^^^^^^^^^^^ | |
| 62 | | | |
| 63 | = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information | |
| 64 | = help: add `#![feature(coroutines)]` to the crate attributes to enable | |
| 65 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 66 | ||
| 67 | 47 | error[E0658]: yield syntax is experimental |
| 68 | 48 | --> $DIR/gen_block.rs:16:16 |
| 69 | 49 | | |
| ... | ... | @@ -85,6 +65,16 @@ help: use `#[coroutine]` to make this closure a coroutine |
| 85 | 65 | LL | let _ = #[coroutine] || yield true; |
| 86 | 66 | | ++++++++++++ |
| 87 | 67 | |
| 68 | error[E0658]: the `#[coroutine]` attribute is an experimental feature | |
| 69 | --> $DIR/gen_block.rs:20:13 | |
| 70 | | | |
| 71 | LL | let _ = #[coroutine] || yield true; | |
| 72 | | ^^^^^^^^^^^^ | |
| 73 | | | |
| 74 | = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information | |
| 75 | = help: add `#![feature(coroutines)]` to the crate attributes to enable | |
| 76 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 77 | ||
| 88 | 78 | error[E0658]: yield syntax is experimental |
| 89 | 79 | --> $DIR/gen_block.rs:20:29 |
| 90 | 80 | | |
| ... | ... | @@ -95,6 +85,16 @@ LL | let _ = #[coroutine] || yield true; |
| 95 | 85 | = help: add `#![feature(yield_expr)]` to the crate attributes to enable |
| 96 | 86 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 97 | 87 | |
| 88 | error[E0658]: the `#[coroutine]` attribute is an experimental feature | |
| 89 | --> $DIR/gen_block.rs:24:13 | |
| 90 | | | |
| 91 | LL | let _ = #[coroutine] || {}; | |
| 92 | | ^^^^^^^^^^^^ | |
| 93 | | | |
| 94 | = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information | |
| 95 | = help: add `#![feature(coroutines)]` to the crate attributes to enable | |
| 96 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 97 | ||
| 98 | 98 | error: aborting due to 11 previous errors |
| 99 | 99 | |
| 100 | 100 | Some errors have detailed explanations: E0422, E0658. |
tests/ui/definition-reachable/auxiliary/field-access-macro.rs created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | #![feature(decl_macro)] | |
| 2 | ||
| 3 | mod n { | |
| 4 | pub struct Struct(i32); | |
| 5 | pub fn get_struct() -> Struct { Struct(0) } | |
| 6 | ||
| 7 | pub macro allow_field_access($x:expr) { | |
| 8 | &mut $x.0 | |
| 9 | } | |
| 10 | } | |
| 11 | ||
| 12 | pub use n::{allow_field_access, get_struct}; | |
| 13 | ||
| 14 | pub macro deny_field_access($x:expr) { | |
| 15 | &mut $x.0 | |
| 16 | } |
tests/ui/definition-reachable/auxiliary/transitive-macro.rs created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | #![feature(decl_macro)] | |
| 2 | ||
| 3 | mod mod1 { | |
| 4 | mod mod2 { | |
| 5 | pub fn foo() {} | |
| 6 | } | |
| 7 | ||
| 8 | pub(crate) macro m1() { | |
| 9 | mod2::foo() | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub macro m() { | |
| 14 | mod1::m1!() | |
| 15 | } |
tests/ui/definition-reachable/field-access.rs created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | //@ aux-build:field-access-macro.rs | |
| 2 | ||
| 3 | extern crate field_access_macro; | |
| 4 | ||
| 5 | fn main() { | |
| 6 | let mut s = field_access_macro::get_struct(); | |
| 7 | ||
| 8 | let try_field_access = field_access_macro::allow_field_access!(s); // Ok | |
| 9 | let try_field_access = field_access_macro::deny_field_access!(s); | |
| 10 | //~^ ERROR field `0` of struct `field_access_macro::n::Struct` is private | |
| 11 | } |
tests/ui/definition-reachable/field-access.stderr created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | error[E0616]: field `0` of struct `field_access_macro::n::Struct` is private | |
| 2 | --> $DIR/field-access.rs:9:28 | |
| 3 | | | |
| 4 | LL | let try_field_access = field_access_macro::deny_field_access!(s); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private field | |
| 6 | | | |
| 7 | = note: this error originates in the macro `field_access_macro::deny_field_access` (in Nightly builds, run with -Z macro-backtrace for more info) | |
| 8 | ||
| 9 | error: aborting due to 1 previous error | |
| 10 | ||
| 11 | For more information about this error, try `rustc --explain E0616`. |
tests/ui/definition-reachable/field-method.rs+4-4| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | // Check that functions accessible through a field visible to a macro are | |
| 1 | // Check that functions visible to macros through paths with >2 segments are | |
| 2 | 2 | // considered reachable |
| 3 | 3 | |
| 4 | //@ aux-build:nested-fn-macro.rs | |
| 4 | //@ aux-build:field-method-macro.rs | |
| 5 | 5 | //@ run-pass |
| 6 | 6 | |
| 7 | extern crate nested_fn_macro; | |
| 7 | extern crate field_method_macro; | |
| 8 | 8 | |
| 9 | 9 | fn main() { |
| 10 | assert_eq!(nested_fn_macro::m!(), 12); | |
| 10 | assert_eq!(field_method_macro::m!(), 33); | |
| 11 | 11 | } |
tests/ui/definition-reachable/nested-fn.rs+4-4| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | // Check that functions visible to macros through paths with >2 segments are | |
| 1 | // Check that functions accessible through a field visible to a macro are | |
| 2 | 2 | // considered reachable |
| 3 | 3 | |
| 4 | //@ aux-build:field-method-macro.rs | |
| 4 | //@ aux-build:nested-fn-macro.rs | |
| 5 | 5 | //@ run-pass |
| 6 | 6 | |
| 7 | extern crate field_method_macro; | |
| 7 | extern crate nested_fn_macro; | |
| 8 | 8 | |
| 9 | 9 | fn main() { |
| 10 | assert_eq!(field_method_macro::m!(), 33); | |
| 10 | assert_eq!(nested_fn_macro::m!(), 12); | |
| 11 | 11 | } |
tests/ui/definition-reachable/transitive.rs created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | //@ aux-build:transitive-macro.rs | |
| 2 | //@ build-fail | |
| 3 | ||
| 4 | extern crate transitive_macro; | |
| 5 | ||
| 6 | fn main() { | |
| 7 | transitive_macro::m!(); | |
| 8 | } | |
| 9 | ||
| 10 | //~? ERROR missing optimized MIR for `transitive_macro::mod1::mod2::foo` in the crate `transitive_macro` |
tests/ui/definition-reachable/transitive.stderr created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | error: missing optimized MIR for `transitive_macro::mod1::mod2::foo` in the crate `transitive_macro` | |
| 2 | | | |
| 3 | note: missing optimized MIR for this item (was the crate `transitive_macro` compiled with `--emit=metadata`?) | |
| 4 | --> $DIR/auxiliary/transitive-macro.rs:5:9 | |
| 5 | | | |
| 6 | LL | pub fn foo() {} | |
| 7 | | ^^^^^^^^^^^^ | |
| 8 | ||
| 9 | error: aborting due to 1 previous error | |
| 10 |
tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr+1-1| ... | ... | @@ -4,8 +4,8 @@ error: `#[deprecated]` attribute cannot be used on delegations |
| 4 | 4 | LL | #[deprecated] |
| 5 | 5 | | ^^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | = note: `#[deny(useless_deprecated)]` on by default |
| 10 | 10 | |
| 11 | 11 | error: aborting due to 1 previous error |
tests/ui/deprecation/deprecated-expr-precedence.stderr+1-1| ... | ... | @@ -4,8 +4,8 @@ warning: `#[deprecated]` attribute cannot be used on expressions |
| 4 | 4 | LL | #[deprecated] 0 |
| 5 | 5 | | ^^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | = note: requested on the command line with `-W unused-attributes` |
| 10 | 10 | |
| 11 | 11 | error[E0308]: mismatched types |
tests/ui/deprecation/deprecation-sanity.stderr+1-1| ... | ... | @@ -101,8 +101,8 @@ error: `#[deprecated]` attribute cannot be used on trait impl blocks |
| 101 | 101 | LL | #[deprecated = "hello"] |
| 102 | 102 | | ^^^^^^^^^^^^^^^^^^^^^^^ |
| 103 | 103 | | |
| 104 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 105 | 104 | = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements |
| 105 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 106 | 106 | = note: `#[deny(useless_deprecated)]` on by default |
| 107 | 107 | |
| 108 | 108 | error: aborting due to 11 previous errors |
tests/ui/eii/auxiliary/unused_extern_crate_decl.rs created+6| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | //@ no-prefer-dynamic | |
| 2 | #![crate_type = "rlib"] | |
| 3 | #![feature(extern_item_impls)] | |
| 4 | ||
| 5 | #[eii(eii1)] | |
| 6 | pub fn decl1(x: u64); |
tests/ui/eii/auxiliary/unused_extern_crate_impl.rs created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | //@ no-prefer-dynamic | |
| 2 | //@ aux-build:unused_extern_crate_decl.rs | |
| 3 | #![crate_type = "rlib"] | |
| 4 | #![feature(extern_item_impls)] | |
| 5 | ||
| 6 | extern crate unused_extern_crate_decl; | |
| 7 | ||
| 8 | #[unused_extern_crate_decl::eii1] | |
| 9 | fn impl1(x: u64) {} |
tests/ui/eii/dylib_needs_impl.rs+1-1| ... | ... | @@ -3,5 +3,5 @@ |
| 3 | 3 | #![crate_type = "dylib"] |
| 4 | 4 | #![feature(extern_item_impls)] |
| 5 | 5 | |
| 6 | #[eii(eii1)] //~ ERROR `#[eii1]` required, but not found | |
| 6 | #[eii(eii1)] //~ ERROR `#[eii1]` function required, but not found | |
| 7 | 7 | fn decl1(x: u64); |
tests/ui/eii/dylib_needs_impl.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: `#[eii1]` required, but not found | |
| 1 | error: `#[eii1]` function required, but not found | |
| 2 | 2 | --> $DIR/dylib_needs_impl.rs:6:7 |
| 3 | 3 | | |
| 4 | 4 | LL | #[eii(eii1)] |
tests/ui/eii/privacy2.rs+2-2| ... | ... | @@ -5,8 +5,8 @@ |
| 5 | 5 | extern crate other_crate_privacy2 as codegen; |
| 6 | 6 | |
| 7 | 7 | // has a span but in the other crate |
| 8 | //~? ERROR `#[eii2]` required, but not found | |
| 9 | //~? ERROR `#[eii3]` required, but not found | |
| 8 | //~? ERROR `#[eii2]` function required, but not found | |
| 9 | //~? ERROR `#[eii3]` function required, but not found | |
| 10 | 10 | |
| 11 | 11 | #[codegen::eii1] |
| 12 | 12 | fn eii1_impl(x: u64) { |
tests/ui/eii/privacy2.stderr+2-2| ... | ... | @@ -16,7 +16,7 @@ note: the function `decl1` is defined here |
| 16 | 16 | LL | fn decl1(x: u64); |
| 17 | 17 | | ^^^^^^^^^^^^^^^^^ |
| 18 | 18 | |
| 19 | error: `#[eii2]` required, but not found | |
| 19 | error: `#[eii2]` function required, but not found | |
| 20 | 20 | --> $DIR/auxiliary/other_crate_privacy2.rs:9:7 |
| 21 | 21 | | |
| 22 | 22 | LL | #[eii(eii2)] |
| ... | ... | @@ -24,7 +24,7 @@ LL | #[eii(eii2)] |
| 24 | 24 | | |
| 25 | 25 | = help: expected at least one implementation in crate `privacy2` or any of its dependencies |
| 26 | 26 | |
| 27 | error: `#[eii3]` required, but not found | |
| 27 | error: `#[eii3]` function required, but not found | |
| 28 | 28 | --> $DIR/auxiliary/other_crate_privacy2.rs:13:11 |
| 29 | 29 | | |
| 30 | 30 | LL | #[eii(eii3)] |
tests/ui/eii/shadow_builtin.rs+2-2| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | #![feature(extern_item_impls)] |
| 6 | 6 | |
| 7 | 7 | #[eii(inline)] |
| 8 | //~^ ERROR `#[inline]` required, but not found | |
| 8 | //~^ ERROR `#[inline]` function required, but not found | |
| 9 | 9 | fn test(x: u64); |
| 10 | 10 | |
| 11 | 11 | #[inline] |
| ... | ... | @@ -14,4 +14,4 @@ fn test_impl(x: u64) { |
| 14 | 14 | println!("{x:?}") |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | fn main() { } | |
| 17 | fn main() {} |
tests/ui/eii/shadow_builtin.stderr+1-1| ... | ... | @@ -13,7 +13,7 @@ LL | #[eii(inline)] |
| 13 | 13 | | ^^^^^^^^^^^^^^ |
| 14 | 14 | = help: use `crate::inline` to refer to this attribute macro unambiguously |
| 15 | 15 | |
| 16 | error: `#[inline]` required, but not found | |
| 16 | error: `#[inline]` function required, but not found | |
| 17 | 17 | --> $DIR/shadow_builtin.rs:7:7 |
| 18 | 18 | | |
| 19 | 19 | LL | #[eii(inline)] |
tests/ui/eii/unused_extern_crate.rs created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | //@ aux-build:unused_extern_crate_decl.rs | |
| 2 | //@ aux-build:unused_extern_crate_impl.rs | |
| 3 | // Tests that dependencies that contain an EII decl without any EII impl are | |
| 4 | // still considered unused. | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | #![deny(unused_extern_crates)] | |
| 7 | ||
| 8 | extern crate unused_extern_crate_decl; //~ ERROR unused extern crate | |
| 9 | extern crate unused_extern_crate_impl; | |
| 10 | ||
| 11 | fn main() {} |
tests/ui/eii/unused_extern_crate.stderr created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | error: unused extern crate | |
| 2 | --> $DIR/unused_extern_crate.rs:8:1 | |
| 3 | | | |
| 4 | LL | extern crate unused_extern_crate_decl; | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused | |
| 6 | | | |
| 7 | note: the lint level is defined here | |
| 8 | --> $DIR/unused_extern_crate.rs:6:9 | |
| 9 | | | |
| 10 | LL | #![deny(unused_extern_crates)] | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^ | |
| 12 | help: remove the unused `extern crate` | |
| 13 | | | |
| 14 | LL - extern crate unused_extern_crate_decl; | |
| 15 | LL + | |
| 16 | | | |
| 17 | ||
| 18 | error: aborting due to 1 previous error | |
| 19 |
tests/ui/error-codes/E0152-duplicate-lang-items.rs-4| ... | ... | @@ -8,10 +8,6 @@ |
| 8 | 8 | |
| 9 | 9 | #![feature(lang_items)] |
| 10 | 10 | |
| 11 | extern crate core; | |
| 12 | ||
| 13 | use core::panic::PanicInfo; | |
| 14 | ||
| 15 | 11 | #[lang = "eh_personality"] |
| 16 | 12 | fn personality() { |
| 17 | 13 | //~^ ERROR: found duplicate lang item `eh_personality` |
tests/ui/error-codes/E0152-duplicate-lang-items.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[E0152]: found duplicate lang item `eh_personality` |
| 2 | --> $DIR/E0152-duplicate-lang-items.rs:16:1 | |
| 2 | --> $DIR/E0152-duplicate-lang-items.rs:12:1 | |
| 3 | 3 | | |
| 4 | 4 | LL | / fn personality() { |
| 5 | 5 | LL | | |
tests/ui/extern/extern-no-mangle.stderr+3-3| ... | ... | @@ -4,8 +4,8 @@ warning: `#[no_mangle]` attribute cannot be used on foreign statics |
| 4 | 4 | LL | #[no_mangle] |
| 5 | 5 | | ^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[no_mangle]` can be applied to functions and statics |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | note: the lint level is defined here |
| 10 | 10 | --> $DIR/extern-no-mangle.rs:1:9 |
| 11 | 11 | | |
| ... | ... | @@ -18,8 +18,8 @@ warning: `#[no_mangle]` attribute cannot be used on foreign functions |
| 18 | 18 | LL | #[no_mangle] |
| 19 | 19 | | ^^^^^^^^^^^^ |
| 20 | 20 | | |
| 21 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 22 | 21 | = help: `#[no_mangle]` can be applied to functions, methods, and statics |
| 22 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 23 | 23 | |
| 24 | 24 | warning: `#[no_mangle]` attribute cannot be used on statements |
| 25 | 25 | --> $DIR/extern-no-mangle.rs:24:5 |
| ... | ... | @@ -27,8 +27,8 @@ warning: `#[no_mangle]` attribute cannot be used on statements |
| 27 | 27 | LL | #[no_mangle] |
| 28 | 28 | | ^^^^^^^^^^^^ |
| 29 | 29 | | |
| 30 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 31 | 30 | = help: `#[no_mangle]` can be applied to functions and statics |
| 31 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 32 | 32 | |
| 33 | 33 | warning: 3 warnings emitted |
| 34 | 34 |
tests/ui/extern/issue-47725.stderr+3-3| ... | ... | @@ -16,8 +16,8 @@ warning: `#[link_name]` attribute cannot be used on structs |
| 16 | 16 | LL | #[link_name = "foo"] |
| 17 | 17 | | ^^^^^^^^^^^^^^^^^^^^ |
| 18 | 18 | | |
| 19 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 20 | 19 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 20 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 21 | 21 | note: the lint level is defined here |
| 22 | 22 | --> $DIR/issue-47725.rs:2:9 |
| 23 | 23 | | |
| ... | ... | @@ -30,8 +30,8 @@ warning: `#[link_name]` attribute cannot be used on foreign modules |
| 30 | 30 | LL | #[link_name = "foobar"] |
| 31 | 31 | | ^^^^^^^^^^^^^^^^^^^^^^^ |
| 32 | 32 | | |
| 33 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 34 | 33 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 34 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 35 | 35 | |
| 36 | 36 | warning: `#[link_name]` attribute cannot be used on foreign modules |
| 37 | 37 | --> $DIR/issue-47725.rs:20:1 |
| ... | ... | @@ -39,8 +39,8 @@ warning: `#[link_name]` attribute cannot be used on foreign modules |
| 39 | 39 | LL | #[link_name] |
| 40 | 40 | | ^^^^^^^^^^^^ |
| 41 | 41 | | |
| 42 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 43 | 42 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 43 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 44 | 44 | |
| 45 | 45 | error: aborting due to 1 previous error; 3 warnings emitted |
| 46 | 46 |
tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs+3-1| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | // Test internal const fn feature gate. |
| 2 | 2 | |
| 3 | #[rustc_const_unstable(feature="fzzzzzt")] //~ ERROR stability attributes may not be used outside | |
| 3 | #[rustc_const_unstable(feature="fzzzzzt")] | |
| 4 | //~^ ERROR stability attributes may not be used outside | |
| 5 | //~| ERROR missing 'issue' | |
| 4 | 6 | pub const fn bazinga() {} |
| 5 | 7 | |
| 6 | 8 | fn main() { |
tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr+10-3| ... | ... | @@ -1,9 +1,16 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/feature-gate-rustc_const_unstable.rs:3:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #[rustc_const_unstable(feature="fzzzzzt")] |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | error: aborting due to 1 previous error | |
| 7 | error[E0547]: missing 'issue' | |
| 8 | --> $DIR/feature-gate-rustc_const_unstable.rs:3:1 | |
| 9 | | | |
| 10 | LL | #[rustc_const_unstable(feature="fzzzzzt")] | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error: aborting due to 2 previous errors | |
| 8 | 14 | |
| 9 | For more information about this error, try `rustc --explain E0734`. | |
| 15 | Some errors have detailed explanations: E0547, E0658. | |
| 16 | For more information about an error, try `rustc --explain E0547`. |
tests/ui/feature-gates/feature-gate-staged_api.stderr+3-3| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/feature-gate-staged_api.rs:1:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #![stable(feature = "a", since = "3.3.3")] |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 7 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 8 | 8 | --> $DIR/feature-gate-staged_api.rs:8:1 |
| 9 | 9 | | |
| 10 | 10 | LL | #[stable(feature = "a", since = "3.3.3")] |
| ... | ... | @@ -12,4 +12,4 @@ LL | #[stable(feature = "a", since = "3.3.3")] |
| 12 | 12 | |
| 13 | 13 | error: aborting due to 2 previous errors |
| 14 | 14 | |
| 15 | For more information about this error, try `rustc --explain E0734`. | |
| 15 | For more information about this error, try `rustc --explain E0658`. |
tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr+12-12| ... | ... | @@ -1,3 +1,11 @@ |
| 1 | error: `#[macro_export]` attribute cannot be used on crates | |
| 2 | --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:9:1 | |
| 3 | | | |
| 4 | LL | #![macro_export] | |
| 5 | | ^^^^^^^^^^^^^^^^ | |
| 6 | | | |
| 7 | = help: `#[macro_export]` can only be applied to macro defs | |
| 8 | ||
| 1 | 9 | error[E0658]: use of an internal attribute |
| 2 | 10 | --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:11:1 |
| 3 | 11 | | |
| ... | ... | @@ -8,14 +16,6 @@ LL | #![rustc_main] |
| 8 | 16 | = note: the `#[rustc_main]` attribute is an internal implementation detail that will never be stable |
| 9 | 17 | = note: the `#[rustc_main]` attribute is used internally to specify test entry point function |
| 10 | 18 | |
| 11 | error: `#[macro_export]` attribute cannot be used on crates | |
| 12 | --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:9:1 | |
| 13 | | | |
| 14 | LL | #![macro_export] | |
| 15 | | ^^^^^^^^^^^^^^^^ | |
| 16 | | | |
| 17 | = help: `#[macro_export]` can only be applied to macro defs | |
| 18 | ||
| 19 | 19 | error: `#[rustc_main]` attribute cannot be used on crates |
| 20 | 20 | --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:11:1 |
| 21 | 21 | | |
| ... | ... | @@ -322,8 +322,8 @@ warning: `#[no_link]` attribute cannot be used on match arms |
| 322 | 322 | LL | #[no_link] |
| 323 | 323 | | ^^^^^^^^^^ |
| 324 | 324 | | |
| 325 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 326 | 325 | = help: `#[no_link]` can only be applied to extern crates |
| 326 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 327 | 327 | |
| 328 | 328 | warning: `#[no_link]` attribute cannot be used on struct fields |
| 329 | 329 | --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:9 |
| ... | ... | @@ -331,8 +331,8 @@ warning: `#[no_link]` attribute cannot be used on struct fields |
| 331 | 331 | LL | #[no_link] |
| 332 | 332 | | ^^^^^^^^^^ |
| 333 | 333 | | |
| 334 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 335 | 334 | = help: `#[no_link]` can only be applied to extern crates |
| 335 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 336 | 336 | |
| 337 | 337 | warning: `#[no_link]` attribute cannot be used on macro defs |
| 338 | 338 | --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:92:5 |
| ... | ... | @@ -340,8 +340,8 @@ warning: `#[no_link]` attribute cannot be used on macro defs |
| 340 | 340 | LL | #[no_link] |
| 341 | 341 | | ^^^^^^^^^^ |
| 342 | 342 | | |
| 343 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 344 | 343 | = help: `#[no_link]` can only be applied to extern crates |
| 344 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 345 | 345 | |
| 346 | 346 | warning: unused attribute |
| 347 | 347 | --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1 |
| ... | ... | @@ -357,8 +357,8 @@ warning: `#[no_mangle]` attribute cannot be used on crates |
| 357 | 357 | LL | #![no_mangle] |
| 358 | 358 | | ^^^^^^^^^^^^^ |
| 359 | 359 | | |
| 360 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 361 | 360 | = help: `#[no_mangle]` can be applied to functions and statics |
| 361 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 362 | 362 | |
| 363 | 363 | error: aborting due to 37 previous errors; 6 warnings emitted |
| 364 | 364 |
tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr+76-76| ... | ... | @@ -277,8 +277,8 @@ warning: `#[macro_use]` attribute cannot be used on functions |
| 277 | 277 | LL | #[macro_use] fn f() { } |
| 278 | 278 | | ^^^^^^^^^^^^ |
| 279 | 279 | | |
| 280 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 281 | 280 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 281 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 282 | 282 | |
| 283 | 283 | warning: `#[macro_use]` attribute cannot be used on structs |
| 284 | 284 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5 |
| ... | ... | @@ -286,8 +286,8 @@ warning: `#[macro_use]` attribute cannot be used on structs |
| 286 | 286 | LL | #[macro_use] struct S; |
| 287 | 287 | | ^^^^^^^^^^^^ |
| 288 | 288 | | |
| 289 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 290 | 289 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 290 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 291 | 291 | |
| 292 | 292 | warning: `#[macro_use]` attribute cannot be used on type aliases |
| 293 | 293 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5 |
| ... | ... | @@ -295,8 +295,8 @@ warning: `#[macro_use]` attribute cannot be used on type aliases |
| 295 | 295 | LL | #[macro_use] type T = S; |
| 296 | 296 | | ^^^^^^^^^^^^ |
| 297 | 297 | | |
| 298 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 299 | 298 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 299 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 300 | 300 | |
| 301 | 301 | warning: `#[macro_use]` attribute cannot be used on inherent impl blocks |
| 302 | 302 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:5 |
| ... | ... | @@ -304,8 +304,8 @@ warning: `#[macro_use]` attribute cannot be used on inherent impl blocks |
| 304 | 304 | LL | #[macro_use] impl S { } |
| 305 | 305 | | ^^^^^^^^^^^^ |
| 306 | 306 | | |
| 307 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 308 | 307 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 308 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 309 | 309 | |
| 310 | 310 | warning: `#[macro_export]` attribute cannot be used on modules |
| 311 | 311 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:214:1 |
| ... | ... | @@ -313,8 +313,8 @@ warning: `#[macro_export]` attribute cannot be used on modules |
| 313 | 313 | LL | #[macro_export] |
| 314 | 314 | | ^^^^^^^^^^^^^^^ |
| 315 | 315 | | |
| 316 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 317 | 316 | = help: `#[macro_export]` can only be applied to macro defs |
| 317 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 318 | 318 | |
| 319 | 319 | warning: `#[macro_export]` attribute cannot be used on modules |
| 320 | 320 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:220:17 |
| ... | ... | @@ -322,8 +322,8 @@ warning: `#[macro_export]` attribute cannot be used on modules |
| 322 | 322 | LL | mod inner { #![macro_export] } |
| 323 | 323 | | ^^^^^^^^^^^^^^^^ |
| 324 | 324 | | |
| 325 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 326 | 325 | = help: `#[macro_export]` can only be applied to macro defs |
| 326 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 327 | 327 | |
| 328 | 328 | warning: `#[macro_export]` attribute cannot be used on functions |
| 329 | 329 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:226:5 |
| ... | ... | @@ -331,8 +331,8 @@ warning: `#[macro_export]` attribute cannot be used on functions |
| 331 | 331 | LL | #[macro_export] fn f() { } |
| 332 | 332 | | ^^^^^^^^^^^^^^^ |
| 333 | 333 | | |
| 334 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 335 | 334 | = help: `#[macro_export]` can only be applied to macro defs |
| 335 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 336 | 336 | |
| 337 | 337 | warning: `#[macro_export]` attribute cannot be used on structs |
| 338 | 338 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:232:5 |
| ... | ... | @@ -340,8 +340,8 @@ warning: `#[macro_export]` attribute cannot be used on structs |
| 340 | 340 | LL | #[macro_export] struct S; |
| 341 | 341 | | ^^^^^^^^^^^^^^^ |
| 342 | 342 | | |
| 343 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 344 | 343 | = help: `#[macro_export]` can only be applied to macro defs |
| 344 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 345 | 345 | |
| 346 | 346 | warning: `#[macro_export]` attribute cannot be used on type aliases |
| 347 | 347 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:238:5 |
| ... | ... | @@ -349,8 +349,8 @@ warning: `#[macro_export]` attribute cannot be used on type aliases |
| 349 | 349 | LL | #[macro_export] type T = S; |
| 350 | 350 | | ^^^^^^^^^^^^^^^ |
| 351 | 351 | | |
| 352 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 353 | 352 | = help: `#[macro_export]` can only be applied to macro defs |
| 353 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 354 | 354 | |
| 355 | 355 | warning: `#[macro_export]` attribute cannot be used on inherent impl blocks |
| 356 | 356 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:244:5 |
| ... | ... | @@ -358,8 +358,8 @@ warning: `#[macro_export]` attribute cannot be used on inherent impl blocks |
| 358 | 358 | LL | #[macro_export] impl S { } |
| 359 | 359 | | ^^^^^^^^^^^^^^^ |
| 360 | 360 | | |
| 361 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 362 | 361 | = help: `#[macro_export]` can only be applied to macro defs |
| 362 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 363 | 363 | |
| 364 | 364 | warning: `#[path]` attribute cannot be used on functions |
| 365 | 365 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:5 |
| ... | ... | @@ -367,8 +367,8 @@ warning: `#[path]` attribute cannot be used on functions |
| 367 | 367 | LL | #[path = "3800"] fn f() { } |
| 368 | 368 | | ^^^^^^^^^^^^^^^^ |
| 369 | 369 | | |
| 370 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 371 | 370 | = help: `#[path]` can only be applied to modules |
| 371 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 372 | 372 | |
| 373 | 373 | warning: `#[path]` attribute cannot be used on structs |
| 374 | 374 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:261:5 |
| ... | ... | @@ -376,8 +376,8 @@ warning: `#[path]` attribute cannot be used on structs |
| 376 | 376 | LL | #[path = "3800"] struct S; |
| 377 | 377 | | ^^^^^^^^^^^^^^^^ |
| 378 | 378 | | |
| 379 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 380 | 379 | = help: `#[path]` can only be applied to modules |
| 380 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 381 | 381 | |
| 382 | 382 | warning: `#[path]` attribute cannot be used on type aliases |
| 383 | 383 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:267:5 |
| ... | ... | @@ -385,8 +385,8 @@ warning: `#[path]` attribute cannot be used on type aliases |
| 385 | 385 | LL | #[path = "3800"] type T = S; |
| 386 | 386 | | ^^^^^^^^^^^^^^^^ |
| 387 | 387 | | |
| 388 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 389 | 388 | = help: `#[path]` can only be applied to modules |
| 389 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 390 | 390 | |
| 391 | 391 | warning: `#[path]` attribute cannot be used on inherent impl blocks |
| 392 | 392 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:273:5 |
| ... | ... | @@ -394,8 +394,8 @@ warning: `#[path]` attribute cannot be used on inherent impl blocks |
| 394 | 394 | LL | #[path = "3800"] impl S { } |
| 395 | 395 | | ^^^^^^^^^^^^^^^^ |
| 396 | 396 | | |
| 397 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 398 | 397 | = help: `#[path]` can only be applied to modules |
| 398 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 399 | 399 | |
| 400 | 400 | warning: `#[automatically_derived]` attribute cannot be used on modules |
| 401 | 401 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:1 |
| ... | ... | @@ -403,8 +403,8 @@ warning: `#[automatically_derived]` attribute cannot be used on modules |
| 403 | 403 | LL | #[automatically_derived] |
| 404 | 404 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 405 | 405 | | |
| 406 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 407 | 406 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 407 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 408 | 408 | |
| 409 | 409 | warning: `#[automatically_derived]` attribute cannot be used on modules |
| 410 | 410 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:286:17 |
| ... | ... | @@ -412,8 +412,8 @@ warning: `#[automatically_derived]` attribute cannot be used on modules |
| 412 | 412 | LL | mod inner { #![automatically_derived] } |
| 413 | 413 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 414 | 414 | | |
| 415 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 416 | 415 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 416 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 417 | 417 | |
| 418 | 418 | warning: `#[automatically_derived]` attribute cannot be used on functions |
| 419 | 419 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:292:5 |
| ... | ... | @@ -421,8 +421,8 @@ warning: `#[automatically_derived]` attribute cannot be used on functions |
| 421 | 421 | LL | #[automatically_derived] fn f() { } |
| 422 | 422 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 423 | 423 | | |
| 424 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 425 | 424 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 425 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 426 | 426 | |
| 427 | 427 | warning: `#[automatically_derived]` attribute cannot be used on structs |
| 428 | 428 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:298:5 |
| ... | ... | @@ -430,8 +430,8 @@ warning: `#[automatically_derived]` attribute cannot be used on structs |
| 430 | 430 | LL | #[automatically_derived] struct S; |
| 431 | 431 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 432 | 432 | | |
| 433 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 434 | 433 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 434 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 435 | 435 | |
| 436 | 436 | warning: `#[automatically_derived]` attribute cannot be used on type aliases |
| 437 | 437 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:304:5 |
| ... | ... | @@ -439,8 +439,8 @@ warning: `#[automatically_derived]` attribute cannot be used on type aliases |
| 439 | 439 | LL | #[automatically_derived] type T = S; |
| 440 | 440 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 441 | 441 | | |
| 442 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 443 | 442 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 443 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 444 | 444 | |
| 445 | 445 | warning: `#[automatically_derived]` attribute cannot be used on traits |
| 446 | 446 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:310:5 |
| ... | ... | @@ -448,8 +448,8 @@ warning: `#[automatically_derived]` attribute cannot be used on traits |
| 448 | 448 | LL | #[automatically_derived] trait W { } |
| 449 | 449 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 450 | 450 | | |
| 451 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 452 | 451 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 452 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 453 | 453 | |
| 454 | 454 | warning: `#[automatically_derived]` attribute cannot be used on inherent impl blocks |
| 455 | 455 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:5 |
| ... | ... | @@ -457,8 +457,8 @@ warning: `#[automatically_derived]` attribute cannot be used on inherent impl bl |
| 457 | 457 | LL | #[automatically_derived] impl S { } |
| 458 | 458 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 459 | 459 | | |
| 460 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 461 | 460 | = help: `#[automatically_derived]` can only be applied to trait impl blocks |
| 461 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 462 | 462 | |
| 463 | 463 | warning: `#[no_mangle]` attribute cannot be used on modules |
| 464 | 464 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:1 |
| ... | ... | @@ -466,8 +466,8 @@ warning: `#[no_mangle]` attribute cannot be used on modules |
| 466 | 466 | LL | #[no_mangle] |
| 467 | 467 | | ^^^^^^^^^^^^ |
| 468 | 468 | | |
| 469 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 470 | 469 | = help: `#[no_mangle]` can be applied to functions and statics |
| 470 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 471 | 471 | |
| 472 | 472 | warning: `#[no_mangle]` attribute cannot be used on modules |
| 473 | 473 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:17 |
| ... | ... | @@ -475,8 +475,8 @@ warning: `#[no_mangle]` attribute cannot be used on modules |
| 475 | 475 | LL | mod inner { #![no_mangle] } |
| 476 | 476 | | ^^^^^^^^^^^^^ |
| 477 | 477 | | |
| 478 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 479 | 478 | = help: `#[no_mangle]` can be applied to functions and statics |
| 479 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 480 | 480 | |
| 481 | 481 | warning: `#[no_mangle]` attribute cannot be used on structs |
| 482 | 482 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:339:5 |
| ... | ... | @@ -484,8 +484,8 @@ warning: `#[no_mangle]` attribute cannot be used on structs |
| 484 | 484 | LL | #[no_mangle] struct S; |
| 485 | 485 | | ^^^^^^^^^^^^ |
| 486 | 486 | | |
| 487 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 488 | 487 | = help: `#[no_mangle]` can be applied to functions and statics |
| 488 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 489 | 489 | |
| 490 | 490 | warning: `#[no_mangle]` attribute cannot be used on type aliases |
| 491 | 491 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:5 |
| ... | ... | @@ -493,8 +493,8 @@ warning: `#[no_mangle]` attribute cannot be used on type aliases |
| 493 | 493 | LL | #[no_mangle] type T = S; |
| 494 | 494 | | ^^^^^^^^^^^^ |
| 495 | 495 | | |
| 496 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 497 | 496 | = help: `#[no_mangle]` can be applied to functions and statics |
| 497 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 498 | 498 | |
| 499 | 499 | warning: `#[no_mangle]` attribute cannot be used on inherent impl blocks |
| 500 | 500 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:351:5 |
| ... | ... | @@ -502,8 +502,8 @@ warning: `#[no_mangle]` attribute cannot be used on inherent impl blocks |
| 502 | 502 | LL | #[no_mangle] impl S { } |
| 503 | 503 | | ^^^^^^^^^^^^ |
| 504 | 504 | | |
| 505 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 506 | 505 | = help: `#[no_mangle]` can be applied to functions and statics |
| 506 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 507 | 507 | |
| 508 | 508 | warning: `#[no_mangle]` attribute cannot be used on required trait methods |
| 509 | 509 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:9 |
| ... | ... | @@ -511,8 +511,8 @@ warning: `#[no_mangle]` attribute cannot be used on required trait methods |
| 511 | 511 | LL | #[no_mangle] fn foo(); |
| 512 | 512 | | ^^^^^^^^^^^^ |
| 513 | 513 | | |
| 514 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 515 | 514 | = help: `#[no_mangle]` can be applied to functions, inherent methods, statics, and trait methods in impl blocks |
| 515 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 516 | 516 | |
| 517 | 517 | warning: `#[no_mangle]` attribute cannot be used on provided trait methods |
| 518 | 518 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:9 |
| ... | ... | @@ -520,8 +520,8 @@ warning: `#[no_mangle]` attribute cannot be used on provided trait methods |
| 520 | 520 | LL | #[no_mangle] fn bar() {} |
| 521 | 521 | | ^^^^^^^^^^^^ |
| 522 | 522 | | |
| 523 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 524 | 523 | = help: `#[no_mangle]` can be applied to functions, inherent methods, statics, and trait methods in impl blocks |
| 524 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 525 | 525 | |
| 526 | 526 | warning: `#[should_panic]` attribute cannot be used on modules |
| 527 | 527 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:372:1 |
| ... | ... | @@ -529,8 +529,8 @@ warning: `#[should_panic]` attribute cannot be used on modules |
| 529 | 529 | LL | #[should_panic] |
| 530 | 530 | | ^^^^^^^^^^^^^^^ |
| 531 | 531 | | |
| 532 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 533 | 532 | = help: `#[should_panic]` can only be applied to functions |
| 533 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 534 | 534 | |
| 535 | 535 | warning: `#[should_panic]` attribute cannot be used on modules |
| 536 | 536 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:378:17 |
| ... | ... | @@ -538,8 +538,8 @@ warning: `#[should_panic]` attribute cannot be used on modules |
| 538 | 538 | LL | mod inner { #![should_panic] } |
| 539 | 539 | | ^^^^^^^^^^^^^^^^ |
| 540 | 540 | | |
| 541 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 542 | 541 | = help: `#[should_panic]` can only be applied to functions |
| 542 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 543 | 543 | |
| 544 | 544 | warning: `#[should_panic]` attribute cannot be used on structs |
| 545 | 545 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5 |
| ... | ... | @@ -547,8 +547,8 @@ warning: `#[should_panic]` attribute cannot be used on structs |
| 547 | 547 | LL | #[should_panic] struct S; |
| 548 | 548 | | ^^^^^^^^^^^^^^^ |
| 549 | 549 | | |
| 550 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 551 | 550 | = help: `#[should_panic]` can only be applied to functions |
| 551 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 552 | 552 | |
| 553 | 553 | warning: `#[should_panic]` attribute cannot be used on type aliases |
| 554 | 554 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5 |
| ... | ... | @@ -556,8 +556,8 @@ warning: `#[should_panic]` attribute cannot be used on type aliases |
| 556 | 556 | LL | #[should_panic] type T = S; |
| 557 | 557 | | ^^^^^^^^^^^^^^^ |
| 558 | 558 | | |
| 559 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 560 | 559 | = help: `#[should_panic]` can only be applied to functions |
| 560 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 561 | 561 | |
| 562 | 562 | warning: `#[should_panic]` attribute cannot be used on inherent impl blocks |
| 563 | 563 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5 |
| ... | ... | @@ -565,8 +565,8 @@ warning: `#[should_panic]` attribute cannot be used on inherent impl blocks |
| 565 | 565 | LL | #[should_panic] impl S { } |
| 566 | 566 | | ^^^^^^^^^^^^^^^ |
| 567 | 567 | | |
| 568 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 569 | 568 | = help: `#[should_panic]` can only be applied to functions |
| 569 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 570 | 570 | |
| 571 | 571 | warning: `#[ignore]` attribute cannot be used on modules |
| 572 | 572 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:1 |
| ... | ... | @@ -574,8 +574,8 @@ warning: `#[ignore]` attribute cannot be used on modules |
| 574 | 574 | LL | #[ignore] |
| 575 | 575 | | ^^^^^^^^^ |
| 576 | 576 | | |
| 577 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 578 | 577 | = help: `#[ignore]` can only be applied to functions |
| 578 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 579 | 579 | |
| 580 | 580 | warning: `#[ignore]` attribute cannot be used on modules |
| 581 | 581 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:17 |
| ... | ... | @@ -583,8 +583,8 @@ warning: `#[ignore]` attribute cannot be used on modules |
| 583 | 583 | LL | mod inner { #![ignore] } |
| 584 | 584 | | ^^^^^^^^^^ |
| 585 | 585 | | |
| 586 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 587 | 586 | = help: `#[ignore]` can only be applied to functions |
| 587 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 588 | 588 | |
| 589 | 589 | warning: `#[ignore]` attribute cannot be used on structs |
| 590 | 590 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:5 |
| ... | ... | @@ -592,8 +592,8 @@ warning: `#[ignore]` attribute cannot be used on structs |
| 592 | 592 | LL | #[ignore] struct S; |
| 593 | 593 | | ^^^^^^^^^ |
| 594 | 594 | | |
| 595 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 596 | 595 | = help: `#[ignore]` can only be applied to functions |
| 596 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 597 | 597 | |
| 598 | 598 | warning: `#[ignore]` attribute cannot be used on type aliases |
| 599 | 599 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:425:5 |
| ... | ... | @@ -601,8 +601,8 @@ warning: `#[ignore]` attribute cannot be used on type aliases |
| 601 | 601 | LL | #[ignore] type T = S; |
| 602 | 602 | | ^^^^^^^^^ |
| 603 | 603 | | |
| 604 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 605 | 604 | = help: `#[ignore]` can only be applied to functions |
| 605 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 606 | 606 | |
| 607 | 607 | warning: `#[ignore]` attribute cannot be used on inherent impl blocks |
| 608 | 608 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:431:5 |
| ... | ... | @@ -610,8 +610,8 @@ warning: `#[ignore]` attribute cannot be used on inherent impl blocks |
| 610 | 610 | LL | #[ignore] impl S { } |
| 611 | 611 | | ^^^^^^^^^ |
| 612 | 612 | | |
| 613 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 614 | 613 | = help: `#[ignore]` can only be applied to functions |
| 614 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 615 | 615 | |
| 616 | 616 | warning: `#[no_implicit_prelude]` attribute cannot be used on functions |
| 617 | 617 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5 |
| ... | ... | @@ -619,8 +619,8 @@ warning: `#[no_implicit_prelude]` attribute cannot be used on functions |
| 619 | 619 | LL | #[no_implicit_prelude] fn f() { } |
| 620 | 620 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 621 | 621 | | |
| 622 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 623 | 622 | = help: `#[no_implicit_prelude]` can be applied to crates and modules |
| 623 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 624 | 624 | |
| 625 | 625 | warning: `#[no_implicit_prelude]` attribute cannot be used on structs |
| 626 | 626 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5 |
| ... | ... | @@ -628,8 +628,8 @@ warning: `#[no_implicit_prelude]` attribute cannot be used on structs |
| 628 | 628 | LL | #[no_implicit_prelude] struct S; |
| 629 | 629 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 630 | 630 | | |
| 631 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 632 | 631 | = help: `#[no_implicit_prelude]` can be applied to crates and modules |
| 632 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 633 | 633 | |
| 634 | 634 | warning: `#[no_implicit_prelude]` attribute cannot be used on type aliases |
| 635 | 635 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:5 |
| ... | ... | @@ -637,8 +637,8 @@ warning: `#[no_implicit_prelude]` attribute cannot be used on type aliases |
| 637 | 637 | LL | #[no_implicit_prelude] type T = S; |
| 638 | 638 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 639 | 639 | | |
| 640 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 641 | 640 | = help: `#[no_implicit_prelude]` can be applied to crates and modules |
| 641 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 642 | 642 | |
| 643 | 643 | warning: `#[no_implicit_prelude]` attribute cannot be used on inherent impl blocks |
| 644 | 644 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:460:5 |
| ... | ... | @@ -646,8 +646,8 @@ warning: `#[no_implicit_prelude]` attribute cannot be used on inherent impl bloc |
| 646 | 646 | LL | #[no_implicit_prelude] impl S { } |
| 647 | 647 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 648 | 648 | | |
| 649 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 650 | 649 | = help: `#[no_implicit_prelude]` can be applied to crates and modules |
| 650 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 651 | 651 | |
| 652 | 652 | warning: `#[macro_escape]` attribute cannot be used on functions |
| 653 | 653 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:5 |
| ... | ... | @@ -655,8 +655,8 @@ warning: `#[macro_escape]` attribute cannot be used on functions |
| 655 | 655 | LL | #[macro_escape] fn f() { } |
| 656 | 656 | | ^^^^^^^^^^^^^^^ |
| 657 | 657 | | |
| 658 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 659 | 658 | = help: `#[macro_escape]` can be applied to crates, extern crates, and modules |
| 659 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 660 | 660 | |
| 661 | 661 | warning: `#[macro_escape]` attribute cannot be used on structs |
| 662 | 662 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:481:5 |
| ... | ... | @@ -664,8 +664,8 @@ warning: `#[macro_escape]` attribute cannot be used on structs |
| 664 | 664 | LL | #[macro_escape] struct S; |
| 665 | 665 | | ^^^^^^^^^^^^^^^ |
| 666 | 666 | | |
| 667 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 668 | 667 | = help: `#[macro_escape]` can be applied to crates, extern crates, and modules |
| 668 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 669 | 669 | |
| 670 | 670 | warning: `#[macro_escape]` attribute cannot be used on type aliases |
| 671 | 671 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 |
| ... | ... | @@ -673,8 +673,8 @@ warning: `#[macro_escape]` attribute cannot be used on type aliases |
| 673 | 673 | LL | #[macro_escape] type T = S; |
| 674 | 674 | | ^^^^^^^^^^^^^^^ |
| 675 | 675 | | |
| 676 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 677 | 676 | = help: `#[macro_escape]` can be applied to crates, extern crates, and modules |
| 677 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 678 | 678 | |
| 679 | 679 | warning: `#[macro_escape]` attribute cannot be used on inherent impl blocks |
| 680 | 680 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:5 |
| ... | ... | @@ -682,8 +682,8 @@ warning: `#[macro_escape]` attribute cannot be used on inherent impl blocks |
| 682 | 682 | LL | #[macro_escape] impl S { } |
| 683 | 683 | | ^^^^^^^^^^^^^^^ |
| 684 | 684 | | |
| 685 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 686 | 685 | = help: `#[macro_escape]` can be applied to crates, extern crates, and modules |
| 686 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 687 | 687 | |
| 688 | 688 | warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` |
| 689 | 689 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:1 |
| ... | ... | @@ -761,8 +761,8 @@ warning: `#[cold]` attribute cannot be used on modules |
| 761 | 761 | LL | #[cold] |
| 762 | 762 | | ^^^^^^^ |
| 763 | 763 | | |
| 764 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 765 | 764 | = help: `#[cold]` can only be applied to functions |
| 765 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 766 | 766 | |
| 767 | 767 | warning: `#[cold]` attribute cannot be used on modules |
| 768 | 768 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:17 |
| ... | ... | @@ -770,8 +770,8 @@ warning: `#[cold]` attribute cannot be used on modules |
| 770 | 770 | LL | mod inner { #![cold] } |
| 771 | 771 | | ^^^^^^^^ |
| 772 | 772 | | |
| 773 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 774 | 773 | = help: `#[cold]` can only be applied to functions |
| 774 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 775 | 775 | |
| 776 | 776 | warning: `#[cold]` attribute cannot be used on structs |
| 777 | 777 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:556:5 |
| ... | ... | @@ -779,8 +779,8 @@ warning: `#[cold]` attribute cannot be used on structs |
| 779 | 779 | LL | #[cold] struct S; |
| 780 | 780 | | ^^^^^^^ |
| 781 | 781 | | |
| 782 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 783 | 782 | = help: `#[cold]` can only be applied to functions |
| 783 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 784 | 784 | |
| 785 | 785 | warning: `#[cold]` attribute cannot be used on type aliases |
| 786 | 786 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:562:5 |
| ... | ... | @@ -788,8 +788,8 @@ warning: `#[cold]` attribute cannot be used on type aliases |
| 788 | 788 | LL | #[cold] type T = S; |
| 789 | 789 | | ^^^^^^^ |
| 790 | 790 | | |
| 791 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 792 | 791 | = help: `#[cold]` can only be applied to functions |
| 792 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 793 | 793 | |
| 794 | 794 | warning: `#[cold]` attribute cannot be used on inherent impl blocks |
| 795 | 795 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:568:5 |
| ... | ... | @@ -797,8 +797,8 @@ warning: `#[cold]` attribute cannot be used on inherent impl blocks |
| 797 | 797 | LL | #[cold] impl S { } |
| 798 | 798 | | ^^^^^^^ |
| 799 | 799 | | |
| 800 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 801 | 800 | = help: `#[cold]` can only be applied to functions |
| 801 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 802 | 802 | |
| 803 | 803 | warning: `#[link_name]` attribute cannot be used on modules |
| 804 | 804 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:575:1 |
| ... | ... | @@ -806,8 +806,8 @@ warning: `#[link_name]` attribute cannot be used on modules |
| 806 | 806 | LL | #[link_name = "1900"] |
| 807 | 807 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 808 | 808 | | |
| 809 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 810 | 809 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 810 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 811 | 811 | |
| 812 | 812 | warning: `#[link_name]` attribute cannot be used on foreign modules |
| 813 | 813 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:581:5 |
| ... | ... | @@ -815,8 +815,8 @@ warning: `#[link_name]` attribute cannot be used on foreign modules |
| 815 | 815 | LL | #[link_name = "1900"] |
| 816 | 816 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 817 | 817 | | |
| 818 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 819 | 818 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 819 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 820 | 820 | |
| 821 | 821 | warning: `#[link_name]` attribute cannot be used on modules |
| 822 | 822 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:588:17 |
| ... | ... | @@ -824,8 +824,8 @@ warning: `#[link_name]` attribute cannot be used on modules |
| 824 | 824 | LL | mod inner { #![link_name="1900"] } |
| 825 | 825 | | ^^^^^^^^^^^^^^^^^^^^ |
| 826 | 826 | | |
| 827 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 828 | 827 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 828 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 829 | 829 | |
| 830 | 830 | warning: `#[link_name]` attribute cannot be used on functions |
| 831 | 831 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:594:5 |
| ... | ... | @@ -833,8 +833,8 @@ warning: `#[link_name]` attribute cannot be used on functions |
| 833 | 833 | LL | #[link_name = "1900"] fn f() { } |
| 834 | 834 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 835 | 835 | | |
| 836 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 837 | 836 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 837 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 838 | 838 | |
| 839 | 839 | warning: `#[link_name]` attribute cannot be used on structs |
| 840 | 840 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:600:5 |
| ... | ... | @@ -842,8 +842,8 @@ warning: `#[link_name]` attribute cannot be used on structs |
| 842 | 842 | LL | #[link_name = "1900"] struct S; |
| 843 | 843 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 844 | 844 | | |
| 845 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 846 | 845 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 846 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 847 | 847 | |
| 848 | 848 | warning: `#[link_name]` attribute cannot be used on type aliases |
| 849 | 849 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:606:5 |
| ... | ... | @@ -851,8 +851,8 @@ warning: `#[link_name]` attribute cannot be used on type aliases |
| 851 | 851 | LL | #[link_name = "1900"] type T = S; |
| 852 | 852 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 853 | 853 | | |
| 854 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 855 | 854 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 855 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 856 | 856 | |
| 857 | 857 | warning: `#[link_name]` attribute cannot be used on inherent impl blocks |
| 858 | 858 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:612:5 |
| ... | ... | @@ -860,8 +860,8 @@ warning: `#[link_name]` attribute cannot be used on inherent impl blocks |
| 860 | 860 | LL | #[link_name = "1900"] impl S { } |
| 861 | 861 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 862 | 862 | | |
| 863 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 864 | 863 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 864 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 865 | 865 | |
| 866 | 866 | warning: `#[link_section]` attribute cannot be used on modules |
| 867 | 867 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:619:1 |
| ... | ... | @@ -869,8 +869,8 @@ warning: `#[link_section]` attribute cannot be used on modules |
| 869 | 869 | LL | #[link_section = ",1800"] |
| 870 | 870 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 871 | 871 | | |
| 872 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 873 | 872 | = help: `#[link_section]` can be applied to functions and statics |
| 873 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 874 | 874 | |
| 875 | 875 | warning: `#[link_section]` attribute cannot be used on modules |
| 876 | 876 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:625:17 |
| ... | ... | @@ -878,8 +878,8 @@ warning: `#[link_section]` attribute cannot be used on modules |
| 878 | 878 | LL | mod inner { #![link_section=",1800"] } |
| 879 | 879 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 880 | 880 | | |
| 881 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 882 | 881 | = help: `#[link_section]` can be applied to functions and statics |
| 882 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 883 | 883 | |
| 884 | 884 | warning: `#[link_section]` attribute cannot be used on structs |
| 885 | 885 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:5 |
| ... | ... | @@ -887,8 +887,8 @@ warning: `#[link_section]` attribute cannot be used on structs |
| 887 | 887 | LL | #[link_section = ",1800"] struct S; |
| 888 | 888 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 889 | 889 | | |
| 890 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 891 | 890 | = help: `#[link_section]` can be applied to functions and statics |
| 891 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 892 | 892 | |
| 893 | 893 | warning: `#[link_section]` attribute cannot be used on type aliases |
| 894 | 894 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5 |
| ... | ... | @@ -896,8 +896,8 @@ warning: `#[link_section]` attribute cannot be used on type aliases |
| 896 | 896 | LL | #[link_section = ",1800"] type T = S; |
| 897 | 897 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 898 | 898 | | |
| 899 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 900 | 899 | = help: `#[link_section]` can be applied to functions and statics |
| 900 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 901 | 901 | |
| 902 | 902 | warning: `#[link_section]` attribute cannot be used on inherent impl blocks |
| 903 | 903 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:645:5 |
| ... | ... | @@ -905,8 +905,8 @@ warning: `#[link_section]` attribute cannot be used on inherent impl blocks |
| 905 | 905 | LL | #[link_section = ",1800"] impl S { } |
| 906 | 906 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 907 | 907 | | |
| 908 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 909 | 908 | = help: `#[link_section]` can be applied to functions and statics |
| 909 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 910 | 910 | |
| 911 | 911 | warning: `#[link_section]` attribute cannot be used on traits |
| 912 | 912 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5 |
| ... | ... | @@ -914,8 +914,8 @@ warning: `#[link_section]` attribute cannot be used on traits |
| 914 | 914 | LL | #[link_section = ",1800"] |
| 915 | 915 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 916 | 916 | | |
| 917 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 918 | 917 | = help: `#[link_section]` can be applied to functions and statics |
| 918 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 919 | 919 | |
| 920 | 920 | warning: `#[link_section]` attribute cannot be used on required trait methods |
| 921 | 921 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:9 |
| ... | ... | @@ -923,8 +923,8 @@ warning: `#[link_section]` attribute cannot be used on required trait methods |
| 923 | 923 | LL | #[link_section = ",1800"] |
| 924 | 924 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 925 | 925 | | |
| 926 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 927 | 926 | = help: `#[link_section]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks |
| 927 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 928 | 928 | |
| 929 | 929 | warning: `#[must_use]` attribute cannot be used on modules |
| 930 | 930 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:1 |
| ... | ... | @@ -932,8 +932,8 @@ warning: `#[must_use]` attribute cannot be used on modules |
| 932 | 932 | LL | #[must_use] |
| 933 | 933 | | ^^^^^^^^^^^ |
| 934 | 934 | | |
| 935 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 936 | 935 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 936 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 937 | 937 | |
| 938 | 938 | warning: `#[must_use]` attribute cannot be used on modules |
| 939 | 939 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17 |
| ... | ... | @@ -941,8 +941,8 @@ warning: `#[must_use]` attribute cannot be used on modules |
| 941 | 941 | LL | mod inner { #![must_use] } |
| 942 | 942 | | ^^^^^^^^^^^^ |
| 943 | 943 | | |
| 944 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 945 | 944 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 945 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 946 | 946 | |
| 947 | 947 | warning: `#[must_use]` attribute cannot be used on type aliases |
| 948 | 948 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5 |
| ... | ... | @@ -950,8 +950,8 @@ warning: `#[must_use]` attribute cannot be used on type aliases |
| 950 | 950 | LL | #[must_use] type T = S; |
| 951 | 951 | | ^^^^^^^^^^^ |
| 952 | 952 | | |
| 953 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 954 | 953 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 954 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 955 | 955 | |
| 956 | 956 | warning: `#[must_use]` attribute cannot be used on inherent impl blocks |
| 957 | 957 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5 |
| ... | ... | @@ -959,8 +959,8 @@ warning: `#[must_use]` attribute cannot be used on inherent impl blocks |
| 959 | 959 | LL | #[must_use] impl S { } |
| 960 | 960 | | ^^^^^^^^^^^ |
| 961 | 961 | | |
| 962 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 963 | 962 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 963 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 964 | 964 | |
| 965 | 965 | warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` |
| 966 | 966 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:1 |
| ... | ... | @@ -1528,8 +1528,8 @@ warning: `#[should_panic]` attribute cannot be used on crates |
| 1528 | 1528 | LL | #![should_panic] |
| 1529 | 1529 | | ^^^^^^^^^^^^^^^^ |
| 1530 | 1530 | | |
| 1531 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1532 | 1531 | = help: `#[should_panic]` can only be applied to functions |
| 1532 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1533 | 1533 | |
| 1534 | 1534 | warning: `#[ignore]` attribute cannot be used on crates |
| 1535 | 1535 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1 |
| ... | ... | @@ -1537,8 +1537,8 @@ warning: `#[ignore]` attribute cannot be used on crates |
| 1537 | 1537 | LL | #![ignore] |
| 1538 | 1538 | | ^^^^^^^^^^ |
| 1539 | 1539 | | |
| 1540 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1541 | 1540 | = help: `#[ignore]` can only be applied to functions |
| 1541 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1542 | 1542 | |
| 1543 | 1543 | warning: `#[proc_macro_derive]` attribute cannot be used on crates |
| 1544 | 1544 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1 |
| ... | ... | @@ -1546,8 +1546,8 @@ warning: `#[proc_macro_derive]` attribute cannot be used on crates |
| 1546 | 1546 | LL | #![proc_macro_derive(Test)] |
| 1547 | 1547 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 1548 | 1548 | | |
| 1549 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1550 | 1549 | = help: `#[proc_macro_derive]` can only be applied to functions |
| 1550 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1551 | 1551 | |
| 1552 | 1552 | warning: `#[cold]` attribute cannot be used on crates |
| 1553 | 1553 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 |
| ... | ... | @@ -1555,8 +1555,8 @@ warning: `#[cold]` attribute cannot be used on crates |
| 1555 | 1555 | LL | #![cold] |
| 1556 | 1556 | | ^^^^^^^^ |
| 1557 | 1557 | | |
| 1558 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1559 | 1558 | = help: `#[cold]` can only be applied to functions |
| 1559 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1560 | 1560 | |
| 1561 | 1561 | warning: `#[link_name]` attribute cannot be used on crates |
| 1562 | 1562 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1 |
| ... | ... | @@ -1564,8 +1564,8 @@ warning: `#[link_name]` attribute cannot be used on crates |
| 1564 | 1564 | LL | #![link_name = "1900"] |
| 1565 | 1565 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 1566 | 1566 | | |
| 1567 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1568 | 1567 | = help: `#[link_name]` can be applied to foreign functions and foreign statics |
| 1568 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1569 | 1569 | |
| 1570 | 1570 | warning: `#[link_section]` attribute cannot be used on crates |
| 1571 | 1571 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:77:1 |
| ... | ... | @@ -1573,8 +1573,8 @@ warning: `#[link_section]` attribute cannot be used on crates |
| 1573 | 1573 | LL | #![link_section = ",1800"] |
| 1574 | 1574 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 1575 | 1575 | | |
| 1576 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1577 | 1576 | = help: `#[link_section]` can be applied to functions and statics |
| 1577 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1578 | 1578 | |
| 1579 | 1579 | warning: `#[must_use]` attribute cannot be used on crates |
| 1580 | 1580 | --> $DIR/issue-43106-gating-of-builtin-attrs.rs:82:1 |
| ... | ... | @@ -1582,8 +1582,8 @@ warning: `#[must_use]` attribute cannot be used on crates |
| 1582 | 1582 | LL | #![must_use] |
| 1583 | 1583 | | ^^^^^^^^^^^^ |
| 1584 | 1584 | | |
| 1585 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1586 | 1585 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 1586 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 1587 | 1587 | |
| 1588 | 1588 | warning: 169 warnings emitted |
| 1589 | 1589 |
tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr+4-4| ... | ... | @@ -40,8 +40,8 @@ warning: `#[macro_use]` attribute cannot be used on structs |
| 40 | 40 | LL | #[macro_use = "2700"] struct S; |
| 41 | 41 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 42 | 42 | | |
| 43 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 44 | 43 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 44 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 45 | 45 | = note: requested on the command line with `-W unused-attributes` |
| 46 | 46 | |
| 47 | 47 | warning: `#[macro_use]` attribute cannot be used on functions |
| ... | ... | @@ -50,8 +50,8 @@ warning: `#[macro_use]` attribute cannot be used on functions |
| 50 | 50 | LL | #[macro_use] fn f() { } |
| 51 | 51 | | ^^^^^^^^^^^^ |
| 52 | 52 | | |
| 53 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 54 | 53 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 54 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 55 | 55 | |
| 56 | 56 | warning: `#[macro_use]` attribute cannot be used on type aliases |
| 57 | 57 | --> $DIR/issue-43106-gating-of-macro_use.rs:24:5 |
| ... | ... | @@ -59,8 +59,8 @@ warning: `#[macro_use]` attribute cannot be used on type aliases |
| 59 | 59 | LL | #[macro_use] type T = S; |
| 60 | 60 | | ^^^^^^^^^^^^ |
| 61 | 61 | | |
| 62 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 63 | 62 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 63 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 64 | 64 | |
| 65 | 65 | warning: `#[macro_use]` attribute cannot be used on inherent impl blocks |
| 66 | 66 | --> $DIR/issue-43106-gating-of-macro_use.rs:28:5 |
| ... | ... | @@ -68,8 +68,8 @@ warning: `#[macro_use]` attribute cannot be used on inherent impl blocks |
| 68 | 68 | LL | #[macro_use] impl S { } |
| 69 | 69 | | ^^^^^^^^^^^^ |
| 70 | 70 | | |
| 71 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 72 | 71 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 72 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 73 | 73 | |
| 74 | 74 | error: aborting due to 4 previous errors; 4 warnings emitted |
| 75 | 75 |
tests/ui/feature-gates/issue-43106-gating-of-stable.rs+14| ... | ... | @@ -6,29 +6,43 @@ |
| 6 | 6 | |
| 7 | 7 | #![stable()] |
| 8 | 8 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 9 | //~| ERROR missing 'since' | |
| 10 | //~| ERROR missing 'feature' | |
| 9 | 11 | |
| 10 | 12 | #[stable()] |
| 11 | 13 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 14 | //~| ERROR missing 'since' | |
| 15 | //~| ERROR missing 'feature' | |
| 12 | 16 | mod stable { |
| 13 | 17 | mod inner { |
| 14 | 18 | #![stable()] |
| 15 | 19 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 20 | //~| ERROR missing 'since' | |
| 21 | //~| ERROR missing 'feature' | |
| 16 | 22 | } |
| 17 | 23 | |
| 18 | 24 | #[stable()] |
| 19 | 25 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 26 | //~| ERROR missing 'since' | |
| 27 | //~| ERROR missing 'feature' | |
| 20 | 28 | fn f() {} |
| 21 | 29 | |
| 22 | 30 | #[stable()] |
| 23 | 31 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 32 | //~| ERROR missing 'since' | |
| 33 | //~| ERROR missing 'feature' | |
| 24 | 34 | struct S; |
| 25 | 35 | |
| 26 | 36 | #[stable()] |
| 27 | 37 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 38 | //~| ERROR missing 'since' | |
| 39 | //~| ERROR missing 'feature' | |
| 28 | 40 | type T = S; |
| 29 | 41 | |
| 30 | 42 | #[stable()] |
| 31 | 43 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 44 | //~| ERROR missing 'since' | |
| 45 | //~| ERROR missing 'feature' | |
| 32 | 46 | impl S {} |
| 33 | 47 | } |
| 34 | 48 |
tests/ui/feature-gates/issue-43106-gating-of-stable.stderr+99-14| ... | ... | @@ -1,45 +1,130 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/issue-43106-gating-of-stable.rs:7:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #![stable()] |
| 5 | 5 | | ^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 8 | --> $DIR/issue-43106-gating-of-stable.rs:10:1 | |
| 7 | error[E0546]: missing 'feature' | |
| 8 | --> $DIR/issue-43106-gating-of-stable.rs:7:1 | |
| 9 | | | |
| 10 | LL | #![stable()] | |
| 11 | | ^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error[E0542]: missing 'since' | |
| 14 | --> $DIR/issue-43106-gating-of-stable.rs:7:1 | |
| 15 | | | |
| 16 | LL | #![stable()] | |
| 17 | | ^^^^^^^^^^^^ | |
| 18 | ||
| 19 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 20 | --> $DIR/issue-43106-gating-of-stable.rs:12:1 | |
| 21 | | | |
| 22 | LL | #[stable()] | |
| 23 | | ^^^^^^^^^^^ | |
| 24 | ||
| 25 | error[E0546]: missing 'feature' | |
| 26 | --> $DIR/issue-43106-gating-of-stable.rs:12:1 | |
| 27 | | | |
| 28 | LL | #[stable()] | |
| 29 | | ^^^^^^^^^^^ | |
| 30 | ||
| 31 | error[E0542]: missing 'since' | |
| 32 | --> $DIR/issue-43106-gating-of-stable.rs:12:1 | |
| 9 | 33 | | |
| 10 | 34 | LL | #[stable()] |
| 11 | 35 | | ^^^^^^^^^^^ |
| 12 | 36 | |
| 13 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 14 | --> $DIR/issue-43106-gating-of-stable.rs:14:9 | |
| 37 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 38 | --> $DIR/issue-43106-gating-of-stable.rs:18:9 | |
| 39 | | | |
| 40 | LL | #![stable()] | |
| 41 | | ^^^^^^^^^^^^ | |
| 42 | ||
| 43 | error[E0546]: missing 'feature' | |
| 44 | --> $DIR/issue-43106-gating-of-stable.rs:18:9 | |
| 15 | 45 | | |
| 16 | 46 | LL | #![stable()] |
| 17 | 47 | | ^^^^^^^^^^^^ |
| 18 | 48 | |
| 19 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 20 | --> $DIR/issue-43106-gating-of-stable.rs:18:5 | |
| 49 | error[E0542]: missing 'since' | |
| 50 | --> $DIR/issue-43106-gating-of-stable.rs:18:9 | |
| 51 | | | |
| 52 | LL | #![stable()] | |
| 53 | | ^^^^^^^^^^^^ | |
| 54 | ||
| 55 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 56 | --> $DIR/issue-43106-gating-of-stable.rs:24:5 | |
| 57 | | | |
| 58 | LL | #[stable()] | |
| 59 | | ^^^^^^^^^^^ | |
| 60 | ||
| 61 | error[E0546]: missing 'feature' | |
| 62 | --> $DIR/issue-43106-gating-of-stable.rs:24:5 | |
| 21 | 63 | | |
| 22 | 64 | LL | #[stable()] |
| 23 | 65 | | ^^^^^^^^^^^ |
| 24 | 66 | |
| 25 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 26 | --> $DIR/issue-43106-gating-of-stable.rs:22:5 | |
| 67 | error[E0542]: missing 'since' | |
| 68 | --> $DIR/issue-43106-gating-of-stable.rs:24:5 | |
| 27 | 69 | | |
| 28 | 70 | LL | #[stable()] |
| 29 | 71 | | ^^^^^^^^^^^ |
| 30 | 72 | |
| 31 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 32 | --> $DIR/issue-43106-gating-of-stable.rs:26:5 | |
| 73 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 74 | --> $DIR/issue-43106-gating-of-stable.rs:30:5 | |
| 75 | | | |
| 76 | LL | #[stable()] | |
| 77 | | ^^^^^^^^^^^ | |
| 78 | ||
| 79 | error[E0546]: missing 'feature' | |
| 80 | --> $DIR/issue-43106-gating-of-stable.rs:30:5 | |
| 33 | 81 | | |
| 34 | 82 | LL | #[stable()] |
| 35 | 83 | | ^^^^^^^^^^^ |
| 36 | 84 | |
| 37 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 85 | error[E0542]: missing 'since' | |
| 38 | 86 | --> $DIR/issue-43106-gating-of-stable.rs:30:5 |
| 39 | 87 | | |
| 40 | 88 | LL | #[stable()] |
| 41 | 89 | | ^^^^^^^^^^^ |
| 42 | 90 | |
| 43 | error: aborting due to 7 previous errors | |
| 91 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 92 | --> $DIR/issue-43106-gating-of-stable.rs:36:5 | |
| 93 | | | |
| 94 | LL | #[stable()] | |
| 95 | | ^^^^^^^^^^^ | |
| 96 | ||
| 97 | error[E0546]: missing 'feature' | |
| 98 | --> $DIR/issue-43106-gating-of-stable.rs:36:5 | |
| 99 | | | |
| 100 | LL | #[stable()] | |
| 101 | | ^^^^^^^^^^^ | |
| 102 | ||
| 103 | error[E0542]: missing 'since' | |
| 104 | --> $DIR/issue-43106-gating-of-stable.rs:36:5 | |
| 105 | | | |
| 106 | LL | #[stable()] | |
| 107 | | ^^^^^^^^^^^ | |
| 108 | ||
| 109 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 110 | --> $DIR/issue-43106-gating-of-stable.rs:42:5 | |
| 111 | | | |
| 112 | LL | #[stable()] | |
| 113 | | ^^^^^^^^^^^ | |
| 114 | ||
| 115 | error[E0546]: missing 'feature' | |
| 116 | --> $DIR/issue-43106-gating-of-stable.rs:42:5 | |
| 117 | | | |
| 118 | LL | #[stable()] | |
| 119 | | ^^^^^^^^^^^ | |
| 120 | ||
| 121 | error[E0542]: missing 'since' | |
| 122 | --> $DIR/issue-43106-gating-of-stable.rs:42:5 | |
| 123 | | | |
| 124 | LL | #[stable()] | |
| 125 | | ^^^^^^^^^^^ | |
| 126 | ||
| 127 | error: aborting due to 21 previous errors | |
| 44 | 128 | |
| 45 | For more information about this error, try `rustc --explain E0734`. | |
| 129 | Some errors have detailed explanations: E0542, E0546, E0658. | |
| 130 | For more information about an error, try `rustc --explain E0542`. |
tests/ui/feature-gates/issue-43106-gating-of-unstable.rs+14| ... | ... | @@ -6,29 +6,43 @@ |
| 6 | 6 | |
| 7 | 7 | #![unstable()] |
| 8 | 8 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 9 | //~| ERROR missing 'issue' | |
| 10 | //~| ERROR missing 'feature' | |
| 9 | 11 | |
| 10 | 12 | #[unstable()] |
| 11 | 13 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 14 | //~| ERROR missing 'issue' | |
| 15 | //~| ERROR missing 'feature' | |
| 12 | 16 | mod unstable { |
| 13 | 17 | mod inner { |
| 14 | 18 | #![unstable()] |
| 15 | 19 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 20 | //~| ERROR missing 'issue' | |
| 21 | //~| ERROR missing 'feature' | |
| 16 | 22 | } |
| 17 | 23 | |
| 18 | 24 | #[unstable()] |
| 19 | 25 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 26 | //~| ERROR missing 'issue' | |
| 27 | //~| ERROR missing 'feature' | |
| 20 | 28 | fn f() {} |
| 21 | 29 | |
| 22 | 30 | #[unstable()] |
| 23 | 31 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 32 | //~| ERROR missing 'issue' | |
| 33 | //~| ERROR missing 'feature' | |
| 24 | 34 | struct S; |
| 25 | 35 | |
| 26 | 36 | #[unstable()] |
| 27 | 37 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 38 | //~| ERROR missing 'issue' | |
| 39 | //~| ERROR missing 'feature' | |
| 28 | 40 | type T = S; |
| 29 | 41 | |
| 30 | 42 | #[unstable()] |
| 31 | 43 | //~^ ERROR stability attributes may not be used outside of the standard library |
| 44 | //~| ERROR missing 'issue' | |
| 45 | //~| ERROR missing 'feature' | |
| 32 | 46 | impl S {} |
| 33 | 47 | } |
| 34 | 48 |
tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr+99-14| ... | ... | @@ -1,45 +1,130 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/issue-43106-gating-of-unstable.rs:7:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #![unstable()] |
| 5 | 5 | | ^^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 8 | --> $DIR/issue-43106-gating-of-unstable.rs:10:1 | |
| 7 | error[E0546]: missing 'feature' | |
| 8 | --> $DIR/issue-43106-gating-of-unstable.rs:7:1 | |
| 9 | | | |
| 10 | LL | #![unstable()] | |
| 11 | | ^^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error[E0547]: missing 'issue' | |
| 14 | --> $DIR/issue-43106-gating-of-unstable.rs:7:1 | |
| 15 | | | |
| 16 | LL | #![unstable()] | |
| 17 | | ^^^^^^^^^^^^^^ | |
| 18 | ||
| 19 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 20 | --> $DIR/issue-43106-gating-of-unstable.rs:12:1 | |
| 21 | | | |
| 22 | LL | #[unstable()] | |
| 23 | | ^^^^^^^^^^^^^ | |
| 24 | ||
| 25 | error[E0546]: missing 'feature' | |
| 26 | --> $DIR/issue-43106-gating-of-unstable.rs:12:1 | |
| 27 | | | |
| 28 | LL | #[unstable()] | |
| 29 | | ^^^^^^^^^^^^^ | |
| 30 | ||
| 31 | error[E0547]: missing 'issue' | |
| 32 | --> $DIR/issue-43106-gating-of-unstable.rs:12:1 | |
| 9 | 33 | | |
| 10 | 34 | LL | #[unstable()] |
| 11 | 35 | | ^^^^^^^^^^^^^ |
| 12 | 36 | |
| 13 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 14 | --> $DIR/issue-43106-gating-of-unstable.rs:14:9 | |
| 37 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 38 | --> $DIR/issue-43106-gating-of-unstable.rs:18:9 | |
| 39 | | | |
| 40 | LL | #![unstable()] | |
| 41 | | ^^^^^^^^^^^^^^ | |
| 42 | ||
| 43 | error[E0546]: missing 'feature' | |
| 44 | --> $DIR/issue-43106-gating-of-unstable.rs:18:9 | |
| 15 | 45 | | |
| 16 | 46 | LL | #![unstable()] |
| 17 | 47 | | ^^^^^^^^^^^^^^ |
| 18 | 48 | |
| 19 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 20 | --> $DIR/issue-43106-gating-of-unstable.rs:18:5 | |
| 49 | error[E0547]: missing 'issue' | |
| 50 | --> $DIR/issue-43106-gating-of-unstable.rs:18:9 | |
| 51 | | | |
| 52 | LL | #![unstable()] | |
| 53 | | ^^^^^^^^^^^^^^ | |
| 54 | ||
| 55 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 56 | --> $DIR/issue-43106-gating-of-unstable.rs:24:5 | |
| 57 | | | |
| 58 | LL | #[unstable()] | |
| 59 | | ^^^^^^^^^^^^^ | |
| 60 | ||
| 61 | error[E0546]: missing 'feature' | |
| 62 | --> $DIR/issue-43106-gating-of-unstable.rs:24:5 | |
| 21 | 63 | | |
| 22 | 64 | LL | #[unstable()] |
| 23 | 65 | | ^^^^^^^^^^^^^ |
| 24 | 66 | |
| 25 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 26 | --> $DIR/issue-43106-gating-of-unstable.rs:22:5 | |
| 67 | error[E0547]: missing 'issue' | |
| 68 | --> $DIR/issue-43106-gating-of-unstable.rs:24:5 | |
| 27 | 69 | | |
| 28 | 70 | LL | #[unstable()] |
| 29 | 71 | | ^^^^^^^^^^^^^ |
| 30 | 72 | |
| 31 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 32 | --> $DIR/issue-43106-gating-of-unstable.rs:26:5 | |
| 73 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 74 | --> $DIR/issue-43106-gating-of-unstable.rs:30:5 | |
| 75 | | | |
| 76 | LL | #[unstable()] | |
| 77 | | ^^^^^^^^^^^^^ | |
| 78 | ||
| 79 | error[E0546]: missing 'feature' | |
| 80 | --> $DIR/issue-43106-gating-of-unstable.rs:30:5 | |
| 33 | 81 | | |
| 34 | 82 | LL | #[unstable()] |
| 35 | 83 | | ^^^^^^^^^^^^^ |
| 36 | 84 | |
| 37 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 85 | error[E0547]: missing 'issue' | |
| 38 | 86 | --> $DIR/issue-43106-gating-of-unstable.rs:30:5 |
| 39 | 87 | | |
| 40 | 88 | LL | #[unstable()] |
| 41 | 89 | | ^^^^^^^^^^^^^ |
| 42 | 90 | |
| 43 | error: aborting due to 7 previous errors | |
| 91 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 92 | --> $DIR/issue-43106-gating-of-unstable.rs:36:5 | |
| 93 | | | |
| 94 | LL | #[unstable()] | |
| 95 | | ^^^^^^^^^^^^^ | |
| 96 | ||
| 97 | error[E0546]: missing 'feature' | |
| 98 | --> $DIR/issue-43106-gating-of-unstable.rs:36:5 | |
| 99 | | | |
| 100 | LL | #[unstable()] | |
| 101 | | ^^^^^^^^^^^^^ | |
| 102 | ||
| 103 | error[E0547]: missing 'issue' | |
| 104 | --> $DIR/issue-43106-gating-of-unstable.rs:36:5 | |
| 105 | | | |
| 106 | LL | #[unstable()] | |
| 107 | | ^^^^^^^^^^^^^ | |
| 108 | ||
| 109 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 110 | --> $DIR/issue-43106-gating-of-unstable.rs:42:5 | |
| 111 | | | |
| 112 | LL | #[unstable()] | |
| 113 | | ^^^^^^^^^^^^^ | |
| 114 | ||
| 115 | error[E0546]: missing 'feature' | |
| 116 | --> $DIR/issue-43106-gating-of-unstable.rs:42:5 | |
| 117 | | | |
| 118 | LL | #[unstable()] | |
| 119 | | ^^^^^^^^^^^^^ | |
| 120 | ||
| 121 | error[E0547]: missing 'issue' | |
| 122 | --> $DIR/issue-43106-gating-of-unstable.rs:42:5 | |
| 123 | | | |
| 124 | LL | #[unstable()] | |
| 125 | | ^^^^^^^^^^^^^ | |
| 126 | ||
| 127 | error: aborting due to 21 previous errors | |
| 44 | 128 | |
| 45 | For more information about this error, try `rustc --explain E0734`. | |
| 129 | Some errors have detailed explanations: E0546, E0547, E0658. | |
| 130 | For more information about an error, try `rustc --explain E0546`. |
tests/ui/internal/internal-unstable.stderr+2-2| ... | ... | @@ -65,8 +65,8 @@ warning: `#[allow_internal_unstable]` attribute cannot be used on struct fields |
| 65 | 65 | LL | #[allow_internal_unstable] |
| 66 | 66 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 67 | 67 | | |
| 68 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 69 | 68 | = help: `#[allow_internal_unstable]` can be applied to functions and macro defs |
| 69 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 70 | 70 | = note: requested on the command line with `-W unused-attributes` |
| 71 | 71 | |
| 72 | 72 | warning: `#[allow_internal_unstable]` attribute cannot be used on match arms |
| ... | ... | @@ -75,8 +75,8 @@ warning: `#[allow_internal_unstable]` attribute cannot be used on match arms |
| 75 | 75 | LL | #[allow_internal_unstable] |
| 76 | 76 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 77 | 77 | | |
| 78 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 79 | 78 | = help: `#[allow_internal_unstable]` can be applied to functions and macro defs |
| 79 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 80 | 80 | |
| 81 | 81 | error: aborting due to 7 previous errors; 2 warnings emitted |
| 82 | 82 |
tests/ui/lang-items/issue-83471.stderr+19-19| ... | ... | @@ -4,6 +4,25 @@ error[E0573]: expected type, found built-in attribute `export_name` |
| 4 | 4 | LL | fn call(export_name); |
| 5 | 5 | | ^^^^^^^^^^^ not a type |
| 6 | 6 | |
| 7 | warning: anonymous parameters are deprecated and will be removed in the next edition | |
| 8 | --> $DIR/issue-83471.rs:24:13 | |
| 9 | | | |
| 10 | LL | fn call(export_name); | |
| 11 | | ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name` | |
| 12 | | | |
| 13 | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! | |
| 14 | = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2018/trait-fn-parameters.html> | |
| 15 | = note: `#[warn(anonymous_parameters)]` (part of `#[warn(rust_2018_compatibility)]`) on by default | |
| 16 | ||
| 17 | error[E0718]: `fn` lang item must be applied to a trait with 1 generic argument | |
| 18 | --> $DIR/issue-83471.rs:20:1 | |
| 19 | | | |
| 20 | LL | #[lang = "fn"] | |
| 21 | | ^^^^^^^^^^^^^^ | |
| 22 | ... | |
| 23 | LL | trait Fn { | |
| 24 | | - this trait has 0 generic arguments | |
| 25 | ||
| 7 | 26 | error[E0658]: lang items are subject to change |
| 8 | 27 | --> $DIR/issue-83471.rs:8:1 |
| 9 | 28 | | |
| ... | ... | @@ -40,25 +59,6 @@ LL | #[lang = "fn"] |
| 40 | 59 | = help: add `#![feature(lang_items)]` to the crate attributes to enable |
| 41 | 60 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 42 | 61 | |
| 43 | warning: anonymous parameters are deprecated and will be removed in the next edition | |
| 44 | --> $DIR/issue-83471.rs:24:13 | |
| 45 | | | |
| 46 | LL | fn call(export_name); | |
| 47 | | ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name` | |
| 48 | | | |
| 49 | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! | |
| 50 | = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2018/trait-fn-parameters.html> | |
| 51 | = note: `#[warn(anonymous_parameters)]` (part of `#[warn(rust_2018_compatibility)]`) on by default | |
| 52 | ||
| 53 | error[E0718]: `fn` lang item must be applied to a trait with 1 generic argument | |
| 54 | --> $DIR/issue-83471.rs:20:1 | |
| 55 | | | |
| 56 | LL | #[lang = "fn"] | |
| 57 | | ^^^^^^^^^^^^^^ | |
| 58 | ... | |
| 59 | LL | trait Fn { | |
| 60 | | - this trait has 0 generic arguments | |
| 61 | ||
| 62 | 62 | error[E0425]: cannot find function `a` in this scope |
| 63 | 63 | --> $DIR/issue-83471.rs:30:5 |
| 64 | 64 | | |
tests/ui/lint/fn_must_use.stderr+1-1| ... | ... | @@ -4,8 +4,8 @@ warning: `#[must_use]` attribute cannot be used on trait methods in impl blocks |
| 4 | 4 | LL | #[must_use] |
| 5 | 5 | | ^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, and traits |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | = note: requested on the command line with `-W unused-attributes` |
| 10 | 10 | |
| 11 | 11 | warning: unused return value of `need_to_use_this_value` that must be used |
tests/ui/lint/inert-attr-macro.stderr+2-2| ... | ... | @@ -4,8 +4,8 @@ warning: `#[inline]` attribute cannot be used on macro calls |
| 4 | 4 | LL | #[inline] foo!(); |
| 5 | 5 | | ^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[inline]` can only be applied to functions |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | note: the lint level is defined here |
| 10 | 10 | --> $DIR/inert-attr-macro.rs:3:9 |
| 11 | 11 | | |
| ... | ... | @@ -31,8 +31,8 @@ warning: `#[inline]` attribute cannot be used on macro calls |
| 31 | 31 | LL | #[allow(warnings)] #[inline] foo!(); |
| 32 | 32 | | ^^^^^^^^^ |
| 33 | 33 | | |
| 34 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 35 | 34 | = help: `#[inline]` can only be applied to functions |
| 35 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 36 | 36 | |
| 37 | 37 | warning: 3 warnings emitted |
| 38 | 38 |
tests/ui/lint/inline-trait-and-foreign-items.stderr+2-2| ... | ... | @@ -44,8 +44,8 @@ warning: `#[inline]` attribute cannot be used on associated consts |
| 44 | 44 | LL | #[inline] |
| 45 | 45 | | ^^^^^^^^^ |
| 46 | 46 | | |
| 47 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 48 | 47 | = help: `#[inline]` can only be applied to functions |
| 48 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 49 | 49 | note: the lint level is defined here |
| 50 | 50 | --> $DIR/inline-trait-and-foreign-items.rs:4:9 |
| 51 | 51 | | |
| ... | ... | @@ -58,8 +58,8 @@ warning: `#[inline]` attribute cannot be used on associated consts |
| 58 | 58 | LL | #[inline] |
| 59 | 59 | | ^^^^^^^^^ |
| 60 | 60 | | |
| 61 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 62 | 61 | = help: `#[inline]` can only be applied to functions |
| 62 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 63 | 63 | |
| 64 | 64 | error: unconstrained opaque type |
| 65 | 65 | --> $DIR/inline-trait-and-foreign-items.rs:26:14 |
tests/ui/lint/unused/unused-attr-macro-rules.stderr+2-2| ... | ... | @@ -4,8 +4,8 @@ error: `#[macro_use]` attribute cannot be used on macro defs |
| 4 | 4 | LL | #[macro_use] |
| 5 | 5 | | ^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[macro_use]` can be applied to crates, extern crates, and modules |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | note: the lint level is defined here |
| 10 | 10 | --> $DIR/unused-attr-macro-rules.rs:1:9 |
| 11 | 11 | | |
| ... | ... | @@ -18,8 +18,8 @@ error: `#[path]` attribute cannot be used on macro defs |
| 18 | 18 | LL | #[path="foo"] |
| 19 | 19 | | ^^^^^^^^^^^^^ |
| 20 | 20 | | |
| 21 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 22 | 21 | = help: `#[path]` can only be applied to modules |
| 22 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 23 | 23 | |
| 24 | 24 | error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` |
| 25 | 25 | --> $DIR/unused-attr-macro-rules.rs:11:1 |
tests/ui/lint/unused/unused_attributes-must_use.stderr+22-22| ... | ... | @@ -4,8 +4,8 @@ error: `#[must_use]` attribute cannot be used on macro calls |
| 4 | 4 | LL | #[must_use] |
| 5 | 5 | | ^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | note: the lint level is defined here |
| 10 | 10 | --> $DIR/unused_attributes-must_use.rs:4:9 |
| 11 | 11 | | |
| ... | ... | @@ -18,8 +18,8 @@ error: `#[must_use]` attribute cannot be used on extern crates |
| 18 | 18 | LL | #[must_use] |
| 19 | 19 | | ^^^^^^^^^^^ |
| 20 | 20 | | |
| 21 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 22 | 21 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 22 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 23 | 23 | |
| 24 | 24 | error: `#[must_use]` attribute cannot be used on modules |
| 25 | 25 | --> $DIR/unused_attributes-must_use.rs:11:1 |
| ... | ... | @@ -27,8 +27,8 @@ error: `#[must_use]` attribute cannot be used on modules |
| 27 | 27 | LL | #[must_use] |
| 28 | 28 | | ^^^^^^^^^^^ |
| 29 | 29 | | |
| 30 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 31 | 30 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 31 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 32 | 32 | |
| 33 | 33 | error: `#[must_use]` attribute cannot be used on use statements |
| 34 | 34 | --> $DIR/unused_attributes-must_use.rs:15:1 |
| ... | ... | @@ -36,8 +36,8 @@ error: `#[must_use]` attribute cannot be used on use statements |
| 36 | 36 | LL | #[must_use] |
| 37 | 37 | | ^^^^^^^^^^^ |
| 38 | 38 | | |
| 39 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 40 | 39 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 40 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 41 | 41 | |
| 42 | 42 | error: `#[must_use]` attribute cannot be used on constants |
| 43 | 43 | --> $DIR/unused_attributes-must_use.rs:19:1 |
| ... | ... | @@ -45,8 +45,8 @@ error: `#[must_use]` attribute cannot be used on constants |
| 45 | 45 | LL | #[must_use] |
| 46 | 46 | | ^^^^^^^^^^^ |
| 47 | 47 | | |
| 48 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 49 | 48 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 49 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 50 | 50 | |
| 51 | 51 | error: `#[must_use]` attribute cannot be used on statics |
| 52 | 52 | --> $DIR/unused_attributes-must_use.rs:22:1 |
| ... | ... | @@ -54,8 +54,8 @@ error: `#[must_use]` attribute cannot be used on statics |
| 54 | 54 | LL | #[must_use] |
| 55 | 55 | | ^^^^^^^^^^^ |
| 56 | 56 | | |
| 57 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 58 | 57 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 58 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 59 | 59 | |
| 60 | 60 | error: `#[must_use]` attribute cannot be used on inherent impl blocks |
| 61 | 61 | --> $DIR/unused_attributes-must_use.rs:40:1 |
| ... | ... | @@ -63,8 +63,8 @@ error: `#[must_use]` attribute cannot be used on inherent impl blocks |
| 63 | 63 | LL | #[must_use] |
| 64 | 64 | | ^^^^^^^^^^^ |
| 65 | 65 | | |
| 66 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 67 | 66 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 67 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 68 | 68 | |
| 69 | 69 | error: `#[must_use]` attribute cannot be used on foreign modules |
| 70 | 70 | --> $DIR/unused_attributes-must_use.rs:55:1 |
| ... | ... | @@ -72,8 +72,8 @@ error: `#[must_use]` attribute cannot be used on foreign modules |
| 72 | 72 | LL | #[must_use] |
| 73 | 73 | | ^^^^^^^^^^^ |
| 74 | 74 | | |
| 75 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 76 | 75 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 76 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 77 | 77 | |
| 78 | 78 | error: `#[must_use]` attribute cannot be used on foreign statics |
| 79 | 79 | --> $DIR/unused_attributes-must_use.rs:59:5 |
| ... | ... | @@ -81,8 +81,8 @@ error: `#[must_use]` attribute cannot be used on foreign statics |
| 81 | 81 | LL | #[must_use] |
| 82 | 82 | | ^^^^^^^^^^^ |
| 83 | 83 | | |
| 84 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 85 | 84 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 85 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 86 | 86 | |
| 87 | 87 | error: `#[must_use]` attribute cannot be used on type aliases |
| 88 | 88 | --> $DIR/unused_attributes-must_use.rs:73:1 |
| ... | ... | @@ -90,8 +90,8 @@ error: `#[must_use]` attribute cannot be used on type aliases |
| 90 | 90 | LL | #[must_use] |
| 91 | 91 | | ^^^^^^^^^^^ |
| 92 | 92 | | |
| 93 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 94 | 93 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 94 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 95 | 95 | |
| 96 | 96 | error: `#[must_use]` attribute cannot be used on type parameters |
| 97 | 97 | --> $DIR/unused_attributes-must_use.rs:77:8 |
| ... | ... | @@ -99,8 +99,8 @@ error: `#[must_use]` attribute cannot be used on type parameters |
| 99 | 99 | LL | fn qux<#[must_use] T>(_: T) {} |
| 100 | 100 | | ^^^^^^^^^^^ |
| 101 | 101 | | |
| 102 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 103 | 102 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 103 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 104 | 104 | |
| 105 | 105 | error: `#[must_use]` attribute cannot be used on associated consts |
| 106 | 106 | --> $DIR/unused_attributes-must_use.rs:82:5 |
| ... | ... | @@ -108,8 +108,8 @@ error: `#[must_use]` attribute cannot be used on associated consts |
| 108 | 108 | LL | #[must_use] |
| 109 | 109 | | ^^^^^^^^^^^ |
| 110 | 110 | | |
| 111 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 112 | 111 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 112 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 113 | 113 | |
| 114 | 114 | error: `#[must_use]` attribute cannot be used on associated types |
| 115 | 115 | --> $DIR/unused_attributes-must_use.rs:85:5 |
| ... | ... | @@ -117,8 +117,8 @@ error: `#[must_use]` attribute cannot be used on associated types |
| 117 | 117 | LL | #[must_use] |
| 118 | 118 | | ^^^^^^^^^^^ |
| 119 | 119 | | |
| 120 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 121 | 120 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 121 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 122 | 122 | |
| 123 | 123 | error: `#[must_use]` attribute cannot be used on trait impl blocks |
| 124 | 124 | --> $DIR/unused_attributes-must_use.rs:95:1 |
| ... | ... | @@ -126,8 +126,8 @@ error: `#[must_use]` attribute cannot be used on trait impl blocks |
| 126 | 126 | LL | #[must_use] |
| 127 | 127 | | ^^^^^^^^^^^ |
| 128 | 128 | | |
| 129 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 130 | 129 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 130 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 131 | 131 | |
| 132 | 132 | error: `#[must_use]` attribute cannot be used on trait methods in impl blocks |
| 133 | 133 | --> $DIR/unused_attributes-must_use.rs:100:5 |
| ... | ... | @@ -135,8 +135,8 @@ error: `#[must_use]` attribute cannot be used on trait methods in impl blocks |
| 135 | 135 | LL | #[must_use] |
| 136 | 136 | | ^^^^^^^^^^^ |
| 137 | 137 | | |
| 138 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 139 | 138 | = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, and traits |
| 139 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 140 | 140 | |
| 141 | 141 | error: `#[must_use]` attribute cannot be used on trait aliases |
| 142 | 142 | --> $DIR/unused_attributes-must_use.rs:107:1 |
| ... | ... | @@ -144,8 +144,8 @@ error: `#[must_use]` attribute cannot be used on trait aliases |
| 144 | 144 | LL | #[must_use] |
| 145 | 145 | | ^^^^^^^^^^^ |
| 146 | 146 | | |
| 147 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 148 | 147 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 148 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 149 | 149 | |
| 150 | 150 | error: `#[must_use]` attribute cannot be used on macro defs |
| 151 | 151 | --> $DIR/unused_attributes-must_use.rs:111:1 |
| ... | ... | @@ -153,8 +153,8 @@ error: `#[must_use]` attribute cannot be used on macro defs |
| 153 | 153 | LL | #[must_use] |
| 154 | 154 | | ^^^^^^^^^^^ |
| 155 | 155 | | |
| 156 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 157 | 156 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 157 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 158 | 158 | |
| 159 | 159 | error: `#[must_use]` attribute cannot be used on statements |
| 160 | 160 | --> $DIR/unused_attributes-must_use.rs:120:5 |
| ... | ... | @@ -162,8 +162,8 @@ error: `#[must_use]` attribute cannot be used on statements |
| 162 | 162 | LL | #[must_use] |
| 163 | 163 | | ^^^^^^^^^^^ |
| 164 | 164 | | |
| 165 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 166 | 165 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 166 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 167 | 167 | |
| 168 | 168 | error: `#[must_use]` attribute cannot be used on closures |
| 169 | 169 | --> $DIR/unused_attributes-must_use.rs:125:13 |
| ... | ... | @@ -171,8 +171,8 @@ error: `#[must_use]` attribute cannot be used on closures |
| 171 | 171 | LL | let x = #[must_use] |
| 172 | 172 | | ^^^^^^^^^^^ |
| 173 | 173 | | |
| 174 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 175 | 174 | = help: `#[must_use]` can be applied to data types, foreign functions, functions, methods, and traits |
| 175 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 176 | 176 | |
| 177 | 177 | error: `#[must_use]` attribute cannot be used on match arms |
| 178 | 178 | --> $DIR/unused_attributes-must_use.rs:148:9 |
| ... | ... | @@ -180,8 +180,8 @@ error: `#[must_use]` attribute cannot be used on match arms |
| 180 | 180 | LL | #[must_use] |
| 181 | 181 | | ^^^^^^^^^^^ |
| 182 | 182 | | |
| 183 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 184 | 183 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 184 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 185 | 185 | |
| 186 | 186 | error: `#[must_use]` attribute cannot be used on struct fields |
| 187 | 187 | --> $DIR/unused_attributes-must_use.rs:157:28 |
| ... | ... | @@ -189,8 +189,8 @@ error: `#[must_use]` attribute cannot be used on struct fields |
| 189 | 189 | LL | let s = PatternField { #[must_use] foo: 123 }; |
| 190 | 190 | | ^^^^^^^^^^^ |
| 191 | 191 | | |
| 192 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 193 | 192 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 193 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 194 | 194 | |
| 195 | 195 | error: `#[must_use]` attribute cannot be used on pattern fields |
| 196 | 196 | --> $DIR/unused_attributes-must_use.rs:159:24 |
| ... | ... | @@ -198,8 +198,8 @@ error: `#[must_use]` attribute cannot be used on pattern fields |
| 198 | 198 | LL | let PatternField { #[must_use] foo } = s; |
| 199 | 199 | | ^^^^^^^^^^^ |
| 200 | 200 | | |
| 201 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 202 | 201 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 202 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 203 | 203 | |
| 204 | 204 | error: unused `X` that must be used |
| 205 | 205 | --> $DIR/unused_attributes-must_use.rs:130:5 |
tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr+2-2| ... | ... | @@ -4,8 +4,8 @@ error: `#[inline]` attribute cannot be used on required trait methods |
| 4 | 4 | LL | #[inline] |
| 5 | 5 | | ^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[inline]` can be applied to closures, functions, inherent methods, provided trait methods, and trait methods in impl blocks |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | note: the lint level is defined here |
| 10 | 10 | --> $DIR/warn-unused-inline-on-fn-prototypes.rs:1:9 |
| 11 | 11 | | |
| ... | ... | @@ -18,8 +18,8 @@ error: `#[inline]` attribute cannot be used on foreign functions |
| 18 | 18 | LL | #[inline] |
| 19 | 19 | | ^^^^^^^^^ |
| 20 | 20 | | |
| 21 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 22 | 21 | = help: `#[inline]` can be applied to closures, functions, and methods |
| 22 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 23 | 23 | |
| 24 | 24 | error: aborting due to 2 previous errors |
| 25 | 25 |
tests/ui/privacy/effective-visibilities-macro-2.rs created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | // Make sure that `Placeholder` will be marked as reachable without `use crate::ty` like in | |
| 2 | // `effective-visibility-macro.rs` test. | |
| 3 | ||
| 4 | #![feature(rustc_attrs, decl_macro)] | |
| 5 | ||
| 6 | pub mod ty { | |
| 7 | pub mod print { | |
| 8 | mod pretty { | |
| 9 | #[rustc_effective_visibility] | |
| 10 | pub macro with_no_queries() {} | |
| 11 | //~^ ERROR Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub | |
| 12 | } | |
| 13 | ||
| 14 | pub use self::pretty::with_no_queries; | |
| 15 | } | |
| 16 | ||
| 17 | #[rustc_effective_visibility] | |
| 18 | mod sty { | |
| 19 | //~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) | |
| 20 | #[rustc_effective_visibility] | |
| 21 | pub type Placeholder = (); | |
| 22 | //~^ ERROR Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub | |
| 23 | } | |
| 24 | } | |
| 25 | ||
| 26 | fn main() {} |
tests/ui/privacy/effective-visibilities-macro-2.stderr created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | error: Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub | |
| 2 | --> $DIR/effective-visibilities-macro-2.rs:10:13 | |
| 3 | | | |
| 4 | LL | pub macro with_no_queries() {} | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | ||
| 7 | error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) | |
| 8 | --> $DIR/effective-visibilities-macro-2.rs:18:5 | |
| 9 | | | |
| 10 | LL | mod sty { | |
| 11 | | ^^^^^^^ | |
| 12 | ||
| 13 | error: Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub | |
| 14 | --> $DIR/effective-visibilities-macro-2.rs:21:9 | |
| 15 | | | |
| 16 | LL | pub type Placeholder = (); | |
| 17 | | ^^^^^^^^^^^^^^^^^^^^ | |
| 18 | ||
| 19 | error: aborting due to 3 previous errors | |
| 20 |
tests/ui/privacy/effective-visibilities-macro.rs created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | #![feature(rustc_attrs, decl_macro)] | |
| 2 | ||
| 3 | pub mod ty { | |
| 4 | pub mod print { | |
| 5 | mod pretty { | |
| 6 | #[rustc_effective_visibility] | |
| 7 | pub macro with_no_queries() {} | |
| 8 | //~^ ERROR Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub | |
| 9 | } | |
| 10 | ||
| 11 | pub use self::pretty::with_no_queries; | |
| 12 | // Start visiting outer modules during macro-reachable phase. | |
| 13 | use crate::ty; | |
| 14 | } | |
| 15 | ||
| 16 | #[rustc_effective_visibility] | |
| 17 | mod sty { | |
| 18 | //~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) | |
| 19 | #[rustc_effective_visibility] | |
| 20 | pub type Placeholder = (); | |
| 21 | //~^ ERROR Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub | |
| 22 | } | |
| 23 | } | |
| 24 | ||
| 25 | fn main() {} |
tests/ui/privacy/effective-visibilities-macro.stderr created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | error: Direct: pub(in crate::ty::print), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub | |
| 2 | --> $DIR/effective-visibilities-macro.rs:7:13 | |
| 3 | | | |
| 4 | LL | pub macro with_no_queries() {} | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | ||
| 7 | error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) | |
| 8 | --> $DIR/effective-visibilities-macro.rs:17:5 | |
| 9 | | | |
| 10 | LL | mod sty { | |
| 11 | | ^^^^^^^ | |
| 12 | ||
| 13 | error: Direct: pub(in crate::ty), Reexported: pub(in crate::ty), Reachable: pub, ReachableThroughImplTrait: pub | |
| 14 | --> $DIR/effective-visibilities-macro.rs:20:9 | |
| 15 | | | |
| 16 | LL | pub type Placeholder = (); | |
| 17 | | ^^^^^^^^^^^^^^^^^^^^ | |
| 18 | ||
| 19 | error: aborting due to 3 previous errors | |
| 20 |
tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.stderr+1-1| ... | ... | @@ -4,8 +4,8 @@ warning: `#[track_caller]` attribute cannot be used on macro defs |
| 4 | 4 | LL | #[track_caller] |
| 5 | 5 | | ^^^^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 8 | 7 | = help: `#[track_caller]` can only be applied to functions |
| 8 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 9 | 9 | = note: requested on the command line with `-W unused-attributes` |
| 10 | 10 | |
| 11 | 11 | warning: 1 warning emitted |
tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr+16-16| ... | ... | @@ -388,8 +388,8 @@ warning: `#[must_use]` attribute cannot be used on function params |
| 388 | 388 | LL | #[must_use] |
| 389 | 389 | | ^^^^^^^^^^^ |
| 390 | 390 | | |
| 391 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 392 | 391 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 392 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 393 | 393 | = note: requested on the command line with `-W unused-attributes` |
| 394 | 394 | |
| 395 | 395 | warning: `#[no_mangle]` attribute cannot be used on function params |
| ... | ... | @@ -398,8 +398,8 @@ warning: `#[no_mangle]` attribute cannot be used on function params |
| 398 | 398 | LL | #[no_mangle] b: i32, |
| 399 | 399 | | ^^^^^^^^^^^^ |
| 400 | 400 | | |
| 401 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 402 | 401 | = help: `#[no_mangle]` can be applied to functions and statics |
| 402 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 403 | 403 | |
| 404 | 404 | warning: `#[must_use]` attribute cannot be used on function params |
| 405 | 405 | --> $DIR/param-attrs-builtin-attrs.rs:64:9 |
| ... | ... | @@ -407,8 +407,8 @@ warning: `#[must_use]` attribute cannot be used on function params |
| 407 | 407 | LL | #[must_use] |
| 408 | 408 | | ^^^^^^^^^^^ |
| 409 | 409 | | |
| 410 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 411 | 410 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 411 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 412 | 412 | |
| 413 | 413 | warning: `#[no_mangle]` attribute cannot be used on function params |
| 414 | 414 | --> $DIR/param-attrs-builtin-attrs.rs:70:9 |
| ... | ... | @@ -416,8 +416,8 @@ warning: `#[no_mangle]` attribute cannot be used on function params |
| 416 | 416 | LL | #[no_mangle] b: i32, |
| 417 | 417 | | ^^^^^^^^^^^^ |
| 418 | 418 | | |
| 419 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 420 | 419 | = help: `#[no_mangle]` can be applied to functions and statics |
| 420 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 421 | 421 | |
| 422 | 422 | warning: `#[must_use]` attribute cannot be used on function params |
| 423 | 423 | --> $DIR/param-attrs-builtin-attrs.rs:83:9 |
| ... | ... | @@ -425,8 +425,8 @@ warning: `#[must_use]` attribute cannot be used on function params |
| 425 | 425 | LL | #[must_use] |
| 426 | 426 | | ^^^^^^^^^^^ |
| 427 | 427 | | |
| 428 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 429 | 428 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 429 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 430 | 430 | |
| 431 | 431 | warning: `#[no_mangle]` attribute cannot be used on function params |
| 432 | 432 | --> $DIR/param-attrs-builtin-attrs.rs:89:9 |
| ... | ... | @@ -434,8 +434,8 @@ warning: `#[no_mangle]` attribute cannot be used on function params |
| 434 | 434 | LL | #[no_mangle] b: i32, |
| 435 | 435 | | ^^^^^^^^^^^^ |
| 436 | 436 | | |
| 437 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 438 | 437 | = help: `#[no_mangle]` can be applied to functions and statics |
| 438 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 439 | 439 | |
| 440 | 440 | warning: `#[must_use]` attribute cannot be used on function params |
| 441 | 441 | --> $DIR/param-attrs-builtin-attrs.rs:108:9 |
| ... | ... | @@ -443,8 +443,8 @@ warning: `#[must_use]` attribute cannot be used on function params |
| 443 | 443 | LL | #[must_use] |
| 444 | 444 | | ^^^^^^^^^^^ |
| 445 | 445 | | |
| 446 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 447 | 446 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 447 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 448 | 448 | |
| 449 | 449 | warning: `#[no_mangle]` attribute cannot be used on function params |
| 450 | 450 | --> $DIR/param-attrs-builtin-attrs.rs:114:9 |
| ... | ... | @@ -452,8 +452,8 @@ warning: `#[no_mangle]` attribute cannot be used on function params |
| 452 | 452 | LL | #[no_mangle] b: i32, |
| 453 | 453 | | ^^^^^^^^^^^^ |
| 454 | 454 | | |
| 455 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 456 | 455 | = help: `#[no_mangle]` can be applied to functions and statics |
| 456 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 457 | 457 | |
| 458 | 458 | warning: `#[must_use]` attribute cannot be used on function params |
| 459 | 459 | --> $DIR/param-attrs-builtin-attrs.rs:131:9 |
| ... | ... | @@ -461,8 +461,8 @@ warning: `#[must_use]` attribute cannot be used on function params |
| 461 | 461 | LL | #[must_use] |
| 462 | 462 | | ^^^^^^^^^^^ |
| 463 | 463 | | |
| 464 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 465 | 464 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 465 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 466 | 466 | |
| 467 | 467 | warning: `#[no_mangle]` attribute cannot be used on function params |
| 468 | 468 | --> $DIR/param-attrs-builtin-attrs.rs:137:9 |
| ... | ... | @@ -470,8 +470,8 @@ warning: `#[no_mangle]` attribute cannot be used on function params |
| 470 | 470 | LL | #[no_mangle] b: i32, |
| 471 | 471 | | ^^^^^^^^^^^^ |
| 472 | 472 | | |
| 473 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 474 | 473 | = help: `#[no_mangle]` can be applied to functions and statics |
| 474 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 475 | 475 | |
| 476 | 476 | warning: `#[must_use]` attribute cannot be used on function params |
| 477 | 477 | --> $DIR/param-attrs-builtin-attrs.rs:150:9 |
| ... | ... | @@ -479,8 +479,8 @@ warning: `#[must_use]` attribute cannot be used on function params |
| 479 | 479 | LL | #[must_use] |
| 480 | 480 | | ^^^^^^^^^^^ |
| 481 | 481 | | |
| 482 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 483 | 482 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 483 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 484 | 484 | |
| 485 | 485 | warning: `#[no_mangle]` attribute cannot be used on function params |
| 486 | 486 | --> $DIR/param-attrs-builtin-attrs.rs:156:9 |
| ... | ... | @@ -488,8 +488,8 @@ warning: `#[no_mangle]` attribute cannot be used on function params |
| 488 | 488 | LL | #[no_mangle] b: i32, |
| 489 | 489 | | ^^^^^^^^^^^^ |
| 490 | 490 | | |
| 491 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 492 | 491 | = help: `#[no_mangle]` can be applied to functions and statics |
| 492 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 493 | 493 | |
| 494 | 494 | warning: `#[must_use]` attribute cannot be used on function params |
| 495 | 495 | --> $DIR/param-attrs-builtin-attrs.rs:174:9 |
| ... | ... | @@ -497,8 +497,8 @@ warning: `#[must_use]` attribute cannot be used on function params |
| 497 | 497 | LL | #[must_use] |
| 498 | 498 | | ^^^^^^^^^^^ |
| 499 | 499 | | |
| 500 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 501 | 500 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 501 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 502 | 502 | |
| 503 | 503 | warning: `#[no_mangle]` attribute cannot be used on function params |
| 504 | 504 | --> $DIR/param-attrs-builtin-attrs.rs:180:9 |
| ... | ... | @@ -506,8 +506,8 @@ warning: `#[no_mangle]` attribute cannot be used on function params |
| 506 | 506 | LL | #[no_mangle] b: i32, |
| 507 | 507 | | ^^^^^^^^^^^^ |
| 508 | 508 | | |
| 509 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 510 | 509 | = help: `#[no_mangle]` can be applied to functions and statics |
| 510 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 511 | 511 | |
| 512 | 512 | warning: `#[must_use]` attribute cannot be used on function params |
| 513 | 513 | --> $DIR/param-attrs-builtin-attrs.rs:195:9 |
| ... | ... | @@ -515,8 +515,8 @@ warning: `#[must_use]` attribute cannot be used on function params |
| 515 | 515 | LL | #[must_use] |
| 516 | 516 | | ^^^^^^^^^^^ |
| 517 | 517 | | |
| 518 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 519 | 518 | = help: `#[must_use]` can be applied to data types, functions, and traits |
| 519 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 520 | 520 | |
| 521 | 521 | warning: `#[no_mangle]` attribute cannot be used on function params |
| 522 | 522 | --> $DIR/param-attrs-builtin-attrs.rs:201:9 |
| ... | ... | @@ -524,8 +524,8 @@ warning: `#[no_mangle]` attribute cannot be used on function params |
| 524 | 524 | LL | #[no_mangle] b: i32 |
| 525 | 525 | | ^^^^^^^^^^^^ |
| 526 | 526 | | |
| 527 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 528 | 527 | = help: `#[no_mangle]` can be applied to functions and statics |
| 528 | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
| 529 | 529 | |
| 530 | 530 | error: aborting due to 64 previous errors; 16 warnings emitted |
| 531 | 531 |
tests/ui/stability-attribute/issue-106589.stderr+3-3| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/issue-106589.rs:3:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #![stable(feature = "foo", since = "1.0.0")] |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 7 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 8 | 8 | --> $DIR/issue-106589.rs:6:1 |
| 9 | 9 | | |
| 10 | 10 | LL | #[unstable(feature = "foo", issue = "none")] |
| ... | ... | @@ -12,4 +12,4 @@ LL | #[unstable(feature = "foo", issue = "none")] |
| 12 | 12 | |
| 13 | 13 | error: aborting due to 2 previous errors |
| 14 | 14 | |
| 15 | For more information about this error, try `rustc --explain E0734`. | |
| 15 | For more information about this error, try `rustc --explain E0658`. |
tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs+8-2| ... | ... | @@ -1,5 +1,11 @@ |
| 1 | 1 | //@ compile-flags:-Zforce-unstable-if-unmarked |
| 2 | 2 | |
| 3 | #[unstable()] //~ ERROR: stability attributes may not be used | |
| 4 | #[stable()] //~ ERROR: stability attributes may not be used | |
| 3 | #[unstable()] | |
| 4 | //~^ ERROR stability attributes may not be used | |
| 5 | //~| ERROR missing 'feature' | |
| 6 | //~| ERROR missing 'issue' | |
| 7 | #[stable()] | |
| 8 | //~^ ERROR stability attributes may not be used | |
| 9 | //~| ERROR missing 'feature' | |
| 10 | //~| ERROR missing 'since' | |
| 5 | 11 | fn main() {} |
tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr+30-5| ... | ... | @@ -1,15 +1,40 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/stability-attribute-non-staged-force-unstable.rs:3:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #[unstable()] |
| 5 | 5 | | ^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 8 | --> $DIR/stability-attribute-non-staged-force-unstable.rs:4:1 | |
| 7 | error[E0546]: missing 'feature' | |
| 8 | --> $DIR/stability-attribute-non-staged-force-unstable.rs:3:1 | |
| 9 | | | |
| 10 | LL | #[unstable()] | |
| 11 | | ^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error[E0547]: missing 'issue' | |
| 14 | --> $DIR/stability-attribute-non-staged-force-unstable.rs:3:1 | |
| 15 | | | |
| 16 | LL | #[unstable()] | |
| 17 | | ^^^^^^^^^^^^^ | |
| 18 | ||
| 19 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 20 | --> $DIR/stability-attribute-non-staged-force-unstable.rs:7:1 | |
| 21 | | | |
| 22 | LL | #[stable()] | |
| 23 | | ^^^^^^^^^^^ | |
| 24 | ||
| 25 | error[E0546]: missing 'feature' | |
| 26 | --> $DIR/stability-attribute-non-staged-force-unstable.rs:7:1 | |
| 27 | | | |
| 28 | LL | #[stable()] | |
| 29 | | ^^^^^^^^^^^ | |
| 30 | ||
| 31 | error[E0542]: missing 'since' | |
| 32 | --> $DIR/stability-attribute-non-staged-force-unstable.rs:7:1 | |
| 9 | 33 | | |
| 10 | 34 | LL | #[stable()] |
| 11 | 35 | | ^^^^^^^^^^^ |
| 12 | 36 | |
| 13 | error: aborting due to 2 previous errors | |
| 37 | error: aborting due to 6 previous errors | |
| 14 | 38 | |
| 15 | For more information about this error, try `rustc --explain E0734`. | |
| 39 | Some errors have detailed explanations: E0542, E0546, E0547, E0658. | |
| 40 | For more information about an error, try `rustc --explain E0542`. |
tests/ui/stability-attribute/stability-attribute-non-staged.rs+8-2| ... | ... | @@ -1,3 +1,9 @@ |
| 1 | #[unstable()] //~ ERROR: stability attributes may not be used | |
| 2 | #[stable()] //~ ERROR: stability attributes may not be used | |
| 1 | #[unstable()] | |
| 2 | //~^ ERROR: stability attributes may not be used | |
| 3 | //~| ERROR missing 'feature' | |
| 4 | //~| ERROR missing 'issue' | |
| 5 | #[stable()] | |
| 6 | //~^ ERROR: stability attributes may not be used | |
| 7 | //~| ERROR missing 'feature' | |
| 8 | //~| ERROR missing 'since' | |
| 3 | 9 | fn main() {} |
tests/ui/stability-attribute/stability-attribute-non-staged.stderr+30-5| ... | ... | @@ -1,15 +1,40 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/stability-attribute-non-staged.rs:1:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #[unstable()] |
| 5 | 5 | | ^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 8 | --> $DIR/stability-attribute-non-staged.rs:2:1 | |
| 7 | error[E0546]: missing 'feature' | |
| 8 | --> $DIR/stability-attribute-non-staged.rs:1:1 | |
| 9 | | | |
| 10 | LL | #[unstable()] | |
| 11 | | ^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error[E0547]: missing 'issue' | |
| 14 | --> $DIR/stability-attribute-non-staged.rs:1:1 | |
| 15 | | | |
| 16 | LL | #[unstable()] | |
| 17 | | ^^^^^^^^^^^^^ | |
| 18 | ||
| 19 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 20 | --> $DIR/stability-attribute-non-staged.rs:5:1 | |
| 21 | | | |
| 22 | LL | #[stable()] | |
| 23 | | ^^^^^^^^^^^ | |
| 24 | ||
| 25 | error[E0546]: missing 'feature' | |
| 26 | --> $DIR/stability-attribute-non-staged.rs:5:1 | |
| 27 | | | |
| 28 | LL | #[stable()] | |
| 29 | | ^^^^^^^^^^^ | |
| 30 | ||
| 31 | error[E0542]: missing 'since' | |
| 32 | --> $DIR/stability-attribute-non-staged.rs:5:1 | |
| 9 | 33 | | |
| 10 | 34 | LL | #[stable()] |
| 11 | 35 | | ^^^^^^^^^^^ |
| 12 | 36 | |
| 13 | error: aborting due to 2 previous errors | |
| 37 | error: aborting due to 6 previous errors | |
| 14 | 38 | |
| 15 | For more information about this error, try `rustc --explain E0734`. | |
| 39 | Some errors have detailed explanations: E0542, E0546, E0547, E0658. | |
| 40 | For more information about an error, try `rustc --explain E0542`. |
tests/ui/tool-attributes/diagnostic_item.rs+1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | #[rustc_diagnostic_item = "foomp"] |
| 2 | 2 | //~^ ERROR use of an internal attribute [E0658] |
| 3 | //~| NOTE the `#[rustc_diagnostic_item]` attribute is an internal implementation detail that will never be stable | |
| 3 | 4 | //~| NOTE the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types from the standard library for diagnostic purposes |
| 4 | 5 | struct Foomp; |
| 5 | 6 | fn main() {} |
tests/ui/tool-attributes/diagnostic_item.stderr+1| ... | ... | @@ -5,6 +5,7 @@ LL | #[rustc_diagnostic_item = "foomp"] |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable |
| 8 | = note: the `#[rustc_diagnostic_item]` attribute is an internal implementation detail that will never be stable | |
| 8 | 9 | = note: the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types from the standard library for diagnostic purposes |
| 9 | 10 | |
| 10 | 11 | error: aborting due to 1 previous error |
tests/ui/traits/unhandled-crate-mod-issue-144888.rs created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | // Regression test for <https://github.com/rust-lang/rust/issues/144888>. | |
| 2 | // This used to ICE with `unhandled node Crate(Mod)`. | |
| 3 | ||
| 4 | trait Super { | |
| 5 | type Assoc; | |
| 6 | } | |
| 7 | ||
| 8 | impl dyn Foo<()> {} | |
| 9 | ||
| 10 | trait Foo<T>: Super<Assoc = T> | |
| 11 | //~^ ERROR type mismatch resolving | |
| 12 | //~| ERROR the size for values of type `Self` cannot be known at compilation time | |
| 13 | where | |
| 14 | <Self as Mirror>::Assoc: Clone, | |
| 15 | //~^ ERROR type mismatch resolving | |
| 16 | //~| ERROR the size for values of type `Self` cannot be known at compilation time | |
| 17 | //~| ERROR type mismatch resolving | |
| 18 | //~| ERROR the size for values of type `Self` cannot be known at compilation time | |
| 19 | { | |
| 20 | fn transmute(&self) {} | |
| 21 | //~^ ERROR type mismatch resolving | |
| 22 | //~| ERROR the size for values of type `Self` cannot be known at compilation time | |
| 23 | //~| ERROR type mismatch resolving | |
| 24 | //~| ERROR the size for values of type `Self` cannot be known at compilation time | |
| 25 | } | |
| 26 | ||
| 27 | trait Mirror { | |
| 28 | type Assoc; | |
| 29 | } | |
| 30 | ||
| 31 | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 32 | //~^ ERROR not all trait items implemented | |
| 33 | ||
| 34 | fn main() {} |
tests/ui/traits/unhandled-crate-mod-issue-144888.stderr created+189| ... | ... | @@ -0,0 +1,189 @@ |
| 1 | error[E0271]: type mismatch resolving `<Self as Super>::Assoc == ()` | |
| 2 | --> $DIR/unhandled-crate-mod-issue-144888.rs:20:5 | |
| 3 | | | |
| 4 | LL | fn transmute(&self) {} | |
| 5 | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found type parameter `T` | |
| 6 | | | |
| 7 | = note: expected unit type `()` | |
| 8 | found type parameter `T` | |
| 9 | note: required for `Self` to implement `Mirror` | |
| 10 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 11 | | | |
| 12 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 13 | | ---------- ^^^^^^ ^ | |
| 14 | | | | |
| 15 | | unsatisfied trait bound introduced here | |
| 16 | ||
| 17 | error[E0277]: the size for values of type `Self` cannot be known at compilation time | |
| 18 | --> $DIR/unhandled-crate-mod-issue-144888.rs:20:5 | |
| 19 | | | |
| 20 | LL | fn transmute(&self) {} | |
| 21 | | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | |
| 22 | | | |
| 23 | note: required for `Self` to implement `Mirror` | |
| 24 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 25 | | | |
| 26 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 27 | | - ^^^^^^ ^ | |
| 28 | | | | |
| 29 | | unsatisfied trait bound implicitly introduced here | |
| 30 | ||
| 31 | error[E0271]: type mismatch resolving `<Self as Super>::Assoc == ()` | |
| 32 | --> $DIR/unhandled-crate-mod-issue-144888.rs:10:1 | |
| 33 | | | |
| 34 | LL | trait Foo<T>: Super<Assoc = T> | |
| 35 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found type parameter `T` | |
| 36 | | | |
| 37 | = note: expected unit type `()` | |
| 38 | found type parameter `T` | |
| 39 | note: required for `Self` to implement `Mirror` | |
| 40 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 41 | | | |
| 42 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 43 | | ---------- ^^^^^^ ^ | |
| 44 | | | | |
| 45 | | unsatisfied trait bound introduced here | |
| 46 | ||
| 47 | error[E0277]: the size for values of type `Self` cannot be known at compilation time | |
| 48 | --> $DIR/unhandled-crate-mod-issue-144888.rs:10:1 | |
| 49 | | | |
| 50 | LL | trait Foo<T>: Super<Assoc = T> | |
| 51 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | |
| 52 | | | |
| 53 | note: required for `Self` to implement `Mirror` | |
| 54 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 55 | | | |
| 56 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 57 | | - ^^^^^^ ^ | |
| 58 | | | | |
| 59 | | unsatisfied trait bound implicitly introduced here | |
| 60 | help: consider further restricting `Self` | |
| 61 | | | |
| 62 | LL | trait Foo<T>: Super<Assoc = T> + Sized | |
| 63 | | +++++++ | |
| 64 | ||
| 65 | error[E0271]: type mismatch resolving `<Self as Super>::Assoc == ()` | |
| 66 | --> $DIR/unhandled-crate-mod-issue-144888.rs:14:30 | |
| 67 | | | |
| 68 | LL | trait Foo<T>: Super<Assoc = T> | |
| 69 | | - found this type parameter | |
| 70 | ... | |
| 71 | LL | <Self as Mirror>::Assoc: Clone, | |
| 72 | | ^^^^^ expected `()`, found type parameter `T` | |
| 73 | | | |
| 74 | = note: expected unit type `()` | |
| 75 | found type parameter `T` | |
| 76 | note: required for `Self` to implement `Mirror` | |
| 77 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 78 | | | |
| 79 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 80 | | ---------- ^^^^^^ ^ | |
| 81 | | | | |
| 82 | | unsatisfied trait bound introduced here | |
| 83 | ||
| 84 | error[E0277]: the size for values of type `Self` cannot be known at compilation time | |
| 85 | --> $DIR/unhandled-crate-mod-issue-144888.rs:14:30 | |
| 86 | | | |
| 87 | LL | <Self as Mirror>::Assoc: Clone, | |
| 88 | | ^^^^^ doesn't have a size known at compile-time | |
| 89 | | | |
| 90 | note: required for `Self` to implement `Mirror` | |
| 91 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 92 | | | |
| 93 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 94 | | - ^^^^^^ ^ | |
| 95 | | | | |
| 96 | | unsatisfied trait bound implicitly introduced here | |
| 97 | help: consider further restricting `Self` | |
| 98 | | | |
| 99 | LL | trait Foo<T>: Super<Assoc = T> + Sized | |
| 100 | | +++++++ | |
| 101 | ||
| 102 | error[E0046]: not all trait items implemented, missing: `Assoc` | |
| 103 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:1 | |
| 104 | | | |
| 105 | LL | type Assoc; | |
| 106 | | ---------- `Assoc` from trait | |
| 107 | ... | |
| 108 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 109 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Assoc` in implementation | |
| 110 | ||
| 111 | error[E0271]: type mismatch resolving `<Self as Super>::Assoc == ()` | |
| 112 | --> $DIR/unhandled-crate-mod-issue-144888.rs:20:5 | |
| 113 | | | |
| 114 | LL | trait Foo<T>: Super<Assoc = T> | |
| 115 | | - found this type parameter | |
| 116 | ... | |
| 117 | LL | fn transmute(&self) {} | |
| 118 | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found type parameter `T` | |
| 119 | | | |
| 120 | = note: expected unit type `()` | |
| 121 | found type parameter `T` | |
| 122 | note: required for `Self` to implement `Mirror` | |
| 123 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 124 | | | |
| 125 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 126 | | ---------- ^^^^^^ ^ | |
| 127 | | | | |
| 128 | | unsatisfied trait bound introduced here | |
| 129 | ||
| 130 | error[E0277]: the size for values of type `Self` cannot be known at compilation time | |
| 131 | --> $DIR/unhandled-crate-mod-issue-144888.rs:20:5 | |
| 132 | | | |
| 133 | LL | fn transmute(&self) {} | |
| 134 | | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | |
| 135 | | | |
| 136 | note: required for `Self` to implement `Mirror` | |
| 137 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 138 | | | |
| 139 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 140 | | - ^^^^^^ ^ | |
| 141 | | | | |
| 142 | | unsatisfied trait bound implicitly introduced here | |
| 143 | help: consider further restricting `Self` | |
| 144 | | | |
| 145 | LL | fn transmute(&self) where Self: Sized {} | |
| 146 | | +++++++++++++++++ | |
| 147 | ||
| 148 | error[E0271]: type mismatch resolving `<Self as Super>::Assoc == ()` | |
| 149 | --> $DIR/unhandled-crate-mod-issue-144888.rs:14:30 | |
| 150 | | | |
| 151 | LL | trait Foo<T>: Super<Assoc = T> | |
| 152 | | - found this type parameter | |
| 153 | ... | |
| 154 | LL | <Self as Mirror>::Assoc: Clone, | |
| 155 | | ^^^^^ expected `()`, found type parameter `T` | |
| 156 | | | |
| 157 | = note: expected unit type `()` | |
| 158 | found type parameter `T` | |
| 159 | note: required for `Self` to implement `Mirror` | |
| 160 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 161 | | | |
| 162 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 163 | | ---------- ^^^^^^ ^ | |
| 164 | | | | |
| 165 | | unsatisfied trait bound introduced here | |
| 166 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` | |
| 167 | ||
| 168 | error[E0277]: the size for values of type `Self` cannot be known at compilation time | |
| 169 | --> $DIR/unhandled-crate-mod-issue-144888.rs:14:30 | |
| 170 | | | |
| 171 | LL | <Self as Mirror>::Assoc: Clone, | |
| 172 | | ^^^^^ doesn't have a size known at compile-time | |
| 173 | | | |
| 174 | note: required for `Self` to implement `Mirror` | |
| 175 | --> $DIR/unhandled-crate-mod-issue-144888.rs:31:28 | |
| 176 | | | |
| 177 | LL | impl<T: Super<Assoc = ()>> Mirror for T {} | |
| 178 | | - ^^^^^^ ^ | |
| 179 | | | | |
| 180 | | unsatisfied trait bound implicitly introduced here | |
| 181 | help: consider further restricting `Self` | |
| 182 | | | |
| 183 | LL | fn transmute(&self) where Self: Sized {} | |
| 184 | | +++++++++++++++++ | |
| 185 | ||
| 186 | error: aborting due to 11 previous errors | |
| 187 | ||
| 188 | Some errors have detailed explanations: E0046, E0271, E0277. | |
| 189 | For more information about an error, try `rustc --explain E0046`. |
tests/ui/unstable-feature-bound/unstable_feature_bound_staged_api.stderr+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error[E0734]: stability attributes may not be used outside of the standard library | |
| 1 | error[E0658]: stability attributes may not be used outside of the standard library | |
| 2 | 2 | --> $DIR/unstable_feature_bound_staged_api.rs:8:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #[unstable_feature_bound(feat_bar)] |
| ... | ... | @@ -6,4 +6,4 @@ LL | #[unstable_feature_bound(feat_bar)] |
| 6 | 6 | |
| 7 | 7 | error: aborting due to 1 previous error |
| 8 | 8 | |
| 9 | For more information about this error, try `rustc --explain E0734`. | |
| 9 | For more information about this error, try `rustc --explain E0658`. |
triagebot.toml+1| ... | ... | @@ -1496,6 +1496,7 @@ libs = [ |
| 1496 | 1496 | "@thomcc", |
| 1497 | 1497 | "@joboet", |
| 1498 | 1498 | "@nia-e", |
| 1499 | "@LawnGnome", | |
| 1499 | 1500 | ] |
| 1500 | 1501 | infra-ci = [ |
| 1501 | 1502 | "@Mark-Simulacrum", |