diff options
| author | The Miri Cronjob Bot <miri@cron.bot> | 2024-11-09 05:12:46 +0000 |
|---|---|---|
| committer | The Miri Cronjob Bot <miri@cron.bot> | 2024-11-09 05:12:46 +0000 |
| commit | 15d883e5b73ce6758926d8e3ef4a307f9ac6092f (patch) | |
| tree | 0c85c9634f6ff5ec409a9589eb9636d8a1d435b9 | |
| parent | beb8d6fac180a48381e7c7c21d94ba4e1cfab1be (diff) | |
| parent | 2ac1c1868f8034dd8a8b8d4c82fd0b9abb66a0f1 (diff) | |
| download | rust-15d883e5b73ce6758926d8e3ef4a307f9ac6092f.tar.gz rust-15d883e5b73ce6758926d8e3ef4a307f9ac6092f.zip | |
Merge from rustc
1351 files changed, 19116 insertions, 8901 deletions
diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md index 59862893611..3a9d8408b3c 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue.md @@ -46,7 +46,7 @@ for larger features an implementation could be broken up into multiple PRs. [stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr [doc-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#documentation-prs -[nightly-style-procedure]: https://github.com/rust-lang/style-team/blob/master/nightly-style-procedure.md +[nightly-style-procedure]: https://github.com/rust-lang/style-team/blob/main/nightly-style-procedure.md [Style Guide]: https://github.com/rust-lang/rust/tree/master/src/doc/style-guide ### Unresolved Questions diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fca71716c1..703f6e5281d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -110,11 +110,7 @@ jobs: # less disk space. - name: free up disk space uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be - if: contains(matrix.os, 'ubuntu') - with: - # Removing packages with APT saves ~5 GiB, but takes several - # minutes (and potentially removes important packages). - large-packages: false + if: matrix.free_disk # Rust Log Analyzer can't currently detect the PR number of a GitHub # Actions build on its own, so a hint in the log message is needed to diff --git a/Cargo.lock b/Cargo.lock index 9fa1daf6546..9cca91c25df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2861,7 +2861,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" dependencies = [ "bitflags 2.6.0", - "getopts", "memchr", "pulldown-cmark-escape 0.11.0", "unicase", @@ -3197,6 +3196,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5c9f15eec8235d7cb775ee6f81891db79b98fd54ba1ad8fae565b88ef1ae4e2" [[package]] +name = "rustc-std-workspace-alloc" +version = "1.0.1" + +[[package]] +name = "rustc-std-workspace-core" +version = "1.0.1" + +[[package]] +name = "rustc-std-workspace-std" +version = "1.0.1" + +[[package]] name = "rustc_abi" version = "0.0.0" dependencies = [ @@ -3262,7 +3273,6 @@ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ "rustc_ast", - "rustc_ast_pretty", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -3346,6 +3356,7 @@ dependencies = [ "either", "itertools", "polonius-engine", + "rustc_abi", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -3359,7 +3370,6 @@ dependencies = [ "rustc_mir_dataflow", "rustc_session", "rustc_span", - "rustc_target", "rustc_trait_selection", "rustc_traits", "smallvec", @@ -3457,7 +3467,6 @@ dependencies = [ "rustc_macros", "rustc_metadata", "rustc_middle", - "rustc_monomorphize", "rustc_query_system", "rustc_serialize", "rustc_session", @@ -3706,6 +3715,7 @@ name = "rustc_hir" version = "0.0.0" dependencies = [ "odht", + "rustc_abi", "rustc_arena", "rustc_ast", "rustc_data_structures", @@ -3732,7 +3742,6 @@ dependencies = [ "rustc_feature", "rustc_fluent_macro", "rustc_hir", - "rustc_hir_pretty", "rustc_index", "rustc_infer", "rustc_lint_defs", @@ -3780,7 +3789,6 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", - "rustc_target", "rustc_trait_selection", "rustc_type_ir", "smallvec", @@ -3840,9 +3848,7 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_middle", - "rustc_next_trait_solver", "rustc_span", - "rustc_target", "rustc_type_ir", "smallvec", "thin-vec", @@ -3921,7 +3927,6 @@ dependencies = [ "rustc_feature", "rustc_fluent_macro", "rustc_hir", - "rustc_hir_pretty", "rustc_index", "rustc_infer", "rustc_macros", @@ -4092,7 +4097,6 @@ dependencies = [ "rustc_macros", "rustc_middle", "rustc_span", - "rustc_target", "smallvec", "tracing", ] @@ -4131,6 +4135,7 @@ dependencies = [ name = "rustc_monomorphize" version = "0.0.0" dependencies = [ + "rustc_abi", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4149,7 +4154,6 @@ dependencies = [ name = "rustc_next_trait_solver" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", "derive-where", "rustc_ast_ir", "rustc_data_structures", @@ -4235,7 +4239,6 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", - "rustc_target", "smallvec", "tracing", "tracing-subscriber", @@ -4335,6 +4338,7 @@ name = "rustc_sanitizers" version = "0.0.0" dependencies = [ "bitflags 2.6.0", + "rustc_abi", "rustc_data_structures", "rustc_hir", "rustc_middle", @@ -4434,7 +4438,6 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", - "rustc_target", "tracing", ] @@ -4446,9 +4449,7 @@ dependencies = [ "object 0.36.4", "rustc_abi", "rustc_data_structures", - "rustc_feature", "rustc_fs_util", - "rustc_index", "rustc_macros", "rustc_serialize", "rustc_span", @@ -4467,6 +4468,7 @@ name = "rustc_trait_selection" version = "0.0.0" dependencies = [ "itertools", + "rustc_abi", "rustc_ast", "rustc_ast_ir", "rustc_attr", @@ -4479,11 +4481,8 @@ dependencies = [ "rustc_middle", "rustc_next_trait_solver", "rustc_parse_format", - "rustc_query_system", - "rustc_serialize", "rustc_session", "rustc_span", - "rustc_target", "rustc_transmute", "rustc_type_ir", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index d4b84250fc4..e1d667bf015 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ resolver = "2" members = [ "compiler/rustc", "src/etc/test-float-parse", + "src/rustc-std-workspace/rustc-std-workspace-core", + "src/rustc-std-workspace/rustc-std-workspace-alloc", + "src/rustc-std-workspace/rustc-std-workspace-std", "src/rustdoc-json-types", "src/tools/build_helper", "src/tools/cargotest", diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index e9a7397557e..ccf88d8ff4b 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -1,5 +1,7 @@ // We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`. #![feature(rustc_private)] +// Several crates are depended upon but unused so that they are present in the sysroot +#![expect(unused_crate_dependencies)] // A note about jemalloc: rustc uses jemalloc when built for CI and // distribution. The obvious way to do this is with the `#[global_allocator]` diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ec6ca70ae0a..997c44cffff 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -414,6 +414,12 @@ pub struct WhereClause { pub span: Span, } +impl WhereClause { + pub fn is_empty(&self) -> bool { + !self.has_where_token && self.predicates.is_empty() + } +} + impl Default for WhereClause { fn default() -> WhereClause { WhereClause { has_where_token: false, predicates: ThinVec::new(), span: DUMMY_SP } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 9311af28f54..54e826585d2 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -136,6 +136,13 @@ impl Attribute { } } + /// Returns a list of meta items if the attribute is delimited with parenthesis: + /// + /// ```text + /// #[attr(a, b = "c")] // Returns `Some()`. + /// #[attr = ""] // Returns `None`. + /// #[attr] // Returns `None`. + /// ``` pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> { match &self.kind { AttrKind::Normal(normal) => normal.item.meta_item_list(), @@ -143,6 +150,21 @@ impl Attribute { } } + /// Returns the string value in: + /// + /// ```text + /// #[attribute = "value"] + /// ^^^^^^^ + /// ``` + /// + /// It returns `None` in any other cases, including doc comments if they + /// are not under the form `#[doc = "..."]`. + /// + /// It also returns `None` for: + /// + /// ```text + /// #[attr("value")] + /// ``` pub fn value_str(&self) -> Option<Symbol> { match &self.kind { AttrKind::Normal(normal) => normal.item.value_str(), @@ -232,6 +254,18 @@ impl AttrItem { } } + /// Returns the string value in: + /// + /// ```text + /// #[attribute = "value"] + /// ^^^^^^^ + /// ``` + /// + /// It returns `None` in any other cases like: + /// + /// ```text + /// #[attr("value")] + /// ``` fn value_str(&self) -> Option<Symbol> { match &self.args { AttrArgs::Eq(_, args) => args.value_str(), @@ -315,6 +349,18 @@ impl MetaItem { Some(self.name_value_literal()?.span) } + /// Returns the string value in: + /// + /// ```text + /// #[attribute = "value"] + /// ^^^^^^^ + /// ``` + /// + /// It returns `None` in any other cases like: + /// + /// ```text + /// #[attr("value")] + /// ``` pub fn value_str(&self) -> Option<Symbol> { match &self.kind { MetaItemKind::NameValue(v) => v.kind.str(), diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 8cc4521e0a7..c47c12b4fd1 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -9,7 +9,6 @@ doctest = false [dependencies] # tidy-alphabetical-start rustc_ast = { path = "../rustc_ast" } -rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 8c3ac9864ed..f65056a494b 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -594,8 +594,8 @@ pub(crate) struct ConstBoundTraitObject { pub span: Span, } -// FIXME(effects): Consider making the note/reason the message of the diagnostic. -// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here). +// FIXME(const_trait_impl): Consider making the note/reason the message of the diagnostic. +// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here). #[derive(Diagnostic)] #[diag(ast_passes_tilde_const_disallowed)] pub(crate) struct TildeConstDisallowed { diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 6af75bc94bb..2753ac529d1 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -273,8 +273,7 @@ pub fn find_stability( /// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable` /// attributes in `attrs`. Returns `None` if no stability attributes are found. /// -/// `is_const_fn` indicates whether this is a function marked as `const`. It will always -/// be false for intrinsics in an `extern` block! +/// `is_const_fn` indicates whether this is a function marked as `const`. pub fn find_const_stability( sess: &Session, attrs: &[Attribute], @@ -330,7 +329,7 @@ pub fn find_const_stability( } } - // Merge promotable and not_exposed_on_stable into stability info + // Merge promotable and const_stable_indirect into stability info if promotable { match &mut const_stab { Some((stab, _)) => stab.promotable = promotable, @@ -352,10 +351,7 @@ pub fn find_const_stability( }) } } - _ => { - // We ignore the `#[rustc_const_stable_indirect]` here, it should be picked up by - // the `default_const_unstable` logic. - } + _ => {} } } // Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index bafc62c7318..89154bf2c23 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" either = "1.5.0" itertools = "0.12" polonius-engine = "0.13.0" +rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } @@ -21,7 +22,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_traits = { path = "../rustc_traits" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index a8ade54732f..16b3d901956 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -20,18 +20,18 @@ pub struct BorrowSet<'tcx> { /// by the `Location` of the assignment statement in which it /// appears on the right hand side. Thus the location is the map /// key, and its position in the map corresponds to `BorrowIndex`. - pub location_map: FxIndexMap<Location, BorrowData<'tcx>>, + pub(crate) location_map: FxIndexMap<Location, BorrowData<'tcx>>, /// Locations which activate borrows. /// NOTE: a given location may activate more than one borrow in the future /// when more general two-phase borrow support is introduced, but for now we /// only need to store one borrow index. - pub activation_map: FxIndexMap<Location, Vec<BorrowIndex>>, + pub(crate) activation_map: FxIndexMap<Location, Vec<BorrowIndex>>, /// Map from local to all the borrows on that local. - pub local_map: FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>>, + pub(crate) local_map: FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>>, - pub locals_state_at_exit: LocalsStateAtExit, + pub(crate) locals_state_at_exit: LocalsStateAtExit, } impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> { @@ -45,7 +45,7 @@ impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> { /// Location where a two-phase borrow is activated, if a borrow /// is in fact a two-phase borrow. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum TwoPhaseActivation { +pub(crate) enum TwoPhaseActivation { NotTwoPhase, NotActivated, ActivatedAt(Location), @@ -55,17 +55,17 @@ pub enum TwoPhaseActivation { pub struct BorrowData<'tcx> { /// Location where the borrow reservation starts. /// In many cases, this will be equal to the activation location but not always. - pub reserve_location: Location, + pub(crate) reserve_location: Location, /// Location where the borrow is activated. - pub activation_location: TwoPhaseActivation, + pub(crate) activation_location: TwoPhaseActivation, /// What kind of borrow this is - pub kind: mir::BorrowKind, + pub(crate) kind: mir::BorrowKind, /// The region for which this borrow is live - pub region: RegionVid, + pub(crate) region: RegionVid, /// Place from which we are borrowing - pub borrowed_place: mir::Place<'tcx>, + pub(crate) borrowed_place: mir::Place<'tcx>, /// Place to which the borrow was stored - pub assigned_place: mir::Place<'tcx>, + pub(crate) assigned_place: mir::Place<'tcx>, } impl<'tcx> fmt::Display for BorrowData<'tcx> { @@ -120,7 +120,7 @@ impl LocalsStateAtExit { } impl<'tcx> BorrowSet<'tcx> { - pub fn build( + pub(crate) fn build( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, locals_are_invalidated_at_exit: bool, @@ -156,7 +156,7 @@ impl<'tcx> BorrowSet<'tcx> { self.activation_map.get(&location).map_or(&[], |activations| &activations[..]) } - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.location_map.len() } diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index ca435ee0865..a52269df682 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -210,7 +210,7 @@ impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> { rustc_index::newtype_index! { #[debug_format = "OutlivesConstraintIndex({})"] - pub struct OutlivesConstraintIndex {} + pub(crate) struct OutlivesConstraintIndex {} } rustc_index::newtype_index! { diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 89ff12c1479..d832decc170 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -254,8 +254,8 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { let sccs = self.regioncx.constraint_sccs(); let universal_regions = self.regioncx.universal_regions(); - // We first handle the cases where the loan doesn't go out of scope, depending on the issuing - // region's successors. + // We first handle the cases where the loan doesn't go out of scope, depending on the + // issuing region's successors. for successor in graph::depth_first_search(&self.regioncx.region_graph(), issuing_region) { // 1. Via applied member constraints // diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 2fa752384a1..0897d140d60 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -3,7 +3,6 @@ use std::rc::Rc; use rustc_errors::Diag; use rustc_hir::def_id::LocalDefId; -use rustc_infer::infer::canonical::CanonicalQueryInput; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_infer::infer::{ InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt as _, @@ -21,7 +20,6 @@ use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError; use rustc_trait_selection::traits::ObligationCtxt; -use rustc_trait_selection::traits::query::type_op; use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause}; use tracing::{debug, instrument}; @@ -31,12 +29,9 @@ use crate::session_diagnostics::{ HigherRankedErrorCause, HigherRankedLifetimeError, HigherRankedSubtypeError, }; -#[derive(Clone)] -pub(crate) struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>); - /// What operation a universe was created for. #[derive(Clone)] -enum UniverseInfoInner<'tcx> { +pub(crate) enum UniverseInfo<'tcx> { /// Relating two types which have binders. RelateTys { expected: Ty<'tcx>, found: Ty<'tcx> }, /// Created from performing a `TypeOp`. @@ -47,11 +42,11 @@ enum UniverseInfoInner<'tcx> { impl<'tcx> UniverseInfo<'tcx> { pub(crate) fn other() -> UniverseInfo<'tcx> { - UniverseInfo(UniverseInfoInner::Other) + UniverseInfo::Other } pub(crate) fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx> { - UniverseInfo(UniverseInfoInner::RelateTys { expected, found }) + UniverseInfo::RelateTys { expected, found } } pub(crate) fn report_error( @@ -61,8 +56,8 @@ impl<'tcx> UniverseInfo<'tcx> { error_element: RegionElement, cause: ObligationCause<'tcx>, ) { - match self.0 { - UniverseInfoInner::RelateTys { expected, found } => { + match *self { + UniverseInfo::RelateTys { expected, found } => { let err = mbcx.infcx.err_ctxt().report_mismatched_types( &cause, mbcx.param_env, @@ -72,10 +67,10 @@ impl<'tcx> UniverseInfo<'tcx> { ); mbcx.buffer_error(err); } - UniverseInfoInner::TypeOp(ref type_op_info) => { + UniverseInfo::TypeOp(ref type_op_info) => { type_op_info.report_error(mbcx, placeholder, error_element, cause); } - UniverseInfoInner::Other => { + UniverseInfo::Other => { // FIXME: This error message isn't great, but it doesn't show // up in the existing UI tests. Consider investigating this // some more. @@ -93,19 +88,16 @@ pub(crate) trait ToUniverseInfo<'tcx> { impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType { + UniverseInfo::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType { base_universe: Some(base_universe), ..self - }))) + })) } } impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpProvePredicateGoal<'tcx> { fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery { - canonical_query: self, - base_universe, - }))) + UniverseInfo::TypeOp(Rc::new(PredicateQuery { canonical_query: self, base_universe })) } } @@ -113,26 +105,13 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUnivers for CanonicalTypeOpNormalizeGoal<'tcx, T> { fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery { - canonical_query: self, - base_universe, - }))) + UniverseInfo::TypeOp(Rc::new(NormalizeQuery { canonical_query: self, base_universe })) } } impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> { fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(AscribeUserTypeQuery { - canonical_query: self, - base_universe, - }))) - } -} - -impl<'tcx, F> ToUniverseInfo<'tcx> for CanonicalQueryInput<'tcx, type_op::custom::CustomTypeOp<F>> { - fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - // We can't rerun custom type ops. - UniverseInfo::other() + UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe })) } } @@ -143,7 +122,7 @@ impl<'tcx> ToUniverseInfo<'tcx> for ! { } #[allow(unused_lifetimes)] -trait TypeOpInfo<'tcx> { +pub(crate) trait TypeOpInfo<'tcx> { /// Returns an error to be reported if rerunning the type op fails to /// recover the error's cause. fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx>; @@ -289,8 +268,8 @@ where // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the // `ObligationCause`. The normalization results are currently different between // `QueryNormalizeExt::query_normalize` used in the query and `normalize` called below: - // the former fails to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. - // Check after #85499 lands to see if its fixes have erased this difference. + // the former fails to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` + // test. Check after #85499 lands to see if its fixes have erased this difference. let (param_env, value) = key.into_parts(); let _ = ocx.normalize(&cause, param_env, value.value); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 511313cca6f..e5b28289faa 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1345,11 +1345,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // See `tests/ui/moves/needs-clone-through-deref.rs` return false; } - // We don't want to suggest `.clone()` in a move closure, since the value has already been captured. + // We don't want to suggest `.clone()` in a move closure, since the value has already been + // captured. if self.in_move_closure(expr) { return false; } - // We also don't want to suggest cloning a closure itself, since the value has already been captured. + // We also don't want to suggest cloning a closure itself, since the value has already been + // captured. if let hir::ExprKind::Closure(_) = expr.kind { return false; } @@ -1381,7 +1383,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } } - // Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch error. (see #126863) + // Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch + // error. (see #126863) if inner_expr.span.lo() != expr.span.lo() && !is_raw_ptr { // Remove "(*" or "(&" sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new())); @@ -1553,8 +1556,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let use_spans = self.move_spans(place.as_ref(), location); let span = use_spans.var_or_use(); - // If the attempted use is in a closure then we do not care about the path span of the place we are currently trying to use - // we call `var_span_label` on `borrow_spans` to annotate if the existing borrow was in a closure + // If the attempted use is in a closure then we do not care about the path span of the + // place we are currently trying to use we call `var_span_label` on `borrow_spans` to + // annotate if the existing borrow was in a closure. let mut err = self.cannot_use_when_mutably_borrowed( span, &self.describe_any_place(place.as_ref()), @@ -2480,7 +2484,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let hir::ExprKind::Closure(closure) = ex.kind && ex.span.contains(self.borrow_span) // To support cases like `|| { v.call(|this| v.get()) }` - // FIXME: actually support such cases (need to figure out how to move from the capture place to original local) + // FIXME: actually support such cases (need to figure out how to move from the + // capture place to original local). && self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span)) { self.res = Some((ex, closure)); @@ -2733,7 +2738,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as /// mutable (via `a.u.s.b`) [E0502] /// ``` - pub(crate) fn describe_place_for_conflicting_borrow( + fn describe_place_for_conflicting_borrow( &self, first_borrowed_place: Place<'tcx>, second_borrowed_place: Place<'tcx>, @@ -3188,8 +3193,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// misleading users in cases like `tests/ui/nll/borrowed-temporary-error.rs`. /// We could expand the analysis to suggest hoising all of the relevant parts of /// the users' code to make the code compile, but that could be too much. - /// We found the `prop_expr` by the way to check whether the expression is a `FormatArguments`, - /// which is a special case since it's generated by the compiler. + /// We found the `prop_expr` by the way to check whether the expression is a + /// `FormatArguments`, which is a special case since it's generated by the + /// compiler. struct NestedStatementVisitor<'tcx> { span: Span, current: usize, @@ -3420,7 +3426,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) { Ok(string) => { let coro_prefix = if string.starts_with("async") { - // `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize` to `u32` + // `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize` + // to `u32`. Some(5) } else if string.starts_with("gen") { // `gen` is 3 chars long @@ -3618,10 +3625,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let stmt_kind = self.body[location.block].statements.get(location.statement_index).map(|s| &s.kind); if let Some(StatementKind::StorageDead(..)) = stmt_kind { - // this analysis only tries to find moves explicitly - // written by the user, so we ignore the move-outs - // created by `StorageDead` and at the beginning - // of a function. + // This analysis only tries to find moves explicitly written by the user, so we + // ignore the move-outs created by `StorageDead` and at the beginning of a + // function. } else { // If we are found a use of a.b.c which was in error, then we want to look for // moves not only of a.b.c but also a.b and a. @@ -3706,13 +3712,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } if (is_argument || !reached_start) && result.is_empty() { - /* Process back edges (moves in future loop iterations) only if - the move path is definitely initialized upon loop entry, - to avoid spurious "in previous iteration" errors. - During DFS, if there's a path from the error back to the start - of the function with no intervening init or move, then the - move path may be uninitialized at loop entry. - */ + // Process back edges (moves in future loop iterations) only if + // the move path is definitely initialized upon loop entry, + // to avoid spurious "in previous iteration" errors. + // During DFS, if there's a path from the error back to the start + // of the function with no intervening init or move, then the + // move path may be uninitialized at loop entry. while let Some(location) = back_edge_stack.pop() { if dfs_iter(&mut result, location, true) { continue; diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 31a5d451ff6..45a8ef0adb6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -130,7 +130,8 @@ impl<'tcx> BorrowExplanation<'tcx> { { suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err); } else if path_span.map_or(true, |path_span| path_span == var_or_use_span) { - // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same + // We can use `var_or_use_span` if either `path_span` is not present, or both + // spans are the same. if borrow_span.map_or(true, |sp| !sp.overlaps(var_or_use_span)) { err.span_label( var_or_use_span, @@ -165,7 +166,8 @@ impl<'tcx> BorrowExplanation<'tcx> { LaterUseKind::FakeLetRead => "borrow later stored here", LaterUseKind::Other => "borrow used here, in later iteration of loop", }; - // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same + // We can use `var_or_use_span` if either `path_span` is not present, or both spans + // are the same. if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) { err.span_label(var_or_use_span, format!("{borrow_desc}{message}")); } else { @@ -285,7 +287,8 @@ impl<'tcx> BorrowExplanation<'tcx> { span: _, pat, init, - // FIXME(#101728): enable rewrite when type ascription is stabilized again + // FIXME(#101728): enable rewrite when type ascription is + // stabilized again. ty: None, recovered: _, }) = cond.kind @@ -353,8 +356,8 @@ impl<'tcx> BorrowExplanation<'tcx> { unsize_ty: Ty<'tcx>, ) { if let ty::Adt(def, args) = unsize_ty.kind() { - // We try to elaborate the object lifetime defaults and present those to the user. This should - // make it clear where the region constraint is coming from. + // We try to elaborate the object lifetime defaults and present those to the user. This + // should make it clear where the region constraint is coming from. let generics = tcx.generics_of(def.did()); let mut has_dyn = false; @@ -531,9 +534,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let mut use_in_later_iteration_of_loop = false; if region_sub == borrow_region_vid { - // When `region_sub` is the same as `borrow_region_vid` (the location where the borrow is - // issued is the same location that invalidates the reference), this is likely a loop iteration - // - in this case, try using the loop terminator location in `find_sub_region_live_at`. + // When `region_sub` is the same as `borrow_region_vid` (the location where the borrow + // is issued is the same location that invalidates the reference), this is likely a + // loop iteration. In this case, try using the loop terminator location in + // `find_sub_region_live_at`. if let Some(loop_terminator_location) = regioncx.find_loop_terminator_location(borrow.region, body) { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 3b600716036..0797bb49bf9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1,5 +1,6 @@ //! Borrow checker diagnostics. +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{self as hir, CoroutineKind, LangItem}; @@ -21,7 +22,6 @@ use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span, Symbol}; -use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{ @@ -763,7 +763,7 @@ impl<'tcx> BorrowedContentSource<'tcx> { } } -///helper struct for explain_captures() +/// Helper struct for `explain_captures`. struct CapturedMessageOpt { is_partial_move: bool, is_loop_message: bool, diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3871816777c..15cc9c20ab7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; use rustc_span::{BytePos, ExpnKind, MacroKind, Span}; use rustc_trait_selection::error_reporting::traits::FindExprBySpan; +use rustc_trait_selection::infer::InferCtxtExt; use tracing::debug; use crate::MirBorrowckCtxt; @@ -267,6 +268,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { kind, self.is_upvar_field_projection(original_path.as_ref()) ); + if self.has_ambiguous_copy(original_path.ty(self.body, self.infcx.tcx).ty) { + // If the type may implement Copy, skip the error. + // It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check + self.dcx().span_delayed_bug( + span, + "Type may implement copy, but there is no other error.", + ); + return; + } ( match kind { &IllegalMoveOriginKind::BorrowedContent { target_place } => self @@ -291,6 +301,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.buffer_error(err); } + fn has_ambiguous_copy(&mut self, ty: Ty<'tcx>) -> bool { + let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false }; + // This is only going to be ambiguous if there are incoherent impls, because otherwise + // ambiguity should never happen in MIR. + self.infcx.type_implements_trait(copy_trait_def, [ty], self.param_env).may_apply() + } + fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> { let description = if place.projection.len() == 1 { format!("static item {}", self.describe_any_place(place.as_ref())) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 315851729b1..d064bf098e4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -4,6 +4,7 @@ use core::ops::ControlFlow; use hir::{ExprKind, Param}; +use rustc_abi::FieldIdx; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, BindingMode, ByRef, Node}; @@ -16,7 +17,6 @@ use rustc_middle::mir::{ use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, Upcast}; use rustc_span::symbol::{Symbol, kw}; use rustc_span::{BytePos, DesugaringKind, Span, sym}; -use rustc_target::abi::FieldIdx; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits; @@ -793,7 +793,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let reason = if let PlaceBase::Upvar(upvar_id) = closure_kind_origin.base { let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin); let root_hir_id = upvar_id.var_path.hir_id; - // we have an origin for this closure kind starting at this root variable so it's safe to unwrap here + // We have an origin for this closure kind starting at this root variable so it's + // safe to unwrap here. let captured_places = tables.closure_min_captures[&closure_local_def_id].get(&root_hir_id).unwrap(); @@ -816,7 +817,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) { match captured_place.info.capture_kind { ty::UpvarCapture::ByRef( - ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow, + ty::BorrowKind::Mutable | ty::BorrowKind::UniqueImmutable, ) => { capture_reason = format!("mutable borrow of `{upvar}`"); } @@ -966,8 +967,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } }; - // If we can detect the expression to be an function or method call where the closure was an argument, - // we point at the function or method definition argument... + // If we can detect the expression to be an function or method call where the closure was + // an argument, we point at the function or method definition argument... if let Some((callee_def_id, call_span, call_args)) = get_call_details() { let arg_pos = call_args .iter() diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 6333d59a1bc..807b5576976 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -189,7 +189,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Returns `true` if a closure is inferred to be an `FnMut` closure. fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref() - && let ty::BoundRegionKind::BrEnv = late_param.bound_region + && let ty::BoundRegionKind::ClosureEnv = late_param.bound_region && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty { return args.as_closure().kind() == ty::ClosureKind::FnMut; @@ -1103,7 +1103,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { peeled_ty, liberated_sig.c_variadic, hir::Safety::Safe, - rustc_target::spec::abi::Abi::Rust, + rustc_abi::ExternAbi::Rust, )), ); let closure_ty = Ty::new_closure( diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 6ca7251295d..d49dee85144 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -30,8 +30,8 @@ pub(crate) struct RegionName { } /// Denotes the source of a region that is named by a `RegionName`. For example, a free region that -/// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get `Static`. -/// This helps to print the right kinds of diagnostics. +/// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get +/// `Static`. This helps to print the right kinds of diagnostics. #[derive(Debug, Clone, Copy)] pub(crate) enum RegionNameSource { /// A bound (not free) region that was instantiated at the def site (not an HRTB). @@ -301,7 +301,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } ty::ReLateParam(late_param) => match late_param.bound_region { - ty::BoundRegionKind::BrNamed(region_def_id, name) => { + ty::BoundRegionKind::Named(region_def_id, name) => { // Get the span to point to, even if we don't use the name. let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP); debug!( @@ -332,7 +332,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } } - ty::BoundRegionKind::BrEnv => { + ty::BoundRegionKind::ClosureEnv => { let def_ty = self.regioncx.universal_regions().defining_ty; let closure_kind = match def_ty { @@ -369,7 +369,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { }) } - ty::BoundRegionKind::BrAnon => None, + ty::BoundRegionKind::Anon => None, }, ty::ReBound(..) @@ -825,8 +825,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// async fn foo() -> i32 { 2 } /// ``` /// - /// this function, given the lowered return type of `foo`, an [`OpaqueDef`] that implements `Future<Output=i32>`, - /// returns the `i32`. + /// this function, given the lowered return type of `foo`, an [`OpaqueDef`] that implements + /// `Future<Output=i32>`, returns the `i32`. /// /// [`OpaqueDef`]: hir::TyKind::OpaqueDef fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index efcee2899c6..657e6e0907c 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -20,7 +20,7 @@ use std::collections::BTreeMap; use std::marker::PhantomData; use std::ops::Deref; -use consumers::{BodyWithBorrowckFacts, ConsumerOptions}; +use rustc_abi::FieldIdx; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; use rustc_errors::Diag; @@ -45,17 +45,24 @@ use rustc_mir_dataflow::move_paths::{ }; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; -use rustc_target::abi::FieldIdx; use smallvec::SmallVec; use tracing::{debug, instrument}; -use self::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName}; -use self::location::LocationTable; -use self::path_utils::*; -use self::prefixes::PrefixSet; +use crate::borrow_set::{BorrowData, BorrowSet}; +use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions}; +use crate::dataflow::{BorrowIndex, BorrowckDomain, BorrowckResults, Borrows}; +use crate::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName}; +use crate::location::LocationTable; +use crate::nll::PoloniusOutput; +use crate::path_utils::*; +use crate::place_ext::PlaceExt; +use crate::places_conflict::{PlaceConflictBias, places_conflict}; +use crate::prefixes::PrefixSet; +use crate::region_infer::RegionInferenceContext; +use crate::renumber::RegionCtxt; use crate::session_diagnostics::VarNeedNotMut; -pub mod borrow_set; +mod borrow_set; mod borrowck_errors; mod constraints; mod dataflow; @@ -81,18 +88,11 @@ mod util; /// A public API provided for the Rust compiler consumers. pub mod consumers; -use borrow_set::{BorrowData, BorrowSet}; -use dataflow::{BorrowIndex, BorrowckDomain, BorrowckResults, Borrows}; -use nll::PoloniusOutput; -use place_ext::PlaceExt; -use places_conflict::{PlaceConflictBias, places_conflict}; -use region_infer::RegionInferenceContext; -use renumber::RegionCtxt; - rustc_fluent_macro::fluent_messages! { "../messages.ftl" } /// Associate some local constants with the `'tcx` lifetime struct TyCtxtConsts<'tcx>(PhantomData<&'tcx ()>); + impl<'tcx> TyCtxtConsts<'tcx> { const DEREF_PROJECTION: &'tcx [PlaceElem<'tcx>; 1] = &[ProjectionElem::Deref]; } @@ -162,7 +162,7 @@ fn do_mir_borrowck<'tcx>( } } - let mut diags = diags::BorrowckDiags::new(); + let diags = &mut diags::BorrowckDiags::new(); // Gather the upvars of a closure, if any. if let Some(e) = input_body.tainted_by_errors { @@ -227,14 +227,7 @@ fn do_mir_borrowck<'tcx>( // We also have a `#[rustc_regions]` annotation that causes us to dump // information. - nll::dump_annotation( - &infcx, - body, - ®ioncx, - &opt_closure_req, - &opaque_type_values, - &mut diags, - ); + nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, &opaque_type_values, diags); // The various `flow_*` structures can be large. We drop `flow_inits` here // so it doesn't overlap with the others below. This reduces peak memory @@ -299,7 +292,6 @@ fn do_mir_borrowck<'tcx>( }; MoveVisitor { ctxt: &mut promoted_mbcx }.visit_body(promoted_body); promoted_mbcx.report_move_errors(); - diags = promoted_mbcx.diags; struct MoveVisitor<'a, 'b, 'infcx, 'tcx> { ctxt: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>, @@ -434,7 +426,7 @@ fn do_mir_borrowck<'tcx>( (result, body_with_facts) } -pub struct BorrowckInferCtxt<'tcx> { +pub(crate) struct BorrowckInferCtxt<'tcx> { pub(crate) infcx: InferCtxt<'tcx>, pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>, } @@ -587,7 +579,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { /// Results of Polonius analysis. polonius_output: Option<Box<PoloniusOutput>>, - diags: diags::BorrowckDiags<'infcx, 'tcx>, + diags: &'a mut diags::BorrowckDiags<'infcx, 'tcx>, move_errors: Vec<MoveError<'tcx>>, } @@ -638,7 +630,9 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> ); } StatementKind::Intrinsic(box kind) => match kind { - NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), state), + NonDivergingIntrinsic::Assume(op) => { + self.consume_operand(location, (op, span), state); + } NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!( span, "Unexpected CopyNonOverlapping, should only appear after lower_intrinsics", @@ -2105,7 +2099,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { | Write(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) => { let is_local_mutation_allowed = match mut_borrow_kind { // `ClosureCapture` is used for mutable variable with an immutable binding. - // This is only behaviour difference between `ClosureCapture` and mutable borrows. + // This is only behaviour difference between `ClosureCapture` and mutable + // borrows. MutBorrowKind::ClosureCapture => LocalMutationIsAllowed::Yes, MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow => { is_local_mutation_allowed @@ -2350,23 +2345,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { ) => Err(place), (Mutability::Not, LocalMutationIsAllowed::Yes) | (Mutability::Mut, _) => { - // Subtle: this is an upvar - // reference, so it looks like - // `self.foo` -- we want to double - // check that the location `*self` - // is mutable (i.e., this is not a - // `Fn` closure). But if that - // check succeeds, we want to - // *blame* the mutability on - // `place` (that is, - // `self.foo`). This is used to - // propagate the info about - // whether mutability declarations - // are used outwards, so that we register - // the outer variable as mutable. Otherwise a - // test like this fails to record the `mut` - // as needed: - // + // Subtle: this is an upvar reference, so it looks like + // `self.foo` -- we want to double check that the location + // `*self` is mutable (i.e., this is not a `Fn` closure). But + // if that check succeeds, we want to *blame* the mutability on + // `place` (that is, `self.foo`). This is used to propagate the + // info about whether mutability declarations are used + // outwards, so that we register the outer variable as mutable. + // Otherwise a test like this fails to record the `mut` as + // needed: // ``` // fn foo<F: FnOnce()>(_f: F) { } // fn main() { @@ -2511,7 +2498,7 @@ mod diags { // Buffer any move errors that we collected and de-duplicated. for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) { // We have already set tainted for this error, so just buffer it. - self.diags.buffered_diags.push(BufferedDiag::Error(diag)); + self.diags.buffer_error(diag); } for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) { if count > 10 { @@ -2519,7 +2506,7 @@ mod diags { #[allow(rustc::untranslatable_diagnostic)] diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } - self.diags.buffered_diags.push(BufferedDiag::Error(diag)); + self.diags.buffer_error(diag); } if !self.diags.buffered_diags.is_empty() { diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index 1ba41cd5244..12a37f56fcf 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -1,7 +1,7 @@ +use rustc_abi::FieldIdx; use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::{BasicBlock, Body, BorrowKind, Location, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::TyCtxt; -use rustc_target::abi::FieldIdx; use tracing::debug; use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index aeb8a6c014a..fc7e6e58641 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -53,7 +53,7 @@ impl<'tcx> Iterator for Prefixes<'tcx> { // may hold one further down (e.g., we never return // downcasts here, but may return a base of a downcast). - 'cursor: loop { + loop { match cursor.last_projection() { None => { self.next = None; @@ -72,7 +72,6 @@ impl<'tcx> Iterator for Prefixes<'tcx> { | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => { cursor = cursor_base; - continue 'cursor; } ProjectionElem::Subtype(..) => { panic!("Subtype projection is not allowed before borrow check") diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index d5c2796932e..7e317ea6554 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -99,9 +99,9 @@ impl RegionTracker { pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self { let (representative_is_placeholder, representative_is_existential) = match definition.origin { - rustc_infer::infer::NllRegionVariableOrigin::FreeRegion => (false, false), - rustc_infer::infer::NllRegionVariableOrigin::Placeholder(_) => (true, false), - rustc_infer::infer::NllRegionVariableOrigin::Existential { .. } => (false, true), + NllRegionVariableOrigin::FreeRegion => (false, false), + NllRegionVariableOrigin::Placeholder(_) => (true, false), + NllRegionVariableOrigin::Existential { .. } => (false, true), }; let placeholder_universe = @@ -553,7 +553,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Returns an iterator over all the region indices. - pub fn regions(&self) -> impl Iterator<Item = RegionVid> + 'tcx { + pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> + 'tcx { self.definitions.indices() } @@ -561,12 +561,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// corresponding index. /// /// (Panics if `r` is not a registered universal region.) - pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { self.universal_regions.to_region_vid(r) } /// Returns an iterator over all the outlives constraints. - pub fn outlives_constraints(&self) -> impl Iterator<Item = OutlivesConstraint<'tcx>> + '_ { + pub(crate) fn outlives_constraints( + &self, + ) -> impl Iterator<Item = OutlivesConstraint<'tcx>> + '_ { self.constraints.outlives().iter().copied() } @@ -1495,6 +1497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex { self.constraint_sccs().annotation(scc).min_universe() } + /// Checks the final value for the free region `fr` to see if it /// grew too large. In particular, examine what `end(X)` points /// wound up in `fr`'s final value; for each `end(X)` where `X != @@ -1667,7 +1670,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { placeholder, }); - // Stop after the first error, it gets too noisy otherwise, and does not provide more information. + // Stop after the first error, it gets too noisy otherwise, and does not provide more + // information. break; } debug!("check_bound_universal_region: all bounds satisfied"); @@ -2000,8 +2004,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint. // Instead, we use it to produce an improved `ObligationCauseCode`. - // FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate` - // constraints. Currently, we just pick the first one. + // FIXME - determine what we should do if we encounter multiple + // `ConstraintCategory::Predicate` constraints. Currently, we just pick the first one. let cause_code = path .iter() .find_map(|constraint| { diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 3a2f5c35c72..f9dd649ab9f 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -145,9 +145,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { continue; } // Sometimes two opaque types are the same only after we remap the generic parameters - // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)` - // and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that - // once we convert the generic parameters to those of the opaque type. + // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to + // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we + // only know that once we convert the generic parameters to those of the opaque type. if let Some(prev) = result.get_mut(&opaque_type_key.def_id) { if prev.ty != ty { let guar = ty.error_reported().err().unwrap_or_else(|| { diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 662e6fa46b5..519edfafda5 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -15,7 +15,7 @@ use crate::BorrowIndex; rustc_index::newtype_index! { /// A single integer representing a `ty::Placeholder`. #[debug_format = "PlaceholderIndex({})"] - pub struct PlaceholderIndex {} + pub(crate) struct PlaceholderIndex {} } /// An individual element in a region value -- the value of a diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index fde68615cc0..aee13ca8cd7 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { { let universe_info = error_info.to_universe_info(old_universe); for u in (old_universe + 1)..=universe { - self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone()); + self.constraints.universe_causes.insert(u, universe_info.clone()); } } diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 141f251244b..7effd5c5a68 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -48,9 +48,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // FIXME(async_closures): It's kind of wacky that we must apply this // transformation here, since we do the same thing in HIR typeck. // Maybe we could just fix up the canonicalized signature during HIR typeck? - if let DefiningTy::CoroutineClosure(_, args) = - self.borrowck_context.universal_regions.defining_ty - { + if let DefiningTy::CoroutineClosure(_, args) = self.universal_regions.defining_ty { assert_matches!( self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)), Some(hir::CoroutineKind::Desugared( @@ -59,8 +57,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { )), "this needs to be modified if we're lowering non-async closures" ); - // Make sure to use the args from `DefiningTy` so the right NLL region vids are prepopulated - // into the type. + // Make sure to use the args from `DefiningTy` so the right NLL region vids are + // prepopulated into the type. let args = args.as_coroutine_closure(); let tupled_upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( self.tcx(), @@ -195,8 +193,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // doing so ends up causing some other trouble. let b = self.normalize(b, Locations::All(span)); - // Note: if we have to introduce new placeholders during normalization above, then we won't have - // added those universes to the universe info, which we would want in `relate_tys`. + // Note: if we have to introduce new placeholders during normalization above, then we + // won't have added those universes to the universe info, which we would want in + // `relate_tys`. if let Err(terr) = self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation) { diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index ccd9fb25739..695a1cdac0d 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -137,56 +137,22 @@ struct LocalUseMapBuild<'me> { locals_with_use_data: IndexVec<Local, bool>, } -impl LocalUseMapBuild<'_> { - fn insert_def(&mut self, local: Local, location: Location) { - Self::insert( - self.elements, - &mut self.local_use_map.first_def_at[local], - &mut self.local_use_map.appearances, - location, - ); - } - - fn insert_use(&mut self, local: Local, location: Location) { - Self::insert( - self.elements, - &mut self.local_use_map.first_use_at[local], - &mut self.local_use_map.appearances, - location, - ); - } - - fn insert_drop(&mut self, local: Local, location: Location) { - Self::insert( - self.elements, - &mut self.local_use_map.first_drop_at[local], - &mut self.local_use_map.appearances, - location, - ); - } - - fn insert( - elements: &DenseLocationMap, - first_appearance: &mut Option<AppearanceIndex>, - appearances: &mut Appearances, - location: Location, - ) { - let point_index = elements.point_from_location(location); - let appearance_index = - appearances.push(Appearance { point_index, next: *first_appearance }); - *first_appearance = Some(appearance_index); - } -} - impl Visitor<'_> for LocalUseMapBuild<'_> { fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { - if self.locals_with_use_data[local] { - match def_use::categorize(context) { - Some(DefUse::Def) => self.insert_def(local, location), - Some(DefUse::Use) => self.insert_use(local, location), - Some(DefUse::Drop) => self.insert_drop(local, location), - _ => (), - } + if self.locals_with_use_data[local] + && let Some(def_use) = def_use::categorize(context) + { + let first_appearance = match def_use { + DefUse::Def => &mut self.local_use_map.first_def_at[local], + DefUse::Use => &mut self.local_use_map.first_use_at[local], + DefUse::Drop => &mut self.local_use_map.first_drop_at[local], + }; + let point_index = self.elements.point_from_location(location); + let appearance_index = self + .local_use_map + .appearances + .push(Appearance { point_index, next: *first_appearance }); + *first_appearance = Some(appearance_index); } } } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index b8e35f882ec..84fb36dd32a 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -39,8 +39,8 @@ pub(super) fn generate<'a, 'tcx>( let free_regions = regions_that_outlive_free_regions( typeck.infcx.num_region_vars(), - typeck.borrowck_context.universal_regions, - &typeck.borrowck_context.constraints.outlives_constraints, + typeck.universal_regions, + &typeck.constraints.outlives_constraints, ); let (relevant_live_locals, boring_locals) = compute_relevant_live_locals(typeck.tcx(), &free_regions, body); @@ -59,11 +59,7 @@ pub(super) fn generate<'a, 'tcx>( // Mark regions that should be live where they appear within rvalues or within a call: like // args, regions, and types. - record_regular_live_regions( - typeck.tcx(), - &mut typeck.borrowck_context.constraints.liveness_constraints, - body, - ); + record_regular_live_regions(typeck.tcx(), &mut typeck.constraints.liveness_constraints, body); } // The purpose of `compute_relevant_live_locals` is to define the subset of `Local` diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index 3a458731f28..e8d8ae0850b 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -88,9 +88,9 @@ pub(super) fn populate_access_facts<'a, 'tcx>( body: &Body<'tcx>, move_data: &MoveData<'tcx>, ) { - if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { + if let Some(facts) = typeck.all_facts.as_mut() { debug!("populate_access_facts()"); - let location_table = typeck.borrowck_context.location_table; + let location_table = typeck.location_table; let mut extractor = UseFactsExtractor { var_defined_at: &mut facts.var_defined_at, @@ -108,7 +108,7 @@ pub(super) fn populate_access_facts<'a, 'tcx>( local, local_decl.ty ); let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - let universal_regions = &typeck.borrowck_context.universal_regions; + let universal_regions = &typeck.universal_regions; typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| { let region_vid = universal_regions.to_region_vid(region); facts.use_of_var_derefs_origin.push((local, region_vid.into())); @@ -125,9 +125,9 @@ pub(super) fn add_drop_of_var_derefs_origin<'tcx>( kind: &GenericArg<'tcx>, ) { debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind); - if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { + if let Some(facts) = typeck.all_facts.as_mut() { let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - let universal_regions = &typeck.borrowck_context.universal_regions; + let universal_regions = &typeck.universal_regions; typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| { let region_vid = universal_regions.to_region_vid(drop_live_region); facts.drop_of_var_derefs_origin.push((local, region_vid.into())); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 35963228181..72f6a605279 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -47,13 +47,12 @@ pub(super) fn trace<'a, 'tcx>( // When using `-Zpolonius=next`, compute the set of loans that can reach a given region. if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() { - let borrowck_context = &mut typeck.borrowck_context; - let borrow_set = &borrowck_context.borrow_set; + let borrow_set = &typeck.borrow_set; let mut live_loans = LiveLoans::new(borrow_set.len()); - let outlives_constraints = &borrowck_context.constraints.outlives_constraints; + let outlives_constraints = &typeck.constraints.outlives_constraints; let graph = outlives_constraints.graph(typeck.infcx.num_region_vars()); let region_graph = - graph.region_graph(outlives_constraints, borrowck_context.universal_regions.fr_static); + graph.region_graph(outlives_constraints, typeck.universal_regions.fr_static); // Traverse each issuing region's constraints, and record the loan as flowing into the // outlived region. @@ -73,7 +72,7 @@ pub(super) fn trace<'a, 'tcx>( // Store the inflowing loans in the liveness constraints: they will be used to compute live // loans when liveness data is recorded there. - borrowck_context.constraints.liveness_constraints.loans = Some(live_loans); + typeck.constraints.liveness_constraints.loans = Some(live_loans); }; let cx = LivenessContext { @@ -222,7 +221,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { // It may be necessary to just pick out the parts of // `add_drop_live_facts_for()` that make sense. let facts_to_add: Vec<_> = { - let drop_used = &self.cx.typeck.borrowck_context.all_facts.as_ref()?.var_dropped_at; + let drop_used = &self.cx.typeck.all_facts.as_ref()?.var_dropped_at; let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect(); @@ -235,12 +234,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { return None; } - let location = match self - .cx - .typeck - .borrowck_context - .location_table - .to_location(*location_index) + let location = match self.cx.typeck.location_table.to_location(*location_index) { RichLocation::Start(l) => l, RichLocation::Mid(l) => l, @@ -251,7 +245,8 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { .collect() }; - // FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end, ...), but I don't know which one. Please help me rename it to something descriptive! + // FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end, + // ...), but I don't know which one. Please help me rename it to something descriptive! // Also, if this IntervalSet is used in many places, it maybe should have a newtype'd // name with a description of what it means for future mortals passing by. let locations = IntervalSet::new(self.cx.elements.num_points()); @@ -615,13 +610,9 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { tcx: typeck.tcx(), param_env: typeck.param_env, op: |r| { - let live_region_vid = typeck.borrowck_context.universal_regions.to_region_vid(r); + let live_region_vid = typeck.universal_regions.to_region_vid(r); - typeck - .borrowck_context - .constraints - .liveness_constraints - .add_points(live_region_vid, live_at); + typeck.constraints.liveness_constraints.add_points(live_region_vid, live_at); }, }); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 26919bfd488..0fe6a4b5fce 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -4,6 +4,7 @@ use std::rc::Rc; use std::{fmt, iter, mem}; use either::Either; +use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::ErrorGuaranteed; @@ -40,7 +41,6 @@ use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; use rustc_trait_selection::traits::query::type_op::custom::{ CustomTypeOp, scrape_region_constraints, }; @@ -156,25 +156,24 @@ pub(crate) fn type_check<'a, 'tcx>( debug!(?normalized_inputs_and_output); - let mut borrowck_context = BorrowCheckContext { + let mut checker = TypeChecker { + infcx, + param_env, + last_span: body.span, + body, + user_type_annotations: &body.user_type_annotations, + region_bound_pairs: ®ion_bound_pairs, + known_type_outlives_obligations, + implicit_region_bound, + reported_errors: Default::default(), universal_regions: &universal_regions, location_table, - borrow_set, all_facts, + borrow_set, constraints: &mut constraints, upvars, }; - let mut checker = TypeChecker::new( - infcx, - body, - param_env, - ®ion_bound_pairs, - known_type_outlives_obligations, - implicit_region_bound, - &mut borrowck_context, - ); - checker.check_user_type_annotations(); let mut verifier = TypeVerifier::new(&mut checker, promoted); @@ -221,13 +220,12 @@ pub(crate) fn type_check<'a, 'tcx>( infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| { match region.kind() { ty::ReVar(_) => region, - ty::RePlaceholder(placeholder) => checker - .borrowck_context - .constraints - .placeholder_region(infcx, placeholder), + ty::RePlaceholder(placeholder) => { + checker.constraints.placeholder_region(infcx, placeholder) + } _ => ty::Region::new_var( infcx.tcx, - checker.borrowck_context.universal_regions.to_region_vid(region), + checker.universal_regions.to_region_vid(region), ), } }); @@ -240,25 +238,26 @@ pub(crate) fn type_check<'a, 'tcx>( } fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { - let cx = &mut typeck.borrowck_context; - if let Some(facts) = cx.all_facts { + if let Some(facts) = typeck.all_facts { let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - let location_table = cx.location_table; - facts.subset_base.extend(cx.constraints.outlives_constraints.outlives().iter().flat_map( - |constraint: &OutlivesConstraint<'_>| { - if let Some(from_location) = constraint.locations.from_location() { - Either::Left(iter::once(( - constraint.sup.into(), - constraint.sub.into(), - location_table.mid_index(from_location), - ))) - } else { - Either::Right(location_table.all_points().map(move |location| { - (constraint.sup.into(), constraint.sub.into(), location) - })) - } - }, - )); + let location_table = typeck.location_table; + facts.subset_base.extend( + typeck.constraints.outlives_constraints.outlives().iter().flat_map( + |constraint: &OutlivesConstraint<'_>| { + if let Some(from_location) = constraint.locations.from_location() { + Either::Left(iter::once(( + constraint.sup.into(), + constraint.sub.into(), + location_table.mid_index(from_location), + ))) + } else { + Either::Right(location_table.all_points().map(move |location| { + (constraint.sup.into(), constraint.sub.into(), location) + })) + } + }, + ), + ); } } @@ -303,13 +302,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { let ty = self.sanitize_type(constant, constant.const_.ty()); self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| { - let live_region_vid = - self.cx.borrowck_context.universal_regions.to_region_vid(live_region); - self.cx - .borrowck_context - .constraints - .liveness_constraints - .add_location(live_region_vid, location); + let live_region_vid = self.cx.universal_regions.to_region_vid(live_region); + self.cx.constraints.liveness_constraints.add_location(live_region_vid, location); }); // HACK(compiler-errors): Constants that are gathered into Body.required_consts @@ -561,15 +555,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // Don't try to add borrow_region facts for the promoted MIR let mut swap_constraints = |this: &mut Self| { - mem::swap(this.cx.borrowck_context.all_facts, all_facts); - mem::swap( - &mut this.cx.borrowck_context.constraints.outlives_constraints, - &mut constraints, - ); - mem::swap( - &mut this.cx.borrowck_context.constraints.liveness_constraints, - &mut liveness_constraints, - ); + mem::swap(this.cx.all_facts, all_facts); + mem::swap(&mut this.cx.constraints.outlives_constraints, &mut constraints); + mem::swap(&mut this.cx.constraints.liveness_constraints, &mut liveness_constraints); }; swap_constraints(self); @@ -594,7 +582,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // temporary from the user's point of view. constraint.category = ConstraintCategory::Boring; } - self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) + self.cx.constraints.outlives_constraints.push(constraint) } // If the region is live at least one location in the promoted MIR, // then add a liveness constraint to the main MIR for this region @@ -604,11 +592,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // unordered. #[allow(rustc::potential_query_instability)] for region in liveness_constraints.live_regions_unordered() { - self.cx - .borrowck_context - .constraints - .liveness_constraints - .add_location(region, location); + self.cx.constraints.liveness_constraints.add_location(region, location); } } @@ -863,15 +847,11 @@ struct TypeChecker<'a, 'tcx> { known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, - borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, -} - -struct BorrowCheckContext<'a, 'tcx> { - pub(crate) universal_regions: &'a UniversalRegions<'tcx>, + universal_regions: &'a UniversalRegions<'tcx>, location_table: &'a LocationTable, all_facts: &'a mut Option<AllFacts>, borrow_set: &'a BorrowSet<'tcx>, - pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>, + constraints: &'a mut MirTypeckRegionConstraints<'tcx>, upvars: &'a [&'a ty::CapturedPlace<'tcx>], } @@ -1006,29 +986,6 @@ impl Locations { } impl<'a, 'tcx> TypeChecker<'a, 'tcx> { - fn new( - infcx: &'a BorrowckInferCtxt<'tcx>, - body: &'a Body<'tcx>, - param_env: ty::ParamEnv<'tcx>, - region_bound_pairs: &'a RegionBoundPairs<'tcx>, - known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], - implicit_region_bound: ty::Region<'tcx>, - borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, - ) -> Self { - Self { - infcx, - last_span: body.span, - body, - user_type_annotations: &body.user_type_annotations, - param_env, - region_bound_pairs, - known_type_outlives_obligations, - implicit_region_bound, - borrowck_context, - reported_errors: Default::default(), - } - } - fn body(&self) -> &Body<'tcx> { self.body } @@ -1067,7 +1024,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { constraint_conversion::ConstraintConversion::new( self.infcx, - self.borrowck_context.universal_regions, + self.universal_regions, self.region_bound_pairs, self.implicit_region_bound, self.param_env, @@ -1075,7 +1032,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations, locations.span(self.body), category, - self.borrowck_context.constraints, + self.constraints, ) .convert_all(data); } @@ -1191,7 +1148,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // though. let category = match place.as_local() { Some(RETURN_PLACE) => { - let defining_ty = &self.borrowck_context.universal_regions.defining_ty; + let defining_ty = &self.universal_regions.defining_ty; if defining_ty.is_const() { if tcx.is_static(defining_ty.def_id()) { ConstraintCategory::UseAsStatic @@ -1375,9 +1332,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let region_ctxt_fn = || { let reg_info = match br.kind { - ty::BoundRegionKind::BrAnon => sym::anon, - ty::BoundRegionKind::BrNamed(_, name) => name, - ty::BoundRegionKind::BrEnv => sym::env, + ty::BoundRegionKind::Anon => sym::anon, + ty::BoundRegionKind::Named(_, name) => name, + ty::BoundRegionKind::ClosureEnv => sym::env, }; RegionCtxt::LateBound(reg_info) @@ -1439,12 +1396,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // output) types in the signature must be live, since // all the inputs that fed into it were live. for &late_bound_region in map.values() { - let region_vid = - self.borrowck_context.universal_regions.to_region_vid(late_bound_region); - self.borrowck_context - .constraints - .liveness_constraints - .add_location(region_vid, term_location); + let region_vid = self.universal_regions.to_region_vid(late_bound_region); + self.constraints.liveness_constraints.add_location(region_vid, term_location); } self.check_call_inputs(body, term, func, &sig, args, term_location, call_source); @@ -1532,18 +1485,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let dest_ty = self.normalize(dest_ty, term_location); let category = match destination.as_local() { Some(RETURN_PLACE) => { - if let BorrowCheckContext { - universal_regions: - UniversalRegions { - defining_ty: - DefiningTy::Const(def_id, _) - | DefiningTy::InlineConst(def_id, _), - .. - }, - .. - } = self.borrowck_context + if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) = + self.universal_regions.defining_ty { - if tcx.is_static(*def_id) { + if tcx.is_static(def_id) { ConstraintCategory::UseAsStatic } else { ConstraintCategory::UseAsConst @@ -1606,9 +1551,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let func_ty = func.ty(body, self.infcx.tcx); if let ty::FnDef(def_id, _) = *func_ty.kind() { - // Some of the SIMD intrinsics are special: they need a particular argument to be a constant. - // (Eventually this should use const-generics, but those are not up for the task yet: - // https://github.com/rust-lang/rust/issues/85229.) + // Some of the SIMD intrinsics are special: they need a particular argument to be a + // constant. (Eventually this should use const-generics, but those are not up for the + // task yet: https://github.com/rust-lang/rust/issues/85229.) if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) = self.tcx().intrinsic(def_id).map(|i| i.name) { @@ -1921,7 +1866,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) { match operand { Operand::Copy(..) | Operand::Constant(..) => { - // These are always okay: direct use of a const, or a value that can evidently be copied. + // These are always okay: direct use of a const, or a value that can + // evidently be copied. } Operand::Move(place) => { // Make sure that repeated elements implement `Copy`. @@ -2402,9 +2348,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let dst_tail = self.struct_tail(dst.ty, location); // This checks (lifetime part of) vtable validity for pointer casts, - // which is irrelevant when there are aren't principal traits on both sides (aka only auto traits). + // which is irrelevant when there are aren't principal traits on + // both sides (aka only auto traits). // - // Note that other checks (such as denying `dyn Send` -> `dyn Debug`) are in `rustc_hir_typeck`. + // Note that other checks (such as denying `dyn Send` -> `dyn + // Debug`) are in `rustc_hir_typeck`. if let ty::Dynamic(src_tty, ..) = src_tail.kind() && let ty::Dynamic(dst_tty, ..) = dst_tail.kind() && src_tty.principal().is_some() @@ -2427,8 +2375,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty::Dyn, )); - // Replace trait object lifetimes with fresh vars, to allow casts like - // `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static`, + // Replace trait object lifetimes with fresh vars, to allow + // casts like + // `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static` let src_obj = freshen_single_trait_object_lifetime(self.infcx, src_obj); let dst_obj = @@ -2650,8 +2599,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { borrowed_place: &Place<'tcx>, ) { // These constraints are only meaningful during borrowck: - let BorrowCheckContext { borrow_set, location_table, all_facts, constraints, .. } = - self.borrowck_context; + let Self { borrow_set, location_table, all_facts, constraints, .. } = self; // In Polonius mode, we also push a `loan_issued_at` fact // linking the loan to the region (in some cases, though, @@ -2681,12 +2629,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); let tcx = self.infcx.tcx; - let field = path_utils::is_upvar_field_projection( - tcx, - self.borrowck_context.upvars, - borrowed_place.as_ref(), - body, - ); + let field = + path_utils::is_upvar_field_projection(tcx, self.upvars, borrowed_place.as_ref(), body); let category = if let Some(field) = field { ConstraintCategory::ClosureUpvar(field) } else { @@ -2840,7 +2784,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements { constraint_conversion::ConstraintConversion::new( self.infcx, - self.borrowck_context.universal_regions, + self.universal_regions, self.region_bound_pairs, self.implicit_region_bound, self.param_env, @@ -2848,7 +2792,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations, self.body.span, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. - self.borrowck_context.constraints, + self.constraints, ) .apply_closure_requirements(closure_requirements, def_id.to_def_id(), args); } diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index cfc14d146bd..e2f3e065bc0 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -240,11 +240,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { fn create_next_universe(&mut self) -> ty::UniverseIndex { let universe = self.type_checker.infcx.create_next_universe(); - self.type_checker - .borrowck_context - .constraints - .universe_causes - .insert(universe, self.universe_info.clone()); + self.type_checker.constraints.universe_causes.insert(universe, self.universe_info.clone()); universe } @@ -264,16 +260,13 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { #[instrument(skip(self), level = "debug")] fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { - let reg = self - .type_checker - .borrowck_context - .constraints - .placeholder_region(self.type_checker.infcx, placeholder); + let reg = + self.type_checker.constraints.placeholder_region(self.type_checker.infcx, placeholder); let reg_info = match placeholder.bound.kind { - ty::BoundRegionKind::BrAnon => sym::anon, - ty::BoundRegionKind::BrNamed(_, name) => name, - ty::BoundRegionKind::BrEnv => sym::env, + ty::BoundRegionKind::Anon => sym::anon, + ty::BoundRegionKind::Named(_, name) => name, + ty::BoundRegionKind::ClosureEnv => sym::env, }; if cfg!(debug_assertions) { @@ -294,19 +287,17 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { sub: ty::Region<'tcx>, info: ty::VarianceDiagInfo<TyCtxt<'tcx>>, ) { - let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub); - let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup); - self.type_checker.borrowck_context.constraints.outlives_constraints.push( - OutlivesConstraint { - sup, - sub, - locations: self.locations, - span: self.locations.span(self.type_checker.body), - category: self.category, - variance_info: info, - from_closure: false, - }, - ); + let sub = self.type_checker.universal_regions.to_region_vid(sub); + let sup = self.type_checker.universal_regions.to_region_vid(sup); + self.type_checker.constraints.outlives_constraints.push(OutlivesConstraint { + sup, + sub, + locations: self.locations, + span: self.locations.span(self.type_checker.body), + category: self.category, + variance_info: info, + from_closure: false, + }); } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index fa44ffcd17d..b63144f560f 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -696,14 +696,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let closure_sig = args.as_closure().sig(); let inputs_and_output = closure_sig.inputs_and_output(); let bound_vars = tcx.mk_bound_variable_kinds_from_iter( - inputs_and_output - .bound_vars() - .iter() - .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + inputs_and_output.bound_vars().iter().chain(iter::once( + ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv), + )), ); let br = ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BrEnv, + kind: ty::BoundRegionKind::ClosureEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); let closure_ty = tcx.closure_env_ty( @@ -751,15 +750,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { DefiningTy::CoroutineClosure(def_id, args) => { assert_eq!(self.mir_def.to_def_id(), def_id); let closure_sig = args.as_coroutine_closure().coroutine_closure_sig(); - let bound_vars = tcx.mk_bound_variable_kinds_from_iter( - closure_sig - .bound_vars() - .iter() - .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), - ); + let bound_vars = + tcx.mk_bound_variable_kinds_from_iter(closure_sig.bound_vars().iter().chain( + iter::once(ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv)), + )); let br = ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BrEnv, + kind: ty::BoundRegionKind::ClosureEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); let closure_kind = args.as_coroutine_closure().kind(); diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 1c2ca95b075..e4f77472802 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ahash" @@ -46,24 +46,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b80c3a50b9c4c7e5b5f73c0ed746687774fc9e36ef652b110da8daebf0c6e0e6" +checksum = "8ea5e7afe85cadb55c4c1176268a2ac046fdff8dfaeca39e18581b9dc319ca9e" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38778758c2ca918b05acb2199134e0c561fb577c50574259b26190b6c2d95ded" +checksum = "8ab25ef3be935a80680e393183e1f94ef507e93a24a8369494d2c6818aedb3e3" [[package]] name = "cranelift-codegen" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58258667ad10e468bfc13a8d620f50dfcd4bb35d668123e97defa2549b9ad397" +checksum = "900a19b84545924f1851cbfe386962edfc4ecbc3366a254825cf1ecbcda8ba08" dependencies = [ "bumpalo", "cranelift-bforest", @@ -74,7 +74,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.14.5", + "hashbrown", "log", "regalloc2", "rustc-hash", @@ -84,42 +84,42 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043f0b702e529dcb07ff92bd7d40e7d5317b5493595172c5eb0983343751ee06" +checksum = "08c73b2395ffe9e7b4fdf7e2ebc052e7e27af13f68a964985346be4da477a5fc" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7763578888ab53eca5ce7da141953f828e82c2bfadcffc106d10d1866094ffbb" +checksum = "7d9ed0854e96a4ff0879bff39d078de8dea7f002721c9494c1fdb4e1baa86ccc" [[package]] name = "cranelift-control" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32db15f08c05df570f11e8ab33cb1ec449a64b37c8a3498377b77650bef33d8b" +checksum = "b4aca921dd422e781409de0129c255768fec5dec1dae83239b497fb9138abb89" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5289cdb399381a27e7bbfa1b42185916007c3d49aeef70b1d01cb4caa8010130" +checksum = "e2d770e6605eccee15b49decdd82cd26f2b6404767802471459ea49c57379a98" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ba8ab24eb9470477e98ddfa3c799a649ac5a0d9a2042868c4c952133c234e8" +checksum = "29268711cb889cb39215b10faf88b9087d4c9e1d2633581e4f722a2bf4bb4ef9" dependencies = [ "cranelift-codegen", "log", @@ -129,15 +129,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b72a3c5c166a70426dcb209bdd0bb71a787c1ea76023dc0974fbabca770e8f9" +checksum = "dc65156f010aed1985767ad1bff0eb8d186743b7b03e23d0c17604a253e3f356" [[package]] name = "cranelift-jit" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df32578a47582e49b4fc1f9a5786839d9be1fedaa9f00bea7612c54425663c6b" +checksum = "40ba6b46367a4f466cfb1abe32793fa1a0f96d862251491b01a44726b8ed9445" dependencies = [ "anyhow", "cranelift-codegen", @@ -150,14 +150,14 @@ dependencies = [ "region", "target-lexicon", "wasmtime-jit-icache-coherence", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "cranelift-module" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96094a758cdb543c9143f70817cd31069fecd49f50981a0fac06820ac011dc2f" +checksum = "007607022a4883ebdffc46c0925e2e10babf2a565ae78518034ade722aa825d2" dependencies = [ "anyhow", "cranelift-codegen", @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a42424c956bbc31fc5c2706073df896156c5420ae8fa2a5d48dbc7b295d71b" +checksum = "d8bf9b361eaf5a7627647270fabf1dc910d993edbeaf272a652c107861ebe9c2" dependencies = [ "cranelift-codegen", "libc", @@ -177,9 +177,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cf5e2484ab47fe38a3150747cdd2016535f13542a925acca152b63383a6591b" +checksum = "30ca5c38fa00c0cd943035391bdcc84ed00748f17c66c682e410f5a62f234d44" dependencies = [ "anyhow", "cranelift-codegen", @@ -213,9 +213,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" dependencies = [ "fallible-iterator", "indexmap", @@ -224,15 +224,6 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" @@ -247,7 +238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -273,10 +264,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] -name = "mach" -version = "0.3.2" +name = "mach2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] @@ -294,7 +285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "crc32fast", - "hashbrown 0.14.5", + "hashbrown", "indexmap", "memchr", ] @@ -325,11 +316,11 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0" dependencies = [ - "hashbrown 0.13.2", + "hashbrown", "log", "rustc-hash", "slice-group-by", @@ -338,21 +329,21 @@ dependencies = [ [[package]] name = "region" -version = "2.2.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" dependencies = [ "bitflags", "libc", - "mach", - "winapi", + "mach2", + "windows-sys 0.52.0", ] [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_codegen_cranelift" @@ -421,43 +412,30 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "24.0.0" +version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15de8429db996f0d17a4163a35eccc3f874cbfb50f29c379951ea1bbb39452e" +checksum = "6e458e6a1a010a53f86ac8d75837c0c6b2ce3e54b7503b2f1dc5629a4a541f5a" dependencies = [ "anyhow", "cfg-if", "libc", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-targets", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] name = "windows-sys" -version = "0.52.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 6594ffb5d66..f352ef72cb0 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,14 +8,14 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.111.0", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.111.0" } -cranelift-module = { version = "0.111.0" } -cranelift-native = { version = "0.111.0" } -cranelift-jit = { version = "0.111.0", optional = true } -cranelift-object = { version = "0.111.0" } +cranelift-codegen = { version = "0.113.0", default-features = false, features = ["std", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.113.0" } +cranelift-module = { version = "0.113.0" } +cranelift-native = { version = "0.113.0" } +cranelift-jit = { version = "0.113.0", optional = true } +cranelift-object = { version = "0.113.0" } target-lexicon = "0.12.0" -gimli = { version = "0.29", default-features = false, features = ["write"] } +gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs index 82558999afa..f1f4489bcbc 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -102,15 +102,6 @@ pub(crate) fn build_sysroot( .install_into_sysroot(&dist_dir); } - // Copy std for the host to the lib dir. This is necessary for the jit mode to find - // libstd. - for lib in host.libs { - let filename = lib.file_name().unwrap().to_str().unwrap(); - if filename.contains("std-") && !filename.contains(".rlib") { - try_hard_link(&lib, dist_dir.join("lib").join(lib.file_name().unwrap())); - } - } - let mut target_compiler = { let rustc_clif = dist_dir.join(wrapper_base_name.replace("____", "rustc-clif")); let rustdoc_clif = dist_dir.join(wrapper_base_name.replace("____", "rustdoc-clif")); diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index 30bd7ae26a1..c6f979f0278 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -1,8 +1,8 @@ use std::ffi::OsStr; -use std::fs; use std::hash::{Hash, Hasher}; use std::path::{Path, PathBuf}; use std::process::Command; +use std::{fs, io}; use crate::path::{Dirs, RelPath}; use crate::utils::{copy_dir_recursively, ensure_empty_dir, spawn_and_wait}; @@ -89,6 +89,19 @@ impl GitRepo { } } + fn verify_checksum(&self, dirs: &Dirs) { + let download_dir = self.download_dir(dirs); + let actual_hash = format!("{:016x}", hash_dir(&download_dir)); + if actual_hash != self.content_hash { + eprintln!( + "Mismatched content hash for {download_dir}: {actual_hash} != {content_hash}. Please run ./y.sh prepare again.", + download_dir = download_dir.display(), + content_hash = self.content_hash, + ); + std::process::exit(1); + } + } + pub(crate) fn fetch(&self, dirs: &Dirs) { let download_dir = self.download_dir(dirs); @@ -126,18 +139,11 @@ impl GitRepo { assert!(target_lockfile.exists()); } - let actual_hash = format!("{:016x}", hash_dir(&download_dir)); - if actual_hash != self.content_hash { - eprintln!( - "Download of {download_dir} failed with mismatched content hash: {actual_hash} != {content_hash}", - download_dir = download_dir.display(), - content_hash = self.content_hash, - ); - std::process::exit(1); - } + self.verify_checksum(dirs); } pub(crate) fn patch(&self, dirs: &Dirs) { + self.verify_checksum(dirs); apply_patches( dirs, self.patch_name, @@ -149,6 +155,13 @@ impl GitRepo { fn clone_repo(download_dir: &Path, repo: &str, rev: &str) { eprintln!("[CLONE] {}", repo); + + match fs::remove_dir_all(download_dir) { + Ok(()) => {} + Err(err) if err.kind() == io::ErrorKind::NotFound => {} + Err(err) => panic!("Failed to remove {path}: {err}", path = download_dir.display()), + } + // Ignore exit code as the repo may already have been checked out git_command(None, "clone").arg(repo).arg(download_dir).spawn().unwrap().wait().unwrap(); diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 42c7f5f0dc6..3da215fe6c0 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -616,25 +616,70 @@ pub union MaybeUninit<T> { } pub mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; - #[rustc_safe_intrinsic] - pub fn size_of<T>() -> usize; - pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize; - #[rustc_safe_intrinsic] - pub fn min_align_of<T>() -> usize; - pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize; - pub fn copy<T>(src: *const T, dst: *mut T, count: usize); - pub fn transmute<T, U>(e: T) -> U; - pub fn ctlz_nonzero<T>(x: T) -> u32; - #[rustc_safe_intrinsic] - pub fn needs_drop<T: ?::Sized>() -> bool; - #[rustc_safe_intrinsic] - pub fn bitreverse<T>(x: T) -> T; - #[rustc_safe_intrinsic] - pub fn bswap<T>(x: T) -> T; - pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize); + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn size_of<T>() -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn min_align_of<T>() -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize) { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn transmute<T, U>(_e: T) -> U { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32 { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn needs_drop<T: ?::Sized>() -> bool { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn bitreverse<T>(_x: T) -> T { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn bswap<T>(_x: T) -> T { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize) { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn unreachable() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch b/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch index 8a2565f1668..01b6a990b72 100644 --- a/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch @@ -7,11 +7,23 @@ Subject: [PATCH] Disable broken tests src/report.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) +diff --git a/src/toolchains/rust.rs b/src/toolchains/rust.rs +index 0c50f7a..bfde2b1 100644 +--- a/src/toolchains/rust.rs ++++ b/src/toolchains/rust.rs +@@ -83,6 +83,7 @@ impl Toolchain for RustcToolchain { + .arg(out_dir) + .arg("--target") + .arg(built_info::TARGET) ++ .arg("-g") + .arg(format!("-Cmetadata={lib_name}")) + .arg(src_path); + if let Some(codegen_backend) = &self.codegen_backend { diff --git a/src/report.rs b/src/report.rs index 958ab43..dcf1044 100644 --- a/src/report.rs +++ b/src/report.rs -@@ -48,6 +48,58 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn Toolchain, callee: &dyn Toolc +@@ -48,6 +48,40 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn Toolchain, callee: &dyn Toolc // // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES @@ -19,10 +31,6 @@ index 958ab43..dcf1044 100644 + if test.test == "F32Array" && test.options.convention == CallingConvention::C { + result.check = Busted(Check); + } -+ -+ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::C { -+ result.check = Busted(Check); -+ } + } + + if cfg!(all(target_arch = "aarch64", target_os = "macos")) { @@ -39,21 +47,7 @@ index 958ab43..dcf1044 100644 + } + } + -+ if cfg!(all(target_arch = "x86_64", unix)) { -+ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::Rust { -+ result.check = Busted(Run); -+ } -+ } -+ + if cfg!(all(target_arch = "x86_64", windows)) { -+ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust { -+ result.check = Busted(Check); -+ } -+ -+ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && (test.caller == "rustc" || test.options.repr == LangRepr::Rust) { -+ result.check = Busted(Run); -+ } -+ + if test.test == "simple" && test.options.convention == CallingConvention::Rust { + result.check = Busted(Check); + } diff --git a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch index 5117b04fd34..6ed22c5a18e 100644 --- a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch @@ -38,7 +38,7 @@ index 42a26ae..5ac1042 100644 @@ -1,3 +1,4 @@ +#![cfg(test)] // tidy-alphabetical-start - #![cfg_attr(bootstrap, feature(const_mut_refs))] - #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] + #![cfg_attr(bootstrap, feature(strict_provenance))] + #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] -- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch index efd721d9df8..50a42aea322 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch @@ -14,13 +14,14 @@ diff --git a/lib.rs b/lib.rs index 1e336bf..35e6f54 100644 --- a/lib.rs +++ b/lib.rs -@@ -1,6 +1,5 @@ - #![cfg(test)] +@@ -2,7 +2,6 @@ // tidy-alphabetical-start - #![cfg_attr(bootstrap, feature(const_mut_refs))] + #![cfg_attr(bootstrap, feature(strict_provenance))] + #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] + #![feature(array_chunks)] diff --git a/atomic.rs b/atomic.rs index b735957..ea728b6 100644 --- a/atomic.rs diff --git a/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch index d7204add7a7..b98326c54a6 100644 --- a/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch @@ -12,7 +12,7 @@ index 8402833..84592e0 100644 --- a/slice.rs +++ b/slice.rs @@ -1809,6 +1809,7 @@ fn sort_unstable() { - assert!(v == [0xDEADBEEF]); + } } +/* @@ -43,26 +43,6 @@ index 8402833..84592e0 100644 #[test] fn test_slice_from_ptr_range() { -diff --git a/lazy.rs b/lazy.rs -index 711511e..49c8d78 100644 ---- a/lazy.rs -+++ b/lazy.rs -@@ -113,6 +113,7 @@ fn lazy_type_inference() { - let _ = LazyCell::new(|| ()); - } - -+/* - #[test] - #[should_panic = "LazyCell instance has previously been poisoned"] - fn lazy_force_mut_panic() { -@@ -123,6 +124,7 @@ fn lazy_force_mut_panic() { - .unwrap_err(); - let _ = &*lazy; - } -+*/ - - #[test] - fn lazy_force_mut() { -- 2.26.2.7.g19db9cfb68 diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 651770be377..2558b2b9f5d 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-09-23" +channel = "nightly-2024-11-02" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 93512f82c8b..a820da286f5 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -47,9 +47,6 @@ rm tests/ui/abi/variadic-ffi.rs # requires callee side vararg support rm -r tests/run-make/c-link-to-rust-va-list-fn # requires callee side vararg support rm tests/ui/delegation/fn-header.rs -# unsized locals -rm -r tests/run-pass-valgrind/unsized-locals - # misc unimplemented things rm tests/ui/target-feature/missing-plusminus.rs # error not implemented rm -r tests/run-make/repr128-dwarf # debuginfo test @@ -148,6 +145,7 @@ rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist +cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/ # prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by # rustdoc-clif @@ -180,92 +178,20 @@ index 9607ff02f96..b7d97caf9a2 100644 Self { cmd } } -diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs -index 2047345d78a..a7e9352bb1c 100644 ---- a/src/bootstrap/src/core/build_steps/test.rs -+++ b/src/bootstrap/src/core/build_steps/test.rs -@@ -1733,11 +1733,6 @@ fn run(self, builder: &Builder<'_>) { - - let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js"); - -- if mode == "run-make" { -- let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host }); -- cmd.arg("--cargo-path").arg(cargo); -- } -- - // Avoid depending on rustdoc when we don't need it. - if mode == "rustdoc" - || mode == "run-make" -diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs -index 414f9f3a7f1..5c18179b6fe 100644 ---- a/src/tools/compiletest/src/common.rs -+++ b/src/tools/compiletest/src/common.rs -@@ -183,9 +183,6 @@ pub struct Config { - /// The rustc executable. - pub rustc_path: PathBuf, - -- /// The cargo executable. -- pub cargo_path: Option<PathBuf>, -- - /// The rustdoc executable. - pub rustdoc_path: Option<PathBuf>, - -diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs -index 3339116d542..250b5084d13 100644 ---- a/src/tools/compiletest/src/lib.rs -+++ b/src/tools/compiletest/src/lib.rs -@@ -47,7 +47,6 @@ pub fn parse_config(args: Vec<String>) -> Config { - opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH") - .reqopt("", "run-lib-path", "path to target shared libraries", "PATH") - .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH") -- .optopt("", "cargo-path", "path to cargo to use for compiling", "PATH") - .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") - .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH") - .reqopt("", "python", "path to python to use for doc tests", "PATH") -@@ -261,7 +260,6 @@ fn make_absolute(path: PathBuf) -> PathBuf { - compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), - run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), - rustc_path: opt_path(matches, "rustc-path"), -- cargo_path: matches.opt_str("cargo-path").map(PathBuf::from), - rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from), - coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from), - python: matches.opt_str("python").unwrap(), -@@ -366,7 +364,6 @@ pub fn log_config(config: &Config) { - logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path)); - logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); - logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); -- logv(c, format!("cargo_path: {:?}", config.cargo_path)); - logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); - logv(c, format!("src_base: {:?}", config.src_base.display())); - logv(c, format!("build_base: {:?}", config.build_base.display())); diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs -index 75fe6a6baaf..852568ae925 100644 +index e7ae773ffa1d3..04bc2d7787da7 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs -@@ -61,10 +61,6 @@ fn run_rmake_legacy_test(&self) { - .env_remove("MFLAGS") - .env_remove("CARGO_MAKEFLAGS"); - -- if let Some(ref cargo) = self.config.cargo_path { -- cmd.env("CARGO", cwd.join(cargo)); -- } -- - if let Some(ref rustdoc) = self.config.rustdoc_path { - cmd.env("RUSTDOC", cwd.join(rustdoc)); - } -@@ -413,10 +409,6 @@ fn run_rmake_v2_test(&self) { - // through a specific CI runner). - .env("LLVM_COMPONENTS", &self.config.llvm_components); +@@ -329,7 +329,6 @@ impl TestCx<'_> { + .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) + .arg("--edition=2021") + .arg(&self.testpaths.file.join("rmake.rs")) +- .arg("-Cprefer-dynamic") + // Provide necessary library search paths for rustc. + .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap()); -- if let Some(ref cargo) = self.config.cargo_path { -- cmd.env("CARGO", source_root.join(cargo)); -- } -- - if let Some(ref rustdoc) = self.config.rustdoc_path { - cmd.env("RUSTDOC", source_root.join(rustdoc)); - } EOF echo "[TEST] rustc test suite" -COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 --test-args=--nocapture tests/{codegen-units,run-make,run-pass-valgrind,ui,incremental} +COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 --test-args=--nocapture tests/{codegen-units,run-make,ui,incremental} popd diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 089b09d06ae..dfca5dcbec8 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -389,7 +389,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let callee = with_no_trimmed_paths!(fx.tcx.def_path_str(def_id)); fx.tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee }); } else { - fx.bcx.ins().trap(TrapCode::User(0)); + fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return; } } @@ -562,6 +562,11 @@ pub(crate) fn codegen_terminator_call<'tcx>( adjust_call_for_c_variadic(fx, &fn_abi, source_info, func_ref, &mut call_args); } + if fx.clif_comments.enabled() { + let nop_inst = fx.bcx.ins().nop(); + with_no_trimmed_paths!(fx.add_comment(nop_inst, format!("abi: {:?}", fn_abi))); + } + match func_ref { CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), CallTarget::Indirect(sig, func_ptr) => { @@ -574,7 +579,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let ret_block = fx.get_block(dest); fx.bcx.ins().jump(ret_block, &[]); } else { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } fn adjust_call_for_c_variadic<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 99e39971b74..10d5dce9b36 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -103,12 +103,12 @@ pub(crate) fn codegen_fn<'tcx>( let block_map: IndexVec<BasicBlock, Block> = (0..mir.basic_blocks.len()).map(|_| bcx.create_block()).collect(); + let fn_abi = RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()); + // Make FunctionCx let target_config = module.target_config(); let pointer_type = target_config.pointer_type(); - let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance); - - let fn_abi = RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()); + let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance, fn_abi); let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context { Some(debug_context.define_function(tcx, type_dbg, instance, fn_abi, &symbol_name, mir.span)) @@ -294,7 +294,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { if arg_uninhabited { fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); return; } fx.tcx @@ -311,7 +311,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { if !reachable_blocks.contains(bb) { // We want to skip this block, because it's not reachable. But we still create // the block so terminators in other blocks can reference it. - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); continue; } @@ -379,7 +379,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { let target = fx.get_block(*target); let failure = fx.bcx.create_block(); - fx.bcx.set_cold_block(failure); if *expected { fx.bcx.ins().brif(cond, target, &[], failure, &[]); @@ -541,10 +540,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } TerminatorKind::UnwindResume => { // FIXME implement unwinding - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } TerminatorKind::Unreachable => { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.set_cold_block(block); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } TerminatorKind::Yield { .. } | TerminatorKind::FalseEdge { .. } @@ -1075,12 +1075,14 @@ fn codegen_panic_inner<'tcx>( args: &[Value], span: Option<Span>, ) { + fx.bcx.set_cold_block(fx.bcx.current_block().unwrap()); + let def_id = fx.tcx.require_lang_item(lang_item, span); let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) { - fx.bcx.ins().trap(TrapCode::User(0)); + fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return; } @@ -1093,5 +1095,5 @@ fn codegen_panic_inner<'tcx>( args, ); - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs index c3d9d635084..fa7b39c836f 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs @@ -50,7 +50,12 @@ fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> { if hash.kind == SourceFileHashAlgorithm::Md5 { let mut buf = [0u8; MD5_LEN]; buf.copy_from_slice(hash.hash_bytes()); - Some(FileInfo { timestamp: 0, size: 0, md5: buf }) + Some(FileInfo { + timestamp: 0, + size: 0, + md5: buf, + source: None, // FIXME implement -Zembed-source + }) } else { None } diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 79d76925df9..78ae43b1c4d 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -101,6 +101,7 @@ impl DebugContext { None => (tcx.crate_name(LOCAL_CRATE).to_string(), None), }; + let file_has_md5 = file_info.is_some(); let mut line_program = LineProgram::new( encoding, LineEncoding::default(), @@ -108,7 +109,7 @@ impl DebugContext { LineString::new(name.as_bytes(), encoding, &mut dwarf.line_strings), file_info, ); - line_program.file_has_md5 = file_info.is_some(); + line_program.file_has_md5 = file_has_md5; dwarf.unit.line_program = line_program; diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs index 9399230f292..362333d35a4 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs @@ -60,8 +60,8 @@ impl UnwindContext { self.frame_table .add_fde(self.cie_id.unwrap(), unwind_info.to_fde(address_for_func(func_id))); } - UnwindInfo::WindowsX64(_) => { - // FIXME implement this + UnwindInfo::WindowsX64(_) | UnwindInfo::WindowsArm64(_) => { + // Windows does not have debug info for its unwind info. } unwind_info => unimplemented!("{:?}", unwind_info), } diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 41f1b30d10b..0fbd5a16830 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -47,7 +47,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for // the LLVM backend. if template.len() == 1 && template[0] == InlineAsmTemplatePiece::String("int $$0x29".into()) { - fx.bcx.ins().trap(TrapCode::User(1)); + fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return; } @@ -137,7 +137,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( fx.bcx.ins().jump(destination_block, &[]); } None => { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(0 /* unreachable */).unwrap()); } } } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index aae6794891d..1e2e41b3122 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1,4 +1,4 @@ -//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, `extern "platform-intrinsic"` +//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, //! and LLVM intrinsics that have symbol names starting with `llvm.`. macro_rules! intrinsic_args { @@ -47,7 +47,7 @@ fn report_atomic_type_validation_error<'tcx>( ), ); // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Type { @@ -449,7 +449,8 @@ fn codegen_regular_intrinsic_call<'tcx>( match intrinsic { sym::abort => { - fx.bcx.ins().trap(TrapCode::User(0)); + fx.bcx.set_cold_block(fx.bcx.current_block().unwrap()); + fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return Ok(()); } sym::likely | sym::unlikely => { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index e7f9f894381..36a35d42c3e 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -1,4 +1,4 @@ -//! Codegen `extern "platform-intrinsic"` intrinsics. +//! Codegen SIMD intrinsics. use cranelift_codegen::ir::immediates::Offset32; use rustc_target::abi::Endian; @@ -14,7 +14,7 @@ fn report_simd_type_validation_error( ) { fx.tcx.dcx().span_err(span, format!("invalid monomorphization of `{}` intrinsic: expected SIMD input type, found non-SIMD `{}`", intrinsic, ty)); // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } pub(super) fn codegen_simd_intrinsic_call<'tcx>( @@ -190,7 +190,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( format!("simd_shuffle index must be a SIMD vector of `u32`, got `{}`", idx_ty), ); // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); return; }; let n: u16 = idx_ty.simd_size_and_type(fx.tcx).0.try_into().unwrap(); @@ -1135,7 +1135,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => { fx.tcx.dcx().span_err(span, format!("Unknown SIMD intrinsic {}", intrinsic)); // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(0 /* unreachable */).unwrap()); return; } } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index fc3bd0abd78..aba0c28f6b8 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -302,8 +302,11 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIs OptLevel::No => { flags_builder.set("opt_level", "none").unwrap(); } - OptLevel::Less | OptLevel::Default => {} - OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => { + OptLevel::Less + | OptLevel::Default + | OptLevel::Size + | OptLevel::SizeMin + | OptLevel::Aggressive => { flags_builder.set("opt_level", "speed_and_size").unwrap(); } } diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 13877b3b1e9..282763279dd 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -62,9 +62,9 @@ use cranelift_codegen::entity::SecondaryMap; use cranelift_codegen::ir::Fact; use cranelift_codegen::ir::entities::AnyEntity; use cranelift_codegen::write::{FuncWriter, PlainWriter}; -use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::config::{OutputFilenames, OutputType}; +use rustc_target::abi::call::FnAbi; use crate::prelude::*; @@ -76,17 +76,18 @@ pub(crate) struct CommentWriter { } impl CommentWriter { - pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { + pub(crate) fn new<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, + ) -> Self { let enabled = should_write_ir(tcx); let global_comments = if enabled { with_no_trimmed_paths!({ vec![ format!("symbol {}", tcx.symbol_name(instance).name), format!("instance {:?}", instance), - format!( - "abi {:?}", - RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()) - ), + format!("abi {:?}", fn_abi), String::new(), ] }) diff --git a/compiler/rustc_codegen_cranelift/src/trap.rs b/compiler/rustc_codegen_cranelift/src/trap.rs index a61e1e334ec..9ef1a523d6d 100644 --- a/compiler/rustc_codegen_cranelift/src/trap.rs +++ b/compiler/rustc_codegen_cranelift/src/trap.rs @@ -30,5 +30,5 @@ pub(crate) fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRe let one = fx.bcx.ins().iconst(types::I32, 1); fx.lib_call("exit", vec![AbiParam::new(types::I32)], vec![], &[one]); - fx.bcx.ins().trap(TrapCode::User(!0)); + fx.bcx.ins().trap(TrapCode::user(3).unwrap()); } diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 0576b64ef6f..c887598f6e9 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -579,28 +579,70 @@ pub union MaybeUninit<T> { } pub mod intrinsics { - use crate::Sized; - - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; - #[rustc_safe_intrinsic] - pub fn size_of<T>() -> usize; - pub fn size_of_val<T: ?Sized>(val: *const T) -> usize; - #[rustc_safe_intrinsic] - pub fn min_align_of<T>() -> usize; - pub fn min_align_of_val<T: ?Sized>(val: *const T) -> usize; - pub fn copy<T>(src: *const T, dst: *mut T, count: usize); - pub fn transmute<T, U>(e: T) -> U; - pub fn ctlz_nonzero<T>(x: T) -> u32; - #[rustc_safe_intrinsic] - pub fn needs_drop<T: ?Sized>() -> bool; - #[rustc_safe_intrinsic] - pub fn bitreverse<T>(x: T) -> T; - #[rustc_safe_intrinsic] - pub fn bswap<T>(x: T) -> T; - pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize); - pub fn unreachable() -> !; + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn size_of<T>() -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn min_align_of<T>() -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize) { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn transmute<T, U>(_e: T) -> U { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32 { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn needs_drop<T: ?::Sized>() -> bool { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn bitreverse<T>(_x: T) -> T { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn bswap<T>(_x: T) -> T { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize) { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn unreachable() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl index bbae59ea7a5..26ddc5732dd 100644 --- a/compiler/rustc_codegen_gcc/messages.ftl +++ b/compiler/rustc_codegen_gcc/messages.ftl @@ -8,6 +8,9 @@ codegen_gcc_invalid_minimum_alignment = codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. +codegen_gcc_forbidden_ctarget_feature = + target feature `{$feature}` cannot be toggled with `-Ctarget-feature` + codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm @@ -24,11 +27,15 @@ codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdyl codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err}) codegen_gcc_unknown_ctarget_feature = - unknown feature specified for `-Ctarget-feature`: `{$feature}` - .note = it is still passed through to the codegen backend + unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future .possible_feature = you might have meant: `{$rust_feature}` .consider_filing_feature_request = consider filing a feature request +codegen_gcc_unstable_ctarget_feature = + unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = this feature is not stably supported; its behavior can change in the future + codegen_gcc_missing_features = add the missing features in a `target_feature` attribute diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index 0cee05f1cea..82e98370b37 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -2,6 +2,7 @@ use std::path::Path; use rustc_codegen_ssa::back::archive::{ ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, + ImportLibraryItem, }; use rustc_session::Session; @@ -16,7 +17,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { &self, _sess: &Session, _lib_name: &str, - _import_name_and_ordinal_vector: Vec<(String, Option<u16>)>, + _items: Vec<ImportLibraryItem>, _output_path: &Path, ) { unimplemented!("creating dll imports is not yet supported"); diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index a04cd4735f4..6b067b35e71 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -654,7 +654,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { unreachable!("clobber-only") } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", @@ -687,6 +688,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { ) => { unreachable!("clobber-only") } + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), InlineAsmRegClass::Err => unreachable!(), }, }; @@ -729,7 +732,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { unreachable!("clobber-only") } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), @@ -765,6 +769,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { unreachable!("clobber-only") } + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), @@ -944,6 +950,7 @@ fn modifier_to_gcc( }, InlineAsmRegClass::Avr(_) => None, InlineAsmRegClass::S390x(_) => None, + InlineAsmRegClass::Sparc(_) => None, InlineAsmRegClass::Msp430(_) => None, InlineAsmRegClass::M68k(_) => None, InlineAsmRegClass::CSKY(_) => None, diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 660badb6a50..07c7a54de1c 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -146,7 +146,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // Wasm statics with custom link sections get special treatment as they // go into custom sections of the wasm executable. - if self.tcx.sess.opts.target_triple.tuple().starts_with("wasm32") { + if self.tcx.sess.target.is_like_wasm { if let Some(_section) = attrs.link_section { unimplemented!(); } diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index dc1895f437b..7a586b5b04c 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -17,6 +17,19 @@ pub(crate) struct UnknownCTargetFeature<'a> { pub rust_feature: PossibleFeature<'a>, } +#[derive(Diagnostic)] +#[diag(codegen_gcc_unstable_ctarget_feature)] +#[note] +pub(crate) struct UnstableCTargetFeature<'a> { + pub feature: &'a str, +} + +#[derive(Diagnostic)] +#[diag(codegen_gcc_forbidden_ctarget_feature)] +pub(crate) struct ForbiddenCTargetFeature<'a> { + pub feature: &'a str, +} + #[derive(Subdiagnostic)] pub(crate) enum PossibleFeature<'a> { #[help(codegen_gcc_possible_feature)] diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 3104088e0d5..65279c9495a 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -5,10 +5,13 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_session::Session; -use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; +use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability}; use smallvec::{SmallVec, smallvec}; -use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix}; +use crate::errors::{ + ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix, + UnstableCTargetFeature, +}; /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, /// `--target` and similar). @@ -43,7 +46,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri ); // -Ctarget-features - let supported_features = sess.target.supported_target_features(); + let known_features = sess.target.rust_target_features(); let mut featsmap = FxHashMap::default(); let feats = sess .opts @@ -62,37 +65,49 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri } }; + // Get the backend feature name, if any. + // This excludes rustc-specific features, that do not get passed down to GCC. let feature = backend_feature_name(s)?; // Warn against use of GCC specific feature names on the CLI. - if diagnostics && !supported_features.iter().any(|&(v, _, _)| v == feature) { - let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| { - let gcc_features = to_gcc_features(sess, rust_feature); - if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) { - Some(rust_feature) - } else { - None + if diagnostics { + let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature); + match feature_state { + None => { + let rust_feature = + known_features.iter().find_map(|&(rust_feature, _, _)| { + let gcc_features = to_gcc_features(sess, rust_feature); + if gcc_features.contains(&feature) + && !gcc_features.contains(&rust_feature) + { + Some(rust_feature) + } else { + None + } + }); + let unknown_feature = if let Some(rust_feature) = rust_feature { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::Some { rust_feature }, + } + } else { + UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } + }; + sess.dcx().emit_warn(unknown_feature); } - }); - let unknown_feature = if let Some(rust_feature) = rust_feature { - UnknownCTargetFeature { - feature, - rust_feature: PossibleFeature::Some { rust_feature }, + Some((_, Stability::Stable, _)) => {} + Some((_, Stability::Unstable(_), _)) => { + // An unstable feature. Warn about using it. + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); } - } else { - UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } - }; - sess.dcx().emit_warn(unknown_feature); - } + Some((_, Stability::Forbidden { .. }, _)) => { + sess.dcx().emit_err(ForbiddenCTargetFeature { feature }); + } + } - if diagnostics { // FIXME(nagisa): figure out how to not allocate a full hashset here. featsmap.insert(feature, enable_disable == '+'); } - // rustc-specific features do not get passed down to GCC… - if RUSTC_SPECIFIC_FEATURES.contains(&feature) { - return None; - } // ... otherwise though we run through `to_gcc_features` when // passing requests down to GCC. This means that all in-language // features also work on the command line instead of having two diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 7486eefeb85..f70dc94b267 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -491,8 +491,9 @@ pub fn target_features( ) -> Vec<Symbol> { // TODO(antoyo): use global_gcc_features. sess.target - .supported_target_features() + .rust_target_features() .iter() + .filter(|(_, gate, _)| gate.is_supported()) .filter_map(|&(feature, gate, _)| { if sess.is_nightly_build() || allow_unstable || gate.is_stable() { Some(feature) diff --git a/compiler/rustc_codegen_gcc/tests/run/abort1.rs b/compiler/rustc_codegen_gcc/tests/run/abort1.rs index 44297e12779..696197d7377 100644 --- a/compiler/rustc_codegen_gcc/tests/run/abort1.rs +++ b/compiler/rustc_codegen_gcc/tests/run/abort1.rs @@ -33,9 +33,11 @@ pub(crate) unsafe auto trait Freeze {} mod intrinsics { use super::Sized; - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/abort2.rs b/compiler/rustc_codegen_gcc/tests/run/abort2.rs index ce816927123..714cd6c0f38 100644 --- a/compiler/rustc_codegen_gcc/tests/run/abort2.rs +++ b/compiler/rustc_codegen_gcc/tests/run/abort2.rs @@ -33,9 +33,11 @@ pub(crate) unsafe auto trait Freeze {} mod intrinsics { use super::Sized; - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/array.rs b/compiler/rustc_codegen_gcc/tests/run/array.rs index 432f11ad8d4..d8de9f28d4c 100644 --- a/compiler/rustc_codegen_gcc/tests/run/array.rs +++ b/compiler/rustc_codegen_gcc/tests/run/array.rs @@ -106,9 +106,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { } mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs index e105d64a8ad..2a47f0c2966 100644 --- a/compiler/rustc_codegen_gcc/tests/run/assign.rs +++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs @@ -56,9 +56,11 @@ mod libc { } mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/closure.rs b/compiler/rustc_codegen_gcc/tests/run/closure.rs index 00e61cc001f..b0d0ca4ee8d 100644 --- a/compiler/rustc_codegen_gcc/tests/run/closure.rs +++ b/compiler/rustc_codegen_gcc/tests/run/closure.rs @@ -98,9 +98,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { } mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/condition.rs b/compiler/rustc_codegen_gcc/tests/run/condition.rs index 7b05b7decd3..770b18a89e3 100644 --- a/compiler/rustc_codegen_gcc/tests/run/condition.rs +++ b/compiler/rustc_codegen_gcc/tests/run/condition.rs @@ -109,9 +109,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { } mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs index 4e96f376555..523544ee6bb 100644 --- a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs +++ b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs @@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { } mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs index 5a3f72b6904..3ae79338216 100644 --- a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs +++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs @@ -58,9 +58,11 @@ mod libc { } mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs index d697bd921cd..2e3c021d5f7 100644 --- a/compiler/rustc_codegen_gcc/tests/run/operations.rs +++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs @@ -64,9 +64,11 @@ mod libc { } mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs index a94279182d6..c7510d16449 100644 --- a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs +++ b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs @@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { } mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/slice.rs b/compiler/rustc_codegen_gcc/tests/run/slice.rs index e86fc823a1a..35ad594ecde 100644 --- a/compiler/rustc_codegen_gcc/tests/run/slice.rs +++ b/compiler/rustc_codegen_gcc/tests/run/slice.rs @@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { mod intrinsics { use super::Sized; - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs index 6247e08f5e3..a17ea2a4893 100644 --- a/compiler/rustc_codegen_gcc/tests/run/static.rs +++ b/compiler/rustc_codegen_gcc/tests/run/static.rs @@ -46,9 +46,11 @@ pub(crate) unsafe auto trait Freeze {} mod intrinsics { use super::Sized; - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} } } diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index 0950e4bb26b..63c64269eb8 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -7,6 +7,11 @@ codegen_llvm_dynamic_linking_with_lto = codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture +codegen_llvm_forbidden_ctarget_feature = + target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason} + .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +codegen_llvm_forbidden_ctarget_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344> + codegen_llvm_from_llvm_diag = {$message} codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message} diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 855ca010611..1d35138b013 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -2,6 +2,7 @@ use std::cmp; use libc::c_uint; use rustc_abi as abi; +pub(crate) use rustc_abi::ExternAbi; use rustc_abi::Primitive::Int; use rustc_abi::{HasDataLayout, Size}; use rustc_codegen_ssa::MemFlags; @@ -13,9 +14,8 @@ use rustc_middle::ty::layout::LayoutOf; pub(crate) use rustc_middle::ty::layout::{WIDE_PTR_ADDR, WIDE_PTR_EXTRA}; use rustc_middle::{bug, ty}; use rustc_session::config; -pub(crate) use rustc_target::abi::call::*; +pub(crate) use rustc_target::callconv::*; use rustc_target::spec::SanitizerSet; -pub(crate) use rustc_target::spec::abi::Abi; use smallvec::SmallVec; use crate::attributes::llfn_attrs_from_instance; @@ -436,7 +436,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { i - 1 }; - let apply_range_attr = |idx: AttributePlace, scalar: rustc_target::abi::Scalar| { + let apply_range_attr = |idx: AttributePlace, scalar: rustc_abi::Scalar| { if cx.sess().opts.optimize != config::OptLevel::No && llvm_util::get_version() >= (19, 0, 0) && matches!(scalar.primitive(), Int(..)) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 53758967552..bb74dfe1487 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -1,6 +1,7 @@ use std::assert_matches::assert_matches; use libc::{c_char, c_uint}; +use rustc_abi::{BackendRepr, Float, Integer, Primitive, Scalar}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::operand::OperandValue; use rustc_codegen_ssa::traits::*; @@ -9,7 +10,6 @@ use rustc_middle::ty::Instance; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, span_bug}; use rustc_span::{Pos, Span, Symbol, sym}; -use rustc_target::abi::*; use rustc_target::asm::*; use smallvec::SmallVec; use tracing::debug; @@ -268,6 +268,15 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { InlineAsmArch::S390x => { constraints.push("~{cc}".to_string()); } + InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => { + // In LLVM, ~{icc} represents icc and xcc in 64-bit code. + // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.td#L64 + constraints.push("~{icc}".to_string()); + constraints.push("~{fcc0}".to_string()); + constraints.push("~{fcc1}".to_string()); + constraints.push("~{fcc2}".to_string()); + constraints.push("~{fcc3}".to_string()); + } InlineAsmArch::SpirV => {} InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {} InlineAsmArch::Bpf => {} @@ -638,7 +647,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> PowerPC(PowerPCInlineAsmRegClass::reg) => "r", PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", PowerPC(PowerPCInlineAsmRegClass::freg) => "f", - PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { + PowerPC(PowerPCInlineAsmRegClass::cr) + | PowerPC(PowerPCInlineAsmRegClass::xer) + | PowerPC(PowerPCInlineAsmRegClass::vreg) => { unreachable!("clobber-only") } RiscV(RiscVInlineAsmRegClass::reg) => "r", @@ -670,6 +681,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { unreachable!("clobber-only") } + Sparc(SparcInlineAsmRegClass::reg) => "r", + Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), Msp430(Msp430InlineAsmRegClass::reg) => "r", M68k(M68kInlineAsmRegClass::reg) => "r", M68k(M68kInlineAsmRegClass::reg_addr) => "a", @@ -763,6 +776,7 @@ fn modifier_to_llvm( }, Avr(_) => None, S390x(_) => None, + Sparc(_) => None, Msp430(_) => None, SpirV(SpirVInlineAsmRegClass::reg) => bug!("LLVM backend does not support SPIR-V"), M68k(_) => None, @@ -800,7 +814,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), - PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { + PowerPC(PowerPCInlineAsmRegClass::cr) + | PowerPC(PowerPCInlineAsmRegClass::xer) + | PowerPC(PowerPCInlineAsmRegClass::vreg) => { unreachable!("clobber-only") } RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), @@ -831,6 +847,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { unreachable!("clobber-only") } + Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), + Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 64bb22e8cb2..cb958c1d4d7 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -419,7 +419,10 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( if bti { to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); } - if let Some(PacRet { leaf, key }) = pac_ret { + if let Some(PacRet { leaf, pc, key }) = pac_ret { + if pc { + to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr")); + } to_add.push(llvm::CreateAttrStringValue( cx.llcx, "sign-return-address", diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 647e9e13fbc..a65ae4df1e3 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -945,23 +945,10 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: asm } -fn target_is_apple(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool { - let triple = cgcx.opts.target_triple.tuple(); - triple.contains("-ios") - || triple.contains("-darwin") - || triple.contains("-tvos") - || triple.contains("-watchos") - || triple.contains("-visionos") -} - -fn target_is_aix(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool { - cgcx.opts.target_triple.tuple().contains("-aix") -} - pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static CStr { - if target_is_apple(cgcx) { + if cgcx.target_is_like_osx { c"__LLVM,__bitcode" - } else if target_is_aix(cgcx) { + } else if cgcx.target_is_like_aix { c".ipa" } else { c".llvmbc" @@ -1028,10 +1015,12 @@ unsafe fn embed_bitcode( // Unfortunately, LLVM provides no way to set custom section flags. For ELF // and COFF we emit the sections using module level inline assembly for that // reason (see issue #90326 for historical background). - let is_aix = target_is_aix(cgcx); - let is_apple = target_is_apple(cgcx); unsafe { - if is_apple || is_aix || cgcx.opts.target_triple.tuple().starts_with("wasm") { + if cgcx.target_is_like_osx + || cgcx.target_is_like_aix + || cgcx.target_arch == "wasm32" + || cgcx.target_arch == "wasm64" + { // We don't need custom section flags, create LLVM globals. let llconst = common::bytes_in_context(llcx, bitcode); let llglobal = llvm::LLVMAddGlobal( @@ -1052,9 +1041,9 @@ unsafe fn embed_bitcode( c"rustc.embedded.cmdline".as_ptr(), ); llvm::LLVMSetInitializer(llglobal, llconst); - let section = if is_apple { + let section = if cgcx.target_is_like_osx { c"__LLVM,__cmdline" - } else if is_aix { + } else if cgcx.target_is_like_aix { c".info" } else { c".llvmcmd" diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 15883c91053..751b2235dc8 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_sanitizers::{cfi, kcfi}; use rustc_session::config::OptLevel; use rustc_span::Span; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target}; use smallvec::SmallVec; use tracing::{debug, instrument}; diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 25037b97375..dcea9d3b391 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -44,6 +44,22 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t let llfn = if tcx.sess.target.arch == "x86" && let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym) { + // When calling functions in generated import libraries, MSVC needs + // the fully decorated name (as would have been in the declaring + // object file), but MinGW wants the name as exported (as would be + // in the def file) which may be missing decorations. + let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&tcx.sess.target); + let llfn = cx.declare_fn( + &common::i686_decorated_name( + dllimport, + mingw_gnu_toolchain, + true, + !mingw_gnu_toolchain, + ), + fn_abi, + Some(instance), + ); + // Fix for https://github.com/rust-lang/rust/issues/104453 // On x86 Windows, LLVM uses 'L' as the prefix for any private // global symbols, so when we create an undecorated function symbol @@ -55,15 +71,6 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t // LLVM will prefix the name with `__imp_`. Ideally, we'd like the // existing logic below to set the Storage Class, but it has an // exemption for MinGW for backwards compatibility. - let llfn = cx.declare_fn( - &common::i686_decorated_name( - dllimport, - common::is_mingw_gnu_toolchain(&tcx.sess.target), - true, - ), - fn_abi, - Some(instance), - ); unsafe { llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 21d996ef460..7ab4f45cd73 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -1,5 +1,8 @@ use std::ops::Range; +use rustc_abi::{ + Align, AlignFromBytesError, HasDataLayout, Primitive, Scalar, Size, WrappingRange, +}; use rustc_codegen_ssa::common; use rustc_codegen_ssa::traits::*; use rustc_hir::def::DefKind; @@ -14,9 +17,6 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_session::config::Lto; -use rustc_target::abi::{ - Align, AlignFromBytesError, HasDataLayout, Primitive, Scalar, Size, WrappingRange, -}; use tracing::{debug, instrument, trace}; use crate::common::{AsCCharPtr, CodegenCx}; @@ -194,16 +194,10 @@ fn check_and_apply_linkage<'ll, 'tcx>( unsafe { llvm::LLVMSetInitializer(g2, g1) }; g2 } else if cx.tcx.sess.target.arch == "x86" + && common::is_mingw_gnu_toolchain(&cx.tcx.sess.target) && let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym) { - cx.declare_global( - &common::i686_decorated_name( - dllimport, - common::is_mingw_gnu_toolchain(&cx.tcx.sess.target), - true, - ), - llty, - ) + cx.declare_global(&common::i686_decorated_name(dllimport, true, true, false), llty) } else { // Generate an external declaration. // FIXME(nagisa): investigate whether it can be changed into define_global diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 03f4fb527a8..ba863d9d74b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell}; use std::ffi::{CStr, c_uint}; use std::str; +use rustc_abi::{HasDataLayout, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::errors as ssa_errors; @@ -24,7 +25,6 @@ use rustc_session::config::{ }; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{HasDataLayout, TargetDataLayout, VariantIdx}; use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel}; use smallvec::SmallVec; @@ -154,6 +154,11 @@ pub(crate) unsafe fn create_module<'ll>( // See https://github.com/llvm/llvm-project/pull/106951 target_data_layout = target_data_layout.replace("-i128:128", ""); } + if sess.target.arch.starts_with("mips64") { + // LLVM 20 updates the mips64 layout to correctly align 128 bit integers to 128 bit. + // See https://github.com/llvm/llvm-project/pull/112084 + target_data_layout = target_data_layout.replace("-i128:128", ""); + } } // Ensure the data-layout values hardcoded remain the defaults. @@ -308,7 +313,13 @@ pub(crate) unsafe fn create_module<'ll>( "sign-return-address", pac_ret.is_some().into(), ); - let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); + let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, pc: false, key: PAuthKey::A }); + llvm::add_module_flag_u32( + llmod, + llvm::ModuleFlagMergeBehavior::Min, + "branch-protection-pauth-lr", + pac_opts.pc.into(), + ); llvm::add_module_flag_u32( llmod, llvm::ModuleFlagMergeBehavior::Min, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs new file mode 100644 index 00000000000..99c2d12b261 --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs @@ -0,0 +1,100 @@ +//! Safe wrappers for coverage-specific FFI functions. + +use std::ffi::CString; + +use crate::common::AsCCharPtr; +use crate::coverageinfo::ffi; +use crate::llvm; + +pub(crate) fn covmap_var_name() -> CString { + CString::new(llvm::build_byte_buffer(|s| unsafe { + llvm::LLVMRustCoverageWriteCovmapVarNameToString(s); + })) + .expect("covmap variable name should not contain NUL") +} + +pub(crate) fn covmap_section_name(llmod: &llvm::Module) -> CString { + CString::new(llvm::build_byte_buffer(|s| unsafe { + llvm::LLVMRustCoverageWriteCovmapSectionNameToString(llmod, s); + })) + .expect("covmap section name should not contain NUL") +} + +pub(crate) fn covfun_section_name(llmod: &llvm::Module) -> CString { + CString::new(llvm::build_byte_buffer(|s| unsafe { + llvm::LLVMRustCoverageWriteCovfunSectionNameToString(llmod, s); + })) + .expect("covfun section name should not contain NUL") +} + +pub(crate) fn create_pgo_func_name_var<'ll>( + llfn: &'ll llvm::Value, + mangled_fn_name: &str, +) -> &'ll llvm::Value { + unsafe { + llvm::LLVMRustCoverageCreatePGOFuncNameVar( + llfn, + mangled_fn_name.as_c_char_ptr(), + mangled_fn_name.len(), + ) + } +} + +pub(crate) fn write_filenames_to_buffer<'a>( + filenames: impl IntoIterator<Item = &'a str>, +) -> Vec<u8> { + let (pointers, lengths) = filenames + .into_iter() + .map(|s: &str| (s.as_c_char_ptr(), s.len())) + .unzip::<_, _, Vec<_>, Vec<_>>(); + + llvm::build_byte_buffer(|buffer| unsafe { + llvm::LLVMRustCoverageWriteFilenamesToBuffer( + pointers.as_ptr(), + pointers.len(), + lengths.as_ptr(), + lengths.len(), + buffer, + ); + }) +} + +pub(crate) fn write_function_mappings_to_buffer( + virtual_file_mapping: &[u32], + expressions: &[ffi::CounterExpression], + code_regions: &[ffi::CodeRegion], + branch_regions: &[ffi::BranchRegion], + mcdc_branch_regions: &[ffi::MCDCBranchRegion], + mcdc_decision_regions: &[ffi::MCDCDecisionRegion], +) -> Vec<u8> { + llvm::build_byte_buffer(|buffer| unsafe { + llvm::LLVMRustCoverageWriteFunctionMappingsToBuffer( + virtual_file_mapping.as_ptr(), + virtual_file_mapping.len(), + expressions.as_ptr(), + expressions.len(), + code_regions.as_ptr(), + code_regions.len(), + branch_regions.as_ptr(), + branch_regions.len(), + mcdc_branch_regions.as_ptr(), + mcdc_branch_regions.len(), + mcdc_decision_regions.as_ptr(), + mcdc_decision_regions.len(), + buffer, + ) + }) +} + +/// Hashes some bytes into a 64-bit hash, via LLVM's `IndexedInstrProf::ComputeHash`, +/// as required for parts of the LLVM coverage mapping format. +pub(crate) fn hash_bytes(bytes: &[u8]) -> u64 { + unsafe { llvm::LLVMRustCoverageHashBytes(bytes.as_c_char_ptr(), bytes.len()) } +} + +/// Returns LLVM's `coverage::CovMapVersion::CurrentVersion` (CoverageMapping.h) +/// as a raw numeric value. For historical reasons, the numeric value is 1 less +/// than the number in the version's name, so `Version7` is actually `6u32`. +pub(crate) fn mapping_version() -> u32 { + unsafe { llvm::LLVMRustCoverageMappingVersion() } +} diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index f6378199fe2..bb2f634cb25 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,4 +1,5 @@ use std::ffi::CString; +use std::iter; use itertools::Itertools as _; use rustc_abi::Align; @@ -17,9 +18,9 @@ use rustc_target::spec::HasTargetSpec; use tracing::debug; use crate::common::CodegenCx; -use crate::coverageinfo::ffi; use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector}; -use crate::{coverageinfo, llvm}; +use crate::coverageinfo::{ffi, llvm_cov}; +use crate::llvm; /// Generates and exports the coverage map, which is embedded in special /// linker sections in the final binary. @@ -33,7 +34,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // agrees with our Rust-side code. Expected versions (encoded as n-1) are: // - `CovMapVersion::Version7` (6) used by LLVM 18-19 let covmap_version = { - let llvm_covmap_version = coverageinfo::mapping_version(); + let llvm_covmap_version = llvm_cov::mapping_version(); let expected_versions = 6..=6; assert!( expected_versions.contains(&llvm_covmap_version), @@ -78,7 +79,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { let filenames_size = filenames_buffer.len(); let filenames_val = cx.const_bytes(&filenames_buffer); - let filenames_ref = coverageinfo::hash_bytes(&filenames_buffer); + let filenames_ref = llvm_cov::hash_bytes(&filenames_buffer); // Generate the coverage map header, which contains the filenames used by // this CGU's coverage mappings, and store it in a well-known global. @@ -187,13 +188,10 @@ impl GlobalFileTable { .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) .to_string_lossy(); - llvm::build_byte_buffer(|buffer| { - coverageinfo::write_filenames_section_to_buffer( - // Insert the working dir at index 0, before the other filenames. - std::iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str)), - buffer, - ); - }) + // Insert the working dir at index 0, before the other filenames. + let filenames = + iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str)); + llvm_cov::write_filenames_to_buffer(filenames) } } @@ -296,17 +294,14 @@ fn encode_mappings_for_function( } // Encode the function's coverage mappings into a buffer. - llvm::build_byte_buffer(|buffer| { - coverageinfo::write_mapping_to_buffer( - virtual_file_mapping.into_vec(), - expressions, - &code_regions, - &branch_regions, - &mcdc_branch_regions, - &mcdc_decision_regions, - buffer, - ); - }) + llvm_cov::write_function_mappings_to_buffer( + &virtual_file_mapping.into_vec(), + &expressions, + &code_regions, + &branch_regions, + &mcdc_branch_regions, + &mcdc_decision_regions, + ) } /// Generates the contents of the covmap record for this CGU, which mostly @@ -335,23 +330,11 @@ fn generate_covmap_record<'ll>( let covmap_data = cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false); - let covmap_var_name = CString::new(llvm::build_byte_buffer(|s| unsafe { - llvm::LLVMRustCoverageWriteMappingVarNameToString(s); - })) - .unwrap(); - debug!("covmap var name: {:?}", covmap_var_name); - - let covmap_section_name = CString::new(llvm::build_byte_buffer(|s| unsafe { - llvm::LLVMRustCoverageWriteMapSectionNameToString(cx.llmod, s); - })) - .expect("covmap section name should not contain NUL"); - debug!("covmap section name: {:?}", covmap_section_name); - - let llglobal = llvm::add_global(cx.llmod, cx.val_ty(covmap_data), &covmap_var_name); + let llglobal = llvm::add_global(cx.llmod, cx.val_ty(covmap_data), &llvm_cov::covmap_var_name()); llvm::set_initializer(llglobal, covmap_data); llvm::set_global_constant(llglobal, true); llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); - llvm::set_section(llglobal, &covmap_section_name); + llvm::set_section(llglobal, &llvm_cov::covmap_section_name(cx.llmod)); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. // <https://llvm.org/docs/CoverageMappingFormat.html> llvm::set_alignment(llglobal, Align::EIGHT); @@ -373,7 +356,7 @@ fn generate_covfun_record( let coverage_mapping_size = coverage_mapping_buffer.len(); let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer); - let func_name_hash = coverageinfo::hash_bytes(mangled_function_name.as_bytes()); + let func_name_hash = llvm_cov::hash_bytes(mangled_function_name.as_bytes()); let func_name_hash_val = cx.const_u64(func_name_hash); let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32); let source_hash_val = cx.const_u64(source_hash); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index e4ff50816b9..bf773cd2667 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -1,24 +1,23 @@ use std::cell::{OnceCell, RefCell}; use std::ffi::{CStr, CString}; -use libc::c_uint; +use rustc_abi::Size; use rustc_codegen_ssa::traits::{ BuilderMethods, ConstCodegenMethods, CoverageInfoBuilderMethods, MiscCodegenMethods, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_llvm::RustString; use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; use rustc_middle::ty::layout::HasTyCtxt; -use rustc_target::abi::Size; use tracing::{debug, instrument}; use crate::builder::Builder; -use crate::common::{AsCCharPtr, CodegenCx}; +use crate::common::CodegenCx; use crate::coverageinfo::map_data::FunctionCoverageCollector; use crate::llvm; pub(crate) mod ffi; +mod llvm_cov; pub(crate) mod map_data; mod mapgen; @@ -80,12 +79,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix) /// - `.lcovfun$M` on Windows (includes `$M` sorting suffix) fn covfun_section_name(&self) -> &CStr { - self.coverage_cx().covfun_section_name.get_or_init(|| { - CString::new(llvm::build_byte_buffer(|s| unsafe { - llvm::LLVMRustCoverageWriteFuncSectionNameToString(self.llmod, s); - })) - .expect("covfun section name should not contain NUL") - }) + self.coverage_cx() + .covfun_section_name + .get_or_init(|| llvm_cov::covfun_section_name(self.llmod)) } /// For LLVM codegen, returns a function-specific `Value` for a global @@ -95,9 +91,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value { debug!("getting pgo_func_name_var for instance={:?}", instance); let mut pgo_func_name_var_map = self.coverage_cx().pgo_func_name_var_map.borrow_mut(); - pgo_func_name_var_map - .entry(instance) - .or_insert_with(|| create_pgo_func_name_var(self, instance)) + pgo_func_name_var_map.entry(instance).or_insert_with(|| { + let llfn = self.get_fn(instance); + let mangled_fn_name: &str = self.tcx.symbol_name(instance).name; + llvm_cov::create_pgo_func_name_var(llfn, mangled_fn_name) + }) } } @@ -225,80 +223,3 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } } - -/// Calls llvm::createPGOFuncNameVar() with the given function instance's -/// mangled function name. The LLVM API returns an llvm::GlobalVariable -/// containing the function name, with the specific variable name and linkage -/// required by LLVM InstrProf source-based coverage instrumentation. Use -/// `bx.get_pgo_func_name_var()` to ensure the variable is only created once per -/// `Instance`. -fn create_pgo_func_name_var<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - instance: Instance<'tcx>, -) -> &'ll llvm::Value { - let mangled_fn_name: &str = cx.tcx.symbol_name(instance).name; - let llfn = cx.get_fn(instance); - unsafe { - llvm::LLVMRustCoverageCreatePGOFuncNameVar( - llfn, - mangled_fn_name.as_c_char_ptr(), - mangled_fn_name.len(), - ) - } -} - -pub(crate) fn write_filenames_section_to_buffer<'a>( - filenames: impl IntoIterator<Item = &'a str>, - buffer: &RustString, -) { - let (pointers, lengths) = filenames - .into_iter() - .map(|s: &str| (s.as_c_char_ptr(), s.len())) - .unzip::<_, _, Vec<_>, Vec<_>>(); - - unsafe { - llvm::LLVMRustCoverageWriteFilenamesSectionToBuffer( - pointers.as_ptr(), - pointers.len(), - lengths.as_ptr(), - lengths.len(), - buffer, - ); - } -} - -pub(crate) fn write_mapping_to_buffer( - virtual_file_mapping: Vec<u32>, - expressions: Vec<ffi::CounterExpression>, - code_regions: &[ffi::CodeRegion], - branch_regions: &[ffi::BranchRegion], - mcdc_branch_regions: &[ffi::MCDCBranchRegion], - mcdc_decision_regions: &[ffi::MCDCDecisionRegion], - buffer: &RustString, -) { - unsafe { - llvm::LLVMRustCoverageWriteMappingToBuffer( - virtual_file_mapping.as_ptr(), - virtual_file_mapping.len() as c_uint, - expressions.as_ptr(), - expressions.len() as c_uint, - code_regions.as_ptr(), - code_regions.len() as c_uint, - branch_regions.as_ptr(), - branch_regions.len() as c_uint, - mcdc_branch_regions.as_ptr(), - mcdc_branch_regions.len() as c_uint, - mcdc_decision_regions.as_ptr(), - mcdc_decision_regions.len() as c_uint, - buffer, - ); - } -} - -pub(crate) fn hash_bytes(bytes: &[u8]) -> u64 { - unsafe { llvm::LLVMRustCoverageHashByteArray(bytes.as_c_char_ptr(), bytes.len()) } -} - -pub(crate) fn mapping_version() -> u32 { - unsafe { llvm::LLVMRustCoverageMappingVersion() } -} diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 0d1fd0163eb..151923a3bd2 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -5,6 +5,7 @@ use std::path::{Path, PathBuf}; use std::{iter, ptr}; use libc::{c_char, c_longlong, c_uint}; +use rustc_abi::{Align, Size}; use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo}; use rustc_codegen_ssa::traits::*; use rustc_hir::def::{CtorKind, DefKind}; @@ -19,7 +20,6 @@ use rustc_session::config::{self, DebugInfo, Lto}; use rustc_span::symbol::Symbol; use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, hygiene}; use rustc_symbol_mangling::typeid_for_trait_ref; -use rustc_target::abi::{Align, Size}; use rustc_target::spec::DebuginfoKind; use smallvec::smallvec; use tracing::{debug, instrument}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 5385d3a9212..100b046cee2 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use libc::c_uint; +use rustc_abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; use rustc_codegen_ssa::traits::ConstCodegenMethods; @@ -8,7 +9,6 @@ use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty}; -use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants}; use smallvec::smallvec; use crate::common::{AsCCharPtr, CodegenCx}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 4c848027b55..b3d4a6642a1 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; +use rustc_abi::{FieldIdx, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::{compute_debuginfo_type_name, cpp_like_debuginfo}; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; use rustc_hir::def::CtorKind; @@ -9,7 +10,6 @@ use rustc_middle::mir::CoroutineLayout; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef}; use rustc_span::Symbol; -use rustc_target::abi::{FieldIdx, TagEncoding, VariantIdx, Variants}; use super::type_map::{DINodeCreationResult, UniqueTypeId}; use super::{SmallVec, size_and_align_of}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index b7400c5aeb2..d4006691d37 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -1,13 +1,13 @@ use std::borrow::Cow; use libc::c_uint; +use rustc_abi::{Size, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; use rustc_codegen_ssa::traits::ConstCodegenMethods; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self}; -use rustc_target::abi::{Size, TagEncoding, VariantIdx, Variants}; use smallvec::smallvec; use crate::common::{AsCCharPtr, CodegenCx}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index d050dc9b406..5120b63d173 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -1,12 +1,12 @@ use std::cell::RefCell; +use rustc_abi::{Align, Size, VariantIdx}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; use rustc_middle::bug; use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; -use rustc_target::abi::{Align, Size, VariantIdx}; use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; use crate::common::{AsCCharPtr, CodegenCx}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index b6c20cdcf0c..9e1e5127e80 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -5,6 +5,7 @@ use std::ops::Range; use std::{iter, ptr}; use libc::c_uint; +use rustc_abi::Size; use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; @@ -22,7 +23,6 @@ use rustc_span::symbol::Symbol; use rustc_span::{ BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span, StableSourceFileId, }; -use rustc_target::abi::Size; use smallvec::SmallVec; use tracing::debug; diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 0d436e1891e..3cdb5b971d9 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -31,6 +31,15 @@ pub(crate) struct UnstableCTargetFeature<'a> { pub feature: &'a str, } +#[derive(Diagnostic)] +#[diag(codegen_llvm_forbidden_ctarget_feature)] +#[note] +#[note(codegen_llvm_forbidden_ctarget_feature_issue)] +pub(crate) struct ForbiddenCTargetFeature<'a> { + pub feature: &'a str, + pub reason: &'a str, +} + #[derive(Subdiagnostic)] pub(crate) enum PossibleFeature<'a> { #[help(codegen_llvm_possible_feature)] diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c77e00aed9a..e9c687d75e3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1,6 +1,7 @@ use std::assert_matches::assert_matches; use std::cmp::Ordering; +use rustc_abi::{self as abi, Align, Float, HasDataLayout, Primitive, Size}; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization}; @@ -13,11 +14,10 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; -use rustc_target::abi::{self, Align, Float, HasDataLayout, Primitive, Size}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use tracing::debug; -use crate::abi::{Abi, FnAbi, FnAbiLlvmExt, LlvmType, PassMode}; +use crate::abi::{ExternAbi, FnAbi, FnAbiLlvmExt, LlvmType, PassMode}; use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm::{self, Metadata}; @@ -1094,7 +1094,7 @@ fn get_rust_try_fn<'ll, 'tcx>( tcx.types.unit, false, hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )), ); // `unsafe fn(*mut i8, *mut i8) -> ()` @@ -1105,7 +1105,7 @@ fn get_rust_try_fn<'ll, 'tcx>( tcx.types.unit, false, hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )), ); // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32` @@ -1114,7 +1114,7 @@ fn get_rust_try_fn<'ll, 'tcx>( tcx.types.i32, false, hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); cx.rust_try_fn.set(Some(rust_try)); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index b85d28a2f1f..49e616b5371 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -22,7 +22,6 @@ use std::any::Any; use std::ffi::CStr; -use std::io::Write; use std::mem::ManuallyDrop; use back::owned_target_machine::OwnedTargetMachine; @@ -165,30 +164,12 @@ impl WriteBackendMethods for LlvmCodegenBackend { type ThinData = back::lto::ThinData; type ThinBuffer = back::lto::ThinBuffer; fn print_pass_timings(&self) { - unsafe { - let mut size = 0; - let cstr = llvm::LLVMRustPrintPassTimings(&raw mut size); - if cstr.is_null() { - println!("failed to get pass timings"); - } else { - let timings = std::slice::from_raw_parts(cstr as *const u8, size); - std::io::stdout().write_all(timings).unwrap(); - libc::free(cstr as *mut _); - } - } + let timings = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintPassTimings(s) }).unwrap(); + print!("{timings}"); } fn print_statistics(&self) { - unsafe { - let mut size = 0; - let cstr = llvm::LLVMRustPrintStatistics(&raw mut size); - if cstr.is_null() { - println!("failed to get pass stats"); - } else { - let stats = std::slice::from_raw_parts(cstr as *const u8, size); - std::io::stdout().write_all(stats).unwrap(); - libc::free(cstr as *mut _); - } - } + let stats = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatistics(s) }).unwrap(); + print!("{stats}"); } fn run_link( cgcx: &CodegenContext<Self>, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 5fad7583e1a..8508f87c8d3 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1765,11 +1765,13 @@ unsafe extern "C" { /// Returns a string describing the last error caused by an LLVMRust* call. pub fn LLVMRustGetLastError() -> *const c_char; - /// Print the pass timings since static dtors aren't picking them up. - pub fn LLVMRustPrintPassTimings(size: *const size_t) -> *const c_char; + /// Prints the timing information collected by `-Ztime-llvm-passes`. + #[expect(improper_ctypes)] + pub(crate) fn LLVMRustPrintPassTimings(OutStr: &RustString); - /// Print the statistics since static dtors aren't picking them up. - pub fn LLVMRustPrintStatistics(size: *const size_t) -> *const c_char; + /// Prints the statistics collected by `-Zprint-codegen-stats`. + #[expect(improper_ctypes)] + pub(crate) fn LLVMRustPrintStatistics(OutStr: &RustString); /// Prepares inline assembly. pub fn LLVMRustInlineAsm( @@ -1790,7 +1792,7 @@ unsafe extern "C" { ) -> bool; #[allow(improper_ctypes)] - pub(crate) fn LLVMRustCoverageWriteFilenamesSectionToBuffer( + pub(crate) fn LLVMRustCoverageWriteFilenamesToBuffer( Filenames: *const *const c_char, FilenamesLen: size_t, Lengths: *const size_t, @@ -1799,19 +1801,19 @@ unsafe extern "C" { ); #[allow(improper_ctypes)] - pub(crate) fn LLVMRustCoverageWriteMappingToBuffer( + pub(crate) fn LLVMRustCoverageWriteFunctionMappingsToBuffer( VirtualFileMappingIDs: *const c_uint, - NumVirtualFileMappingIDs: c_uint, + NumVirtualFileMappingIDs: size_t, Expressions: *const crate::coverageinfo::ffi::CounterExpression, - NumExpressions: c_uint, + NumExpressions: size_t, CodeRegions: *const crate::coverageinfo::ffi::CodeRegion, - NumCodeRegions: c_uint, + NumCodeRegions: size_t, BranchRegions: *const crate::coverageinfo::ffi::BranchRegion, - NumBranchRegions: c_uint, + NumBranchRegions: size_t, MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion, - NumMCDCBranchRegions: c_uint, + NumMCDCBranchRegions: size_t, MCDCDecisionRegions: *const crate::coverageinfo::ffi::MCDCDecisionRegion, - NumMCDCDecisionRegions: c_uint, + NumMCDCDecisionRegions: size_t, BufferOut: &RustString, ); @@ -1820,16 +1822,16 @@ unsafe extern "C" { FuncName: *const c_char, FuncNameLen: size_t, ) -> &Value; - pub(crate) fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64; + pub(crate) fn LLVMRustCoverageHashBytes(Bytes: *const c_char, NumBytes: size_t) -> u64; #[allow(improper_ctypes)] - pub(crate) fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString); + pub(crate) fn LLVMRustCoverageWriteCovmapSectionNameToString(M: &Module, OutStr: &RustString); #[allow(improper_ctypes)] - pub(crate) fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString); + pub(crate) fn LLVMRustCoverageWriteCovfunSectionNameToString(M: &Module, OutStr: &RustString); #[allow(improper_ctypes)] - pub(crate) fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString); + pub(crate) fn LLVMRustCoverageWriteCovmapVarNameToString(OutStr: &RustString); pub(crate) fn LLVMRustCoverageMappingVersion() -> u32; pub fn LLVMRustDebugMetadataVersion() -> u32; @@ -2190,12 +2192,8 @@ unsafe extern "C" { pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; - pub fn LLVMRustPrintTargetCPUs( - T: &TargetMachine, - cpu: *const c_char, - print: unsafe extern "C" fn(out: *mut c_void, string: *const c_char, len: usize), - out: *mut c_void, - ); + #[allow(improper_ctypes)] + pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString); pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; pub fn LLVMRustGetTargetFeature( T: &TargetMachine, @@ -2204,7 +2202,7 @@ unsafe extern "C" { Desc: &mut *const c_char, ); - pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char; + pub fn LLVMRustGetHostCPUName(LenOut: &mut size_t) -> *const u8; // This function makes copies of pointed to data, so the data's lifetime may end after this // function returns. diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 00a5cd3b859..3b0bf47366e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -8,8 +8,8 @@ use std::str::FromStr; use std::string::FromUtf8Error; use libc::c_uint; +use rustc_abi::{Align, Size, WrappingRange}; use rustc_llvm::RustString; -use rustc_target::abi::{Align, Size, WrappingRange}; pub use self::AtomicRmwBinOp::*; pub use self::CallConv::*; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 9adb1299b3d..6f2d86cc601 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,4 +1,5 @@ -use std::ffi::{CStr, CString, c_char, c_void}; +use std::collections::VecDeque; +use std::ffi::{CStr, CString}; use std::fmt::Write; use std::path::Path; use std::sync::Once; @@ -16,12 +17,12 @@ use rustc_session::Session; use rustc_session::config::{PrintKind, PrintRequest}; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport}; -use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES}; +use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES, Stability}; use crate::back::write::create_informational_target_machine; use crate::errors::{ - FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, UnknownCTargetFeature, - UnknownCTargetFeaturePrefix, UnstableCTargetFeature, + FixedX18InvalidArch, ForbiddenCTargetFeature, InvalidTargetFeaturePrefix, PossibleFeature, + UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; @@ -276,23 +277,36 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea ("x86", s) if s.starts_with("avx512") => { Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512"))) } + // Support for `wide-arithmetic` will first land in LLVM 20 as part of + // llvm/llvm-project#111598 + ("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None, (_, s) => Some(LLVMFeature::new(s)), } } -/// Used to generate cfg variables and apply features -/// Must express features in the way Rust understands them +/// Used to generate cfg variables and apply features. +/// Must express features in the way Rust understands them. +/// +/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen. pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { - let mut features = vec![]; - - // Add base features for the target + let mut features: FxHashSet<Symbol> = Default::default(); + + // Add base features for the target. + // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below. + // The reason is that if LLVM considers a feature implied but we do not, we don't want that to + // show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of + // the target CPU, that is still expanded to target features (with all their implied features) by + // LLVM. let target_machine = create_informational_target_machine(sess, true); + // Compute which of the known target features are enabled in the 'base' target machine. + // We only consider "supported" features; "forbidden" features are not reflected in `cfg` as of now. features.extend( sess.target - .supported_target_features() + .rust_target_features() .iter() + .filter(|(_, gate, _)| gate.is_supported()) .filter(|(feature, _, _)| { - // skip checking special features, as LLVM may not understands them + // skip checking special features, as LLVM may not understand them if RUSTC_SPECIAL_FEATURES.contains(feature) { return true; } @@ -323,7 +337,12 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { if enabled { features.extend(sess.target.implied_target_features(std::iter::once(feature))); } else { + // We don't care about the order in `features` since the only thing we use it for is the + // `features.contains` below. + #[allow(rustc::potential_query_instability)] features.retain(|f| { + // Keep a feature if it does not imply `feature`. Or, equivalently, + // remove the reverse-dependencies of `feature`. !sess.target.implied_target_features(std::iter::once(*f)).contains(&feature) }); } @@ -331,8 +350,9 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { // Filter enabled features based on feature gates sess.target - .supported_target_features() + .rust_target_features() .iter() + .filter(|(_, gate, _)| gate.is_supported()) .filter_map(|&(feature, gate, _)| { if sess.is_nightly_build() || allow_unstable || gate.is_stable() { Some(feature) @@ -387,14 +407,76 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> { ret } -fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMachine) { +pub(crate) fn print(req: &PrintRequest, out: &mut String, sess: &Session) { + require_inited(); + let tm = create_informational_target_machine(sess, false); + match req.kind { + PrintKind::TargetCPUs => print_target_cpus(sess, &tm, out), + PrintKind::TargetFeatures => print_target_features(sess, &tm, out), + _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), + } +} + +fn print_target_cpus(sess: &Session, tm: &llvm::TargetMachine, out: &mut String) { + let cpu_names = llvm::build_string(|s| unsafe { + llvm::LLVMRustPrintTargetCPUs(&tm, s); + }) + .unwrap(); + + struct Cpu<'a> { + cpu_name: &'a str, + remark: String, + } + // Compare CPU against current target to label the default. + let target_cpu = handle_native(&sess.target.cpu); + let make_remark = |cpu_name| { + if cpu_name == target_cpu { + // FIXME(#132514): This prints the LLVM target string, which can be + // different from the Rust target string. Is that intended? + let target = &sess.target.llvm_target; + format!( + " - This is the default target CPU for the current build target (currently {target})." + ) + } else { + "".to_owned() + } + }; + let mut cpus = cpu_names + .lines() + .map(|cpu_name| Cpu { cpu_name, remark: make_remark(cpu_name) }) + .collect::<VecDeque<_>>(); + + // Only print the "native" entry when host and target are the same arch, + // since otherwise it could be wrong or misleading. + if sess.host.arch == sess.target.arch { + let host = get_host_cpu_name(); + cpus.push_front(Cpu { + cpu_name: "native", + remark: format!(" - Select the CPU of the current host (currently {host})."), + }); + } + + let max_name_width = cpus.iter().map(|cpu| cpu.cpu_name.len()).max().unwrap_or(0); + writeln!(out, "Available CPUs for this target:").unwrap(); + for Cpu { cpu_name, remark } in cpus { + // Only pad the CPU name if there's a remark to print after it. + let width = if remark.is_empty() { 0 } else { max_name_width }; + writeln!(out, " {cpu_name:<width$}{remark}").unwrap(); + } +} + +fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut String) { let mut llvm_target_features = llvm_target_features(tm); let mut known_llvm_target_features = FxHashSet::<&'static str>::default(); let mut rustc_target_features = sess .target - .supported_target_features() + .rust_target_features() .iter() - .filter_map(|(feature, _gate, _implied)| { + .filter_map(|(feature, gate, _implied)| { + if !gate.is_supported() { + // Only list (experimentally) supported features. + return None; + } // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these // strings. let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name; @@ -447,52 +529,31 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach writeln!(out, "and may be renamed or removed in a future version of LLVM or rustc.\n").unwrap(); } -pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) { - require_inited(); - let tm = create_informational_target_machine(sess, false); - match req.kind { - PrintKind::TargetCPUs => { - // SAFETY generate a C compatible string from a byte slice to pass - // the target CPU name into LLVM, the lifetime of the reference is - // at least as long as the C function - let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref())) - .unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e)); - unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) { - let out = unsafe { &mut *(out as *mut &mut String) }; - let bytes = unsafe { slice::from_raw_parts(string as *const u8, len) }; - write!(out, "{}", String::from_utf8_lossy(bytes)).unwrap(); - } - unsafe { - llvm::LLVMRustPrintTargetCPUs( - &tm, - cpu_cstring.as_ptr(), - callback, - (&raw mut out) as *mut c_void, - ); - } - } - PrintKind::TargetFeatures => print_target_features(out, sess, &tm), - _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), - } +/// Returns the host CPU name, according to LLVM. +fn get_host_cpu_name() -> &'static str { + let mut len = 0; + // SAFETY: The underlying C++ global function returns a `StringRef` that + // isn't tied to any particular backing buffer, so it must be 'static. + let slice: &'static [u8] = unsafe { + let ptr = llvm::LLVMRustGetHostCPUName(&mut len); + assert!(!ptr.is_null()); + slice::from_raw_parts(ptr, len) + }; + str::from_utf8(slice).expect("host CPU name should be UTF-8") } -fn handle_native(name: &str) -> &str { - if name != "native" { - return name; - } - - unsafe { - let mut len = 0; - let ptr = llvm::LLVMRustGetHostCPUName(&mut len); - str::from_utf8(slice::from_raw_parts(ptr as *const u8, len)).unwrap() +/// If the given string is `"native"`, returns the host CPU name according to +/// LLVM. Otherwise, the string is returned as-is. +fn handle_native(cpu_name: &str) -> &str { + match cpu_name { + "native" => get_host_cpu_name(), + _ => cpu_name, } } pub(crate) fn target_cpu(sess: &Session) -> &str { - match sess.opts.cg.target_cpu { - Some(ref name) => handle_native(name), - None => handle_native(sess.target.cpu.as_ref()), - } + let cpu_name = sess.opts.cg.target_cpu.as_deref().unwrap_or_else(|| &sess.target.cpu); + handle_native(cpu_name) } /// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, @@ -567,7 +628,7 @@ pub(crate) fn global_llvm_features( // -Ctarget-features if !only_base_features { - let supported_features = sess.target.supported_target_features(); + let known_features = sess.target.rust_target_features(); let mut featsmap = FxHashMap::default(); // insert implied features @@ -601,50 +662,53 @@ pub(crate) fn global_llvm_features( } }; + // Get the backend feature name, if any. + // This excludes rustc-specific features, which do not get passed to LLVM. let feature = backend_feature_name(sess, s)?; // Warn against use of LLVM specific feature names and unstable features on the CLI. if diagnostics { - let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature); - if feature_state.is_none() { - let rust_feature = - supported_features.iter().find_map(|&(rust_feature, _, _)| { - let llvm_features = to_llvm_features(sess, rust_feature)?; - if llvm_features.contains(feature) - && !llvm_features.contains(rust_feature) - { - Some(rust_feature) - } else { - None + let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature); + match feature_state { + None => { + let rust_feature = + known_features.iter().find_map(|&(rust_feature, _, _)| { + let llvm_features = to_llvm_features(sess, rust_feature)?; + if llvm_features.contains(feature) + && !llvm_features.contains(rust_feature) + { + Some(rust_feature) + } else { + None + } + }); + let unknown_feature = if let Some(rust_feature) = rust_feature { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::Some { rust_feature }, } - }); - let unknown_feature = if let Some(rust_feature) = rust_feature { - UnknownCTargetFeature { - feature, - rust_feature: PossibleFeature::Some { rust_feature }, - } - } else { - UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } - }; - sess.dcx().emit_warn(unknown_feature); - } else if feature_state - .is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable()) - { - // An unstable feature. Warn about using it. - sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } else { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::None, + } + }; + sess.dcx().emit_warn(unknown_feature); + } + Some((_, Stability::Stable, _)) => {} + Some((_, Stability::Unstable(_), _)) => { + // An unstable feature. Warn about using it. + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } + Some((_, Stability::Forbidden { reason }, _)) => { + sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); + } } - } - if diagnostics { // FIXME(nagisa): figure out how to not allocate a full hashset here. featsmap.insert(feature, enable_disable == '+'); } - // rustc-specific features do not get passed down to LLVM… - if RUSTC_SPECIFIC_FEATURES.contains(&feature) { - return None; - } - - // ... otherwise though we run through `to_llvm_features` when + // We run through `to_llvm_features` when // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index f1efc7a3dac..6aec078e0de 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -1,14 +1,14 @@ use std::{fmt, ptr}; use libc::{c_char, c_uint}; +use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::*; use rustc_data_structures::small_c_str::SmallCStr; use rustc_middle::bug; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; -use rustc_target::abi::{AddressSpace, Align, Integer, Size}; +use rustc_target::callconv::{CastTarget, FnAbi, Reg}; use crate::abi::{FnAbiLlvmExt, LlvmType}; use crate::context::CodegenCx; diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index f12b94d5887..e4c3e748cb5 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -1,9 +1,9 @@ +use rustc_abi::{Align, Endian, HasDataLayout, Size}; use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; -use rustc_target::abi::{Align, Endian, HasDataLayout, Size}; use crate::builder::Builder; use crate::type_::Type; diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index dffb7a7271e..b898cfec796 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -28,7 +28,6 @@ rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } -rustc_monomorphize = { path = "../rustc_monomorphize" } rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 3b34eb063ec..62db3d5a98c 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -2,6 +2,8 @@ codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not imp codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} +codegen_ssa_aix_strip_not_used = using host's `strip` binary to cross-compile to AIX which is not guaranteed to work + codegen_ssa_apple_deployment_target_invalid = failed to parse deployment target specified in {$env_var}: {$error} @@ -64,6 +66,9 @@ codegen_ssa_failed_to_write = failed to write {$path}: {$error} codegen_ssa_field_associated_value_expected = associated value expected for `{$name}` +codegen_ssa_forbidden_target_feature_attr = + target feature `{$feature}` cannot be toggled with `#[target_feature]`: {$reason} + codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 2f48c1fbf0d..e83bfa7b70d 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -26,6 +26,35 @@ use crate::errors::{ DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile, }; +/// An item to be included in an import library. +/// This is a slimmed down version of `COFFShortExport` from `ar-archive-writer`. +pub struct ImportLibraryItem { + /// The name to be exported. + pub name: String, + /// The ordinal to be exported, if any. + pub ordinal: Option<u16>, + /// The original, decorated name if `name` is not decorated. + pub symbol_name: Option<String>, + /// True if this is a data export, false if it is a function export. + pub is_data: bool, +} + +impl From<ImportLibraryItem> for COFFShortExport { + fn from(item: ImportLibraryItem) -> Self { + COFFShortExport { + name: item.name, + ext_name: None, + symbol_name: item.symbol_name, + alias_target: None, + ordinal: item.ordinal.unwrap_or(0), + noname: item.ordinal.is_some(), + data: item.is_data, + private: false, + constant: false, + } + } +} + pub trait ArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>; @@ -38,7 +67,7 @@ pub trait ArchiveBuilderBuilder { &self, sess: &Session, lib_name: &str, - import_name_and_ordinal_vector: Vec<(String, Option<u16>)>, + items: Vec<ImportLibraryItem>, output_path: &Path, ) { if common::is_mingw_gnu_toolchain(&sess.target) { @@ -47,21 +76,16 @@ pub trait ArchiveBuilderBuilder { // that loaded but crashed with an AV upon calling one of the imported // functions. Therefore, use binutils to create the import library instead, // by writing a .DEF file to the temp dir and calling binutils's dlltool. - create_mingw_dll_import_lib( - sess, - lib_name, - import_name_and_ordinal_vector, - output_path, - ); + create_mingw_dll_import_lib(sess, lib_name, items, output_path); } else { trace!("creating import library"); trace!(" dll_name {:#?}", lib_name); trace!(" output_path {}", output_path.display()); trace!( " import names: {}", - import_name_and_ordinal_vector + items .iter() - .map(|(name, _ordinal)| name.clone()) + .map(|ImportLibraryItem { name, .. }| name.clone()) .collect::<Vec<_>>() .join(", "), ); @@ -79,20 +103,7 @@ pub trait ArchiveBuilderBuilder { .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }), }; - let exports = import_name_and_ordinal_vector - .iter() - .map(|(name, ordinal)| COFFShortExport { - name: name.to_string(), - ext_name: None, - symbol_name: None, - alias_target: None, - ordinal: ordinal.unwrap_or(0), - noname: ordinal.is_some(), - data: false, - private: false, - constant: false, - }) - .collect::<Vec<_>>(); + let exports = items.into_iter().map(Into::into).collect::<Vec<_>>(); let machine = match &*sess.target.arch { "x86_64" => MachineTypes::AMD64, "x86" => MachineTypes::I386, @@ -160,16 +171,16 @@ pub trait ArchiveBuilderBuilder { fn create_mingw_dll_import_lib( sess: &Session, lib_name: &str, - import_name_and_ordinal_vector: Vec<(String, Option<u16>)>, + items: Vec<ImportLibraryItem>, output_path: &Path, ) { let def_file_path = output_path.with_extension("def"); let def_file_content = format!( "EXPORTS\n{}", - import_name_and_ordinal_vector + items .into_iter() - .map(|(name, ordinal)| { + .map(|ImportLibraryItem { name, ordinal, .. }| { match ordinal { Some(n) => format!("{name} @{n} NONAME"), None => name, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 20920d16f3c..8f754debaf0 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -45,7 +45,7 @@ use rustc_target::spec::{ use tempfile::Builder as TempFileBuilder; use tracing::{debug, info, warn}; -use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; +use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; @@ -85,11 +85,7 @@ pub fn link_binary( } if invalid_output_for_target(sess, crate_type) { - bug!( - "invalid output type `{:?}` for target os `{}`", - crate_type, - sess.opts.target_triple - ); + bug!("invalid output type `{:?}` for target `{}`", crate_type, sess.opts.target_triple); } sess.time("link_binary_check_files_are_writeable", || { @@ -499,16 +495,35 @@ fn create_dll_import_libs<'a>( let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target); - let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports + let items: Vec<ImportLibraryItem> = raw_dylib_imports .iter() .map(|import: &DllImport| { if sess.target.arch == "x86" { - ( - common::i686_decorated_name(import, mingw_gnu_toolchain, false), - import.ordinal(), - ) + ImportLibraryItem { + name: common::i686_decorated_name( + import, + mingw_gnu_toolchain, + false, + false, + ), + ordinal: import.ordinal(), + symbol_name: import.is_missing_decorations().then(|| { + common::i686_decorated_name( + import, + mingw_gnu_toolchain, + false, + true, + ) + }), + is_data: !import.is_fn, + } } else { - (import.name.to_string(), import.ordinal()) + ImportLibraryItem { + name: import.name.to_string(), + ordinal: import.ordinal(), + symbol_name: None, + is_data: !import.is_fn, + } } }) .collect(); @@ -516,7 +531,7 @@ fn create_dll_import_libs<'a>( archive_builder_builder.create_dll_import_lib( sess, &raw_dylib_name, - import_name_and_ordinal_vector, + items, &output_path, ); @@ -996,6 +1011,7 @@ fn link_natively( && (code < 1000 || code > 9999) { let is_vs_installed = windows_registry::find_vs_version().is_ok(); + // FIXME(cc-rs#1265) pass only target arch to find_tool() let has_linker = windows_registry::find_tool( sess.opts.target_triple.tuple(), "link.exe", @@ -1088,9 +1104,7 @@ fn link_natively( let strip = sess.opts.cg.strip; if sess.target.is_like_osx { - // Use system `strip` when running on host macOS. - // <https://github.com/rust-lang/rust/pull/130781> - let stripcmd = if cfg!(target_os = "macos") { "/usr/bin/strip" } else { "strip" }; + let stripcmd = "rust-objcopy"; match (strip, crate_type) { (Strip::Debuginfo, _) => { strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-S")) @@ -1106,11 +1120,14 @@ fn link_natively( } } - if sess.target.os == "illumos" { + if sess.target.is_like_solaris { // Many illumos systems will have both the native 'strip' utility and // the GNU one. Use the native version explicitly and do not rely on // what's in the path. - let stripcmd = "/usr/bin/strip"; + // + // If cross-compiling and there is not a native version, then use + // `llvm-strip` and hope. + let stripcmd = if !sess.host.is_like_solaris { "rust-objcopy" } else { "/usr/bin/strip" }; match strip { // Always preserve the symbol table (-x). Strip::Debuginfo => { @@ -1123,6 +1140,10 @@ fn link_natively( } if sess.target.is_like_aix { + // `llvm-strip` doesn't work for AIX - their strip must be used. + if !sess.host.is_like_aix { + sess.dcx().emit_warn(errors::AixStripNotUsed); + } let stripcmd = "/usr/bin/strip"; match strip { Strip::Debuginfo => { @@ -1150,6 +1171,13 @@ fn strip_symbols_with_external_utility( if let Some(option) = option { cmd.arg(option); } + + let mut new_path = sess.get_tools_search_paths(false); + if let Some(path) = env::var_os("PATH") { + new_path.extend(env::split_paths(&path)); + } + cmd.env("PATH", env::join_paths(new_path).unwrap()); + let prog = cmd.arg(out_filename).output(); match prog { Ok(prog) => { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3b4429535d4..4f3664a503d 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -47,6 +47,7 @@ pub(crate) fn get_linker<'a>( self_contained: bool, target_cpu: &'a str, ) -> Box<dyn Linker + 'a> { + // FIXME(cc-rs#1265) pass only target arch to find_tool() let msvc_tool = windows_registry::find_tool(sess.opts.target_triple.tuple(), "link.exe"); // If our linker looks like a batch script on Windows then to execute this diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index a7d95d56784..3f3cb8b4073 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -11,6 +11,7 @@ use object::{ SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, elf, pe, xcoff, }; +use rustc_abi::Endian; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owned_slice::{OwnedSlice, try_slice_owned}; use rustc_metadata::EncodedMetadata; @@ -19,7 +20,6 @@ use rustc_metadata::fs::METADATA_FILENAME; use rustc_middle::bug; use rustc_session::Session; use rustc_span::sym; -use rustc_target::abi::Endian; use rustc_target::spec::{RelocModel, Target, ef_avr_arch}; use super::apple; @@ -211,7 +211,15 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static "powerpc64" => (Architecture::PowerPc64, None), "riscv32" => (Architecture::Riscv32, None), "riscv64" => (Architecture::Riscv64, None), - "sparc" => (Architecture::Sparc32Plus, None), + "sparc" => { + if sess.target.options.cpu == "v9" { + // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode + (Architecture::Sparc32Plus, None) + } else { + // Target uses V7 or V8, aka EM_SPARC + (Architecture::Sparc, None) + } + } "sparc64" => (Architecture::Sparc64, None), "avr" => (Architecture::Avr, None), "msp430" => (Architecture::Msp430, None), diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d9669453f5a..850d36872dd 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -548,7 +548,7 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( symbol: ExportedSymbol<'tcx>, instantiating_crate: CrateNum, ) -> String { - use rustc_target::abi::call::Conv; + use rustc_target::callconv::Conv; let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index d977cca247e..a2285bf9204 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -345,6 +345,8 @@ pub struct CodegenContext<B: WriteBackendMethods> { pub is_pe_coff: bool, pub target_can_use_split_dwarf: bool, pub target_arch: String, + pub target_is_like_osx: bool, + pub target_is_like_aix: bool, pub split_debuginfo: rustc_target::spec::SplitDebuginfo, pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, @@ -1195,6 +1197,8 @@ fn start_executing_work<B: ExtraBackendMethods>( is_pe_coff: tcx.sess.target.is_like_windows, target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(), target_arch: tcx.sess.target.arch.to_string(), + target_is_like_osx: tcx.sess.target.is_like_osx, + target_is_like_aix: tcx.sess.target.is_like_aix, split_debuginfo: tcx.sess.split_debuginfo(), split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index cb4c9c078b1..ef95ab94062 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -3,6 +3,7 @@ use std::collections::BTreeSet; use std::time::{Duration, Instant}; use itertools::Itertools; +use rustc_abi::FIRST_VARIANT; use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; @@ -26,7 +27,6 @@ use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Symbol}; -use rustc_target::abi::FIRST_VARIANT; use rustc_trait_selection::infer::at::ToTrace; use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index a5bd3adbcdd..32e9422e005 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -20,8 +20,8 @@ use rustc_span::symbol::Ident; use rustc_span::{Span, sym}; use rustc_target::spec::{SanitizerSet, abi}; -use crate::errors::{self, MissingFeatures, TargetFeatureDisableOrEnable}; -use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature}; +use crate::errors; +use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature_attr}; fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage { use rustc_middle::mir::mono::Linkage::*; @@ -73,7 +73,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS; } - let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); + let rust_target_features = tcx.rust_target_features(LOCAL_CRATE); let mut inline_span = None; let mut link_ordinal_span = None; @@ -281,10 +281,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { check_target_feature_trait_unsafe(tcx, did, attr.span); } } - from_target_feature( + from_target_feature_attr( tcx, attr, - supported_target_features, + rust_target_features, &mut codegen_fn_attrs.target_features, ); } @@ -676,10 +676,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { .next() .map_or_else(|| tcx.def_span(did), |a| a.span); tcx.dcx() - .create_err(TargetFeatureDisableOrEnable { + .create_err(errors::TargetFeatureDisableOrEnable { features, span: Some(span), - missing_features: Some(MissingFeatures), + missing_features: Some(errors::MissingFeatures), }) .emit(); } @@ -710,7 +710,7 @@ pub fn check_tied_features( /// applied to the method prototype. fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { if let Some(impl_item) = tcx.opt_associated_item(def_id) - && let ty::AssocItemContainer::ImplContainer = impl_item.container + && let ty::AssocItemContainer::Impl = impl_item.container && let Some(trait_item) = impl_item.trait_item_def_id { return tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER); diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 582a2a87e48..965bd34ac14 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -187,12 +187,15 @@ pub fn i686_decorated_name( dll_import: &DllImport, mingw: bool, disable_name_mangling: bool, + force_fully_decorated: bool, ) -> String { let name = dll_import.name.as_str(); - let (add_prefix, add_suffix) = match dll_import.import_name_type { - Some(PeImportNameType::NoPrefix) => (false, true), - Some(PeImportNameType::Undecorated) => (false, false), + let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) { + // No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will + // ignore `force_fully_decorated` and always partially decorate it. + (_, Some(PeImportNameType::NoPrefix)) => (false, true), + (false, Some(PeImportNameType::Undecorated)) => (false, false), _ => (true, true), }; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs index bfd1b94c790..88d36b19da4 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs @@ -1,7 +1,7 @@ +use rustc_abi::{Integer, Primitive, Size, TagEncoding, Variants}; use rustc_middle::bug; use rustc_middle::ty::layout::{IntegerExt, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_target::abi::{Integer, Primitive, Size, TagEncoding, Variants}; // FIXME(eddyb) find a place for this (or a way to replace it). pub mod type_names; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 1e5b4f3433d..27bc58516c0 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -13,6 +13,7 @@ use std::fmt::Write; +use rustc_abi::Integer; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_hir::def_id::DefId; @@ -23,7 +24,6 @@ use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{ self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt, }; -use rustc_target::abi::Integer; use smallvec::SmallVec; use crate::debuginfo::wants_c_like_enum_debuginfo; @@ -364,7 +364,7 @@ fn push_debuginfo_type_name<'tcx>( } else { output.push_str(sig.safety.prefix_str()); - if sig.abi != rustc_target::spec::abi::Abi::Rust { + if sig.abi != rustc_abi::ExternAbi::Rust { output.push_str("extern \""); output.push_str(sig.abi.name()); output.push_str("\" "); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index cf8d1cfa0d1..f93cb52ea3e 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1028,6 +1028,15 @@ pub(crate) struct TargetFeatureSafeTrait { } #[derive(Diagnostic)] +#[diag(codegen_ssa_forbidden_target_feature_attr)] +pub struct ForbiddenTargetFeatureAttr<'a> { + #[primary_span] + pub span: Span, + pub feature: &'a str, + pub reason: &'a str, +} + +#[derive(Diagnostic)] #[diag(codegen_ssa_failed_to_get_layout)] pub struct FailedToGetLayout<'tcx> { #[primary_span] @@ -1101,3 +1110,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_ diag } } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_aix_strip_not_used)] +pub(crate) struct AixStripNotUsed; diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 7eb0ecd12ff..64cd4c38937 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -2,7 +2,7 @@ use rustc_middle::bug; use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_session::config::Lto; use rustc_symbol_mangling::typeid_for_trait_ref; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use tracing::{debug, instrument}; use crate::traits::*; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 283740fa664..027d80350e4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1,5 +1,6 @@ use std::cmp; +use rustc_abi::{self as abi, ExternAbi, HasDataLayout, WrappingRange}; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; @@ -13,9 +14,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::source_map::Spanned; use rustc_span::{Span, sym}; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; -use rustc_target::abi::{self, HasDataLayout, WrappingRange}; -use rustc_target::spec::abi::Abi; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode, Reg}; use tracing::{debug, info}; use super::operand::OperandRef; @@ -977,7 +976,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }); // Split the rust-call tupled arguments off. - let (first_args, untuple) = if abi == Abi::RustCall && !args.is_empty() { + let (first_args, untuple) = if abi == ExternAbi::RustCall && !args.is_empty() { let (tup, args) = args.split_last().unwrap(); (args, Some(tup)) } else { diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 32cc78187b9..c9e38bb80c2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,9 +1,9 @@ +use rustc_abi::WrappingRange; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::{Span, sym}; -use rustc_target::abi::WrappingRange; -use rustc_target::abi::call::{FnAbi, PassMode}; +use rustc_target::callconv::{FnAbi, PassMode}; use super::FunctionCx; use super::operand::OperandRef; diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 8bd172a9ce6..20fd08923ec 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::{UnwindTerminateReason, traversal}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::{bug, mir, span_bug}; -use rustc_target::abi::call::{FnAbi, PassMode}; +use rustc_target::callconv::{FnAbi, PassMode}; use tracing::{debug, instrument}; use crate::base; diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 15c8e534461..b8fa8c0351b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -1,10 +1,9 @@ use rustc_abi::Primitive::{Int, Pointer}; -use rustc_abi::{Align, FieldsShape, Size, TagEncoding, Variants}; +use rustc_abi::{Align, FieldsShape, Size, TagEncoding, VariantIdx, Variants}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir}; -use rustc_target::abi::VariantIdx; use tracing::{debug, instrument}; use super::operand::OperandValue; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 86cf0f9614d..0e1cd662f91 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1,13 +1,13 @@ use std::assert_matches::assert_matches; use arrayvec::ArrayVec; +use rustc_abi::{self as abi, FIRST_VARIANT, FieldIdx}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug}; use rustc_session::config::OptLevel; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{self, FIRST_VARIANT, FieldIdx}; use tracing::{debug, instrument}; use super::operand::{OperandRef, OperandValue}; diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 6338d16c897..1681ea1de5f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -78,7 +78,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let count = self.codegen_operand(bx, count).immediate(); let pointee_layout = dst_val .layout - .pointee_info_at(bx, rustc_target::abi::Size::ZERO) + .pointee_info_at(bx, rustc_abi::Size::ZERO) .expect("Expected pointer"); let bytes = bx.mul(count, bx.const_usize(pointee_layout.size.bytes())); diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index 827b939217e..71a2f916db5 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -1,10 +1,10 @@ //! Computing the size and alignment of a value. +use rustc_abi::WrappingRange; use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::WrappingRange; use tracing::{debug, trace}; use crate::common::IntPredicate; diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 0845bcc5749..eee7cc75400 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -11,13 +11,16 @@ use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; +use rustc_target::target_features::{self, Stability}; use crate::errors; -pub(crate) fn from_target_feature( +/// Compute the enabled target features from the `#[target_feature]` function attribute. +/// Enabled target features are added to `target_features`. +pub(crate) fn from_target_feature_attr( tcx: TyCtxt<'_>, attr: &ast::Attribute, - supported_target_features: &UnordMap<String, Option<Symbol>>, + rust_target_features: &UnordMap<String, target_features::Stability>, target_features: &mut Vec<TargetFeature>, ) { let Some(list) = attr.meta_item_list() else { return }; @@ -46,12 +49,12 @@ pub(crate) fn from_target_feature( // We allow comma separation to enable multiple features. added_target_features.extend(value.as_str().split(',').filter_map(|feature| { - let Some(feature_gate) = supported_target_features.get(feature) else { + let Some(stability) = rust_target_features.get(feature) else { let msg = format!("the feature named `{feature}` is not valid for this target"); let mut err = tcx.dcx().struct_span_err(item.span(), msg); err.span_label(item.span(), format!("`{feature}` is not valid for this target")); if let Some(stripped) = feature.strip_prefix('+') { - let valid = supported_target_features.contains_key(stripped); + let valid = rust_target_features.contains_key(stripped); if valid { err.help("consider removing the leading `+` in the feature name"); } @@ -61,18 +64,31 @@ pub(crate) fn from_target_feature( }; // Only allow target features whose feature gates have been enabled. - let allowed = match feature_gate.as_ref().copied() { - Some(name) => rust_features.enabled(name), - None => true, + let allowed = match stability { + Stability::Forbidden { .. } => false, + Stability::Stable => true, + Stability::Unstable(name) => rust_features.enabled(*name), }; if !allowed { - feature_err( - &tcx.sess, - feature_gate.unwrap(), - item.span(), - format!("the target feature `{feature}` is currently unstable"), - ) - .emit(); + match stability { + Stability::Stable => unreachable!(), + &Stability::Unstable(lang_feature_name) => { + feature_err( + &tcx.sess, + lang_feature_name, + item.span(), + format!("the target feature `{feature}` is currently unstable"), + ) + .emit(); + } + Stability::Forbidden { reason } => { + tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { + span: item.span(), + feature, + reason, + }); + } + } } Some(Symbol::intern(feature)) })); @@ -138,20 +154,20 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { - supported_target_features: |tcx, cnum| { + rust_target_features: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all - rustc_target::target_features::all_known_features() - .map(|(a, b)| (a.to_string(), b.as_feature_name())) + rustc_target::target_features::all_rust_features() + .map(|(a, b)| (a.to_string(), b)) .collect() } else { tcx.sess .target - .supported_target_features() + .rust_target_features() .iter() - .map(|&(a, b, _)| (a.to_string(), b.as_feature_name())) + .map(|&(a, b, _)| (a.to_string(), b)) .collect() } }, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 768a0439ab5..74cd522a30f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::{Instance, Ty}; use rustc_session::config::OptLevel; use rustc_span::Span; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use super::abi::AbiBuilderMethods; use super::asm::AsmBuilderMethods; diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index c26d4532d0f..670433a6c33 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -1,10 +1,10 @@ use std::ops::Range; +use rustc_abi::Size; use rustc_middle::mir; use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; use rustc_span::{SourceFile, Span, Symbol}; -use rustc_target::abi::Size; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use super::BackendTypes; use crate::mir::debuginfo::{FunctionDebugContext, VariableKind}; diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index 5b9274b4824..88cf8dbf0c5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -1,6 +1,6 @@ use rustc_middle::ty::{self, Ty}; use rustc_span::Span; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use super::BackendTypes; use crate::mir::operand::OperandRef; diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index 800470286bc..90fcfbe4da7 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -29,7 +29,7 @@ use std::fmt; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; pub use self::abi::AbiBuilderMethods; pub use self::asm::{ diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs index c10733fb0ed..ece0ea1b2ea 100644 --- a/compiler/rustc_codegen_ssa/src/traits/statics.rs +++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs @@ -1,5 +1,5 @@ +use rustc_abi::Align; use rustc_hir::def_id::DefId; -use rustc_target::abi::Align; use super::BackendTypes; diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index f862434c8ef..44ba2262149 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -1,8 +1,8 @@ +use rustc_abi::{AddressSpace, Float, Integer}; use rustc_middle::bug; use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg}; -use rustc_target::abi::{AddressSpace, Float, Integer}; +use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi, Reg}; use super::BackendTypes; use super::misc::MiscCodegenMethods; diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 2bc5adb2dce..826e34930ea 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -399,7 +399,7 @@ const_eval_uninhabited_enum_variant_written = const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable .help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable - .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval) + .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) const_eval_unreachable = entering unreachable code const_eval_unreachable_unwind = diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 303c490d827..aea3d5bd3e7 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -20,7 +20,6 @@ use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_span::{Span, Symbol, sym}; -use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{ Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt, }; @@ -419,13 +418,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { let errors = ocx.select_all_or_error(); if !errors.is_empty() { - // FIXME(effects): Soon this should be unconditionally delaying a bug. - if matches!(call_source, CallSource::Normal) && tcx.features().effects() { - tcx.dcx() - .span_delayed_bug(call_span, "this should have reported a ~const error in HIR"); - } else { - infcx.err_ctxt().report_fulfillment_errors(errors); - } + tcx.dcx() + .span_delayed_bug(call_span, "this should have reported a ~const error in HIR"); } } } @@ -663,8 +657,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // typeck ensures the conditions for calling a const trait method are met, // so we only error if the trait isn't const. We try to resolve the trait // into the concrete method, and uses that for const stability checks. - // FIXME(effects) we might consider moving const stability checks to typeck as well. - if tcx.features().effects() && trait_is_const { + // FIXME(const_trait_impl) we might consider moving const stability checks + // to typeck as well. + if tcx.features().const_trait_impl() && trait_is_const { // This skips the check below that ensures we only call `const fn`. is_trait = true; @@ -741,16 +736,25 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Intrinsics are language primitives, not regular calls, so treat them separately. if let Some(intrinsic) = tcx.intrinsic(callee) { + // We use `intrinsic.const_stable` to determine if this can be safely exposed to + // stable code, rather than `const_stable_indirect`. This is to make + // `#[rustc_const_stable_indirect]` an attribute that is always safe to add. + // We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic + // fallback body is safe to expose on stable. + let is_const_stable = intrinsic.const_stable + || (!intrinsic.must_be_overridden + && tcx.is_const_fn(callee) + && is_safe_to_expose_on_stable_const_fn(tcx, callee)); match tcx.lookup_const_stability(callee) { None => { // Non-const intrinsic. self.check_op(ops::IntrinsicNonConst { name: intrinsic.name }); } - Some(ConstStability { feature: None, const_stable_indirect, .. }) => { + Some(ConstStability { feature: None, .. }) => { // Intrinsic does not need a separate feature gate (we rely on the // regular stability checker). However, we have to worry about recursive // const stability. - if !const_stable_indirect && self.enforce_recursive_const_stability() { + if !is_const_stable && self.enforce_recursive_const_stability() { self.dcx().emit_err(errors::UnmarkedIntrinsicExposed { span: self.span, def_path: self.tcx.def_path_str(callee), @@ -760,17 +764,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Some(ConstStability { feature: Some(feature), level: StabilityLevel::Unstable { .. }, - const_stable_indirect, .. }) => { self.check_op(ops::IntrinsicUnstable { name: intrinsic.name, feature, - const_stable_indirect, + const_stable: is_const_stable, }); } Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { - // All good. + // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it + // can be *directly* invoked from stable const code) does not always + // have the `#[rustc_const_stable_intrinsic]` attribute (which controls + // exposing an intrinsic indirectly); we accept this call anyway. } } // This completes the checks for intrinsics. diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index ce36701a942..2931159842f 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -120,7 +120,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { let implsrc = selcx.select(&obligation); if let Ok(Some(ImplSource::UserDefined(data))) = implsrc { - // FIXME(effects) revisit this + // FIXME(const_trait_impl) revisit this if !tcx.is_const_trait_impl(data.impl_def_id) { let span = tcx.def_span(data.impl_def_id); err.subdiagnostic(errors::NonConstImplNote { span }); @@ -354,14 +354,14 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicNonConst { pub(crate) struct IntrinsicUnstable { pub name: Symbol, pub feature: Symbol, - pub const_stable_indirect: bool, + pub const_stable: bool, } impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable { fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { Status::Unstable { gate: self.feature, - safe_to_expose_on_stable: self.const_stable_indirect, + safe_to_expose_on_stable: self.const_stable, // We do *not* want to suggest to mark the intrinsic as `const_stable_indirect`, // that's not a trivial change! is_function_call: false, diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index e8637ba45cf..29a08579175 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -192,7 +192,7 @@ impl Qualif for NeedsNonConstDrop { return false; } - // FIXME(effects): Reimplement const drop checking. + // FIXME(const_trait_impl): Reimplement const drop checking. NeedsDrop::in_any_value_of_ty(cx, ty) } diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index bc2661c4fc7..e49d702127d 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -86,7 +86,7 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine { fn find_mir_or_eval_fn( _ecx: &mut InterpCx<'tcx, Self>, _instance: ty::Instance<'tcx>, - _abi: rustc_target::spec::abi::Abi, + _abi: rustc_abi::ExternAbi, _args: &[interpret::FnArg<'tcx, Self::Provenance>], _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>, _target: Option<BasicBlock>, diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 037fdcbcf9b..beff0cd99fc 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -25,15 +25,9 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { hir::Constness::Const } hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness, - hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => { - // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other - // foreign items cannot be evaluated at compile-time. - let is_const = if tcx.intrinsic(def_id).is_some() { - tcx.lookup_const_stability(def_id).is_some() - } else { - false - }; - if is_const { hir::Constness::Const } else { hir::Constness::NotConst } + hir::Node::ForeignItem(_) => { + // Foreign items cannot be evaluated at compile-time. + hir::Constness::NotConst } hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness, _ => { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 5938e836a8b..62115aef4a7 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -2,6 +2,7 @@ use std::borrow::{Borrow, Cow}; use std::fmt; use std::hash::Hash; +use rustc_abi::{Align, ExternAbi, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -13,8 +14,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; -use rustc_target::abi::{Align, Size}; -use rustc_target::spec::abi::Abi as CallAbi; use tracing::debug; use super::error::*; @@ -335,7 +334,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { fn find_mir_or_eval_fn( ecx: &mut InterpCx<'tcx, Self>, orig_instance: ty::Instance<'tcx>, - _abi: CallAbi, + _abi: ExternAbi, args: &[FnArg<'tcx>], dest: &MPlaceTy<'tcx>, ret: Option<mir::BasicBlock>, @@ -355,7 +354,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { // sensitive check here. But we can at least rule out functions that are not const at // all. That said, we have to allow calling functions inside a trait marked with // #[const_trait]. These *are* const-checked! - // FIXME(effects): why does `is_const_fn` not classify them as const? + // FIXME(const_trait_impl): why does `is_const_fn` not classify them as const? if (!ecx.tcx.is_const_fn(def) && !ecx.tcx.is_const_default_method(def)) || ecx.tcx.has_attr(def, sym::rustc_do_not_const_check) { diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index e2e4754a45c..d5012236c34 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -1,9 +1,9 @@ // Not in interpret to make sure we do not use private implementation details +use rustc_abi::VariantIdx; use rustc_middle::query::{Key, TyCtxtAt}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; -use rustc_target::abi::VariantIdx; use tracing::instrument; use crate::interpret::InterpCx; diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 38b87b72634..14e8bebbb18 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::fmt::Write; use either::Either; +use rustc_abi::WrappingRange; use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level, @@ -15,8 +16,7 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::ty::{self, Mutability, Ty}; use rustc_span::{Span, Symbol}; -use rustc_target::abi::WrappingRange; -use rustc_target::abi::call::AdjustForForeignAbiError; +use rustc_target::callconv::AdjustForForeignAbiError; use crate::interpret::InternKind; diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 1915bf75c95..ef0902e4226 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -4,13 +4,12 @@ use std::assert_matches::assert_matches; use std::borrow::Cow; use either::{Left, Right}; +use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; use rustc_middle::ty::layout::{FnAbiOf, IntegerExt, LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, AdtDef, Instance, Ty}; +use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::sym; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; -use rustc_target::abi::{self, FieldIdx, Integer}; -use rustc_target::spec::abi::Abi; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use tracing::{info, instrument, trace}; use super::{ @@ -93,29 +92,46 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Unwrap types that are guaranteed a null-pointer-optimization fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> { - // Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and - // another type. + // Check if this is an option-like type wrapping some type. let ty::Adt(def, args) = layout.ty.kind() else { // Not an ADT, so definitely no NPO. return interp_ok(layout); }; - let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) { - // The wrapped type is the only arg. - self.layout_of(args[0].as_type().unwrap())? - } else if self.tcx.is_diagnostic_item(sym::Result, def.did()) { - // We want to extract which (if any) of the args is not a 1-ZST. - let lhs = self.layout_of(args[0].as_type().unwrap())?; - let rhs = self.layout_of(args[1].as_type().unwrap())?; - if lhs.is_1zst() { - rhs - } else if rhs.is_1zst() { - lhs - } else { - return interp_ok(layout); // no NPO + if def.variants().len() != 2 { + // Not a 2-variant enum, so no NPO. + return interp_ok(layout); + } + assert!(def.is_enum()); + + let all_fields_1zst = |variant: &VariantDef| -> InterpResult<'tcx, _> { + for field in &variant.fields { + let ty = field.ty(*self.tcx, args); + let layout = self.layout_of(ty)?; + if !layout.is_1zst() { + return interp_ok(false); + } } + interp_ok(true) + }; + + // If one variant consists entirely of 1-ZST, then the other variant + // is the only "relevant" one for this check. + let var0 = VariantIdx::from_u32(0); + let var1 = VariantIdx::from_u32(1); + let relevant_variant = if all_fields_1zst(def.variant(var0))? { + def.variant(var1) + } else if all_fields_1zst(def.variant(var1))? { + def.variant(var0) } else { - return interp_ok(layout); // no NPO + // No varant is all-1-ZST, so no NPO. + return interp_ok(layout); }; + // The "relevant" variant must have exactly one field, and its type is the "inner" type. + if relevant_variant.fields.len() != 1 { + return interp_ok(layout); + } + let inner = relevant_variant.fields[FieldIdx::from_u32(0)].ty(*self.tcx, args); + let inner = self.layout_of(inner)?; // Check if the inner type is one of the NPO-guaranteed ones. // For that we first unpeel transparent *structs* (but not unions). @@ -488,7 +504,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub(super) fn init_fn_call( &mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>, - (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>), + (caller_abi, caller_fn_abi): (ExternAbi, &FnAbi<'tcx, Ty<'tcx>>), args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, destination: &MPlaceTy<'tcx, M::Provenance>, @@ -566,7 +582,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Special handling for the closure ABI: untuple the last argument. let args: Cow<'_, [FnArg<'tcx, M::Provenance>]> = - if caller_abi == Abi::RustCall && !args.is_empty() { + if caller_abi == ExternAbi::RustCall && !args.is_empty() { // Untuple let (untuple_arg, args) = args.split_last().unwrap(); trace!("init_fn_call: Will pass last argument by untupling"); @@ -732,7 +748,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub(super) fn init_fn_tail_call( &mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>, - (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>), + (caller_abi, caller_fn_abi): (ExternAbi, &FnAbi<'tcx, Ty<'tcx>>), args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, ) -> InterpResult<'tcx> { @@ -817,7 +833,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.init_fn_call( FnVal::Instance(instance), - (Abi::Rust, fn_abi), + (ExternAbi::Rust, fn_abi), &[FnArg::Copy(arg.into())], false, &ret, diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 60d5e904bd9..49559059265 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -1,5 +1,6 @@ use std::assert_matches::assert_matches; +use rustc_abi::Integer; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::CastKind; @@ -8,7 +9,6 @@ use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty}; use rustc_middle::{bug, span_bug}; -use rustc_target::abi::Integer; use rustc_type_ir::TyKind::*; use tracing::trace; diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index bb4ac9556ea..f94d0cbb42b 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -1,9 +1,9 @@ //! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines). +use rustc_abi::{self as abi, TagEncoding, VariantIdx, Variants}; use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty}; use rustc_middle::{mir, span_bug}; -use rustc_target::abi::{self, TagEncoding, VariantIdx, Variants}; use tracing::{instrument, trace}; use super::{ diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 9043bd3e28e..ff6d5b28b3b 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1,4 +1,5 @@ use either::{Left, Right}; +use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -15,8 +16,7 @@ use rustc_middle::ty::{ use rustc_middle::{mir, span_bug}; use rustc_session::Limit; use rustc_span::Span; -use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; +use rustc_target::callconv::FnAbi; use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument, trace}; diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 80e14ee887c..c7a56a80e81 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -4,6 +4,7 @@ use std::assert_matches::assert_matches; +use rustc_abi::Size; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_hir::def_id::DefId; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; @@ -11,7 +12,6 @@ use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement}; use rustc_middle::ty::{GenericArgsRef, Ty, TyCtxt}; use rustc_middle::{bug, ty}; use rustc_span::symbol::{Symbol, sym}; -use rustc_target::abi::Size; use tracing::trace; use super::memory::MemoryKind; diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 89d49ba046e..dbe09d55b2d 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -6,6 +6,7 @@ use std::borrow::{Borrow, Cow}; use std::fmt::Debug; use std::hash::Hash; +use rustc_abi::{Align, ExternAbi, Size}; use rustc_apfloat::{Float, FloatConvert}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::query::TyCtxtAt; @@ -14,8 +15,6 @@ use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{mir, ty}; use rustc_span::Span; use rustc_span::def_id::DefId; -use rustc_target::abi::{Align, Size}; -use rustc_target::spec::abi::Abi as CallAbi; use super::{ AllocBytes, AllocId, AllocKind, AllocRange, Allocation, CTFE_ALLOC_SALT, ConstAllocation, @@ -202,7 +201,7 @@ pub trait Machine<'tcx>: Sized { fn find_mir_or_eval_fn( ecx: &mut InterpCx<'tcx, Self>, instance: ty::Instance<'tcx>, - abi: CallAbi, + abi: ExternAbi, args: &[FnArg<'tcx, Self::Provenance>], destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, @@ -214,7 +213,7 @@ pub trait Machine<'tcx>: Sized { fn call_extra_fn( ecx: &mut InterpCx<'tcx, Self>, fn_val: Self::ExtraFnVal, - abi: CallAbi, + abi: ExternAbi, args: &[FnArg<'tcx, Self::Provenance>], destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, @@ -653,7 +652,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) { fn call_extra_fn( _ecx: &mut InterpCx<$tcx, Self>, fn_val: !, - _abi: CallAbi, + _abi: ExternAbi, _args: &[FnArg<$tcx>], _destination: &MPlaceTy<$tcx, Self::Provenance>, _target: Option<mir::BasicBlock>, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 7700eb792ef..1ad8ffa4b53 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -11,13 +11,13 @@ use std::borrow::{Borrow, Cow}; use std::collections::VecDeque; use std::{fmt, mem, ptr}; +use rustc_abi::{Align, HasDataLayout, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir::def::DefKind; use rustc_middle::bug; use rustc_middle::mir::display_allocation; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; -use rustc_target::abi::{Align, HasDataLayout, Size}; use tracing::{debug, instrument, trace}; use super::{ diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index cf280e0c1ae..fbc85d37953 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -1,4 +1,5 @@ use either::Either; +use rustc_abi::Size; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::NullOp; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; @@ -6,7 +7,6 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::sym; -use rustc_target::abi::Size; use tracing::trace; use super::{ImmTy, InterpCx, Machine, MemPlaceMeta, interp_ok, throw_ub}; diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index e636090a324..65a93784e2c 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -10,10 +10,10 @@ use std::marker::PhantomData; use std::ops::Range; +use rustc_abi::{self as abi, Size, VariantIdx}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::{bug, mir, span_bug, ty}; -use rustc_target::abi::{self, Size, VariantIdx}; use tracing::{debug, instrument}; use super::{ diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index aa752955675..18cff2c5e0f 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -3,13 +3,13 @@ //! The main entry point is the `step` method. use either::Either; +use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_index::IndexSlice; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::source_map::Spanned; -use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; +use rustc_target::callconv::FnAbi; use tracing::{info, instrument, trace}; use super::{ diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index da7d6853c0e..af8d618b6b5 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -1,7 +1,7 @@ +use rustc_abi::{Align, Size}; use rustc_middle::mir::interpret::{InterpResult, Pointer}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt, Ty, TyCtxt, VtblEntry}; -use rustc_target::abi::{Align, Size}; use tracing::trace; use super::util::ensure_monomorphic_enough; diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 647917dbb67..76ab0bb544f 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -3,11 +3,11 @@ use std::num::NonZero; +use rustc_abi::{FieldIdx, FieldsShape, VariantIdx, Variants}; use rustc_index::IndexVec; use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::{FieldIdx, FieldsShape, VariantIdx, Variants}; use tracing::trace; use super::{InterpCx, MPlaceTy, Machine, Projectable, interp_ok, throw_inval}; diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 5ad55968398..6fa7d369229 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -1,6 +1,6 @@ +use rustc_abi::Align; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; -use rustc_target::abi::Align; use tracing::debug; /// Returns `true` if this place is allowed to be less aligned diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index ef577c03218..74da0d11e4b 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -49,7 +49,7 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" shlex = "1.0" -time = { version = "0.3.36", default-features = false, features = ["alloc", "formatting", "parsing", "macros"] } +time = { version = "0.3.36", default-features = false, features = ["alloc", "formatting", "macros"] } tracing = { version = "0.1.35" } # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 4362007d4ba..d2c4335cf2b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -64,6 +64,7 @@ use rustc_span::source_map::FileLoader; use rustc_target::json::ToJson; use rustc_target::spec::{Target, TargetTuple}; use time::OffsetDateTime; +use time::macros::format_description; use tracing::trace; #[allow(unused_macros)] @@ -1356,8 +1357,7 @@ fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option<Pat let file_now = now .format( // Don't use a standard datetime format because Windows doesn't support `:` in paths - &time::format_description::parse("[year]-[month]-[day]T[hour]_[minute]_[second]") - .unwrap(), + &format_description!("[year]-[month]-[day]T[hour]_[minute]_[second]"), ) .unwrap_or_default(); let pid = std::process::id(); diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index d8c1a3cb55c..efbfa0851a8 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -3,13 +3,15 @@ An invalid number of generic parameters was passed to an intrinsic function. Erroneous code example: ```compile_fail,E0094 -#![feature(intrinsics, rustc_attrs)] +#![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - fn size_of<T, U>() -> usize; // error: intrinsic has wrong number - // of type parameters +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +fn size_of<T, U>() -> usize // error: intrinsic has wrong number + // of type parameters +{ + loop {} } ``` @@ -18,11 +20,13 @@ and verify with the function declaration in the Rust source code. Example: ``` -#![feature(intrinsics, rustc_attrs)] +#![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - fn size_of<T>() -> usize; // ok! +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +fn size_of<T>() -> usize // ok! +{ + loop {} } ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md index 19a482f6c93..7aa42628549 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0211.md +++ b/compiler/rustc_error_codes/src/error_codes/E0211.md @@ -4,12 +4,11 @@ You used a function or type which doesn't fit the requirements for where it was used. Erroneous code examples: ```compile_fail -#![feature(intrinsics, rustc_attrs)] +#![feature(intrinsics)] #![allow(internal_features)] extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - fn size_of<T>(); // error: intrinsic has wrong type + fn unreachable(); // error: intrinsic has wrong type } // or: @@ -41,12 +40,11 @@ impl Foo { For the first code example, please check the function definition. Example: ``` -#![feature(intrinsics, rustc_attrs)] +#![feature(intrinsics)] #![allow(internal_features)] extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - fn size_of<T>() -> usize; // ok! + fn unreachable() -> !; // ok! } ``` diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 0069b07ad62..a4820ba8b72 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -837,6 +837,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_const_stable_indirect, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL, ), + rustc_attr!( + rustc_const_stable_intrinsic, Normal, + template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL, + ), gated!( rustc_allow_const_fn_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No, @@ -993,23 +997,18 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing, EncodeCrossCrate::Yes, r#"`rustc_doc_primitive` is a rustc internal attribute"#, ), - rustc_attr!( - rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, - "the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe" - ), - rustc_attr!( - rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, + gated!( + rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics, "the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies", ), + gated!( + rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics, + "the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies", + ), rustc_attr!( rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, "#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen" ), - rustc_attr!( - rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, - "the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies", - ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 8d2e1e8c804..6ff70044eed 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -100,6 +100,9 @@ declare_features! ( Some("renamed to `doc_notable_trait`")), /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (removed, dropck_parametricity, "1.38.0", Some(28498), None), + /// Uses generic effect parameters for ~const bounds + (removed, effects, "CURRENT_RUSTC_VERSION", Some(102090), + Some("removed, redundant with `#![feature(const_trait_impl)]`")), /// Allows defining `existential type`s. (removed, existential_type, "1.38.0", Some(63063), Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a99d9048886..5f83c211b38 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -462,8 +462,6 @@ declare_features! ( (unstable, doc_masked, "1.21.0", Some(44027)), /// Allows `dyn* Trait` objects. (incomplete, dyn_star, "1.65.0", Some(102425)), - /// Uses generic effect parameters for ~const bounds - (incomplete, effects, "1.72.0", Some(102090)), /// Allows exhaustive pattern matching on types that contain uninhabited types. (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Allows explicit tail calls via `become` expression. diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index ac24c47d0b7..85c6da83379 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start odht = { version = "0.3.1", features = ["nightly"] } +rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index fa76f8652ea..554097bf115 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,5 +1,6 @@ use std::fmt; +use rustc_abi::ExternAbi; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{ self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, @@ -19,7 +20,6 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Span}; use rustc_target::asm::InlineAsmRegOrRegClass; -use rustc_target::spec::abi::Abi; use smallvec::SmallVec; use tracing::debug; @@ -2735,7 +2735,7 @@ impl PrimTy { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct BareFnTy<'hir> { pub safety: Safety, - pub abi: Abi, + pub abi: ExternAbi, pub generic_params: &'hir [GenericParam<'hir>], pub decl: &'hir FnDecl<'hir>, pub param_names: &'hir [Ident], @@ -3313,7 +3313,7 @@ impl<'hir> Item<'hir> { expect_mod, &'hir Mod<'hir>, ItemKind::Mod(m), m; - expect_foreign_mod, (Abi, &'hir [ForeignItemRef]), + expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]), ItemKind::ForeignMod { abi, items }, (*abi, items); expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm(asm), asm; @@ -3386,7 +3386,7 @@ pub struct FnHeader { pub safety: Safety, pub constness: Constness, pub asyncness: IsAsync, - pub abi: Abi, + pub abi: ExternAbi, } impl FnHeader { @@ -3428,7 +3428,7 @@ pub enum ItemKind<'hir> { /// A module. Mod(&'hir Mod<'hir>), /// An external module, e.g. `extern { .. }`. - ForeignMod { abi: Abi, items: &'hir [ForeignItemRef] }, + ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). GlobalAsm(&'hir InlineAsm<'hir>), /// A type alias, e.g., `type Foo = Bar<u8>`. diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 3c8887f08bc..581ef2272d1 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -19,7 +19,6 @@ rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } -rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_lint_defs = { path = "../rustc_lint_defs" } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 38b11aa4017..6e8ba51612e 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -311,8 +311,8 @@ hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snip hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}` .note = default implementation of `{$missing_item_name}` is unstable - .some_note = use of unstable library feature '{$feature}': {$reason} - .none_note = use of unstable library feature '{$feature}' + .some_note = use of unstable library feature `{$feature}`: {$reason} + .none_note = use of unstable library feature `{$feature}` hir_analysis_missing_type_params = the type {$parameterCount -> diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 476814c261e..50ea8018e76 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -37,7 +37,7 @@ use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_i use super::*; use crate::check::intrinsicck::InlineAsmCtxt; -pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) { +pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) { if !tcx.sess.target.is_abi_supported(abi) { struct_span_code_err!( tcx.dcx(), @@ -49,7 +49,7 @@ pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) { } } -pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { +pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) { if !tcx.sess.target.is_abi_supported(abi) { tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { lint.primary_message(format!( @@ -628,7 +628,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { def_id, tcx.def_ident_span(def_id).unwrap(), i.name, - Abi::Rust, + ExternAbi::Rust, ) } // Everything else is checked entirely within check_item_body @@ -699,7 +699,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_abi(tcx, it.span, abi); match abi { - Abi::RustIntrinsic => { + ExternAbi::RustIntrinsic => { for item in items { intrinsic::check_intrinsic_type( tcx, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 0b7d3f8b085..77c324183c3 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -205,7 +205,6 @@ fn compare_method_predicate_entailment<'tcx>( trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate), ); - // FIXME(effects): This should be replaced with a more dedicated method. let is_conditionally_const = tcx.is_conditionally_const(impl_def_id); if is_conditionally_const { // Augment the hybrid param-env with the const conditions @@ -1190,8 +1189,8 @@ fn compare_self_type<'tcx>( let self_string = |method: ty::AssocItem| { let untransformed_self_ty = match method.container { - ty::ImplContainer => impl_trait_ref.self_ty(), - ty::TraitContainer => tcx.types.self_param, + ty::AssocItemContainer::Impl => impl_trait_ref.self_ty(), + ty::AssocItemContainer::Trait => tcx.types.self_param, }; let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0); let param_env = ty::ParamEnv::reveal_all(); @@ -2225,10 +2224,8 @@ fn param_env_with_gat_bounds<'tcx>( for impl_ty in impl_tys_to_install { let trait_ty = match impl_ty.container { - ty::AssocItemContainer::TraitContainer => impl_ty, - ty::AssocItemContainer::ImplContainer => { - tcx.associated_item(impl_ty.trait_item_def_id.unwrap()) - } + ty::AssocItemContainer::Trait => impl_ty, + ty::AssocItemContainer::Impl => tcx.associated_item(impl_ty.trait_item_def_id.unwrap()), }; let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> = @@ -2247,7 +2244,7 @@ fn param_env_with_gat_bounds<'tcx>( .into() } GenericParamDefKind::Lifetime => { - let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); + let kind = ty::BoundRegionKind::Named(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Region(kind); bound_vars.push(bound_var); ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 0beb1f98d56..f3dd13c84b9 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -1,5 +1,6 @@ use std::ops::Not; +use rustc_abi::ExternAbi; use rustc_hir as hir; use rustc_hir::Node; use rustc_infer::infer::TyCtxtInferExt; @@ -9,7 +10,6 @@ use rustc_session::config::EntryFnType; use rustc_span::Span; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_span::symbol::sym; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; @@ -158,7 +158,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { expected_return_type, false, hir::Safety::Safe, - Abi::Rust, + ExternAbi::Rust, )); if check_function_signature( @@ -254,7 +254,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { tcx.types.isize, false, hir::Safety::Safe, - Abi::Rust, + ExternAbi::Rust, )); let _ = check_function_signature( diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs deleted file mode 100644 index 64307407b73..00000000000 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ /dev/null @@ -1,88 +0,0 @@ -use rustc_hir as hir; -use rustc_lint_defs::builtin::STATIC_MUT_REFS; -use rustc_middle::ty::{Mutability, TyCtxt}; -use rustc_span::Span; - -use crate::errors; - -/// Check for shared or mutable references of `static mut` inside expression -pub(crate) fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { - let span = expr.span; - let hir_id = expr.hir_id; - if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind - && matches!(borrow_kind, hir::BorrowKind::Ref) - && path_if_static_mut(expr) - { - handle_static_mut_ref( - tcx, - span, - span.with_hi(expr.span.lo()), - span.shrink_to_hi(), - span.edition().at_least_rust_2024(), - m, - hir_id, - ); - } -} - -/// Check for shared or mutable references of `static mut` inside statement -pub(crate) fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { - if let hir::StmtKind::Let(loc) = stmt.kind - && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind - && let hir::ByRef::Yes(rmutbl) = ba.0 - && let Some(init) = loc.init - && path_if_static_mut(init) - { - handle_static_mut_ref( - tcx, - init.span, - init.span.shrink_to_lo(), - init.span.shrink_to_hi(), - loc.span.edition().at_least_rust_2024(), - rmutbl, - stmt.hir_id, - ); - } -} - -fn path_if_static_mut(expr: &hir::Expr<'_>) -> bool { - if let hir::ExprKind::Path(qpath) = expr.kind - && let hir::QPath::Resolved(_, path) = qpath - && let hir::def::Res::Def(def_kind, _) = path.res - && let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } = - def_kind - { - return true; - } - false -} - -fn handle_static_mut_ref( - tcx: TyCtxt<'_>, - span: Span, - lo: Span, - hi: Span, - e2024: bool, - mutable: Mutability, - hir_id: hir::HirId, -) { - if e2024 { - let (sugg, shared) = if mutable == Mutability::Mut { - (errors::MutRefSugg::Mut { lo, hi }, "mutable") - } else { - (errors::MutRefSugg::Shared { lo, hi }, "shared") - }; - tcx.dcx().emit_err(errors::StaticMutRef { span, sugg, shared }); - } else { - let (sugg, shared) = if mutable == Mutability::Mut { - (errors::MutRefSugg::Mut { lo, hi }, "mutable") - } else { - (errors::MutRefSugg::Shared { lo, hi }, "shared") - }; - tcx.emit_node_span_lint(STATIC_MUT_REFS, hir_id, span, errors::RefOfMutStatic { - span, - sugg, - shared, - }); - } -} diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index c75bdcec388..cb954b0adcb 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,16 +1,15 @@ -//! Type-checking for the rust-intrinsic and platform-intrinsic -//! intrinsics that the compiler exposes. +//! Type-checking for the rust-intrinsic intrinsics that the compiler exposes. +use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{DiagMessage, struct_span_code_err}; -use rustc_hir as hir; +use rustc_hir::{self as hir, Safety}; use rustc_middle::bug; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; -use rustc_target::spec::abi::Abi; use crate::check::check_function_signature; use crate::errors::{ @@ -76,10 +75,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) { tcx.fn_sig(intrinsic_id).skip_binder().safety() } else { - match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) { - true => hir::Safety::Safe, - false => hir::Safety::Unsafe, - } + // Old-style intrinsics are never safe + Safety::Unsafe }; let is_in_list = match tcx.item_name(intrinsic_id.into()) { // When adding a new intrinsic to this list, @@ -163,7 +160,7 @@ pub fn check_intrinsic_type( intrinsic_id: LocalDefId, span: Span, intrinsic_name: Symbol, - abi: Abi, + abi: ExternAbi, ) { let generics = tcx.generics_of(intrinsic_id); let param = |n| { @@ -178,19 +175,19 @@ pub fn check_intrinsic_type( let name_str = intrinsic_name.as_str(); let bound_vars = tcx.mk_bound_variable_kinds(&[ - ty::BoundVariableKind::Region(ty::BrAnon), - ty::BoundVariableKind::Region(ty::BrAnon), - ty::BoundVariableKind::Region(ty::BrEnv), + ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon), + ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon), + ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv), ]); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { let region = ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::ZERO, - kind: ty::BrAnon, + kind: ty::BoundRegionKind::Anon, }); let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(2), - kind: ty::BrEnv, + kind: ty::BoundRegionKind::ClosureEnv, }); let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]); (Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty) @@ -509,7 +506,8 @@ pub fn check_intrinsic_type( ); let discriminant_def_id = assoc_items[0]; - let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BrAnon }; + let br = + ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon }; ( 1, 0, @@ -533,14 +531,14 @@ pub fn check_intrinsic_type( tcx.types.unit, false, hir::Safety::Safe, - Abi::Rust, + ExternAbi::Rust, )); let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( [mut_u8, mut_u8], tcx.types.unit, false, hir::Safety::Safe, - Abi::Rust, + ExternAbi::Rust, )); ( 0, @@ -573,10 +571,14 @@ pub fn check_intrinsic_type( } sym::raw_eq => { - let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BrAnon }; + let br = + ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon }; let param_ty_lhs = Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0)); - let br = ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(1), + kind: ty::BoundRegionKind::Anon, + }; let param_ty_rhs = Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0)); (1, 0, vec![param_ty_lhs, param_ty_rhs], tcx.types.bool) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index e9eea36a0e6..375cbfd1c4f 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -74,7 +74,7 @@ pub mod wfcheck; use std::num::NonZero; pub use check::{check_abi, check_abi_fn_ptr}; -use rustc_abi::VariantIdx; +use rustc_abi::{ExternAbi, VariantIdx}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -91,7 +91,6 @@ use rustc_session::parse::feature_err; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::symbol::{Ident, kw, sym}; use rustc_span::{BytePos, DUMMY_SP, Span, Symbol}; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::infer::ObligationCauseExt as _; use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor; @@ -142,8 +141,8 @@ fn get_owner_return_paths( /// Forbid defining intrinsics in Rust code, /// as they must always be defined by the compiler. // FIXME: Move this to a more appropriate place. -pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: Abi) { - if let Abi::RustIntrinsic = abi { +pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: ExternAbi) { + if let ExternAbi::RustIntrinsic = abi { tcx.dcx().span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block"); } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d01c3784ade..3a6ea545741 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2,6 +2,7 @@ use std::cell::LazyCell; use std::ops::{ControlFlow, Deref}; use hir::intravisit::{self, Visitor}; +use rustc_abi::ExternAbi; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; @@ -23,7 +24,6 @@ use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; use rustc_span::symbol::{Ident, sym}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::misc::{ @@ -1048,8 +1048,10 @@ fn check_associated_item( .coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?; let self_ty = match item.container { - ty::TraitContainer => tcx.types.self_param, - ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(), + ty::AssocItemContainer::Trait => tcx.types.self_param, + ty::AssocItemContainer::Impl => { + tcx.type_of(item.container_id(tcx)).instantiate_identity() + } }; match item.kind { @@ -1072,7 +1074,7 @@ fn check_associated_item( check_method_receiver(wfcx, hir_sig, item, self_ty) } ty::AssocKind::Type => { - if let ty::AssocItemContainer::TraitContainer = item.container { + if let ty::AssocItemContainer::Trait = item.container { check_associated_type_bounds(wfcx, item, span) } if item.defaultness(tcx).has_value() { @@ -1644,7 +1646,7 @@ fn check_fn_or_method<'tcx>( check_where_clauses(wfcx, span, def_id); - if sig.abi == Abi::RustCall { + if sig.abi == ExternAbi::RustCall { let span = tcx.def_span(def_id); let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None; let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 }); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 3f6198dbd31..63a0e7d31c3 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -18,6 +18,7 @@ use std::cell::Cell; use std::iter; use std::ops::Bound; +use rustc_abi::ExternAbi; use rustc_ast::Recovered; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; @@ -38,7 +39,6 @@ use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMo use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::spec::abi; use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::ObligationCtxt; @@ -634,7 +634,7 @@ fn get_new_lifetime_name<'tcx>( .collect_referenced_late_bound_regions(poly_trait_ref) .into_iter() .filter_map(|lt| { - if let ty::BoundRegionKind::BrNamed(_, name) = lt { + if let ty::BoundRegionKind::Named(_, name) = lt { Some(name.as_str().to_string()) } else { None @@ -1361,7 +1361,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe, _ => hir::Safety::Unsafe, }; - ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, abi::Abi::Rust)) + ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust)) } Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => { @@ -1686,10 +1686,10 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, decl: &'tcx hir::FnDecl<'tcx>, - abi: abi::Abi, + abi: ExternAbi, safety: hir::Safety, ) -> ty::PolyFnSig<'tcx> { - let safety = if abi == abi::Abi::RustIntrinsic { + let safety = if abi == ExternAbi::RustIntrinsic { intrinsic_operation_unsafety(tcx, def_id) } else { safety @@ -1700,7 +1700,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw - if abi != abi::Abi::RustIntrinsic && !tcx.features().simd_ffi() { + if abi != ExternAbi::RustIntrinsic && !tcx.features().simd_ffi() { let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| { if ty.is_simd() { let snip = tcx diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index dc3ef9952f0..cc55f57c46c 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -322,7 +322,7 @@ fn late_arg_as_bound_arg<'tcx>( let name = tcx.item_name(def_id); match param.kind { GenericParamKind::Lifetime { .. } => { - ty::BoundVariableKind::Region(ty::BrNamed(def_id, name)) + ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name)) } GenericParamKind::Type { .. } => { ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name)) @@ -337,7 +337,7 @@ fn late_arg_as_bound_arg<'tcx>( fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind { match param.kind { ty::GenericParamDefKind::Lifetime => { - ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(param.def_id, param.name)) + ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id, param.name)) } ty::GenericParamDefKind::Type { .. } => { ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name)) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 84161ec7648..816761fd00f 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -175,19 +175,13 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span // arm would handle this. // // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU - Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => { + Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(ty, segment)), .. }) => { // Find the Item containing the associated type so we can create an ItemCtxt. // Using the ItemCtxt lower the HIR for the unresolved assoc type into a // ty which is a fully resolved projection. // For the code example above, this would mean lowering `Self::Assoc<3>` // to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`). - let item_def_id = tcx - .hir() - .parent_owner_iter(arg_hir_id) - .find(|(_, node)| matches!(node, OwnerNode::Item(_))) - .unwrap() - .0 - .def_id; + let item_def_id = tcx.hir().get_parent_item(ty.hir_id).def_id; let ty = ItemCtxt::new(tcx, item_def_id).lower_ty(hir_ty); // Iterate through the generics of the projection to find the one that corresponds to diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 85ba88333f9..1cade402c54 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -644,7 +644,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::GenericParamDefKind::Lifetime => { ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_usize(num_bound_vars), - kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name), + kind: ty::BoundRegionKind::Named(param.def_id, param.name), }) .into() } @@ -830,8 +830,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 't } ty::ReBound(db, br) if db >= self.depth => { self.vars.insert(match br.kind { - ty::BrNamed(def_id, name) => (def_id, name), - ty::BrAnon | ty::BrEnv => { + ty::BoundRegionKind::Named(def_id, name) => (def_id, name), + ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => { let guar = self .cx .dcx() diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 672dc8ddeda..92f38a7dde0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -1,9 +1,9 @@ +use rustc_abi::ExternAbi; use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; use rustc_hir::{self as hir, HirId}; use rustc_middle::bug; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, ParamEnv, TyCtxt}; -use rustc_target::spec::abi; use crate::errors; @@ -14,13 +14,13 @@ pub(crate) fn validate_cmse_abi<'tcx>( tcx: TyCtxt<'tcx>, dcx: DiagCtxtHandle<'_>, hir_id: HirId, - abi: abi::Abi, + abi: ExternAbi, fn_sig: ty::PolyFnSig<'tcx>, ) { let abi_name = abi.name(); match abi { - abi::Abi::CCmseNonSecureCall => { + ExternAbi::CCmseNonSecureCall => { let hir_node = tcx.hir_node(hir_id); let hir::Node::Ty(hir::Ty { span: bare_fn_span, @@ -78,7 +78,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( } }; } - abi::Abi::CCmseNonSecureEntry => { + ExternAbi::CCmseNonSecureEntry => { let hir_node = tcx.hir_node(hir_id); let Some(hir::FnSig { decl, span: fn_sig_span, .. }) = hir_node.fn_sig() else { // might happen when this ABI is used incorrectly. That will be handled elsewhere @@ -195,17 +195,17 @@ fn is_valid_cmse_output<'tcx>( Ok(ret_ty == tcx.types.i64 || ret_ty == tcx.types.u64 || ret_ty == tcx.types.f64) } -fn should_emit_generic_error<'tcx>(abi: abi::Abi, layout_err: &'tcx LayoutError<'tcx>) -> bool { +fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError<'tcx>) -> bool { use LayoutError::*; match layout_err { Unknown(ty) => { match abi { - abi::Abi::CCmseNonSecureCall => { + ExternAbi::CCmseNonSecureCall => { // prevent double reporting of this error !ty.is_impl_trait() } - abi::Abi::CCmseNonSecureEntry => true, + ExternAbi::CCmseNonSecureEntry => true, _ => bug!("invalid ABI: {abi}"), } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index fb23ad1b248..ed39708981b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -47,7 +47,6 @@ use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{Ident, Symbol, kw}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::spec::abi; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -315,7 +314,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let name = lifetime_name(def_id); let br = ty::BoundRegion { var: ty::BoundVar::from_u32(index), - kind: ty::BrNamed(def_id.to_def_id(), name), + kind: ty::BoundRegionKind::Named(def_id.to_def_id(), name), }; ty::Region::new_bound(tcx, debruijn, br) } @@ -333,7 +332,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::Region::new_late_param( tcx, scope.to_def_id(), - ty::BrNamed(id.to_def_id(), name), + ty::BoundRegionKind::Named(id.to_def_id(), name), ) // (*) -- not late-bound, won't change @@ -563,7 +562,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Err(guar) = ty.error_reported() { return ty::Const::new_error(tcx, guar).into(); } - // FIXME(effects) see if we should special case effect params here if !infer_args && has_default { tcx.const_param_default(param.def_id) .instantiate(tcx, preceding_args) @@ -2353,7 +2351,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, hir_id: HirId, safety: hir::Safety, - abi: abi::Abi, + abi: rustc_abi::ExternAbi, decl: &hir::FnDecl<'tcx>, generics: Option<&hir::Generics<'_>>, hir_ty: Option<&hir::Ty<'_>>, @@ -2451,15 +2449,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) { for br in referenced_regions.difference(&constrained_regions) { let br_name = match *br { - ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon | ty::BrEnv => { - "an anonymous lifetime".to_string() - } - ty::BrNamed(_, name) => format!("lifetime `{name}`"), + ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime) + | ty::BoundRegionKind::Anon + | ty::BoundRegionKind::ClosureEnv => "an anonymous lifetime".to_string(), + ty::BoundRegionKind::Named(_, name) => format!("lifetime `{name}`"), }; let mut err = generate_err(&br_name); - if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon = *br { + if let ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime) + | ty::BoundRegionKind::Anon = *br + { // The only way for an anonymous lifetime to wind up // in the return type but **also** be unconstrained is // if it only appears in "associated types" in the diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index b0c9aed5d85..34effd199f1 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -459,7 +459,7 @@ fn trait_predicates_eq<'tcx>( predicate1: ty::Predicate<'tcx>, predicate2: ty::Predicate<'tcx>, ) -> bool { - // FIXME(effects) + // FIXME(const_trait_impl) predicate1 == predicate2 } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 339eddeeade..5830636c6e8 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -91,6 +91,7 @@ mod impl_wf_check; mod outlives; mod variance; +use rustc_abi::ExternAbi; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::middle; @@ -100,19 +101,23 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::parse::feature_err; use rustc_span::Span; use rustc_span::symbol::sym; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } -fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { +fn require_c_abi_if_c_variadic( + tcx: TyCtxt<'_>, + decl: &hir::FnDecl<'_>, + abi: ExternAbi, + span: Span, +) { const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`"; const CONVENTIONS_STABLE: &str = "`C` or `cdecl`"; const UNSTABLE_EXPLAIN: &str = "using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; - if !decl.c_variadic || matches!(abi, Abi::C { .. } | Abi::Cdecl { .. }) { + if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) { return; } diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 894402a8c2e..8ddbb4b3397 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -23,7 +23,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index f9a21a9bef3..20502de38a2 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -16,7 +16,6 @@ use rustc_middle::{bug, span_bug}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{Ident, sym}; -use rustc_target::spec::abi; use rustc_trait_selection::error_reporting::traits::DefIdOrName; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -461,7 +460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } (fn_sig, Some(def_id)) } - // FIXME(effects): these arms should error because we can't enforce them + // FIXME(const_trait_impl): these arms should error because we can't enforce them ty::FnPtr(sig_tys, hdr) => (sig_tys.with(hdr), None), _ => { for arg in arg_exprs { @@ -509,7 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { def_id, ); - if fn_sig.abi == abi::Abi::RustCall { + if fn_sig.abi == rustc_abi::ExternAbi::RustCall { let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span); if let Some(ty) = fn_sig.inputs().last().copied() { self.register_bound( @@ -843,11 +842,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_did: DefId, callee_args: GenericArgsRef<'tcx>, ) { - // FIXME(effects): We should be enforcing these effects unconditionally. + // FIXME(const_trait_impl): We should be enforcing these effects unconditionally. // This can be done as soon as we convert the standard library back to // using const traits, since if we were to enforce these conditions now, // we'd fail on basically every builtin trait call (i.e. `1 + 2`). - if !self.tcx.features().effects() { + if !self.tcx.features().const_trait_impl() { return; } @@ -864,11 +863,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => return, }; - // FIXME(effects): Should this be `is_const_fn_raw`? It depends on if we move + // FIXME(const_trait_impl): Should this be `is_const_fn_raw`? It depends on if we move // const stability checking here too, I guess. if self.tcx.is_conditionally_const(callee_did) { let q = self.tcx.const_conditions(callee_did); - // FIXME(effects): Use this span with a better cause code. + // FIXME(const_trait_impl): Use this span with a better cause code. for (cond, _) in q.instantiate(self.tcx, callee_args) { self.register_predicate(Obligation::new( self.tcx, @@ -878,7 +877,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } } else { - // FIXME(effects): This should eventually be caught here. + // FIXME(const_trait_impl): This should eventually be caught here. // For now, though, we defer some const checking to MIR. } } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 2d8943c6159..2026fd9a614 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; +use rustc_abi::ExternAbi; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; @@ -10,7 +11,6 @@ use rustc_infer::traits::WellFormedLoc; use rustc_middle::ty::{self, Binder, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::sym; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; use tracing::{debug, instrument}; @@ -194,24 +194,24 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> let panic_info_ty = tcx.type_of(panic_info_did).instantiate(tcx, &[ty::GenericArg::from( ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(1), - kind: ty::BrAnon, + kind: ty::BoundRegionKind::Anon, }), )]); let panic_info_ref_ty = Ty::new_imm_ref( tcx, ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::ZERO, - kind: ty::BrAnon, + kind: ty::BoundRegionKind::Anon, }), panic_info_ty, ); let bounds = tcx.mk_bound_variable_kinds(&[ - ty::BoundVariableKind::Region(ty::BrAnon), - ty::BoundVariableKind::Region(ty::BrAnon), + ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon), + ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon), ]); let expected_sig = ty::Binder::bind_with_vars( - tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.safety, Abi::Rust), + tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.safety, ExternAbi::Rust), bounds, ); @@ -234,7 +234,7 @@ fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id: let generic_ty = Ty::new_param(tcx, fn_generic.index, fn_generic.name); let main_fn_ty = Ty::new_fn_ptr( tcx, - Binder::dummy(tcx.mk_fn_sig([], generic_ty, false, hir::Safety::Safe, Abi::Rust)), + Binder::dummy(tcx.mk_fn_sig([], generic_ty, false, hir::Safety::Safe, ExternAbi::Rust)), ); let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig( @@ -247,7 +247,7 @@ fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id: tcx.types.isize, false, fn_sig.safety, - Abi::Rust, + ExternAbi::Rust, )); let _ = check_function_signature( diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index fd6ac7de14a..e715a7f7e15 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -3,6 +3,7 @@ use std::iter; use std::ops::ControlFlow; +use rustc_abi::ExternAbi; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; @@ -15,7 +16,6 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::LocalDefId; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::error_reporting::traits::ArgKind; use rustc_trait_selection::traits; use rustc_type_ir::ClosureKind; @@ -508,7 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ret_param_ty, false, hir::Safety::Safe, - Abi::Rust, + ExternAbi::Rust, )); Some(ExpectedSig { cause_span, sig }) @@ -594,7 +594,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_ty, false, hir::Safety::Safe, - Abi::Rust, + ExternAbi::Rust, )); Some(ExpectedSig { cause_span, sig }) @@ -706,7 +706,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sig.output(), sig.c_variadic, hir::Safety::Safe, - Abi::RustCall, + ExternAbi::RustCall, ) }); @@ -845,7 +845,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { supplied_output_ty, expected_sigs.liberated_sig.c_variadic, hir::Safety::Safe, - Abi::RustCall, + ExternAbi::RustCall, ); Ok(InferOk { value: expected_sigs, obligations: all_obligations }) @@ -922,7 +922,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { supplied_return, decl.c_variadic, hir::Safety::Safe, - Abi::RustCall, + ExternAbi::RustCall, ), bound_vars, ); @@ -1086,7 +1086,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err_ty, decl.c_variadic, hir::Safety::Safe, - Abi::RustCall, + ExternAbi::RustCall, )); debug!("supplied_sig_of_closure: result={:?}", result); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 87798ca3fd9..11e03229265 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -37,6 +37,7 @@ use std::ops::Deref; +use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; use rustc_hir as hir; @@ -60,7 +61,6 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span}; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ @@ -1244,7 +1244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) { // Intrinsics are not coercible to function pointers. - if a_sig.abi() == Abi::RustIntrinsic || b_sig.abi() == Abi::RustIntrinsic { + if a_sig.abi() == ExternAbi::RustIntrinsic || b_sig.abi() == ExternAbi::RustIntrinsic { return Err(TypeError::IntrinsicCast); } // The signature must match. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d6e5fab610e..b05731c6d52 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -5,6 +5,7 @@ //! //! See [`rustc_hir_analysis::check`] for more context on type checking in general. +use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordMap; @@ -34,7 +35,6 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::{Ident, Symbol, kw, sym}; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; use tracing::{debug, instrument, trace}; @@ -103,9 +103,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx> { + self.check_expr_coercible_to_type_or_error(expr, expected, expected_ty_expr, |_, _| {}) + } + + pub(crate) fn check_expr_coercible_to_type_or_error( + &self, + expr: &'tcx hir::Expr<'tcx>, + expected: Ty<'tcx>, + expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, + extend_err: impl FnOnce(&mut Diag<'_>, Ty<'tcx>), + ) -> Ty<'tcx> { let ty = self.check_expr_with_hint(expr, expected); // checks don't need two phase - self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No) + match self.demand_coerce_diag(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No) { + Ok(ty) => ty, + Err(mut err) => { + extend_err(&mut err, ty); + err.emit(); + // Return the original type instead of an error type here, otherwise the type of `x` in + // `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not + // report errors, even though `x` is definitely `u32`. + expected + } + } } pub(super) fn check_expr_with_hint( diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 041ccfcddbb..59bef8315d8 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -9,6 +9,7 @@ use std::slice::from_ref; use hir::Expr; use hir::def::DefKind; use hir::pat_util::EnumerateAndAdjustIterator as _; +use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def::{CtorOf, Res}; @@ -20,14 +21,12 @@ use rustc_middle::hir::place::ProjectionKind; pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection}; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{ - self, AdtKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, + self, AdtKind, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, }; use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, Span}; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_trait_selection::infer::InferCtxtExt; use tracing::{debug, trace}; -use ty::BorrowKind::ImmBorrow; use crate::fn_ctxt::FnCtxt; @@ -63,7 +62,7 @@ pub trait Delegate<'tcx> { fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { // In most cases, copying data from `x` is equivalent to doing `*&x`, so by default // we treat a copy of `x` as a borrow of `x`. - self.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow) + self.borrow(place_with_id, diag_expr_id, ty::BorrowKind::Immutable) } /// The path at `assignee_place` is being assigned to. @@ -387,7 +386,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } hir::ExprKind::Let(hir::LetExpr { pat, init, .. }) => { - self.walk_local(init, pat, None, || self.borrow_expr(init, ty::ImmBorrow))?; + self.walk_local(init, pat, None, || self.borrow_expr(init, BorrowKind::Immutable))?; } hir::ExprKind::Match(discr, arms, _) => { @@ -626,7 +625,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } if needs_to_be_read { - self.borrow_expr(discr, ty::ImmBorrow)?; + self.borrow_expr(discr, BorrowKind::Immutable)?; } else { let closure_def_id = match discr_place.place.base { PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), @@ -785,8 +784,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // Reborrowing a Pin is like a combinations of a deref and a borrow, so we do // both. let bk = match mutbl { - ty::Mutability::Not => ty::BorrowKind::ImmBorrow, - ty::Mutability::Mut => ty::BorrowKind::MutBorrow, + ty::Mutability::Not => ty::BorrowKind::Immutable, + ty::Mutability::Mut => ty::BorrowKind::Mutable, }; self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk); } @@ -909,7 +908,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // binding when lowering pattern guards to ensure that the guard does not // modify the scrutinee. if has_guard { - self.delegate.borrow_mut().borrow(place, discr_place.hir_id, ImmBorrow); + self.delegate.borrow_mut().borrow( + place, + discr_place.hir_id, + BorrowKind::Immutable, + ); } // It is also a borrow or copy/move of the value being matched. diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 8d8573c65c5..97f3807c252 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -643,7 +643,7 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> { fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) -> Self::Result { // Try to replace `_` with `()`. if let hir::TyKind::Infer = hir_ty.kind - && let ty = self.fcx.typeck_results.borrow().node_type(hir_ty.hir_id) + && let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(hir_ty.hir_id) && let Some(vid) = self.fcx.root_vid(ty) && self.reachable_vids.contains(&vid) { @@ -680,7 +680,8 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let Res::Def(DefKind::AssocFn, def_id) = path.res && self.fcx.tcx.trait_of_item(def_id).is_some() - && let self_ty = self.fcx.typeck_results.borrow().node_args(expr.hir_id).type_at(0) + && let Some(args) = self.fcx.typeck_results.borrow().node_args_opt(expr.hir_id) + && let self_ty = args.type_at(0) && let Some(vid) = self.fcx.root_vid(self_ty) && self.reachable_vids.contains(&vid) && let [.., trait_segment, _method_segment] = path.segments @@ -701,7 +702,7 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> { fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) -> Self::Result { // For a local, try suggest annotating the type if it's missing. if let None = local.ty - && let ty = self.fcx.typeck_results.borrow().node_type(local.hir_id) + && let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(local.hir_id) && let Some(vid) = self.fcx.root_vid(ty) && self.reachable_vids.contains(&vid) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a1a78371fbd..ce0ab8a913b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1,6 +1,7 @@ use std::collections::hash_map::Entry; use std::slice; +use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey}; use rustc_hir as hir; @@ -32,7 +33,6 @@ use rustc_span::Span; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::kw; -use rustc_target::abi::FieldIdx; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; use rustc_trait_selection::traits::{ self, NormalizeExt, ObligationCauseCode, StructurallyNormalizeExt, @@ -254,10 +254,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } for a in &adj { - if let Adjust::NeverToAny = a.kind { - if a.target.is_ty_var() { - self.diverging_type_vars.borrow_mut().insert(a.target); - debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); + match a.kind { + Adjust::NeverToAny => { + if a.target.is_ty_var() { + self.diverging_type_vars.borrow_mut().insert(a.target); + debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); + } + } + Adjust::Deref(Some(overloaded_deref)) => { + self.enforce_context_effects( + expr.span, + overloaded_deref.method_call(self.tcx), + self.tcx.mk_args(&[a.target.into()]), + ); + } + Adjust::Deref(None) => { + // FIXME(effects): We *could* enforce `&T: ~const Deref` here. + } + Adjust::Pointer(_pointer_coercion) => { + // FIXME(effects): We should probably enforce these. + } + Adjust::ReborrowPin(_mutability) => { + // FIXME(effects): We could enforce these; they correspond to + // `&mut T: DerefMut` tho, so it's kinda moot. + } + Adjust::Borrow(_) => { + // No effects to enforce here. } } } @@ -1025,7 +1047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let container_id = assoc_item.container_id(tcx); debug!(?def_id, ?container, ?container_id); match container { - ty::TraitContainer => { + ty::AssocItemContainer::Trait => { if let Err(e) = callee::check_legal_trait_for_method_call( tcx, path_span, @@ -1037,7 +1059,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.set_tainted_by_errors(e); } } - ty::ImplContainer => { + ty::AssocItemContainer::Impl => { if segments.len() == 1 { // `<T>::assoc` will end up here, and so // can `T::assoc`. If this came from an diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3f703c2fcf6..919e83724d7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1796,7 +1796,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false, |did| { let assoc_item = self.tcx.associated_item(did); - assoc_item.container == ty::AssocItemContainer::TraitContainer + assoc_item.container == ty::AssocItemContainer::Trait && assoc_item.container_id(self.tcx) == clone_trait_did }, ) @@ -3390,4 +3390,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(block.span, "this block is missing a tail expression"); } } + + pub(crate) fn suggest_swapping_lhs_and_rhs( + &self, + err: &mut Diag<'_>, + rhs_ty: Ty<'tcx>, + lhs_ty: Ty<'tcx>, + rhs_expr: &'tcx hir::Expr<'tcx>, + lhs_expr: &'tcx hir::Expr<'tcx>, + op: hir::BinOp, + ) { + match op.node { + hir::BinOpKind::Eq => { + if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait() + && self + .infcx + .type_implements_trait(partial_eq_def_id, [rhs_ty, lhs_ty], self.param_env) + .must_apply_modulo_regions() + { + let sm = self.tcx.sess.source_map(); + if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_expr.span) + && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_expr.span) + { + err.note(format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`")); + err.multipart_suggestion( + "consider swapping the equality", + vec![(lhs_expr.span, rhs_snippet), (rhs_expr.span, lhs_snippet)], + Applicability::MaybeIncorrect, + ); + } + } + } + _ => {} + } + } } diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 8a7005ac328..a754f7fddc9 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -1,5 +1,6 @@ use hir::HirId; use rustc_abi::Primitive::Pointer; +use rustc_abi::VariantIdx; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; @@ -7,7 +8,6 @@ use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_target::abi::VariantIdx; use tracing::trace; use super::FnCtxt; diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index d8b63eef577..f5987a11fa5 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -239,7 +239,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = node.ty() { if let Some(item) = tcx.opt_associated_item(def_id.into()) && let ty::AssocKind::Const = item.kind - && let ty::ImplContainer = item.container + && let ty::AssocItemContainer::Impl = item.container && let Some(trait_item_def_id) = item.trait_item_def_id { let impl_def_id = item.container_id(tcx); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index eb5581f421b..640729576fc 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -480,7 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::Single(def_id) => { let item = self.tcx.associated_item(def_id); // FIXME(fn_delegation): Delegation to inherent methods is not yet supported. - assert_eq!(item.container, AssocItemContainer::TraitContainer); + assert_eq!(item.container, AssocItemContainer::Trait); let trait_def_id = self.tcx.parent(def_id); let trait_span = self.tcx.def_span(trait_def_id); @@ -1406,7 +1406,7 @@ impl<'tcx> Pick<'tcx> { tcx.def_path_str(self.item.def_id), )); } - (ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => { + (ty::AssocKind::Const, ty::AssocItemContainer::Trait) => { let def_id = self.item.container_id(tcx); lint.span_suggestion( span, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 9c1459ee188..9a3492abc9f 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -249,7 +249,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); // see `NB` above - let rhs_ty = self.check_expr_coercible_to_type(rhs_expr, rhs_ty_var, Some(lhs_expr)); + let rhs_ty = self.check_expr_coercible_to_type_or_error( + rhs_expr, + rhs_ty_var, + Some(lhs_expr), + |err, ty| { + self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr, op); + }, + ); let rhs_ty = self.resolve_vars_with_obligations(rhs_ty); let return_ty = match result { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index cba6586f01d..2a8ed26aa2b 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1,6 +1,7 @@ use std::cmp; use std::collections::hash_map::Entry::{Occupied, Vacant}; +use rustc_abi::FieldIdx; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; @@ -20,7 +21,6 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::{Ident, kw, sym}; use rustc_span::{BytePos, DUMMY_SP, Span}; -use rustc_target::abi::FieldIdx; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; use tracing::{debug, instrument, trace}; @@ -2071,6 +2071,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { s = pluralize!(len), them = if len == 1 { "it" } else { "them" }, ), + format!( + "{}{}{}{}", + prefix, + unmentioned_fields + .iter() + .map(|(_, name)| { + let field_name = name.to_string(); + format!("{field_name}: _") + }) + .collect::<Vec<_>>() + .join(", "), + if have_inaccessible_fields { ", .." } else { "" }, + postfix, + ), + Applicability::MachineApplicable, + ); + err.span_suggestion( + sp, + "or always ignore missing fields here", format!("{prefix}..{postfix}"), Applicability::MachineApplicable, ); diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index d5c7fe5fff3..3d401cef76f 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -296,6 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); }; *deref = OverloadedDeref { mutbl, span: deref.span }; + self.enforce_context_effects(expr.span, method.def_id, method.args); // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514). // This helps avoid accidental drops. if inside_union diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 88982661c8f..175fca327f3 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -32,6 +32,7 @@ use std::iter; +use rustc_abi::FIRST_VARIANT; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::{ExtendUnord, UnordSet}; use rustc_errors::{Applicability, MultiSpan}; @@ -43,13 +44,12 @@ use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, Pro use rustc_middle::mir::FakeReadCause; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::{ - self, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, UpvarArgs, - UpvarCapture, + self, BorrowKind, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, + UpvarArgs, UpvarCapture, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_span::{BytePos, Pos, Span, Symbol, sym}; -use rustc_target::abi::FIRST_VARIANT; use rustc_trait_selection::infer::InferCtxtExt; use tracing::{debug, instrument}; @@ -381,7 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let closure_env_region: ty::Region<'_> = ty::Region::new_bound(self.tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::ZERO, - kind: ty::BoundRegionKind::BrEnv, + kind: ty::BoundRegionKind::ClosureEnv, }); let num_args = args @@ -438,10 +438,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tupled_upvars_ty_for_borrow, false, hir::Safety::Safe, - rustc_target::spec::abi::Abi::Rust, + rustc_abi::ExternAbi::Rust, ), self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region( - ty::BoundRegionKind::BrEnv, + ty::BoundRegionKind::ClosureEnv, )]), ), ); @@ -646,7 +646,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ty::UpvarCapture::ByRef( - ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow, + ty::BorrowKind::Mutable | ty::BorrowKind::UniqueImmutable, ) => { match closure_kind { ty::ClosureKind::Fn => { @@ -1681,7 +1681,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::UpvarCapture::ByValue } hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => { - ty::UpvarCapture::ByRef(ty::ImmBorrow) + ty::UpvarCapture::ByRef(BorrowKind::Immutable) } } } @@ -1869,7 +1869,7 @@ fn should_reborrow_from_env_of_parent_coroutine_closure<'tcx>( Some(Projection { kind: ProjectionKind::Deref, .. }) )) // (2.) - || matches!(child_capture.info.capture_kind, UpvarCapture::ByRef(ty::BorrowKind::MutBorrow)) + || matches!(child_capture.info.capture_kind, UpvarCapture::ByRef(ty::BorrowKind::Mutable)) } /// Truncate the capture so that the place being borrowed is in accordance with RFC 1240, @@ -1984,7 +1984,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> { // We need to restrict Fake Read precision to avoid fake reading unsafe code, // such as deref of a raw pointer. - let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow); + let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::Immutable); let (place, _) = restrict_capture_precision(place.place.clone(), dummy_capture_kind); @@ -2025,7 +2025,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> { // Raw pointers don't inherit mutability if place_with_id.place.deref_tys().any(Ty::is_unsafe_ptr) { - capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow); + capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::Immutable); } self.capture_information.push((place, ty::CaptureInfo { @@ -2037,7 +2037,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> { #[instrument(skip(self), level = "debug")] fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { - self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow); + self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::Mutable); } } @@ -2331,16 +2331,16 @@ fn determine_capture_info( (ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => { match (ref_a, ref_b) { // Take LHS: - (ty::UniqueImmBorrow | ty::MutBorrow, ty::ImmBorrow) - | (ty::MutBorrow, ty::UniqueImmBorrow) => capture_info_a, + (BorrowKind::UniqueImmutable | BorrowKind::Mutable, BorrowKind::Immutable) + | (BorrowKind::Mutable, BorrowKind::UniqueImmutable) => capture_info_a, // Take RHS: - (ty::ImmBorrow, ty::UniqueImmBorrow | ty::MutBorrow) - | (ty::UniqueImmBorrow, ty::MutBorrow) => capture_info_b, + (BorrowKind::Immutable, BorrowKind::UniqueImmutable | BorrowKind::Mutable) + | (BorrowKind::UniqueImmutable, BorrowKind::Mutable) => capture_info_b, - (ty::ImmBorrow, ty::ImmBorrow) - | (ty::UniqueImmBorrow, ty::UniqueImmBorrow) - | (ty::MutBorrow, ty::MutBorrow) => { + (BorrowKind::Immutable, BorrowKind::Immutable) + | (BorrowKind::UniqueImmutable, BorrowKind::UniqueImmutable) + | (BorrowKind::Mutable, BorrowKind::Mutable) => { bug!("Expected unequal capture kinds"); } } @@ -2367,12 +2367,12 @@ fn truncate_place_to_len_and_update_capture_kind<'tcx>( // Note that if the place contained Deref of a raw pointer it would've not been MutBorrow, so // we don't need to worry about that case here. match curr_mode { - ty::UpvarCapture::ByRef(ty::BorrowKind::MutBorrow) => { + ty::UpvarCapture::ByRef(ty::BorrowKind::Mutable) => { for i in len..place.projections.len() { if place.projections[i].kind == ProjectionKind::Deref && is_mut_ref(place.ty_before_projection(i)) { - *curr_mode = ty::UpvarCapture::ByRef(ty::BorrowKind::UniqueImmBorrow); + *curr_mode = ty::UpvarCapture::ByRef(ty::BorrowKind::UniqueImmutable); break; } } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 8769c4173c8..f6c3e8ebbcb 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -585,23 +585,17 @@ fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime fn timestamp_to_string(timestamp: SystemTime) -> BaseNString { let duration = timestamp.duration_since(UNIX_EPOCH).unwrap(); - let micros = duration.as_secs() * 1_000_000 + (duration.subsec_nanos() as u64) / 1000; + let micros: u64 = duration.as_micros().try_into().unwrap(); micros.to_base_fixed_len(CASE_INSENSITIVE) } fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> { - let micros_since_unix_epoch = u64::from_str_radix(s, INT_ENCODE_BASE as u32); - - if micros_since_unix_epoch.is_err() { - return Err("timestamp not an int"); - } - - let micros_since_unix_epoch = micros_since_unix_epoch.unwrap(); + let micros_since_unix_epoch = match u64::from_str_radix(s, INT_ENCODE_BASE as u32) { + Ok(micros) => micros, + Err(_) => return Err("timestamp not an int"), + }; - let duration = Duration::new( - micros_since_unix_epoch / 1_000_000, - 1000 * (micros_since_unix_epoch % 1_000_000) as u32, - ); + let duration = Duration::from_micros(micros_since_unix_epoch); Ok(UNIX_EPOCH + duration) } diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index ef5a1468c87..6d1a2d3de9e 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -16,9 +16,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_next_trait_solver = { path = "../rustc_next_trait_solver" } rustc_span = { path = "../rustc_span" } -rustc_target = { path = "../rustc_target" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index c9d8ebecef0..f87c43a0ecd 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -753,7 +753,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - let br = ty::BoundRegion { var, kind: ty::BrAnon }; + let br = ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }; ty::Region::new_bound(self.cx(), self.binder_index, br) } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 35bba149d0a..ce90ceeda56 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -764,7 +764,7 @@ fn test_unstable_options_tracking_hash() { branch_protection, Some(BranchProtection { bti: true, - pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B }) + pac_ret: Some(PacRet { leaf: true, pc: true, key: PAuthKey::B }) }) ); tracked!(codegen_backend, Some("abc".to_string())); diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index dd7b40d0a32..ec5f0f06c59 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -14,7 +14,6 @@ rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } -rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 026826021c8..002ab027982 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -154,7 +154,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { } for bound_var in sig.bound_vars() { - let ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, name)) = bound_var + let ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name)) = bound_var else { span_bug!(tcx.def_span(parent_def_id), "unexpected non-lifetime binder on fn sig"); }; @@ -215,7 +215,7 @@ where for arg in t.bound_vars() { let arg: ty::BoundVariableKind = arg; match arg { - ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, ..)) + ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, ..)) | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, _)) => { added.push(def_id); let unique = self.in_scope_parameters.insert(def_id, ParamKind::Late); @@ -318,7 +318,7 @@ where ParamKind::Free(def_id, name) => ty::Region::new_late_param( self.tcx, self.parent_def_id.to_def_id(), - ty::BoundRegionKind::BrNamed(def_id, name), + ty::BoundRegionKind::Named(def_id, name), ), // Totally ignore late bound args from binders. ParamKind::Late => return true, @@ -489,11 +489,11 @@ fn extract_def_id_from_arg<'tcx>( ty::ReEarlyParam(ebr) => generics.region_param(ebr, tcx).def_id, ty::ReBound( _, - ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. }, + ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id, ..), .. }, ) | ty::ReLateParam(ty::LateParamRegion { scope: _, - bound_region: ty::BoundRegionKind::BrNamed(def_id, ..), + bound_region: ty::BoundRegionKind::Named(def_id, ..), }) => def_id, _ => unreachable!(), }, @@ -558,11 +558,11 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> { ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id, ty::ReBound( _, - ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. }, + ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id, ..), .. }, ) | ty::ReLateParam(ty::LateParamRegion { scope: _, - bound_region: ty::BoundRegionKind::BrNamed(def_id, ..), + bound_region: ty::BoundRegionKind::Named(def_id, ..), }) => def_id, _ => { return Ok(a); diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 9d35ce19b57..a4d50c73104 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -422,6 +422,9 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { .into_iter() .filter(|pass| { let lints = (**pass).get_lints(); + // Lintless passes are always in + lints.is_empty() || + // If the pass doesn't have a single needed lint, omit it !lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint))) }) .collect(); diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 1c27e1daa90..4d8ebf2909e 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,3 +1,4 @@ +use rustc_abi::ExternAbi; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::FnKind; use rustc_hir::{GenericParamKind, PatKind}; @@ -7,7 +8,6 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{Ident, sym}; use rustc_span::{BytePos, Span}; -use rustc_target::spec::abi::Abi; use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; use crate::lints::{ @@ -26,8 +26,8 @@ pub(crate) enum MethodLateContext { pub(crate) fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext { let item = cx.tcx.associated_item(id); match item.container { - ty::TraitContainer => MethodLateContext::TraitAutoImpl, - ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) { + ty::AssocItemContainer::Trait => MethodLateContext::TraitAutoImpl, + ty::AssocItemContainer::Impl => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) { Some(_) => MethodLateContext::TraitImpl, None => MethodLateContext::PlainImpl, }, @@ -397,7 +397,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { match &fk { FnKind::Method(ident, sig, ..) => match method_context(cx, id) { MethodLateContext::PlainImpl => { - if sig.header.abi != Abi::Rust && cx.tcx.has_attr(id, sym::no_mangle) { + if sig.header.abi != ExternAbi::Rust && cx.tcx.has_attr(id, sym::no_mangle) { return; } self.check_snake_case(cx, "method", ident); @@ -409,7 +409,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { }, FnKind::ItemFn(ident, _, header) => { // Skip foreign-ABI #[no_mangle] functions (Issue #31924) - if header.abi != Abi::Rust && cx.tcx.has_attr(id, sym::no_mangle) { + if header.abi != ExternAbi::Rust && cx.tcx.has_attr(id, sym::no_mangle) { return; } self.check_snake_case(cx, "function", ident); diff --git a/compiler/rustc_lint/src/static_mut_refs.rs b/compiler/rustc_lint/src/static_mut_refs.rs index 5d78b41944f..fed5c29284b 100644 --- a/compiler/rustc_lint/src/static_mut_refs.rs +++ b/compiler/rustc_lint/src/static_mut_refs.rs @@ -3,8 +3,8 @@ use rustc_hir::{Expr, Stmt}; use rustc_middle::ty::{Mutability, TyKind}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::Span; use rustc_span::edition::Edition; +use rustc_span::{BytePos, Span}; use crate::lints::{MutRefSugg, RefOfMutStatic}; use crate::{LateContext, LateLintPass, LintContext}; @@ -71,13 +71,24 @@ impl<'tcx> LateLintPass<'tcx> for StaticMutRefs { if matches!(borrow_kind, hir::BorrowKind::Ref) && let Some(err_span) = path_is_static_mut(ex, err_span) => { - emit_static_mut_refs( - cx, - err_span, - err_span.with_hi(ex.span.lo()), - m, - !expr.span.from_expansion(), - ); + let source_map = cx.sess().source_map(); + let snippet = source_map.span_to_snippet(err_span); + + let sugg_span = if let Ok(snippet) = snippet { + // ( ( &IDENT ) ) + // ~~~~ exclude these from the suggestion span to avoid unmatching parens + let exclude_n_bytes: u32 = snippet + .chars() + .take_while(|ch| ch.is_whitespace() || *ch == '(') + .map(|ch| ch.len_utf8() as u32) + .sum(); + + err_span.with_lo(err_span.lo() + BytePos(exclude_n_bytes)).with_hi(ex.span.lo()) + } else { + err_span.with_hi(ex.span.lo()) + }; + + emit_static_mut_refs(cx, err_span, sugg_span, m, !expr.span.from_expansion()); } hir::ExprKind::MethodCall(_, e, _, _) if let Some(err_span) = path_is_static_mut(e, expr.span) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 48dd8e38a03..be70149b664 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1,7 +1,7 @@ use std::iter; use std::ops::ControlFlow; -use rustc_abi::{BackendRepr, TagEncoding, Variants, WrappingRange}; +use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, Variants, WrappingRange}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagMessage; use rustc_hir::{Expr, ExprKind}; @@ -14,7 +14,6 @@ use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol, source_map}; -use rustc_target::spec::abi::Abi as SpecAbi; use tracing::debug; use {rustc_ast as ast, rustc_hir as hir}; @@ -1294,10 +1293,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { self.check_type_for_ffi_and_report_errors(span, ty, true, false); } - fn is_internal_abi(&self, abi: SpecAbi) -> bool { + fn is_internal_abi(&self, abi: ExternAbi) -> bool { matches!( abi, - SpecAbi::Rust | SpecAbi::RustCall | SpecAbi::RustCold | SpecAbi::RustIntrinsic + ExternAbi::Rust | ExternAbi::RustCall | ExternAbi::RustCold | ExternAbi::RustIntrinsic ) } diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index b32af5e5e75..2ee7454b652 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -123,13 +123,13 @@ fromRust(LLVMRustCounterExprKind Kind) { report_fatal_error("Bad LLVMRustCounterExprKind!"); } -extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( +extern "C" void LLVMRustCoverageWriteFilenamesToBuffer( const char *const Filenames[], size_t FilenamesLen, // String start pointers const size_t *const Lengths, size_t LengthsLen, // Corresponding lengths RustStringRef BufferOut) { if (FilenamesLen != LengthsLen) { report_fatal_error( - "Mismatched lengths in LLVMRustCoverageWriteFilenamesSectionToBuffer"); + "Mismatched lengths in LLVMRustCoverageWriteFilenamesToBuffer"); } SmallVector<std::string, 32> FilenameRefs; @@ -143,16 +143,15 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( FilenamesWriter.write(OS); } -extern "C" void LLVMRustCoverageWriteMappingToBuffer( - const unsigned *VirtualFileMappingIDs, unsigned NumVirtualFileMappingIDs, - const LLVMRustCounterExpression *RustExpressions, unsigned NumExpressions, - const LLVMRustCoverageCodeRegion *CodeRegions, unsigned NumCodeRegions, - const LLVMRustCoverageBranchRegion *BranchRegions, - unsigned NumBranchRegions, +extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer( + const unsigned *VirtualFileMappingIDs, size_t NumVirtualFileMappingIDs, + const LLVMRustCounterExpression *RustExpressions, size_t NumExpressions, + const LLVMRustCoverageCodeRegion *CodeRegions, size_t NumCodeRegions, + const LLVMRustCoverageBranchRegion *BranchRegions, size_t NumBranchRegions, const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions, - unsigned NumMCDCBranchRegions, + size_t NumMCDCBranchRegions, const LLVMRustCoverageMCDCDecisionRegion *MCDCDecisionRegions, - unsigned NumMCDCDecisionRegions, RustStringRef BufferOut) { + size_t NumMCDCDecisionRegions, RustStringRef BufferOut) { // Convert from FFI representation to LLVM representation. // Expressions: @@ -219,34 +218,37 @@ LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName, return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef)); } -extern "C" uint64_t LLVMRustCoverageHashByteArray(const char *Bytes, - size_t NumBytes) { - auto StrRef = StringRef(Bytes, NumBytes); - return IndexedInstrProf::ComputeHash(StrRef); +extern "C" uint64_t LLVMRustCoverageHashBytes(const char *Bytes, + size_t NumBytes) { + return IndexedInstrProf::ComputeHash(StringRef(Bytes, NumBytes)); } -static void WriteSectionNameToString(LLVMModuleRef M, InstrProfSectKind SK, - RustStringRef Str) { +// Private helper function for getting the covmap and covfun section names. +static void writeInstrProfSectionNameToString(LLVMModuleRef M, + InstrProfSectKind SectKind, + RustStringRef OutStr) { auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); - auto name = getInstrProfSectionName(SK, TargetTriple.getObjectFormat()); - auto OS = RawRustStringOstream(Str); + auto name = getInstrProfSectionName(SectKind, TargetTriple.getObjectFormat()); + auto OS = RawRustStringOstream(OutStr); OS << name; } -extern "C" void LLVMRustCoverageWriteMapSectionNameToString(LLVMModuleRef M, - RustStringRef Str) { - WriteSectionNameToString(M, IPSK_covmap, Str); +extern "C" void +LLVMRustCoverageWriteCovmapSectionNameToString(LLVMModuleRef M, + RustStringRef OutStr) { + writeInstrProfSectionNameToString(M, IPSK_covmap, OutStr); } extern "C" void -LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M, - RustStringRef Str) { - WriteSectionNameToString(M, IPSK_covfun, Str); +LLVMRustCoverageWriteCovfunSectionNameToString(LLVMModuleRef M, + RustStringRef OutStr) { + writeInstrProfSectionNameToString(M, IPSK_covfun, OutStr); } -extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { +extern "C" void +LLVMRustCoverageWriteCovmapVarNameToString(RustStringRef OutStr) { auto name = getCoverageMappingVarName(); - auto OS = RawRustStringOstream(Str); + auto OS = RawRustStringOstream(OutStr); OS << name; } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 3b7dc6de825..eb99d560e57 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -317,49 +317,17 @@ template <typename KV> static size_t getLongestEntryLength(ArrayRef<KV> Table) { return MaxLen; } -using PrintBackendInfo = void(void *, const char *Data, size_t Len); - extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM, - const char *TargetCPU, - PrintBackendInfo Print, void *Out) { - const TargetMachine *Target = unwrap(TM); - const Triple::ArchType HostArch = - Triple(sys::getDefaultTargetTriple()).getArch(); - const Triple::ArchType TargetArch = Target->getTargetTriple().getArch(); - - std::ostringstream Buf; + RustStringRef OutStr) { + ArrayRef<SubtargetSubTypeKV> CPUTable = + unwrap(TM)->getMCSubtargetInfo()->getAllProcessorDescriptions(); + auto OS = RawRustStringOstream(OutStr); - const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const ArrayRef<SubtargetSubTypeKV> CPUTable = - MCInfo->getAllProcessorDescriptions(); - unsigned MaxCPULen = getLongestEntryLength(CPUTable); - - Buf << "Available CPUs for this target:\n"; - // Don't print the "native" entry when the user specifies --target with a - // different arch since that could be wrong or misleading. - if (HostArch == TargetArch) { - MaxCPULen = std::max(MaxCPULen, (unsigned)std::strlen("native")); - const StringRef HostCPU = sys::getHostCPUName(); - Buf << " " << std::left << std::setw(MaxCPULen) << "native" - << " - Select the CPU of the current host " - "(currently " - << HostCPU.str() << ").\n"; - } + // Just print a bare list of target CPU names, and let Rust-side code handle + // the full formatting of `--print=target-cpus`. for (auto &CPU : CPUTable) { - // Compare cpu against current target to label the default - if (strcmp(CPU.Key, TargetCPU) == 0) { - Buf << " " << std::left << std::setw(MaxCPULen) << CPU.Key - << " - This is the default target CPU for the current build target " - "(currently " - << Target->getTargetTriple().str() << ")."; - } else { - Buf << " " << CPU.Key; - } - Buf << "\n"; + OS << CPU.Key << "\n"; } - - const auto &BufString = Buf.str(); - Print(Out, BufString.data(), BufString.size()); } extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) { @@ -382,9 +350,9 @@ extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index, *Desc = Feat.Desc; } -extern "C" const char *LLVMRustGetHostCPUName(size_t *len) { +extern "C" const char *LLVMRustGetHostCPUName(size_t *OutLen) { StringRef Name = sys::getHostCPUName(); - *len = Name.size(); + *OutLen = Name.size(); return Name.data(); } @@ -777,10 +745,8 @@ extern "C" LLVMRustResult LLVMRustOptimize( CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; - // FIXME: We may want to expose this as an option. - bool DebugPassManager = false; - - StandardInstrumentations SI(TheModule->getContext(), DebugPassManager); + StandardInstrumentations SI(TheModule->getContext(), + /*DebugLogging=*/false); SI.registerCallbacks(PIC, &MAM); if (LLVMPluginsLen) { @@ -818,16 +784,22 @@ extern "C" LLVMRustResult LLVMRustOptimize( // the PassBuilder does not create a pipeline. std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>> PipelineStartEPCallbacks; +#if LLVM_VERSION_GE(20, 0) + std::vector<std::function<void(ModulePassManager &, OptimizationLevel, + ThinOrFullLTOPhase)>> + OptimizerLastEPCallbacks; +#else std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>> OptimizerLastEPCallbacks; +#endif if (!IsLinkerPluginLTO && SanitizerOptions && SanitizerOptions->SanitizeCFI && !NoPrepopulatePasses) { PipelineStartEPCallbacks.push_back( [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr, - /*ImportSummary=*/nullptr, - /*DropTypeTests=*/false)); + MPM.addPass(LowerTypeTestsPass( + /*ExportSummary=*/nullptr, + /*ImportSummary=*/nullptr)); }); } @@ -866,7 +838,12 @@ extern "C" LLVMRustResult LLVMRustOptimize( SanitizerOptions->SanitizeDataFlowABIList + SanitizerOptions->SanitizeDataFlowABIListLen); OptimizerLastEPCallbacks.push_back( +#if LLVM_VERSION_GE(20, 0) + [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level, + ThinOrFullLTOPhase phase) { +#else [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level) { +#endif MPM.addPass(DataFlowSanitizerPass(ABIListFiles)); }); } @@ -878,23 +855,39 @@ extern "C" LLVMRustResult LLVMRustOptimize( /*CompileKernel=*/false, /*EagerChecks=*/true); OptimizerLastEPCallbacks.push_back( +#if LLVM_VERSION_GE(20, 0) + [Options](ModulePassManager &MPM, OptimizationLevel Level, + ThinOrFullLTOPhase phase) { +#else [Options](ModulePassManager &MPM, OptimizationLevel Level) { +#endif MPM.addPass(MemorySanitizerPass(Options)); }); } if (SanitizerOptions->SanitizeThread) { - OptimizerLastEPCallbacks.push_back([](ModulePassManager &MPM, - OptimizationLevel Level) { - MPM.addPass(ModuleThreadSanitizerPass()); - MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); - }); + OptimizerLastEPCallbacks.push_back( +#if LLVM_VERSION_GE(20, 0) + [](ModulePassManager &MPM, OptimizationLevel Level, + ThinOrFullLTOPhase phase) { +#else + [](ModulePassManager &MPM, OptimizationLevel Level) { +#endif + MPM.addPass(ModuleThreadSanitizerPass()); + MPM.addPass( + createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); + }); } if (SanitizerOptions->SanitizeAddress || SanitizerOptions->SanitizeKernelAddress) { OptimizerLastEPCallbacks.push_back( +#if LLVM_VERSION_GE(20, 0) + [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level, + ThinOrFullLTOPhase phase) { +#else [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { +#endif auto CompileKernel = SanitizerOptions->SanitizeKernelAddress; AddressSanitizerOptions opts = AddressSanitizerOptions{ CompileKernel, @@ -908,7 +901,12 @@ extern "C" LLVMRustResult LLVMRustOptimize( } if (SanitizerOptions->SanitizeHWAddress) { OptimizerLastEPCallbacks.push_back( +#if LLVM_VERSION_GE(20, 0) + [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level, + ThinOrFullLTOPhase phase) { +#else [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { +#endif HWAddressSanitizerOptions opts( /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover, @@ -932,8 +930,9 @@ extern "C" LLVMRustResult LLVMRustOptimize( for (const auto &C : OptimizerLastEPCallbacks) PB.registerOptimizerLastEPCallback(C); - // Pass false as we manually schedule ThinLTOBufferPasses below. - MPM = PB.buildO0DefaultPipeline(OptLevel, /* PreLinkLTO */ false); + // We manually schedule ThinLTOBufferPasses below, so don't pass the value + // to enable it here. + MPM = PB.buildO0DefaultPipeline(OptLevel); } else { for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); @@ -942,7 +941,7 @@ extern "C" LLVMRustResult LLVMRustOptimize( switch (OptStage) { case LLVMRustOptStage::PreLinkNoLTO: - MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager); + MPM = PB.buildPerModuleDefaultPipeline(OptLevel); break; case LLVMRustOptStage::PreLinkThinLTO: MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel); @@ -968,7 +967,11 @@ extern "C" LLVMRustResult LLVMRustOptimize( for (const auto &C : PipelineStartEPCallbacks) C(MPM, OptLevel); for (const auto &C : OptimizerLastEPCallbacks) +#if LLVM_VERSION_GE(20, 0) + C(MPM, OptLevel, ThinOrFullLTOPhase::None); +#else C(MPM, OptLevel); +#endif } if (ExtraPassesLen) { diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 645b4082be5..a68eed03e61 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -140,26 +140,14 @@ extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M, unwrap(M)->setTargetTriple(Triple::normalize(Triple)); } -extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) { - std::string buf; - auto SS = raw_string_ostream(buf); - TimerGroup::printAll(SS); - SS.flush(); - *Len = buf.length(); - char *CStr = (char *)malloc(*Len); - memcpy(CStr, buf.c_str(), *Len); - return CStr; -} - -extern "C" const char *LLVMRustPrintStatistics(size_t *Len) { - std::string buf; - auto SS = raw_string_ostream(buf); - llvm::PrintStatistics(SS); - SS.flush(); - *Len = buf.length(); - char *CStr = (char *)malloc(*Len); - memcpy(CStr, buf.c_str(), *Len); - return CStr; +extern "C" void LLVMRustPrintPassTimings(RustStringRef OutBuf) { + auto OS = RawRustStringOstream(OutBuf); + TimerGroup::printAll(OS); +} + +extern "C" void LLVMRustPrintStatistics(RustStringRef OutBuf) { + auto OS = RawRustStringOstream(OutBuf); + llvm::PrintStatistics(OS); } extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name, diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 1e6bc413118..b7695216f3c 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,6 +1,7 @@ use std::ops::ControlFlow; use std::path::{Path, PathBuf}; +use rustc_abi::ExternAbi; use rustc_ast::CRATE_NODE_ID; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; @@ -17,7 +18,6 @@ use rustc_session::utils::NativeLibKind; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::{Symbol, sym}; use rustc_target::spec::LinkSelfContainedComponents; -use rustc_target::spec::abi::Abi; use crate::{errors, fluent_generated}; @@ -203,7 +203,7 @@ impl<'tcx> Collector<'tcx> { let sess = self.tcx.sess; - if matches!(abi, Abi::Rust | Abi::RustIntrinsic) { + if matches!(abi, ExternAbi::Rust | ExternAbi::RustIntrinsic) { return; } @@ -625,7 +625,7 @@ impl<'tcx> Collector<'tcx> { fn build_dll_import( &self, - abi: Abi, + abi: ExternAbi, import_name_type: Option<PeImportNameType>, item: DefId, ) -> DllImport { @@ -634,12 +634,14 @@ impl<'tcx> Collector<'tcx> { // this logic is similar to `Target::adjust_abi` (in rustc_target/src/spec/mod.rs) but errors on unsupported inputs let calling_convention = if self.tcx.sess.target.arch == "x86" { match abi { - Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C, - Abi::Stdcall { .. } => DllCallingConvention::Stdcall(self.i686_arg_list_size(item)), + ExternAbi::C { .. } | ExternAbi::Cdecl { .. } => DllCallingConvention::C, + ExternAbi::Stdcall { .. } => { + DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) + } // On Windows, `extern "system"` behaves like msvc's `__stdcall`. // `__stdcall` only applies on x86 and on non-variadic functions: // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170 - Abi::System { .. } => { + ExternAbi::System { .. } => { let c_variadic = self.tcx.type_of(item).instantiate_identity().fn_sig(self.tcx).c_variadic(); @@ -649,10 +651,10 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) } } - Abi::Fastcall { .. } => { + ExternAbi::Fastcall { .. } => { DllCallingConvention::Fastcall(self.i686_arg_list_size(item)) } - Abi::Vectorcall { .. } => { + ExternAbi::Vectorcall { .. } => { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { @@ -661,7 +663,9 @@ impl<'tcx> Collector<'tcx> { } } else { match abi { - Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C, + ExternAbi::C { .. } | ExternAbi::Win64 { .. } | ExternAbi::System { .. } => { + DllCallingConvention::C + } _ => { self.tcx.dcx().emit_fatal(errors::UnsupportedAbi { span }); } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f06f2fdc5e5..045fd0565ba 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -384,6 +384,7 @@ provide! { tcx, def_id, other, cdata, crate_hash => { cdata.root.header.hash } crate_host_hash => { cdata.host_hash } crate_name => { cdata.root.header.name } + num_extern_def_ids => { cdata.num_def_ids() } extra_filename => { cdata.root.extra_filename.clone() } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7277039bb7d..b5391247cea 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1203,8 +1203,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> DefKind::AssocTy => { let assoc_item = tcx.associated_item(def_id); match assoc_item.container { - ty::AssocItemContainer::ImplContainer => true, - ty::AssocItemContainer::TraitContainer => assoc_item.defaultness(tcx).has_value(), + ty::AssocItemContainer::Impl => true, + ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(), } } DefKind::TyParam => { @@ -1336,7 +1336,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { if let Some(assoc_item) = tcx.opt_associated_item(def_id) - && assoc_item.container == ty::AssocItemContainer::TraitContainer + && assoc_item.container == ty::AssocItemContainer::Trait && assoc_item.kind == ty::AssocKind::Fn { true @@ -1649,7 +1649,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.assoc_container.set_some(def_id.index, item.container); match item.container { - AssocItemContainer::TraitContainer => { + AssocItemContainer::Trait => { if let ty::AssocKind::Type = item.kind { self.encode_explicit_item_bounds(def_id); self.encode_explicit_item_super_predicates(def_id); @@ -1659,7 +1659,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } } - AssocItemContainer::ImplContainer => { + AssocItemContainer::Impl => { if let Some(trait_item_def_id) = item.trait_item_def_id { self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into()); } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 949e26f5f60..58f58efb116 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -6,7 +6,7 @@ use decoder::{DecodeContext, Metadata}; use def_path_hash_map::DefPathHashMapRef; use encoder::EncodeContext; pub use encoder::{EncodedMetadata, encode_metadata, rendered_const}; -use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_abi::{FieldIdx, ReprOptions, VariantIdx}; use rustc_ast::expand::StrippedCfgItem; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; @@ -27,7 +27,7 @@ use rustc_middle::middle::lib_features::FeatureStability; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{ - self, DeducedParamAttrs, ParameterizedOverTcx, ReprOptions, Ty, TyCtxt, UnusedGenericParams, + self, DeducedParamAttrs, ParameterizedOverTcx, Ty, TyCtxt, UnusedGenericParams, }; use rustc_middle::util::Providers; use rustc_middle::{mir, trivially_parameterized_over_tcx}; diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 3a6f3543317..63abd2be9a5 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -223,8 +223,8 @@ fixed_size_enum! { fixed_size_enum! { ty::AssocItemContainer { - ( TraitContainer ) - ( ImplContainer ) + ( Trait ) + ( Impl ) } } diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 39485a324f2..52c3212ab80 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -68,8 +68,8 @@ middle_deprecated_in_version = use of {$kind} `{$path}` that will be deprecated middle_deprecated_suggestion = replace the use of the deprecated {$kind} middle_drop_check_overflow = - overflow while adding drop-check rules for {$ty} - .note = overflowed on {$overflow_ty} + overflow while adding drop-check rules for `{$ty}` + .note = overflowed on `{$overflow_ty}` middle_erroneous_constant = erroneous constant encountered diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 7e77923fcdf..b664230d10b 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -9,7 +9,7 @@ macro_rules! arena_types { ($macro:path) => ( $macro!([ [] layout: rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx>, - [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, + [] fn_abi: rustc_target::callconv::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, // AdtDef are interned and compared by address [decode] adt_def: rustc_middle::ty::AdtDefData, [] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<'tcx>>, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 926691013dd..007e6f46006 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,3 +1,4 @@ +use rustc_abi::ExternAbi; use rustc_ast::visit::{VisitorResult, walk_list}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -12,7 +13,6 @@ use rustc_middle::hir::nested_filter; use rustc_span::def_id::StableCrateId; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{ErrorGuaranteed, Span}; -use rustc_target::spec::abi::Abi; use {rustc_ast as ast, rustc_hir_pretty as pprust_hir}; use crate::hir::ModuleItems; @@ -668,7 +668,7 @@ impl<'hir> Map<'hir> { } } - pub fn get_foreign_abi(self, hir_id: HirId) -> Abi { + pub fn get_foreign_abi(self, hir_id: HirId) -> ExternAbi { let parent = self.get_parent_item(hir_id); if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = self.tcx.hir_owner_node(parent) diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 4c7af0bc372..66b701523b7 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -1,6 +1,6 @@ +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_hir::HirId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; -use rustc_target::abi::{FieldIdx, VariantIdx}; use crate::ty; use crate::ty::Ty; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 90dff0f5c7d..44428471a5f 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -1,7 +1,7 @@ +use rustc_abi::Align; use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::symbol::Symbol; -use rustc_target::abi::Align; use rustc_target::spec::SanitizerSet; use crate::mir::mono::Linkage; diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index c0688aff183..e6b36299d7f 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -112,8 +112,8 @@ pub fn report_unstable( soft_handler: impl FnOnce(&'static Lint, Span, String), ) { let msg = match reason { - Some(r) => format!("use of unstable library feature '{feature}': {r}"), - None => format!("use of unstable library feature '{feature}'"), + Some(r) => format!("use of unstable library feature `{feature}`: {r}"), + None => format!("use of unstable library feature `{feature}`"), }; if is_soft { diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 465aa0eee03..1ae0bd6740d 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -1,12 +1,12 @@ use std::fmt::{self, Debug, Display, Formatter}; use either::Either; +use rustc_abi::{HasDataLayout, Size}; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{HasDataLayout, Size}; use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range}; use crate::mir::{Promoted, pretty_print_const_value}; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index ac3baf74ca7..509f2667b35 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -12,10 +12,10 @@ use either::{Left, Right}; use init_mask::*; pub use init_mask::{InitChunk, InitChunkIter}; use provenance_map::*; +use rustc_abi::{Align, HasDataLayout, Size}; use rustc_ast::Mutability; use rustc_data_structures::intern::Interned; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ AllocId, BadBytesAccess, CtfeProvenance, InterpErrorKind, InterpResult, Pointer, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs index dfaf96e14f6..cc6389e2989 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs @@ -4,9 +4,9 @@ mod tests; use std::ops::Range; use std::{hash, iter}; +use rustc_abi::Size; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_serialize::{Decodable, Encodable}; -use rustc_target::abi::Size; use rustc_type_ir::{TyDecoder, TyEncoder}; use super::AllocRange; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index b3940530f69..5c47fc6a399 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -3,10 +3,10 @@ use std::cmp; +use rustc_abi::{HasDataLayout, Size}; use rustc_data_structures::sorted_map::SortedMap; use rustc_macros::HashStable; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use rustc_target::abi::{HasDataLayout, Size}; use tracing::trace; use super::{AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance, alloc_range}; diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index b520f21ce20..8ec7e1851a5 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -4,6 +4,7 @@ use std::borrow::Cow; use std::{convert, fmt, mem, ops}; use either::Either; +use rustc_abi::{Align, Size, VariantIdx, WrappingRange}; use rustc_ast_ir::Mutability; use rustc_data_structures::sync::Lock; use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg}; @@ -11,7 +12,6 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_session::CtfeBacktrace; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol}; -use rustc_target::abi::{Align, Size, VariantIdx, WrappingRange, call}; use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar}; use crate::error; @@ -217,7 +217,7 @@ pub enum InvalidProgramInfo<'tcx> { /// An error occurred during FnAbi computation: the passed --target lacks FFI support /// (which unfortunately typeck does not reject). /// Not using `FnAbiError` as that contains a nested `LayoutError`. - FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError), + FnAbiAdjustForForeignAbi(rustc_target::callconv::AdjustForForeignAbiError), } /// Details of why a pointer had to be in-bounds. diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 790ff3e2fe0..b0c0e1be500 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -12,6 +12,7 @@ use std::io::{Read, Write}; use std::num::NonZero; use std::{fmt, io}; +use rustc_abi::{AddressSpace, Endian, HasDataLayout}; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; @@ -20,7 +21,6 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; -use rustc_target::abi::{AddressSpace, Endian, HasDataLayout}; use tracing::{debug, trace}; // Also make the error macros available from this module. pub use { diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 1700b0f02ec..1d5afe22573 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -1,9 +1,9 @@ use std::fmt; use std::num::NonZero; +use rustc_abi::{HasDataLayout, Size}; use rustc_data_structures::static_assert_size; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_target::abi::{HasDataLayout, Size}; use super::AllocId; diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 061a55bfda8..9d462093b9e 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -1,10 +1,10 @@ use std::fmt; use either::{Either, Left, Right}; +use rustc_abi::{HasDataLayout, Size}; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_target::abi::{HasDataLayout, Size}; use super::{ AllocId, CtfeProvenance, InterpResult, Pointer, PointerArithmetic, Provenance, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 978abab8b08..260c6543f98 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -10,6 +10,7 @@ use std::{iter, mem}; pub use basic_blocks::BasicBlocks; use either::Either; use polonius_engine::Atom; +use rustc_abi::{FieldIdx, VariantIdx}; pub use rustc_ast::Mutability; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -27,7 +28,6 @@ use rustc_serialize::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{FieldIdx, VariantIdx}; use tracing::trace; pub use self::query::*; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 80ae5a7146d..d0f93c19e44 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -4,6 +4,7 @@ use std::fs; use std::io::{self, Write as _}; use std::path::{Path, PathBuf}; +use rustc_abi::Size; use rustc_ast::InlineAsmTemplatePiece; use rustc_middle::mir::interpret::{ AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, alloc_range, @@ -11,7 +12,6 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use rustc_target::abi::Size; use tracing::trace; use super::graphviz::write_mir_fn_graphviz; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 70331214ac5..86abeb50382 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -4,6 +4,7 @@ use std::cell::Cell; use std::fmt::{self, Debug}; use derive_where::derive_where; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; @@ -12,7 +13,6 @@ use rustc_index::{Idx, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::Span; use rustc_span::symbol::Symbol; -use rustc_target::abi::{FieldIdx, VariantIdx}; use smallvec::SmallVec; use super::{ConstValue, SourceInfo}; @@ -317,7 +317,10 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { let inner = tcx.fold_regions(ty, |r, depth| match r.kind() { ty::ReVar(vid) => { - let br = ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon }; + let br = ty::BoundRegion { + var: ty::BoundVar::new(vid.index()), + kind: ty::BoundRegionKind::Anon, + }; ty::Region::new_bound(tcx, depth, br) } _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"), diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 85beb6ef1e7..f01ac305d3f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -3,6 +3,7 @@ //! This is in a dedicated file so that changes to this file can be reviewed more carefully. //! The intention is that this file only contains datatype declarations, no code. +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece, Mutability}; use rustc_data_structures::packed::Pu128; use rustc_hir::CoroutineKind; @@ -13,7 +14,6 @@ use rustc_span::Span; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; -use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::asm::InlineAsmRegOrRegClass; use smallvec::SmallVec; diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 8cfc7f1e33e..1d4c36e28bd 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -132,12 +132,10 @@ impl EraseType for Result<bool, &ty::layout::LayoutError<'_>> { type Result = [u8; size_of::<Result<bool, &'static ty::layout::LayoutError<'static>>>()]; } -impl EraseType - for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>> -{ +impl EraseType for Result<rustc_abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>> { type Result = [u8; size_of::< Result< - rustc_target::abi::TyAndLayout<'static, Ty<'static>>, + rustc_abi::TyAndLayout<'static, Ty<'static>>, &'static ty::layout::LayoutError<'static>, >, >()]; @@ -253,13 +251,14 @@ trivial! { Option<rustc_span::def_id::DefId>, Option<rustc_span::def_id::LocalDefId>, Option<rustc_span::Span>, - Option<rustc_target::abi::FieldIdx>, + Option<rustc_abi::FieldIdx>, Option<rustc_target::spec::PanicStrategy>, Option<usize>, Option<rustc_middle::ty::IntrinsicDef>, Result<(), rustc_errors::ErrorGuaranteed>, Result<(), rustc_middle::traits::query::NoSolution>, Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>, + rustc_abi::ReprOptions, rustc_ast::expand::allocator::AllocatorKind, rustc_attr::ConstStability, rustc_attr::DefaultBodyStability, @@ -311,7 +310,6 @@ trivial! { rustc_middle::ty::fast_reject::SimplifiedType, rustc_middle::ty::ImplPolarity, rustc_middle::ty::Representability, - rustc_middle::ty::ReprOptions, rustc_middle::ty::UnusedGenericParams, rustc_middle::ty::util::AlwaysRequiresDrop, rustc_middle::ty::Visibility<rustc_span::def_id::DefId>, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index ba7b57c891c..fe28ef0f70c 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -5,7 +5,6 @@ use rustc_hir::hir_id::{HirId, OwnerId}; use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi; use crate::infer::canonical::CanonicalQueryInput; use crate::ty::fast_reject::SimplifiedType; @@ -509,7 +508,7 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) { } } -impl<'tcx> Key for (Ty<'tcx>, abi::VariantIdx) { +impl<'tcx> Key for (Ty<'tcx>, rustc_abi::VariantIdx) { type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 3f61d7cc66f..54ead9a7a75 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -42,9 +42,8 @@ use rustc_session::lint::LintExpectationId; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::Symbol; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi; use rustc_target::spec::PanicStrategy; -use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; +use {rustc_abi as abi, rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; @@ -1465,7 +1464,7 @@ rustc_queries! { /// instead, where the instance is an `InstanceKind::Virtual`. query fn_abi_of_fn_ptr( key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)> - ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { + ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } } @@ -1476,7 +1475,7 @@ rustc_queries! { /// to an `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`). query fn_abi_of_instance( key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)> - ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { + ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } } @@ -1845,6 +1844,16 @@ rustc_queries! { desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) } } + /// Gets the number of definitions in a foreign crate. + /// + /// This allows external tools to iterate over all definitions in a foreign crate. + /// + /// This should never be used for the local crate, instead use `iter_local_def_id`. + query num_extern_def_ids(_: CrateNum) -> usize { + desc { "fetching the number of definitions in a crate" } + separate_provide_extern + } + query lib_features(_: CrateNum) -> &'tcx LibFeatures { desc { "calculating the lib features defined in a crate" } separate_provide_extern @@ -2201,10 +2210,11 @@ rustc_queries! { desc { "computing autoderef types for `{}`", goal.canonical.value.value } } - query supported_target_features(_: CrateNum) -> &'tcx UnordMap<String, Option<Symbol>> { + /// Returns the Rust target features for the current target. These are not always the same as LLVM target features! + query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> { arena_cache eval_always - desc { "looking up supported target features" } + desc { "looking up Rust target features" } } query implied_target_features(feature: Symbol) -> &'tcx Vec<Symbol> { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index fe865b8a515..45ceb0a555d 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -12,6 +12,7 @@ use std::cmp::Ordering; use std::fmt; use std::ops::Index; +use rustc_abi::{FieldIdx, Integer, Size, VariantIdx}; use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -29,7 +30,6 @@ use rustc_middle::ty::{ }; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol}; -use rustc_target::abi::{FieldIdx, Integer, Size, VariantIdx}; use rustc_target::asm::InlineAsmRegOrRegClass; use tracing::instrument; @@ -1063,7 +1063,7 @@ impl<'tcx> PatRangeBoundary<'tcx> { a.partial_cmp(&b) } ty::Int(ity) => { - let size = rustc_target::abi::Integer::from_int_ty(&tcx, *ity).size(); + let size = rustc_abi::Integer::from_int_ty(&tcx, *ity).size(); let a = size.sign_extend(a) as i128; let b = size.sign_extend(b) as i128; Some(a.cmp(&b)) diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index c56038d358c..f8ab555305f 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -1,8 +1,9 @@ +use rustc_abi::FieldIdx; use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::Span; -use rustc_target::abi::FieldIdx; use crate::ty::{self, Ty, TyCtxt}; @@ -123,19 +124,18 @@ pub struct OverloadedDeref { } impl OverloadedDeref { - /// Get the zst function item type for this method call. - pub fn method_call<'tcx>(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> { + /// Get the [`DefId`] of the method call for the given `Deref`/`DerefMut` trait + /// for this overloaded deref's mutability. + pub fn method_call<'tcx>(&self, tcx: TyCtxt<'tcx>) -> DefId { let trait_def_id = match self.mutbl { hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None), hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None), }; - let method_def_id = tcx - .associated_items(trait_def_id) + tcx.associated_items(trait_def_id) .in_definition_order() .find(|m| m.kind == ty::AssocKind::Fn) .unwrap() - .def_id; - Ty::new_fn_def(tcx, method_def_id, [source]) + .def_id } } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 3322a2643d7..0773eb7a3be 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -3,6 +3,7 @@ use std::hash::{Hash, Hasher}; use std::ops::Range; use std::str; +use rustc_abi::{FIRST_VARIANT, ReprOptions, VariantIdx}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; @@ -17,7 +18,6 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_query_system::ich::StableHashingContext; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; -use rustc_target::abi::{FIRST_VARIANT, ReprOptions, VariantIdx}; use tracing::{debug, info, trace}; use super::{ diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 3137fe9bd1d..62157d9bfe2 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -10,8 +10,8 @@ use crate::ty; #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)] pub enum AssocItemContainer { - TraitContainer, - ImplContainer, + Trait, + Impl, } /// Information about an associated item @@ -63,16 +63,16 @@ impl AssocItem { #[inline] pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> { match self.container { - AssocItemContainer::ImplContainer => None, - AssocItemContainer::TraitContainer => Some(tcx.parent(self.def_id)), + AssocItemContainer::Impl => None, + AssocItemContainer::Trait => Some(tcx.parent(self.def_id)), } } #[inline] pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> { match self.container { - AssocItemContainer::ImplContainer => Some(tcx.parent(self.def_id)), - AssocItemContainer::TraitContainer => None, + AssocItemContainer::Impl => Some(tcx.parent(self.def_id)), + AssocItemContainer::Trait => None, } } diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 9ee82942911..6ab4d76e545 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -10,7 +10,6 @@ use rustc_span::def_id::LocalDefIdMap; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; -use self::BorrowKind::*; use super::TyCtxt; use crate::hir::place::{ Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind, @@ -334,7 +333,7 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc #[derive(TypeFoldable, TypeVisitable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. - ImmBorrow, + Immutable, /// Data must be immutable but not aliasable. This kind of borrow /// cannot currently be expressed by the user and is used only in @@ -382,17 +381,17 @@ pub enum BorrowKind { /// borrow, it's just used when translating closures. /// /// FIXME: Rename this to indicate the borrow is actually not immutable. - UniqueImmBorrow, + UniqueImmutable, /// Data is mutable and not aliasable. - MutBorrow, + Mutable, } impl BorrowKind { pub fn from_mutbl(m: hir::Mutability) -> BorrowKind { match m { - hir::Mutability::Mut => MutBorrow, - hir::Mutability::Not => ImmBorrow, + hir::Mutability::Mut => BorrowKind::Mutable, + hir::Mutability::Not => BorrowKind::Immutable, } } @@ -402,13 +401,13 @@ impl BorrowKind { /// question. pub fn to_mutbl_lossy(self) -> hir::Mutability { match self { - MutBorrow => hir::Mutability::Mut, - ImmBorrow => hir::Mutability::Not, + BorrowKind::Mutable => hir::Mutability::Mut, + BorrowKind::Immutable => hir::Mutability::Not, // We have no type corresponding to a unique imm borrow, so // use `&mut`. It gives all the capabilities of a `&uniq` // and hence is a safe "over approximation". - UniqueImmBorrow => hir::Mutability::Mut, + BorrowKind::UniqueImmutable => hir::Mutability::Mut, } } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index ef9dfdd2f96..b5358f0ca35 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -10,12 +10,12 @@ use std::hash::Hash; use std::intrinsics; use std::marker::DiscriminantKind; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; use rustc_serialize::{Decodable, Encodable}; use rustc_span::Span; -use rustc_target::abi::{FieldIdx, VariantIdx}; pub use rustc_type_ir::{TyDecoder, TyEncoder}; use crate::arena::ArenaAllocatable; diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 1732374ab8c..b72edc1c532 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -1,11 +1,11 @@ use std::fmt; use std::num::NonZero; +use rustc_abi::Size; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use rustc_target::abi::Size; use crate::ty::TyCtxt; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9abad6d1a68..c55733da7b3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -12,7 +12,7 @@ use std::marker::PhantomData; use std::ops::{Bound, Deref}; use std::{fmt, iter, mem}; -use rustc_abi::{FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx}; +use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx}; use rustc_ast::{self as ast, attr}; use rustc_data_structures::defer; use rustc_data_structures::fingerprint::Fingerprint; @@ -49,7 +49,6 @@ use rustc_session::{Limit, MetadataKind, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::spec::abi; use rustc_type_ir::TyKind::*; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::lang_items::TraitSolverLangItem; @@ -136,7 +135,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type AllocId = crate::mir::interpret::AllocId; type Pat = Pattern<'tcx>; type Safety = hir::Safety; - type Abi = abi::Abi; + type Abi = ExternAbi; type Const = ty::Const<'tcx>; type PlaceholderConst = ty::PlaceholderConst; @@ -695,13 +694,13 @@ impl<'tcx> rustc_type_ir::inherent::DefId<TyCtxt<'tcx>> for DefId { } } -impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi { +impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for ExternAbi { fn rust() -> Self { - abi::Abi::Rust + ExternAbi::Rust } fn is_rust(self) -> bool { - matches!(self, abi::Abi::Rust) + matches!(self, ExternAbi::Rust) } } @@ -1060,7 +1059,7 @@ impl<'tcx> CommonLifetimes<'tcx> { .map(|v| { mk(ty::ReBound(ty::DebruijnIndex::from(i), ty::BoundRegion { var: ty::BoundVar::from(v), - kind: ty::BrAnon, + kind: ty::BoundRegionKind::Anon, })) }) .collect() @@ -1983,7 +1982,10 @@ impl<'tcx> TyCtxt<'tcx> { region = self.map_opaque_lifetime_to_parent_lifetime(def_id); continue; } - break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into()))); + break ( + scope, + ty::BoundRegionKind::Named(def_id.into(), self.item_name(def_id.into())), + ); }; let is_impl_item = match self.hir_node_by_def_id(suitable_region_binding_scope) { @@ -2557,7 +2559,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(params) => *params, _ => bug!(), }; - self.mk_fn_sig(params, s.output(), s.c_variadic, safety, abi::Abi::Rust) + self.mk_fn_sig(params, s.output(), s.c_variadic, safety, ExternAbi::Rust) }) } @@ -2819,7 +2821,7 @@ impl<'tcx> TyCtxt<'tcx> { output: I::Item, c_variadic: bool, safety: hir::Safety, - abi: abi::Abi, + abi: ExternAbi, ) -> T::Output where I: IntoIterator<Item = T>, @@ -3092,7 +3094,7 @@ impl<'tcx> TyCtxt<'tcx> { return ty::Region::new_late_param( self, new_parent.to_def_id(), - ty::BoundRegionKind::BrNamed( + ty::BoundRegionKind::Named( lbv.to_def_id(), self.item_name(lbv.to_def_id()), ), @@ -3125,7 +3127,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - // FIXME(effects): Please remove this. It's a footgun. /// Whether the trait impl is marked const. This does not consider stability or feature gates. pub fn is_const_trait_impl(self, def_id: DefId) -> bool { self.def_kind(def_id) == DefKind::Impl { of_trait: true } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index b5a77b3c942..7adbd556141 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -399,7 +399,7 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let kind = entry - .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon)) + .or_insert_with(|| ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)) .expect_region(); let br = ty::BoundRegion { var, kind }; ty::Region::new_bound(self.tcx, ty::INNERMOST, br) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index e237d382900..0d1c56f0d38 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -71,7 +71,7 @@ pub enum InstanceKind<'tcx> { /// - coroutines Item(DefId), - /// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI). + /// An intrinsic `fn` item (with `"rust-intrinsic"` ABI). /// /// Alongside `Virtual`, this is the only `InstanceKind` that does not have its own callable MIR. /// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the @@ -690,7 +690,7 @@ impl<'tcx> Instance<'tcx> { && !matches!( tcx.opt_associated_item(def), Some(ty::AssocItem { - container: ty::AssocItemContainer::TraitContainer, + container: ty::AssocItemContainer::Trait, .. }) ) diff --git a/compiler/rustc_middle/src/ty/intrinsic.rs b/compiler/rustc_middle/src/ty/intrinsic.rs index ed0fb37d3b8..6a3ddacb424 100644 --- a/compiler/rustc_middle/src/ty/intrinsic.rs +++ b/compiler/rustc_middle/src/ty/intrinsic.rs @@ -9,6 +9,8 @@ pub struct IntrinsicDef { pub name: Symbol, /// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it. pub must_be_overridden: bool, + /// Whether the intrinsic can be invoked from stable const fn + pub const_stable: bool, } impl TyCtxt<'_> { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0560ffe058a..76e3183fcbb 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,11 +2,10 @@ use std::num::NonZero; use std::ops::Bound; use std::{cmp, fmt}; -use rustc_abi::Primitive::{self, Float, Int, Pointer}; use rustc_abi::{ - AddressSpace, Align, BackendRepr, FieldsShape, HasDataLayout, Integer, LayoutCalculator, - LayoutData, PointeeInfo, PointerKind, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, - Variants, + AddressSpace, Align, BackendRepr, ExternAbi, FieldIdx, FieldsShape, HasDataLayout, LayoutData, + PointeeInfo, PointerKind, Primitive, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, + TyAbiInterface, VariantIdx, Variants, }; use rustc_error_messages::DiagMessage; use rustc_errors::{ @@ -19,9 +18,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; use rustc_session::config::OptLevel; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; -use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{FieldIdx, TyAbiInterface, VariantIdx, call}; -use rustc_target::spec::abi::Abi as SpecAbi; +use rustc_target::callconv::FnAbi; use rustc_target::spec::{ HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, PanicStrategy, Target, WasmCAbi, X86Abi, }; @@ -86,16 +83,16 @@ impl abi::Integer { repr: &ReprOptions, min: i128, max: i128, - ) -> (Integer, bool) { + ) -> (abi::Integer, bool) { // Theoretically, negative values could be larger in unsigned representation // than the unsigned representation of the signed minimum. However, if there // are any negative values, the only valid unsigned representation is u128 // which can fit all i128 values, so the result remains unaffected. - let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128)); - let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max)); + let unsigned_fit = abi::Integer::fit_unsigned(cmp::max(min as u128, max as u128)); + let signed_fit = cmp::max(abi::Integer::fit_signed(min), abi::Integer::fit_signed(max)); if let Some(ity) = repr.int { - let discr = Integer::from_attr(&tcx, ity); + let discr = abi::Integer::from_attr(&tcx, ity); let fit = if ity.is_signed() { signed_fit } else { unsigned_fit }; if discr < fit { bug!( @@ -113,7 +110,7 @@ impl abi::Integer { tcx.data_layout().c_enum_min_size } else { // repr(Rust) enums try to be as small as possible - Integer::I8 + abi::Integer::I8 }; // If there are no negative values, we can use the unsigned fit. @@ -154,10 +151,10 @@ impl Primitive { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { - Int(i, signed) => i.to_ty(tcx, signed), - Float(f) => f.to_ty(tcx), + Primitive::Int(i, signed) => i.to_ty(tcx, signed), + Primitive::Float(f) => f.to_ty(tcx), // FIXME(erikdesjardins): handle non-default addrspace ptr sizes - Pointer(_) => Ty::new_mut_ptr(tcx, tcx.types.unit), + Primitive::Pointer(_) => Ty::new_mut_ptr(tcx, tcx.types.unit), } } @@ -166,13 +163,13 @@ impl Primitive { #[inline] fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { - Int(i, signed) => i.to_ty(tcx, signed), + Primitive::Int(i, signed) => i.to_ty(tcx, signed), // FIXME(erikdesjardins): handle non-default addrspace ptr sizes - Pointer(_) => { + Primitive::Pointer(_) => { let signed = false; tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed) } - Float(_) => bug!("floats do not have an int type"), + Primitive::Float(_) => bug!("floats do not have an int type"), } } } @@ -299,13 +296,13 @@ impl<'tcx> IntoDiagArg for LayoutError<'tcx> { #[derive(Clone, Copy)] pub struct LayoutCx<'tcx> { - pub calc: LayoutCalculator<TyCtxt<'tcx>>, + pub calc: abi::LayoutCalculator<TyCtxt<'tcx>>, pub param_env: ty::ParamEnv<'tcx>, } impl<'tcx> LayoutCx<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - Self { calc: LayoutCalculator::new(tcx), param_env } + Self { calc: abi::LayoutCalculator::new(tcx), param_env } } } @@ -645,7 +642,7 @@ impl<T, E> MaybeResult<T> for Result<T, E> { } } -pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>; +pub type TyAndLayout<'tcx> = rustc_abi::TyAndLayout<'tcx, Ty<'tcx>>; /// Trait for contexts that want to be able to compute layouts of types. /// This automatically gives access to `LayoutOf`, through a blanket `impl`. @@ -1048,7 +1045,7 @@ where if let Some(variant) = data_variant { // FIXME(erikdesjardins): handle non-default addrspace ptr sizes // (requires passing in the expected address space from the caller) - let ptr_end = offset + Pointer(AddressSpace::DATA).size(cx); + let ptr_end = offset + Primitive::Pointer(AddressSpace::DATA).size(cx); for i in 0..variant.fields.count() { let field_start = variant.fields.offset(i); if field_start <= offset { @@ -1163,7 +1160,7 @@ where /// affects various optimizations and codegen. #[inline] #[tracing::instrument(level = "debug", skip(tcx))] -pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool { +pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi) -> bool { if let Some(did) = fn_def_id { // Special attribute for functions which can't unwind. if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) { @@ -1195,7 +1192,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> // ABIs have such an option. Otherwise the only other thing here is Rust // itself, and those ABIs are determined by the panic strategy configured // for this compilation. - use SpecAbi::*; + use ExternAbi::*; match abi { C { unwind } | System { unwind } @@ -1231,17 +1228,16 @@ pub enum FnAbiError<'tcx> { Layout(LayoutError<'tcx>), /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. - AdjustForForeignAbi(call::AdjustForForeignAbiError), + AdjustForForeignAbi(rustc_target::callconv::AdjustForForeignAbiError), } impl<'a, 'b, G: EmissionGuarantee> Diagnostic<'a, G> for FnAbiError<'b> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { match self { Self::Layout(e) => e.into_diagnostic().into_diag(dcx, level), - Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported { - arch, - abi, - }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diag(dcx, level), + Self::AdjustForForeignAbi( + rustc_target::callconv::AdjustForForeignAbiError::Unsupported { arch, abi }, + ) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diag(dcx, level), } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dac81a6dfbb..6d9ba3d60e3 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -24,6 +24,7 @@ pub use assoc::*; pub use generic_args::{GenericArgKind, TermKind, *}; pub use generics::*; pub use intrinsic::IntrinsicDef; +use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx}; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::node_id::NodeMap; pub use rustc_ast_ir::{Movability, Mutability, try_visit}; @@ -48,21 +49,12 @@ pub use rustc_session::lint::RegisteredTools; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{ExpnId, ExpnKind, Span}; -use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx}; -pub use rustc_target::abi::{ReprFlags, ReprOptions}; -pub use rustc_type_ir::ConstKind::{ - Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt, - Placeholder as PlaceholderCt, Unevaluated, Value, -}; pub use rustc_type_ir::relate::VarianceDiagInfo; pub use rustc_type_ir::*; use tracing::{debug, instrument}; pub use vtable::*; use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; -pub use self::AssocItemContainer::*; -pub use self::BorrowKind::*; -pub use self::IntVarValue::*; pub use self::closure::{ BorrowKind, CAPTURE_STRUCT_LOCAL, CaptureInfo, CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId, @@ -92,7 +84,6 @@ pub use self::predicate::{ RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, TraitPredicate, TraitRef, TypeOutlivesPredicate, }; -pub use self::region::BoundRegionKind::*; pub use self::region::{ BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, Region, RegionKind, RegionVid, }; @@ -903,7 +894,7 @@ impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderRegion { } fn new(ui: UniverseIndex, var: BoundVar) -> Self { - Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::BrAnon } } + Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::Anon } } } } @@ -2079,7 +2070,7 @@ impl<'tcx> TyCtxt<'tcx> { let Some(item) = self.opt_associated_item(def_id) else { return false; }; - if item.container != ty::AssocItemContainer::ImplContainer { + if item.container != ty::AssocItemContainer::Impl { return false; } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 2480cee3dc4..039c988f5c9 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3,6 +3,7 @@ use std::fmt::{self, Write as _}; use std::iter; use std::ops::{Deref, DerefMut}; +use rustc_abi::{ExternAbi, Size}; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; @@ -17,8 +18,6 @@ use rustc_session::Limit; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_span::FileNameDisplayPreference; use rustc_span::symbol::{Ident, Symbol, kw}; -use rustc_target::abi::Size; -use rustc_target::spec::abi::Abi; use rustc_type_ir::{Upcast as _, elaborate}; use smallvec::SmallVec; @@ -2484,7 +2483,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. }) => { - if let ty::BrNamed(_, name) = br + if let ty::BoundRegionKind::Named(_, name) = br && br.is_named() { p!(write("{}", name)); @@ -2570,7 +2569,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound match kind { - ty::BrAnon | ty::BrEnv => r, + ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => r, _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind }; @@ -2689,12 +2688,13 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { binder_level_idx: ty::DebruijnIndex, br: ty::BoundRegion| { let (name, kind) = match br.kind { - ty::BrAnon | ty::BrEnv => { + ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => { let name = next_name(self); if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { - let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name); + let kind = + ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name); return ty::Region::new_bound( tcx, ty::INNERMOST, @@ -2703,14 +2703,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } } - (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)) + (name, ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name)) } - ty::BrNamed(def_id, kw::UnderscoreLifetime | kw::Empty) => { + ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime | kw::Empty) => { let name = next_name(self); if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { - let kind = ty::BrNamed(def_id, name); + let kind = ty::BoundRegionKind::Named(def_id, name); return ty::Region::new_bound( tcx, ty::INNERMOST, @@ -2719,9 +2719,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } } - (name, ty::BrNamed(def_id, name)) + (name, ty::BoundRegionKind::Named(def_id, name)) } - ty::BrNamed(_, name) => { + ty::BoundRegionKind::Named(_, name) => { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = br.kind; @@ -3029,7 +3029,7 @@ define_print! { ty::FnSig<'tcx> { p!(write("{}", self.safety.prefix_str())); - if self.abi != Abi::Rust { + if self.abi != ExternAbi::Rust { p!(write("extern {} ", self.abi)); } diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index be4772e888f..60c2c322d4f 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -56,7 +56,7 @@ impl<'tcx> Region<'tcx> { bound_region: ty::BoundRegion, ) -> Region<'tcx> { // Use a pre-interned one when possible. - if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region + if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) && let Some(re) = inner.get(var.as_usize()).copied() { @@ -147,7 +147,7 @@ impl<'tcx> rustc_type_ir::inherent::Region<TyCtxt<'tcx>> for Region<'tcx> { } fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { - Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon }) + Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }) } fn new_static(tcx: TyCtxt<'tcx>) -> Self { @@ -311,7 +311,7 @@ impl<'tcx> Region<'tcx> { Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id) } ty::ReLateParam(ty::LateParamRegion { - bound_region: ty::BoundRegionKind::BrNamed(def_id, _), + bound_region: ty::BoundRegionKind::Named(def_id, _), .. }) => Some(def_id), _ => None, @@ -355,7 +355,7 @@ impl std::fmt::Debug for EarlyParamRegion { /// Similar to a placeholder region as we create `LateParam` regions when entering a binder /// except they are always in the root universe and instead of using a boundvar to distinguish /// between others we use the `DefId` of the parameter. For this reason the `bound_region` field -/// should basically always be `BoundRegionKind::BrNamed` as otherwise there is no way of telling +/// should basically always be `BoundRegionKind::Named` as otherwise there is no way of telling /// different parameters apart. pub struct LateParamRegion { pub scope: DefId, @@ -366,17 +366,17 @@ pub struct LateParamRegion { #[derive(HashStable)] pub enum BoundRegionKind { /// An anonymous region parameter for a given fn (&T) - BrAnon, + Anon, /// Named region parameters for functions (a in &'a T) /// /// The `DefId` is needed to distinguish free regions in /// the event of shadowing. - BrNamed(DefId, Symbol), + Named(DefId, Symbol), /// Anonymous region for the implicit env pointer parameter /// to a closure - BrEnv, + ClosureEnv, } #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] @@ -399,9 +399,9 @@ impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundRegion { impl core::fmt::Debug for BoundRegion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.kind { - BoundRegionKind::BrAnon => write!(f, "{:?}", self.var), - BoundRegionKind::BrEnv => write!(f, "{:?}.Env", self.var), - BoundRegionKind::BrNamed(def, symbol) => { + BoundRegionKind::Anon => write!(f, "{:?}", self.var), + BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var), + BoundRegionKind::Named(def, symbol) => { write!(f, "{:?}.Named({:?}, {:?})", self.var, def, symbol) } } @@ -411,9 +411,7 @@ impl core::fmt::Debug for BoundRegion { impl BoundRegionKind { pub fn is_named(&self) -> bool { match *self { - BoundRegionKind::BrNamed(_, name) => { - name != kw::UnderscoreLifetime && name != kw::Empty - } + BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime && name != kw::Empty, _ => false, } } @@ -421,7 +419,7 @@ impl BoundRegionKind { pub fn get_name(&self) -> Option<Symbol> { if self.is_named() { match *self { - BoundRegionKind::BrNamed(_, name) => return Some(name), + BoundRegionKind::Named(_, name) => return Some(name), _ => unreachable!(), } } @@ -431,7 +429,7 @@ impl BoundRegionKind { pub fn get_id(&self) -> Option<DefId> { match *self { - BoundRegionKind::BrNamed(id, _) => Some(id), + BoundRegionKind::Named(id, _) => Some(id), _ => None, } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 4872d8c89eb..e48fac6c7e8 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -5,11 +5,11 @@ use std::fmt::{self, Debug}; +use rustc_abi::TyAndLayout; use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; use rustc_hir::def::Namespace; use rustc_span::source_map::Spanned; -use rustc_target::abi::TyAndLayout; use rustc_type_ir::ConstKind; use super::print::PrettyPrinter; @@ -62,15 +62,15 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { impl fmt::Debug for ty::BoundRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::BrAnon => write!(f, "BrAnon"), - ty::BrNamed(did, name) => { + ty::BoundRegionKind::Anon => write!(f, "BrAnon"), + ty::BoundRegionKind::Named(did, name) => { if did.is_crate_root() { write!(f, "BrNamed({name})") } else { write!(f, "BrNamed({did:?}, {name})") } } - ty::BrEnv => write!(f, "BrEnv"), + ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"), } } } @@ -218,8 +218,8 @@ TrivialLiftImpls! { // provide any traversal implementations, we need to provide a traversal // implementation (only for TyCtxt<'_> interners). TrivialTypeTraversalImpls! { - ::rustc_target::abi::FieldIdx, - ::rustc_target::abi::VariantIdx, + ::rustc_abi::FieldIdx, + ::rustc_abi::VariantIdx, crate::middle::region::Scope, ::rustc_ast::InlineAsmOptions, ::rustc_ast::InlineAsmTemplatePiece, @@ -271,12 +271,12 @@ TrivialTypeTraversalAndLiftImpls! { interpret::AllocId, interpret::CtfeProvenance, interpret::Scalar, - rustc_target::abi::Size, + rustc_abi::Size, } TrivialLiftImpls! { ::rustc_hir::Safety, - ::rustc_target::spec::abi::Abi, + ::rustc_abi::ExternAbi, } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f54afdbc929..e27bb2fd135 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -8,6 +8,7 @@ use std::iter; use std::ops::{ControlFlow, Range}; use hir::def::{CtorKind, DefKind}; +use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_data_structures::captures::Captures; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; @@ -16,8 +17,6 @@ use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension}; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; -use rustc_target::spec::abi; use rustc_type_ir::TyKind::*; use rustc_type_ir::visit::TypeVisitableExt; use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind}; @@ -1365,7 +1364,7 @@ impl<'tcx> Ty<'tcx> { inputs_and_output: ty::List::empty(), c_variadic: false, safety: hir::Safety::Safe, - abi: abi::Abi::Rust, + abi: ExternAbi::Rust, }) } Closure(..) => bug!( diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 6aa2b2cd480..8cba5f33278 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -2,6 +2,7 @@ use std::collections::hash_map::Entry; use std::hash::Hash; use std::iter; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet}; use rustc_errors::ErrorGuaranteed; @@ -16,7 +17,6 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisit use rustc_middle::mir::FakeReadCause; use rustc_session::Session; use rustc_span::Span; -use rustc_target::abi::{FieldIdx, VariantIdx}; use super::RvalueScopes; use crate::hir::place::Place as HirPlace; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7fd7e463acf..fc5a3b762e5 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -2,6 +2,7 @@ use std::{fmt, iter}; +use rustc_abi::{ExternAbi, Float, Integer, IntegerType, Size}; use rustc_apfloat::Float as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher}; @@ -14,8 +15,6 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; use rustc_session::Limit; use rustc_span::sym; -use rustc_target::abi::{Float, Integer, IntegerType, Size}; -use rustc_target::spec::abi::Abi; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -736,8 +735,11 @@ impl<'tcx> TyCtxt<'tcx> { let ty = self.fold_regions(decl.ty, |re, debruijn| { assert_eq!(re, self.lifetimes.re_erased); let var = ty::BoundVar::from_usize(vars.len()); - vars.push(ty::BoundVariableKind::Region(ty::BrAnon)); - ty::Region::new_bound(self, debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) + vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)); + ty::Region::new_bound(self, debruijn, ty::BoundRegion { + var, + kind: ty::BoundRegionKind::Anon, + }) }); ty::EarlyBinder::bind(ty::Binder::bind_with_vars( ty, @@ -1783,13 +1785,14 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { /// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may /// cause an ICE that we otherwise may want to prevent. pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> { - if (matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic) - && tcx.features().intrinsics()) - || (tcx.has_attr(def_id, sym::rustc_intrinsic) && tcx.features().rustc_attrs()) + if tcx.features().intrinsics() + && (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic) + || tcx.has_attr(def_id, sym::rustc_intrinsic)) { Some(ty::IntrinsicDef { name: tcx.item_name(def_id.into()), must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden), + const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic), }) } else { None diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs index fe30cbfae4e..ed27a880562 100644 --- a/compiler/rustc_middle/src/util/call_kind.rs +++ b/compiler/rustc_middle/src/util/call_kind.rs @@ -72,8 +72,8 @@ pub fn call_kind<'tcx>( let parent = tcx.opt_associated_item(method_did).and_then(|assoc| { let container_id = assoc.container_id(tcx); match assoc.container { - AssocItemContainer::ImplContainer => tcx.trait_id_of_impl(container_id), - AssocItemContainer::TraitContainer => Some(container_id), + AssocItemContainer::Impl => tcx.trait_id_of_impl(container_id), + AssocItemContainer::Trait => Some(container_id), } }); diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 48ca38344cf..48d744a9ef6 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -67,7 +67,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> { err, false, rustc_hir::Safety::Safe, - rustc_target::spec::abi::Abi::Rust, + rustc_abi::ExternAbi::Rust, )); // SAFETY: This is never called when `Self` is not `ty::Binder<'tcx, ty::FnSig<'tcx>>`. diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 0481f715019..64457031997 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -136,7 +136,9 @@ impl<'tcx> Cx<'tcx> { Adjust::Deref(Some(deref)) => { // We don't need to do call adjust_span here since // deref coercions always start with a built-in deref. - let call = deref.method_call(self.tcx(), expr.ty); + let call_def_id = deref.method_call(self.tcx()); + let overloaded_callee = + Ty::new_fn_def(self.tcx(), call_def_id, self.tcx().mk_args(&[expr.ty.into()])); expr = Expr { temp_lifetime, @@ -150,7 +152,13 @@ impl<'tcx> Cx<'tcx> { let expr = Box::new([self.thir.exprs.push(expr)]); - self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span) + self.overloaded_place( + hir_expr, + adjustment.target, + Some(overloaded_callee), + expr, + deref.span, + ) } Adjust::Borrow(AutoBorrow::Ref(m)) => ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), @@ -1185,11 +1193,11 @@ impl<'tcx> Cx<'tcx> { ty::UpvarCapture::ByValue => captured_place_expr, ty::UpvarCapture::ByRef(upvar_borrow) => { let borrow_kind = match upvar_borrow { - ty::BorrowKind::ImmBorrow => BorrowKind::Shared, - ty::BorrowKind::UniqueImmBorrow => { + ty::BorrowKind::Immutable => BorrowKind::Shared, + ty::BorrowKind::UniqueImmutable => { BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } } - ty::BorrowKind::MutBorrow => { + ty::BorrowKind::Mutable => { BorrowKind::Mut { kind: mir::MutBorrowKind::Default } } }; diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 62a69b3464f..f84a0663897 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -18,7 +18,6 @@ rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } -rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 84c8a91b082..03f11885d58 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -1,9 +1,9 @@ +use rustc_abi::ExternAbi; use rustc_ast::InlineAsmOptions; use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt, layout}; use rustc_target::spec::PanicStrategy; -use rustc_target::spec::abi::Abi; /// A pass that runs which is targeted at ensuring that codegen guarantees about /// unwinding are upheld for compilations of panic=abort programs. @@ -38,9 +38,9 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { let body_ty = tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::CoroutineClosure(..) => Abi::RustCall, - ty::Coroutine(..) => Abi::Rust, + ty::Closure(..) => ExternAbi::RustCall, + ty::CoroutineClosure(..) => ExternAbi::RustCall, + ty::Coroutine(..) => ExternAbi::Rust, ty::Error(_) => return, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; @@ -79,10 +79,10 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { } TerminatorKind::Drop { .. } => { tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Unwind - && layout::fn_can_unwind(tcx, None, Abi::Rust) + && layout::fn_can_unwind(tcx, None, ExternAbi::Rust) } TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => { - layout::fn_can_unwind(tcx, None, Abi::Rust) + layout::fn_can_unwind(tcx, None, ExternAbi::Rust) } TerminatorKind::InlineAsm { options, .. } => { options.contains(InlineAsmOptions::MAY_UNWIND) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 6d5665b4331..063f220501f 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -54,6 +54,7 @@ mod by_move_body; use std::{iter, ops}; pub(super) use by_move_body::coroutine_by_move_body_def_id; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_hir as hir; @@ -75,7 +76,6 @@ use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::sym; -use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::spec::PanicStrategy; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt as _; diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 2c622b1927e..36eb435c63a 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -69,6 +69,7 @@ //! in case precise captures (edition 2021 closure capture rules) caused the inner coroutine //! to split one field capture into two. +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; @@ -80,7 +81,6 @@ use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{self, dump_mir}; use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::kw; -use rustc_target::abi::{FieldIdx, VariantIdx}; pub(crate) fn coroutine_by_move_body_def_id<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 168262bf01c..092bce1de2c 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; use std::collections::VecDeque; -use std::iter; use std::ops::{Index, IndexMut}; +use std::{iter, mem, slice}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; @@ -127,10 +127,10 @@ impl CoverageGraph { let mut bcbs = IndexVec::<BasicCoverageBlock, _>::with_capacity(num_basic_blocks); let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks); - let mut add_basic_coverage_block = |basic_blocks: &mut Vec<BasicBlock>| { + let mut flush_chain_into_new_bcb = |current_chain: &mut Vec<BasicBlock>| { // Take the accumulated list of blocks, leaving the vector empty // to be used by subsequent BCBs. - let basic_blocks = std::mem::take(basic_blocks); + let basic_blocks = mem::take(current_chain); let bcb = bcbs.next_index(); for &bb in basic_blocks.iter() { @@ -141,48 +141,41 @@ impl CoverageGraph { bcb_filtered_successors(mir_body[bb].terminator()).is_out_summable() }); let bcb_data = BasicCoverageBlockData { basic_blocks, is_out_summable }; - debug!("adding bcb{}: {:?}", bcb.index(), bcb_data); + debug!("adding {bcb:?}: {bcb_data:?}"); bcbs.push(bcb_data); }; - // Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows - // each block terminator's `successors()`. Coverage spans must map to actual source code, - // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal - // intentionally omits unwind paths. - // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and - // `catch_unwind()` handlers. + // Traverse the MIR control-flow graph, accumulating chains of blocks + // that can be combined into a single node in the coverage graph. + // A depth-first search ensures that if two nodes can be chained + // together, they will be adjacent in the traversal order. // Accumulates a chain of blocks that will be combined into one BCB. - let mut basic_blocks = Vec::new(); + let mut current_chain = vec![]; - let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator()); - for bb in short_circuit_preorder(mir_body, filtered_successors) + let subgraph = CoverageRelevantSubgraph::new(&mir_body.basic_blocks); + for bb in graph::depth_first_search(subgraph, mir::START_BLOCK) .filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable) { - // If the previous block can't be chained into `bb`, flush the accumulated - // blocks into a new BCB, then start building the next chain. - if let Some(&prev) = basic_blocks.last() - && (!filtered_successors(prev).is_chainable() || { - // If `bb` has multiple predecessor blocks, or `prev` isn't - // one of its predecessors, we can't chain and must flush. - let predecessors = &mir_body.basic_blocks.predecessors()[bb]; - predecessors.len() > 1 || !predecessors.contains(&prev) - }) - { - debug!( - terminator_kind = ?mir_body[prev].terminator().kind, - predecessors = ?&mir_body.basic_blocks.predecessors()[bb], - "can't chain from {prev:?} to {bb:?}" - ); - add_basic_coverage_block(&mut basic_blocks); + if let Some(&prev) = current_chain.last() { + // Adding a block to a non-empty chain is allowed if the + // previous block permits chaining, and the current block has + // `prev` as its sole predecessor. + let can_chain = subgraph.coverage_successors(prev).is_out_chainable() + && mir_body.basic_blocks.predecessors()[bb].as_slice() == &[prev]; + if !can_chain { + // The current block can't be added to the existing chain, so + // flush that chain into a new BCB, and start a new chain. + flush_chain_into_new_bcb(&mut current_chain); + } } - basic_blocks.push(bb); + current_chain.push(bb); } - if !basic_blocks.is_empty() { + if !current_chain.is_empty() { debug!("flushing accumulated blocks into one last BCB"); - add_basic_coverage_block(&mut basic_blocks); + flush_chain_into_new_bcb(&mut current_chain); } (bcbs, bb_to_bcb) @@ -389,34 +382,28 @@ impl BasicCoverageBlockData { /// indicates whether that block can potentially be combined into the same BCB /// as its sole successor. #[derive(Clone, Copy, Debug)] -enum CoverageSuccessors<'a> { - /// The terminator has exactly one straight-line successor, so its block can - /// potentially be combined into the same BCB as that successor. - Chainable(BasicBlock), - /// The block cannot be combined into the same BCB as its successor(s). - NotChainable(&'a [BasicBlock]), - /// Yield terminators are not chainable, and their execution count can also - /// differ from the execution count of their out-edge. - Yield(BasicBlock), +struct CoverageSuccessors<'a> { + /// Coverage-relevant successors of the corresponding terminator. + /// There might be 0, 1, or multiple targets. + targets: &'a [BasicBlock], + /// `Yield` terminators are not chainable, because their sole out-edge is + /// only followed if/when the generator is resumed after the yield. + is_yield: bool, } impl CoverageSuccessors<'_> { - fn is_chainable(&self) -> bool { - match self { - Self::Chainable(_) => true, - Self::NotChainable(_) => false, - Self::Yield(_) => false, - } + /// If `false`, this terminator cannot be chained into another block when + /// building the coverage graph. + fn is_out_chainable(&self) -> bool { + // If a terminator is out-summable and has exactly one out-edge, then + // it is eligible to be chained into its successor block. + self.is_out_summable() && self.targets.len() == 1 } /// Returns true if the terminator itself is assumed to have the same /// execution count as the sum of its out-edges (assuming no panics). fn is_out_summable(&self) -> bool { - match self { - Self::Chainable(_) => true, - Self::NotChainable(_) => true, - Self::Yield(_) => false, - } + !self.is_yield && !self.targets.is_empty() } } @@ -425,12 +412,7 @@ impl IntoIterator for CoverageSuccessors<'_> { type IntoIter = impl DoubleEndedIterator<Item = Self::Item>; fn into_iter(self) -> Self::IntoIter { - match self { - Self::Chainable(bb) | Self::Yield(bb) => { - Some(bb).into_iter().chain((&[]).iter().copied()) - } - Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()), - } + self.targets.iter().copied() } } @@ -440,14 +422,17 @@ impl IntoIterator for CoverageSuccessors<'_> { // `catch_unwind()` handlers. fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> { use TerminatorKind::*; - match terminator.kind { + let mut is_yield = false; + let targets = match &terminator.kind { // A switch terminator can have many coverage-relevant successors. - // (If there is exactly one successor, we still treat it as not chainable.) - SwitchInt { ref targets, .. } => CoverageSuccessors::NotChainable(targets.all_targets()), + SwitchInt { targets, .. } => targets.all_targets(), // A yield terminator has exactly 1 successor, but should not be chained, // because its resume edge has a different execution count. - Yield { resume, .. } => CoverageSuccessors::Yield(resume), + Yield { resume, .. } => { + is_yield = true; + slice::from_ref(resume) + } // These terminators have exactly one coverage-relevant successor, // and can be chained into it. @@ -455,24 +440,15 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera | Drop { target, .. } | FalseEdge { real_target: target, .. } | FalseUnwind { real_target: target, .. } - | Goto { target } => CoverageSuccessors::Chainable(target), + | Goto { target } => slice::from_ref(target), // A call terminator can normally be chained, except when it has no // successor because it is known to diverge. - Call { target: maybe_target, .. } => match maybe_target { - Some(target) => CoverageSuccessors::Chainable(target), - None => CoverageSuccessors::NotChainable(&[]), - }, + Call { target: maybe_target, .. } => maybe_target.as_slice(), // An inline asm terminator can normally be chained, except when it // diverges or uses asm goto. - InlineAsm { ref targets, .. } => { - if let [target] = targets[..] { - CoverageSuccessors::Chainable(target) - } else { - CoverageSuccessors::NotChainable(targets) - } - } + InlineAsm { targets, .. } => &targets, // These terminators have no coverage-relevant successors. CoroutineDrop @@ -480,8 +456,10 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera | TailCall { .. } | Unreachable | UnwindResume - | UnwindTerminate(_) => CoverageSuccessors::NotChainable(&[]), - } + | UnwindTerminate(_) => &[], + }; + + CoverageSuccessors { targets, is_yield } } /// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the @@ -616,28 +594,31 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> { } } -fn short_circuit_preorder<'a, 'tcx, F, Iter>( - body: &'a mir::Body<'tcx>, - filtered_successors: F, -) -> impl Iterator<Item = BasicBlock> + Captures<'a> + Captures<'tcx> -where - F: Fn(BasicBlock) -> Iter, - Iter: IntoIterator<Item = BasicBlock>, -{ - let mut visited = BitSet::new_empty(body.basic_blocks.len()); - let mut worklist = vec![mir::START_BLOCK]; - - std::iter::from_fn(move || { - while let Some(bb) = worklist.pop() { - if !visited.insert(bb) { - continue; - } - - worklist.extend(filtered_successors(bb)); +/// Wrapper around a [`mir::BasicBlocks`] graph that restricts each node's +/// successors to only the ones considered "relevant" when building a coverage +/// graph. +#[derive(Clone, Copy)] +struct CoverageRelevantSubgraph<'a, 'tcx> { + basic_blocks: &'a mir::BasicBlocks<'tcx>, +} +impl<'a, 'tcx> CoverageRelevantSubgraph<'a, 'tcx> { + fn new(basic_blocks: &'a mir::BasicBlocks<'tcx>) -> Self { + Self { basic_blocks } + } - return Some(bb); - } + fn coverage_successors(&self, bb: BasicBlock) -> CoverageSuccessors<'_> { + bcb_filtered_successors(self.basic_blocks[bb].terminator()) + } +} +impl<'a, 'tcx> graph::DirectedGraph for CoverageRelevantSubgraph<'a, 'tcx> { + type Node = BasicBlock; - None - }) + fn num_nodes(&self) -> usize { + self.basic_blocks.num_nodes() + } +} +impl<'a, 'tcx> graph::Successors for CoverageRelevantSubgraph<'a, 'tcx> { + fn successors(&self, bb: Self::Node) -> impl Iterator<Item = Self::Node> { + self.coverage_successors(bb).into_iter() + } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index dd85d06540d..7d073f1fa57 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -662,7 +662,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { // Exactly one side is known, attempt some algebraic simplifications. (FlatSet::Elem(const_arg), _) | (_, FlatSet::Elem(const_arg)) => { let layout = const_arg.layout; - if !matches!(layout.backend_repr, rustc_target::abi::BackendRepr::Scalar(..)) { + if !matches!(layout.backend_repr, rustc_abi::BackendRepr::Scalar(..)) { return (FlatSet::Top, FlatSet::Top); } diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 57f7a9ef7f5..b909dfa1320 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -2,13 +2,13 @@ //! //! Box is not actually a pointer so it is incorrect to dereference it directly. +use rustc_abi::FieldIdx; use rustc_hir::def_id::DefId; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::{Ty, TyCtxt}; -use rustc_target::abi::FieldIdx; /// Constructs the types used when accessing a Box's pointer fn build_ptr_tys<'tcx>( diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 58e1db19438..74572100db3 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -1,5 +1,6 @@ use std::fmt; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; use rustc_middle::mir::patch::MirPatch; @@ -14,7 +15,6 @@ use rustc_mir_dataflow::{ Analysis, MoveDataParamEnv, ResultsCursor, on_all_children_bits, on_lookup_result_bits, }; use rustc_span::Span; -use rustc_target::abi::{FieldIdx, VariantIdx}; use tracing::{debug, instrument}; use crate::deref_separator::deref_finder; diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 99892a1296b..3d560bdf75c 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -1,3 +1,4 @@ +use rustc_abi::ExternAbi; use rustc_hir::def_id::{LOCAL_CRATE, LocalDefId}; use rustc_middle::mir::*; use rustc_middle::query::{LocalCrate, Providers}; @@ -5,7 +6,6 @@ use rustc_middle::ty::{self, TyCtxt, layout}; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::FFI_UNWIND_CALLS; use rustc_target::spec::PanicStrategy; -use rustc_target::spec::abi::Abi; use tracing::debug; use crate::errors; @@ -26,9 +26,9 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { let body_ty = tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::CoroutineClosure(..) => Abi::RustCall, - ty::Coroutine(..) => Abi::Rust, + ty::Closure(..) => ExternAbi::RustCall, + ty::CoroutineClosure(..) => ExternAbi::RustCall, + ty::Coroutine(..) => ExternAbi::Rust, ty::Error(_) => return false, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; @@ -53,7 +53,11 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { // Rust calls cannot themselves create foreign unwinds. // We assume this is true for intrinsics as well. - if let Abi::RustIntrinsic | Abi::Rust | Abi::RustCall | Abi::RustCold = sig.abi() { + if let ExternAbi::RustIntrinsic + | ExternAbi::Rust + | ExternAbi::RustCall + | ExternAbi::RustCold = sig.abi() + { continue; }; diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index e55aeeac6e0..2945fc6f3d5 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -1,4 +1,5 @@ use itertools::Itertools; +use rustc_abi::ExternAbi; use rustc_hir::def_id::DefId; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -7,7 +8,6 @@ use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES; use rustc_span::Span; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; -use rustc_target::spec::abi::Abi; use crate::errors; @@ -161,7 +161,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { let fn_sig = self.tcx.fn_sig(fn_id).instantiate(self.tcx, fn_args); let unsafety = fn_sig.safety().prefix_str(); let abi = match fn_sig.abi() { - Abi::Rust => String::from(""), + ExternAbi::Rust => String::from(""), other_abi => { let mut s = String::from("extern \""); s.push_str(other_abi.name()); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 404470db5c5..e95ab4ffe16 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -3,6 +3,7 @@ use std::iter; use std::ops::{Range, RangeFrom}; +use rustc_abi::{ExternAbi, FieldIdx}; use rustc_attr::InlineAttr; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -18,8 +19,6 @@ use rustc_middle::ty::{ use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; use rustc_span::sym; -use rustc_target::abi::FieldIdx; -use rustc_target::spec::abi::Abi; use tracing::{debug, instrument, trace, trace_span}; use crate::cost_checker::CostChecker; @@ -254,7 +253,7 @@ impl<'tcx> Inliner<'tcx> { trace!(?output_type, ?destination_ty); return Err("failed to normalize return type"); } - if callsite.fn_sig.abi() == Abi::RustCall { + if callsite.fn_sig.abi() == ExternAbi::RustCall { // FIXME: Don't inline user-written `extern "rust-call"` functions, // since this is generally perf-negative on rustc, and we hope that // LLVM will inline these functions instead. @@ -808,7 +807,7 @@ impl<'tcx> Inliner<'tcx> { // tmp2 = tuple_tmp.2 // // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`. - if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() { + if callsite.fn_sig.abi() == ExternAbi::RustCall && callee_body.spread_arg.is_none() { // FIXME(edition_2024): switch back to a normal method call. let mut args = <_>::into_iter(args); let self_ = self.create_temp_if_necessary( diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 8bcc91b4488..9471c1b2a9a 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -1,5 +1,6 @@ //! Performs various peephole optimizations. +use rustc_abi::ExternAbi; use rustc_ast::attr; use rustc_hir::LangItem; use rustc_middle::bug; @@ -8,7 +9,6 @@ use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, layout}; use rustc_span::sym; use rustc_span::symbol::Symbol; -use rustc_target::spec::abi::Abi; use crate::simplify::simplify_duplicate_switch_targets; use crate::take_array; @@ -321,8 +321,8 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { let body_ty = self.tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::Coroutine(..) => Abi::Rust, + ty::Closure(..) => ExternAbi::RustCall, + ty::Coroutine(..) => ExternAbi::Rust, _ => bug!("unexpected body ty: {:?}", body_ty), }; diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 9b9b0b705bf..3772589ac4e 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -35,6 +35,7 @@ //! Likewise, applying the optimisation can create a lot of new MIR, so we bound the instruction //! cost by `MAX_COST`. +use rustc_abi::{TagEncoding, Variants}; use rustc_arena::DroplessArena; use rustc_const_eval::const_eval::DummyMachine; use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; @@ -50,7 +51,6 @@ use rustc_middle::ty::{self, ScalarInt, TyCtxt}; use rustc_mir_dataflow::lattice::HasBottom; use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, State, TrackElem}; use rustc_span::DUMMY_SP; -use rustc_target::abi::{TagEncoding, Variants}; use tracing::{debug, instrument, trace}; use crate::cost_checker::CostChecker; diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 3e263aa4067..fa659a56a27 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -1,10 +1,10 @@ +use rustc_abi::{HasDataLayout, Size, TagEncoding, Variants}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt}; use rustc_session::Session; -use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants}; /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large /// enough discrepancy between them. @@ -249,8 +249,8 @@ impl EnumSizeOpt { macro_rules! encode_store { ($curr_idx: expr, $endian: expr, $bytes: expr) => { let bytes = match $endian { - rustc_target::abi::Endian::Little => $bytes.to_le_bytes(), - rustc_target::abi::Endian::Big => $bytes.to_be_bytes(), + rustc_abi::Endian::Little => $bytes.to_le_bytes(), + rustc_abi::Endian::Big => $bytes.to_be_bytes(), }; for (i, b) in bytes.into_iter().enumerate() { data[$curr_idx + i] = b; @@ -263,10 +263,10 @@ impl EnumSizeOpt { target_bytes * adt_def.discriminant_for_variant(tcx, var_idx).val as usize; let sz = layout.size; match ptr_sized_int { - rustc_target::abi::Integer::I32 => { + rustc_abi::Integer::I32 => { encode_store!(curr_idx, data_layout.endian, sz.bytes() as u32); } - rustc_target::abi::Integer::I64 => { + rustc_abi::Integer::I64 => { encode_store!(curr_idx, data_layout.endian, sz.bytes()); } _ => unreachable!(), diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index ad3126f66a6..237227f5294 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -1,11 +1,11 @@ use std::iter; +use rustc_abi::Integer; use rustc_index::IndexSlice; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt}; -use rustc_target::abi::Integer; use rustc_type_ir::TyKind::*; use super::simplify::simplify_cfg; diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 55dd96100b0..20c34a7469e 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -1,10 +1,10 @@ +use rustc_abi::FieldIdx; use rustc_index::bit_set::ChunkedBitSet; use rustc_middle::mir::{Body, TerminatorKind}; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{Analysis, MaybeReachable, move_path_children_matching}; -use rustc_target::abi::FieldIdx; /// Removes `Drop` terminators whose target is known to be uninitialized at /// that point. diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e872878a751..ffa11f5b213 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1,6 +1,7 @@ use std::assert_matches::assert_matches; use std::{fmt, iter}; +use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -15,8 +16,6 @@ use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; -use rustc_target::spec::abi::Abi; use tracing::{debug, instrument}; use crate::{ @@ -905,7 +904,7 @@ fn build_call_shim<'tcx>( let mut body = new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span); - if let Abi::RustCall = sig.abi { + if let ExternAbi::RustCall = sig.abi { body.spread_arg = Some(Local::new(sig.inputs().len())); } diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 71723f040b3..f1672272862 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -1,6 +1,7 @@ use std::iter; use itertools::Itertools; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; use rustc_const_eval::interpret; use rustc_hir::def_id::DefId; @@ -18,7 +19,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::source_map::respan; use rustc_span::{Span, Symbol}; -use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::spec::PanicStrategy; use tracing::debug; diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 2de0059bc7f..53bbb122096 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -1,3 +1,4 @@ +use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_hir::LangItem; use rustc_index::IndexVec; @@ -8,7 +9,6 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; use tracing::{debug, instrument}; pub(super) struct ScalarReplacementOfAggregates; diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index f3dafd13824..9cd32459c7b 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -2,13 +2,13 @@ //! when all of their successors are unreachable. This is achieved through a //! post-order traversal of the blocks. +use rustc_abi::Size; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; -use rustc_target::abi::Size; pub(super) struct UnreachablePropagation; diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 8109a9b8ba0..ae4e6ea6a74 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1,5 +1,6 @@ //! Validates the MIR to ensure that invariants are upheld. +use rustc_abi::{ExternAbi, FIRST_VARIANT, Size}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::LangItem; use rustc_index::IndexVec; @@ -15,8 +16,6 @@ use rustc_middle::ty::{ Variance, }; use rustc_middle::{bug, span_bug}; -use rustc_target::abi::{FIRST_VARIANT, Size}; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::ObligationCtxt; use rustc_type_ir::Upcast; @@ -60,9 +59,9 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { let body_ty = tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::CoroutineClosure(..) => Abi::RustCall, - ty::Coroutine(..) => Abi::Rust, + ty::Closure(..) => ExternAbi::RustCall, + ty::CoroutineClosure(..) => ExternAbi::RustCall, + ty::Coroutine(..) => ExternAbi::Rust, // No need to do MIR validation on error bodies ty::Error(_) => return, _ => { diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index c7f1b9fa784..6c881fd7e06 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 63afad5df49..85151e5f093 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -211,6 +211,7 @@ mod move_check; use std::path::PathBuf; use move_check::MoveCheckState; +use rustc_abi::Size; use rustc_data_structures::sync::{LRef, MTLock, par_for_each_in}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; @@ -237,7 +238,6 @@ use rustc_session::config::EntryFnType; use rustc_span::source_map::{Spanned, dummy_spanned, respan}; use rustc_span::symbol::{Ident, sym}; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::Size; use tracing::{debug, instrument, trace}; use crate::errors::{self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit}; diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index fdf44e12378..451c215566b 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -bitflags = "2.4.1" derive-where = "1.2.7" rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } rustc_data_structures = { path = "../rustc_data_structures", optional = true } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 5bfc156ed94..0912e5effa6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -84,7 +84,7 @@ where let cx = ecx.cx(); let mut candidates = vec![]; - // FIXME(effects): We elaborate here because the implied const bounds + // FIXME(const_trait_impl): We elaborate here because the implied const bounds // aren't necessarily elaborated. We probably should prefix this query // with `explicit_`... for clause in elaborate::elaborate( diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index e23e475a2a6..df4f0ffdd57 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -609,8 +609,6 @@ where return Err(NoSolution); } - // FIXME(effects): Implement this when we get const working in the new solver - // `Destruct` is automatically implemented for every type in // non-const environments. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 8bd615e6d79..c85d0bd05cb 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -136,8 +136,9 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { node_replacements.array_windows() { assert!( - node_range.0.end <= next_node_range.0.start, - "Node ranges should be disjoint: ({:?}, {:?}) ({:?}, {:?})", + node_range.0.end <= next_node_range.0.start + || node_range.0.end >= next_node_range.0.end, + "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", node_range, tokens, next_node_range, @@ -145,8 +146,20 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { ); } - // Process the replace ranges. - for (node_range, target) in node_replacements.into_iter() { + // Process the replace ranges, starting from the highest start + // position and working our way back. If have tokens like: + // + // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }` + // + // Then we will generate replace ranges for both + // the `#[cfg(FALSE)] field: bool` and the entire + // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }` + // + // By starting processing from the replace range with the greatest + // start position, we ensure that any (outer) replace range which + // encloses another (inner) replace range will fully overwrite the + // inner range's replacement. + for (node_range, target) in node_replacements.into_iter().rev() { assert!( !node_range.0.is_empty(), "Cannot replace an empty node range: {:?}", @@ -383,9 +396,10 @@ impl<'a> Parser<'a> { // from `ParserRange` form to `NodeRange` form. We will perform the actual // replacement only when we convert the `LazyAttrTokenStream` to an // `AttrTokenStream`. - self.capture_state - .parser_replacements - .drain(parser_replacements_start..parser_replacements_end) + self.capture_state.parser_replacements + [parser_replacements_start..parser_replacements_end] + .iter() + .cloned() .chain(inner_attr_parser_replacements) .map(|(parser_range, data)| { (NodeRange::new(parser_range, collect_pos.start_pos), data) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index e5e70ba2033..6f0bcf5c3f0 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -679,10 +679,6 @@ passes_rustc_pub_transparent = attribute should be applied to `#[repr(transparent)]` types .label = not a `#[repr(transparent)]` type -passes_rustc_safe_intrinsic = - attribute should be applied to intrinsic functions - .label = not an intrinsic function - passes_rustc_std_internal_symbol = attribute should be applied to functions or statics .label = not a function or static diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0a2926c0404..64a527ef106 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -210,9 +210,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | [sym::rustc_promotable, ..] => self.check_stability_promotable(attr, target), [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), [sym::rustc_confusables, ..] => self.check_confusables(attr, target), - [sym::rustc_safe_intrinsic, ..] => { - self.check_rustc_safe_intrinsic(hir_id, attr, span, target) - } [sym::cold, ..] => self.check_cold(hir_id, attr, span, target), [sym::link, ..] => self.check_link(hir_id, attr, span, target), [sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target), @@ -2055,25 +2052,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_rustc_safe_intrinsic( - &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, - ) { - if let Target::ForeignFn = target - && let hir::Node::Item(Item { - kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic, .. }, - .. - }) = self.tcx.parent_hir_node(hir_id) - { - return; - } - - self.dcx().emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span }); - } - fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) { match target { Target::Fn | Target::Static => {} diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 8bd767c1243..70c92f0144c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -642,15 +642,6 @@ pub(crate) struct RustcAllowConstFnUnstable { } #[derive(Diagnostic)] -#[diag(passes_rustc_safe_intrinsic)] -pub(crate) struct RustcSafeIntrinsic { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(passes_rustc_std_internal_symbol)] pub(crate) struct RustcStdInternalSymbol { #[primary_span] diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 27714a0fdcc..55fdbac8ad6 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -3,7 +3,7 @@ // completely accurate (some things might be counted twice, others missed). use rustc_ast::visit::BoundKind; -use rustc_ast::{self as ast, AttrId, NodeId, visit as ast_visit}; +use rustc_ast::{self as ast, NodeId, visit as ast_visit}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::{HirId, intravisit as hir_visit}; @@ -13,13 +13,6 @@ use rustc_middle::util::common::to_readable_str; use rustc_span::Span; use rustc_span::def_id::LocalDefId; -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -enum Id { - Node(HirId), - Attr(AttrId), - None, -} - struct NodeStats { count: usize, size: usize, @@ -62,7 +55,7 @@ impl Node { struct StatCollector<'k> { krate: Option<Map<'k>>, nodes: FxHashMap<&'static str, Node>, - seen: FxHashSet<Id>, + seen: FxHashSet<HirId>, } pub fn print_hir_stats(tcx: TyCtxt<'_>) { @@ -87,12 +80,18 @@ pub fn print_ast_stats(krate: &ast::Crate, title: &str, prefix: &str) { impl<'k> StatCollector<'k> { // Record a top-level node. - fn record<T>(&mut self, label: &'static str, id: Id, val: &T) { + fn record<T>(&mut self, label: &'static str, id: Option<HirId>, val: &T) { self.record_inner(label, None, id, val); } // Record a two-level entry, with a top-level enum type and a variant. - fn record_variant<T>(&mut self, label1: &'static str, label2: &'static str, id: Id, val: &T) { + fn record_variant<T>( + &mut self, + label1: &'static str, + label2: &'static str, + id: Option<HirId>, + val: &T, + ) { self.record_inner(label1, Some(label2), id, val); } @@ -100,10 +99,10 @@ impl<'k> StatCollector<'k> { &mut self, label1: &'static str, label2: Option<&'static str>, - id: Id, + id: Option<HirId>, val: &T, ) { - if id != Id::None && !self.seen.insert(id) { + if id.is_some_and(|x| !self.seen.insert(x)) { return; } @@ -191,7 +190,7 @@ macro_rules! record_variants { impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_param(&mut self, param: &'v hir::Param<'v>) { - self.record("Param", Id::Node(param.hir_id), param); + self.record("Param", Some(param.hir_id), param); hir_visit::walk_param(self, param) } @@ -221,7 +220,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_item(&mut self, i: &'v hir::Item<'v>) { - record_variants!((self, i, i.kind, Id::Node(i.hir_id()), hir, Item, ItemKind), [ + record_variants!((self, i, i.kind, Some(i.hir_id()), hir, Item, ItemKind), [ ExternCrate, Use, Static, @@ -243,47 +242,46 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_body(&mut self, b: &hir::Body<'v>) { - self.record("Body", Id::None, b); + self.record("Body", None, b); hir_visit::walk_body(self, b); } fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, n: HirId) { - self.record("Mod", Id::None, m); + self.record("Mod", None, m); hir_visit::walk_mod(self, m, n) } fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) { - record_variants!( - (self, i, i.kind, Id::Node(i.hir_id()), hir, ForeignItem, ForeignItemKind), - [Fn, Static, Type] - ); + record_variants!((self, i, i.kind, Some(i.hir_id()), hir, ForeignItem, ForeignItemKind), [ + Fn, Static, Type + ]); hir_visit::walk_foreign_item(self, i) } fn visit_local(&mut self, l: &'v hir::LetStmt<'v>) { - self.record("Local", Id::Node(l.hir_id), l); + self.record("Local", Some(l.hir_id), l); hir_visit::walk_local(self, l) } fn visit_block(&mut self, b: &'v hir::Block<'v>) { - self.record("Block", Id::Node(b.hir_id), b); + self.record("Block", Some(b.hir_id), b); hir_visit::walk_block(self, b) } fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) { - record_variants!((self, s, s.kind, Id::Node(s.hir_id), hir, Stmt, StmtKind), [ + record_variants!((self, s, s.kind, Some(s.hir_id), hir, Stmt, StmtKind), [ Let, Item, Expr, Semi ]); hir_visit::walk_stmt(self, s) } fn visit_arm(&mut self, a: &'v hir::Arm<'v>) { - self.record("Arm", Id::Node(a.hir_id), a); + self.record("Arm", Some(a.hir_id), a); hir_visit::walk_arm(self, a) } fn visit_pat(&mut self, p: &'v hir::Pat<'v>) { - record_variants!((self, p, p.kind, Id::Node(p.hir_id), hir, Pat, PatKind), [ + record_variants!((self, p, p.kind, Some(p.hir_id), hir, Pat, PatKind), [ Wild, Binding, Struct, @@ -304,12 +302,12 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_pat_field(&mut self, f: &'v hir::PatField<'v>) { - self.record("PatField", Id::Node(f.hir_id), f); + self.record("PatField", Some(f.hir_id), f); hir_visit::walk_pat_field(self, f) } fn visit_expr(&mut self, e: &'v hir::Expr<'v>) { - record_variants!((self, e, e.kind, Id::Node(e.hir_id), hir, Expr, ExprKind), [ + record_variants!((self, e, e.kind, Some(e.hir_id), hir, Expr, ExprKind), [ ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index, Path, AddrOf, Break, Continue, Ret, Become, InlineAsm, OffsetOf, Struct, Repeat, Yield, Err @@ -318,12 +316,12 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_expr_field(&mut self, f: &'v hir::ExprField<'v>) { - self.record("ExprField", Id::Node(f.hir_id), f); + self.record("ExprField", Some(f.hir_id), f); hir_visit::walk_expr_field(self, f) } fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { - record_variants!((self, t, t.kind, Id::Node(t.hir_id), hir, Ty, TyKind), [ + record_variants!((self, t, t.kind, Some(t.hir_id), hir, Ty, TyKind), [ InferDelegation, Slice, Array, @@ -345,17 +343,17 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - self.record("GenericParam", Id::Node(p.hir_id), p); + self.record("GenericParam", Some(p.hir_id), p); hir_visit::walk_generic_param(self, p) } fn visit_generics(&mut self, g: &'v hir::Generics<'v>) { - self.record("Generics", Id::None, g); + self.record("Generics", None, g); hir_visit::walk_generics(self, g) } fn visit_where_predicate(&mut self, p: &'v hir::WherePredicate<'v>) { - record_variants!((self, p, p, Id::None, hir, WherePredicate, WherePredicate), [ + record_variants!((self, p, p, None, hir, WherePredicate, WherePredicate), [ BoundPredicate, RegionPredicate, EqPredicate @@ -371,66 +369,64 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { _: Span, id: LocalDefId, ) { - self.record("FnDecl", Id::None, fd); + self.record("FnDecl", None, fd); hir_visit::walk_fn(self, fk, fd, b, id) } fn visit_use(&mut self, p: &'v hir::UsePath<'v>, hir_id: HirId) { // This is `visit_use`, but the type is `Path` so record it that way. - self.record("Path", Id::None, p); + self.record("Path", None, p); hir_visit::walk_use(self, p, hir_id) } fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) { - record_variants!( - (self, ti, ti.kind, Id::Node(ti.hir_id()), hir, TraitItem, TraitItemKind), - [Const, Fn, Type] - ); + record_variants!((self, ti, ti.kind, Some(ti.hir_id()), hir, TraitItem, TraitItemKind), [ + Const, Fn, Type + ]); hir_visit::walk_trait_item(self, ti) } fn visit_trait_item_ref(&mut self, ti: &'v hir::TraitItemRef) { - self.record("TraitItemRef", Id::Node(ti.id.hir_id()), ti); + self.record("TraitItemRef", Some(ti.id.hir_id()), ti); hir_visit::walk_trait_item_ref(self, ti) } fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) { - record_variants!( - (self, ii, ii.kind, Id::Node(ii.hir_id()), hir, ImplItem, ImplItemKind), - [Const, Fn, Type] - ); + record_variants!((self, ii, ii.kind, Some(ii.hir_id()), hir, ImplItem, ImplItemKind), [ + Const, Fn, Type + ]); hir_visit::walk_impl_item(self, ii) } fn visit_foreign_item_ref(&mut self, fi: &'v hir::ForeignItemRef) { - self.record("ForeignItemRef", Id::Node(fi.id.hir_id()), fi); + self.record("ForeignItemRef", Some(fi.id.hir_id()), fi); hir_visit::walk_foreign_item_ref(self, fi) } fn visit_impl_item_ref(&mut self, ii: &'v hir::ImplItemRef) { - self.record("ImplItemRef", Id::Node(ii.id.hir_id()), ii); + self.record("ImplItemRef", Some(ii.id.hir_id()), ii); hir_visit::walk_impl_item_ref(self, ii) } fn visit_param_bound(&mut self, b: &'v hir::GenericBound<'v>) { - record_variants!((self, b, b, Id::None, hir, GenericBound, GenericBound), [ + record_variants!((self, b, b, None, hir, GenericBound, GenericBound), [ Trait, Outlives, Use ]); hir_visit::walk_param_bound(self, b) } fn visit_field_def(&mut self, s: &'v hir::FieldDef<'v>) { - self.record("FieldDef", Id::Node(s.hir_id), s); + self.record("FieldDef", Some(s.hir_id), s); hir_visit::walk_field_def(self, s) } fn visit_variant(&mut self, v: &'v hir::Variant<'v>) { - self.record("Variant", Id::None, v); + self.record("Variant", None, v); hir_visit::walk_variant(self, v) } fn visit_generic_arg(&mut self, ga: &'v hir::GenericArg<'v>) { - record_variants!((self, ga, ga, Id::Node(ga.hir_id()), hir, GenericArg, GenericArg), [ + record_variants!((self, ga, ga, Some(ga.hir_id()), hir, GenericArg, GenericArg), [ Lifetime, Type, Const, Infer ]); match ga { @@ -442,50 +438,50 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { - self.record("Lifetime", Id::Node(lifetime.hir_id), lifetime); + self.record("Lifetime", Some(lifetime.hir_id), lifetime); hir_visit::walk_lifetime(self, lifetime) } fn visit_path(&mut self, path: &hir::Path<'v>, _id: HirId) { - self.record("Path", Id::None, path); + self.record("Path", None, path); hir_visit::walk_path(self, path) } fn visit_path_segment(&mut self, path_segment: &'v hir::PathSegment<'v>) { - self.record("PathSegment", Id::None, path_segment); + self.record("PathSegment", None, path_segment); hir_visit::walk_path_segment(self, path_segment) } fn visit_generic_args(&mut self, ga: &'v hir::GenericArgs<'v>) { - self.record("GenericArgs", Id::None, ga); + self.record("GenericArgs", None, ga); hir_visit::walk_generic_args(self, ga) } fn visit_assoc_item_constraint(&mut self, constraint: &'v hir::AssocItemConstraint<'v>) { - self.record("AssocItemConstraint", Id::Node(constraint.hir_id), constraint); + self.record("AssocItemConstraint", Some(constraint.hir_id), constraint); hir_visit::walk_assoc_item_constraint(self, constraint) } fn visit_attribute(&mut self, attr: &'v ast::Attribute) { - self.record("Attribute", Id::Attr(attr.id), attr); + self.record("Attribute", None, attr); } fn visit_inline_asm(&mut self, asm: &'v hir::InlineAsm<'v>, id: HirId) { - self.record("InlineAsm", Id::None, asm); + self.record("InlineAsm", None, asm); hir_visit::walk_inline_asm(self, asm, id); } } impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) { - record_variants!((self, i, i.kind, Id::None, ast, ForeignItem, ForeignItemKind), [ + record_variants!((self, i, i.kind, None, ast, ForeignItem, ForeignItemKind), [ Static, Fn, TyAlias, MacCall ]); ast_visit::walk_item(self, i) } fn visit_item(&mut self, i: &'v ast::Item) { - record_variants!((self, i, i.kind, Id::None, ast, Item, ItemKind), [ + record_variants!((self, i, i.kind, None, ast, Item, ItemKind), [ ExternCrate, Use, Static, @@ -510,34 +506,34 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_local(&mut self, l: &'v ast::Local) { - self.record("Local", Id::None, l); + self.record("Local", None, l); ast_visit::walk_local(self, l) } fn visit_block(&mut self, b: &'v ast::Block) { - self.record("Block", Id::None, b); + self.record("Block", None, b); ast_visit::walk_block(self, b) } fn visit_stmt(&mut self, s: &'v ast::Stmt) { - record_variants!((self, s, s.kind, Id::None, ast, Stmt, StmtKind), [ + record_variants!((self, s, s.kind, None, ast, Stmt, StmtKind), [ Let, Item, Expr, Semi, Empty, MacCall ]); ast_visit::walk_stmt(self, s) } fn visit_param(&mut self, p: &'v ast::Param) { - self.record("Param", Id::None, p); + self.record("Param", None, p); ast_visit::walk_param(self, p) } fn visit_arm(&mut self, a: &'v ast::Arm) { - self.record("Arm", Id::None, a); + self.record("Arm", None, a); ast_visit::walk_arm(self, a) } fn visit_pat(&mut self, p: &'v ast::Pat) { - record_variants!((self, p, p.kind, Id::None, ast, Pat, PatKind), [ + record_variants!((self, p, p.kind, None, ast, Pat, PatKind), [ Wild, Ident, Struct, @@ -563,7 +559,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_expr(&mut self, e: &'v ast::Expr) { #[rustfmt::skip] record_variants!( - (self, e, e.kind, Id::None, ast, Expr, ExprKind), + (self, e, e.kind, None, ast, Expr, ExprKind), [ Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let, If, While, ForLoop, Loop, Match, Closure, Block, Await, TryBlock, Assign, @@ -576,7 +572,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_ty(&mut self, t: &'v ast::Ty) { - record_variants!((self, t, t.kind, Id::None, ast, Ty, TyKind), [ + record_variants!((self, t, t.kind, None, ast, Ty, TyKind), [ Slice, Array, Ptr, @@ -603,12 +599,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_generic_param(&mut self, g: &'v ast::GenericParam) { - self.record("GenericParam", Id::None, g); + self.record("GenericParam", None, g); ast_visit::walk_generic_param(self, g) } fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) { - record_variants!((self, p, p, Id::None, ast, WherePredicate, WherePredicate), [ + record_variants!((self, p, p, None, ast, WherePredicate, WherePredicate), [ BoundPredicate, RegionPredicate, EqPredicate @@ -617,12 +613,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, _: Span, _: NodeId) { - self.record("FnDecl", Id::None, fk.decl()); + self.record("FnDecl", None, fk.decl()); ast_visit::walk_fn(self, fk) } fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) { - record_variants!((self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind), [ + record_variants!((self, i, i.kind, None, ast, AssocItem, AssocItemKind), [ Const, Fn, Type, @@ -634,19 +630,19 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_param_bound(&mut self, b: &'v ast::GenericBound, _ctxt: BoundKind) { - record_variants!((self, b, b, Id::None, ast, GenericBound, GenericBound), [ + record_variants!((self, b, b, None, ast, GenericBound, GenericBound), [ Trait, Outlives, Use ]); ast_visit::walk_param_bound(self, b) } fn visit_field_def(&mut self, s: &'v ast::FieldDef) { - self.record("FieldDef", Id::None, s); + self.record("FieldDef", None, s); ast_visit::walk_field_def(self, s) } fn visit_variant(&mut self, v: &'v ast::Variant) { - self.record("Variant", Id::None, v); + self.record("Variant", None, v); ast_visit::walk_variant(self, v) } @@ -660,7 +656,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { // common than the former case, so we implement this visitor and tolerate // the double counting in the former case. fn visit_path_segment(&mut self, path_segment: &'v ast::PathSegment) { - self.record("PathSegment", Id::None, path_segment); + self.record("PathSegment", None, path_segment); ast_visit::walk_path_segment(self, path_segment) } @@ -669,7 +665,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { // common, so we implement `visit_generic_args` and tolerate the double // counting in the former case. fn visit_generic_args(&mut self, g: &'v ast::GenericArgs) { - record_variants!((self, g, g, Id::None, ast, GenericArgs, GenericArgs), [ + record_variants!((self, g, g, None, ast, GenericArgs, GenericArgs), [ AngleBracketed, Parenthesized, ParenthesizedElided @@ -678,24 +674,24 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_attribute(&mut self, attr: &'v ast::Attribute) { - record_variants!((self, attr, attr.kind, Id::None, ast, Attribute, AttrKind), [ + record_variants!((self, attr, attr.kind, None, ast, Attribute, AttrKind), [ Normal, DocComment ]); ast_visit::walk_attribute(self, attr) } fn visit_expr_field(&mut self, f: &'v ast::ExprField) { - self.record("ExprField", Id::None, f); + self.record("ExprField", None, f); ast_visit::walk_expr_field(self, f) } fn visit_crate(&mut self, krate: &'v ast::Crate) { - self.record("Crate", Id::None, krate); + self.record("Crate", None, krate); ast_visit::walk_crate(self, krate) } fn visit_inline_asm(&mut self, asm: &'v ast::InlineAsm) { - self.record("InlineAsm", Id::None, asm); + self.record("InlineAsm", None, asm); ast_visit::walk_inline_asm(self, asm) } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index f69cc74fba2..cd47c8ece60 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -106,7 +106,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { def_id: LocalDefId, item_sp: Span, fn_sig: Option<&'tcx hir::FnSig<'tcx>>, - is_foreign_item: bool, kind: AnnotationKind, inherit_deprecation: InheritDeprecation, inherit_const_stability: InheritConstStability, @@ -175,11 +174,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // implied), check if the function/method is const or the parent impl block is const. if let Some(fn_sig) = fn_sig && !fn_sig.header.is_const() - // We have to exclude foreign items as they might be intrinsics. Sadly we can't check - // their ABI; `fn_sig.abi` is *not* correct for foreign functions. - && !is_foreign_item && const_stab.is_some() - && (!self.in_trait_impl || !self.tcx.is_const_fn(def_id.to_def_id())) { self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span }); } @@ -217,7 +212,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // `impl const Trait for Type` items forward their const stability to their // immediate children. - // FIXME(effects): how is this supposed to interact with `#[rustc_const_stable_indirect]`? + // FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`? // Currently, once that is set, we do not inherit anything from the parent any more. if const_stab.is_none() { debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab); @@ -398,7 +393,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { ctor_def_id, i.span, None, - /* is_foreign_item */ false, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -417,7 +411,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { i.owner_id.def_id, i.span, fn_sig, - /* is_foreign_item */ false, kind, InheritDeprecation::Yes, const_stab_inherit, @@ -437,7 +430,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { ti.owner_id.def_id, ti.span, fn_sig, - /* is_foreign_item */ false, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -461,7 +453,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { ii.owner_id.def_id, ii.span, fn_sig, - /* is_foreign_item */ false, kind, InheritDeprecation::Yes, InheritConstStability::No, @@ -477,7 +468,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { var.def_id, var.span, None, - /* is_foreign_item */ false, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -488,7 +478,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { ctor_def_id, var.span, None, - /* is_foreign_item */ false, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -507,7 +496,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { s.def_id, s.span, None, - /* is_foreign_item */ false, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -527,7 +515,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { i.owner_id.def_id, i.span, fn_sig, - /* is_foreign_item */ true, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -550,7 +537,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { p.def_id, p.span, None, - /* is_foreign_item */ false, kind, InheritDeprecation::No, InheritConstStability::No, @@ -712,7 +698,6 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), None, - /* is_foreign_item */ false, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index f98e4243375..16eea9e4ff9 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -19,7 +19,6 @@ rustc_macros = { path = "../rustc_macros", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } rustc_session = { path = "../rustc_session", optional = true } rustc_span = { path = "../rustc_span", optional = true } -rustc_target = { path = "../rustc_target", optional = true } smallvec = { version = "1.8.1", features = ["union"] } tracing = "0.1" # tidy-alphabetical-end @@ -41,7 +40,6 @@ rustc = [ "dep:rustc_middle", "dep:rustc_session", "dep:rustc_span", - "dep:rustc_target", "smallvec/may_dangle", "rustc_index/nightly", ] diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 5e30f17d626..e7ed8288499 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1098,7 +1098,7 @@ impl<D: Deps> CurrentDepGraph<D> { use std::time::{SystemTime, UNIX_EPOCH}; let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); - let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64; + let nanos = duration.as_nanos(); let mut stable_hasher = StableHasher::new(); nanos.hash(&mut stable_hasher); let anon_id_seed = stable_hasher.finish(); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index f0632a21091..42455983575 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -459,7 +459,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { return (err, Vec::new()); } - let (found, mut candidates) = self.try_lookup_name_relaxed( + let (found, suggested_candidates, mut candidates) = self.try_lookup_name_relaxed( &mut err, source, path, @@ -478,7 +478,15 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); - fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error); + fallback |= self.suggest_typo( + &mut err, + source, + path, + following_seg, + span, + &base_error, + suggested_candidates, + ); if fallback { // Fallback label. @@ -589,7 +597,16 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: Span, res: Option<Res>, base_error: &BaseError, - ) -> (bool, Vec<ImportSuggestion>) { + ) -> (bool, FxHashSet<String>, Vec<ImportSuggestion>) { + let span = match following_seg { + Some(_) if path[0].ident.span.eq_ctxt(path[path.len() - 1].ident.span) => { + // The path `span` that comes in includes any following segments, which we don't + // want to replace in the suggestions. + path[0].ident.span.to(path[path.len() - 1].ident.span) + } + _ => span, + }; + let mut suggested_candidates = FxHashSet::default(); // Try to lookup name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; let is_expected = &|res| source.is_expected(res); @@ -646,6 +663,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { }; let msg = format!("{preamble}try using the variant's enum"); + suggested_candidates.extend( + enum_candidates + .iter() + .map(|(_variant_path, enum_ty_path)| enum_ty_path.clone()), + ); err.span_suggestions( span, msg, @@ -658,7 +680,8 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // Try finding a suitable replacement. let typo_sugg = self .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected) - .to_opt_suggestion(); + .to_opt_suggestion() + .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())); if let [segment] = path && !matches!(source, PathSource::Delegation) && self.self_type_is_available() @@ -719,7 +742,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } self.r.add_typo_suggestion(err, typo_sugg, ident_span); - return (true, candidates); + return (true, suggested_candidates, candidates); } // If the first argument in call is `self` suggest calling a method. @@ -737,7 +760,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { format!("self.{path_str}({args_snippet})"), Applicability::MachineApplicable, ); - return (true, candidates); + return (true, suggested_candidates, candidates); } } @@ -754,7 +777,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ) { // We do this to avoid losing a secondary span when we override the main error span. self.r.add_typo_suggestion(err, typo_sugg, ident_span); - return (true, candidates); + return (true, suggested_candidates, candidates); } } @@ -772,7 +795,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ident.span, format!("the binding `{path_str}` is available in a different scope in the same function"), ); - return (true, candidates); + return (true, suggested_candidates, candidates); } } } @@ -781,7 +804,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } - (false, candidates) + (false, suggested_candidates, candidates) } fn suggest_trait_and_bounds( @@ -869,13 +892,16 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { following_seg: Option<&Segment>, span: Span, base_error: &BaseError, + suggested_candidates: FxHashSet<String>, ) -> bool { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); let typo_sugg = self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); let mut fallback = false; - let typo_sugg = typo_sugg.to_opt_suggestion(); + let typo_sugg = typo_sugg + .to_opt_suggestion() + .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())); if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) { fallback = true; match self.diag_metadata.current_let_binding { @@ -894,10 +920,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // If the trait has a single item (which wasn't matched by the algorithm), suggest it let suggestion = self.get_single_associated_item(path, &source, is_expected); - if !self.r.add_typo_suggestion(err, suggestion, ident_span) { - fallback = !self.let_binding_suggestion(err, ident_span); - } + self.r.add_typo_suggestion(err, suggestion, ident_span); } + + if self.let_binding_suggestion(err, ident_span) { + fallback = false; + } + fallback } diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml index aea2f7dda7f..5623a493cf0 100644 --- a/compiler/rustc_sanitizers/Cargo.toml +++ b/compiler/rustc_sanitizers/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" bitflags = "2.5.0" tracing = "0.1" twox-hash = "1.6.3" +rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index ca75952fe3d..0e6f905e7a1 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -7,6 +7,7 @@ use std::fmt::Write as _; +use rustc_abi::{ExternAbi, Integer}; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; @@ -18,8 +19,6 @@ use rustc_middle::ty::{ }; use rustc_span::def_id::DefId; use rustc_span::sym; -use rustc_target::abi::Integer; -use rustc_target::spec::abi::Abi; use tracing::instrument; use crate::cfi::typeid::TypeIdOptions; @@ -185,7 +184,7 @@ fn encode_fnsig<'tcx>( let mut encode_ty_options = EncodeTyOptions::from_bits(options.bits()) .unwrap_or_else(|| bug!("encode_fnsig: invalid option(s) `{:?}`", options.bits())); match fn_sig.abi { - Abi::C { .. } => { + ExternAbi::C { .. } => { encode_ty_options.insert(EncodeTyOptions::GENERALIZE_REPR_C); } _ => { diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs index 39842763bfe..01568a0f61c 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; -use rustc_target::abi::call::{Conv, FnAbi, PassMode}; +use rustc_target::callconv::{Conv, FnAbi, PassMode}; use tracing::instrument; mod encode; diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/mod.rs index f37ffcbc4db..5d1ee3d7978 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/mod.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/mod.rs @@ -6,7 +6,7 @@ use bitflags::bitflags; use rustc_middle::ty::{Instance, Ty, TyCtxt}; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; bitflags! { /// Options for typeid_for_fnabi. diff --git a/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs b/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs index 5e2e6a2b8ed..3243e23fcf9 100644 --- a/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs +++ b/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs @@ -7,7 +7,7 @@ use std::hash::Hasher; use rustc_middle::ty::{Instance, InstanceKind, ReifyReason, Ty, TyCtxt}; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use twox_hash::XxHash64; pub use crate::cfi::typeid::{TypeIdOptions, itanium_cxx_abi}; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 9f8b76d4c57..fe05605c1b9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1320,6 +1320,7 @@ pub enum PAuthKey { #[derive(Clone, Copy, Hash, Debug, PartialEq)] pub struct PacRet { pub leaf: bool, + pub pc: bool, pub key: PAuthKey, } @@ -1350,19 +1351,6 @@ pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: & early_dcx.early_warn(warning) } - // The `wasm32-wasi` target is being renamed to `wasm32-wasip1` as - // part of rust-lang/compiler-team#607 and - // rust-lang/compiler-team#695. Warn unconditionally on usage to - // raise awareness of the renaming. This code will be deleted in - // October 2024. - if opts.target_triple.tuple() == "wasm32-wasi" { - early_dcx.early_warn( - "the `wasm32-wasi` target is being renamed to \ - `wasm32-wasip1` and the `wasm32-wasi` target will be \ - removed from nightly in October 2024 and removed from \ - stable Rust in January 2025", - ) - } if !matches!(target.pointer_width, 16 | 32 | 64) { early_dcx.early_fatal(format!( "target specification was invalid: unrecognized target-pointer-width {}", diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 347d298bacc..99d9d5b7665 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -370,8 +370,9 @@ impl CheckCfg { ins!(sym::sanitizer_cfi_normalize_integers, no_values); ins!(sym::target_feature, empty_values).extend( - rustc_target::target_features::all_known_features() - .map(|(f, _sb)| f) + rustc_target::target_features::all_rust_features() + .filter(|(_, s)| s.is_supported()) + .map(|(f, _s)| f) .chain(rustc_target::target_features::RUSTC_SPECIFIC_FEATURES.iter().cloned()) .map(Symbol::intern), ); diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 041a10475ea..3e2cbc18933 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -5,6 +5,7 @@ use std::any::Any; use std::path::PathBuf; +use rustc_abi::ExternAbi; use rustc_ast as ast; use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock}; use rustc_hir::def_id::{ @@ -14,7 +15,6 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::Span; use rustc_span::symbol::Symbol; -use rustc_target::spec::abi::Abi; use crate::search_paths::PathKind; use crate::utils::NativeLibKind; @@ -130,6 +130,11 @@ impl DllImport { None } } + + pub fn is_missing_decorations(&self) -> bool { + self.import_name_type == Some(PeImportNameType::Undecorated) + || self.import_name_type == Some(PeImportNameType::NoPrefix) + } } /// Calling convention for a function defined in an external library. @@ -148,7 +153,7 @@ pub enum DllCallingConvention { pub struct ForeignModule { pub foreign_items: Vec<DefId>, pub def_id: DefId, - pub abi: Abi, + pub abi: ExternAbi, } #[derive(Copy, Clone, Debug, HashStable_Generic)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index eefd67b0bc8..087ba0522eb 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -442,8 +442,7 @@ mod desc { pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`"; pub(crate) const parse_stack_protector: &str = "one of (`none` (default), `basic`, `strong`, or `all`)"; - pub(crate) const parse_branch_protection: &str = - "a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`"; + pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf`"; pub(crate) const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; pub(crate) const parse_remap_path_scope: &str = @@ -1401,7 +1400,7 @@ pub mod parse { match opt { "bti" => slot.bti = true, "pac-ret" if slot.pac_ret.is_none() => { - slot.pac_ret = Some(PacRet { leaf: false, key: PAuthKey::A }) + slot.pac_ret = Some(PacRet { leaf: false, pc: false, key: PAuthKey::A }) } "leaf" => match slot.pac_ret.as_mut() { Some(pac) => pac.leaf = true, @@ -1411,6 +1410,10 @@ pub mod parse { Some(pac) => pac.key = PAuthKey::B, _ => return false, }, + "pc" => match slot.pac_ret.as_mut() { + Some(pac) => pac.pc = true, + _ => return false, + }, _ => return false, }; } @@ -1590,7 +1593,7 @@ options! { link_dead_code: Option<bool> = (None, parse_opt_bool, [TRACKED], "keep dead code at link time (useful for code coverage) (default: no)"), link_self_contained: LinkSelfContained = (LinkSelfContained::default(), parse_link_self_contained, [UNTRACKED], - "control whether to link Rust provided C objects/libraries or rely + "control whether to link Rust provided C objects/libraries or rely \ on a C toolchain or linker installed in the system"), linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED], "system linker to link outputs with"), diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 7be7db1fd3d..dec2a77619b 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -237,10 +237,10 @@ impl RustcInternal for FnSig { } impl RustcInternal for VariantIdx { - type T<'tcx> = rustc_target::abi::VariantIdx; + type T<'tcx> = rustc_abi::VariantIdx; fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { - rustc_target::abi::VariantIdx::from(self.to_index()) + rustc_abi::VariantIdx::from(self.to_index()) } } @@ -335,12 +335,12 @@ impl RustcInternal for BoundVariableKind { ), }), BoundVariableKind::Region(kind) => rustc_ty::BoundVariableKind::Region(match kind { - BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::BrAnon, - BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::BrNamed( + BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::Anon, + BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::Named( def.0.internal(tables, tcx), Symbol::intern(symbol), ), - BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::BrEnv, + BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::ClosureEnv, }), BoundVariableKind::Const => rustc_ty::BoundVariableKind::Const, } @@ -451,35 +451,35 @@ impl RustcInternal for AdtDef { } impl RustcInternal for Abi { - type T<'tcx> = rustc_target::spec::abi::Abi; + type T<'tcx> = rustc_abi::ExternAbi; fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { match *self { - Abi::Rust => rustc_target::spec::abi::Abi::Rust, - Abi::C { unwind } => rustc_target::spec::abi::Abi::C { unwind }, - Abi::Cdecl { unwind } => rustc_target::spec::abi::Abi::Cdecl { unwind }, - Abi::Stdcall { unwind } => rustc_target::spec::abi::Abi::Stdcall { unwind }, - Abi::Fastcall { unwind } => rustc_target::spec::abi::Abi::Fastcall { unwind }, - Abi::Vectorcall { unwind } => rustc_target::spec::abi::Abi::Vectorcall { unwind }, - Abi::Thiscall { unwind } => rustc_target::spec::abi::Abi::Thiscall { unwind }, - Abi::Aapcs { unwind } => rustc_target::spec::abi::Abi::Aapcs { unwind }, - Abi::Win64 { unwind } => rustc_target::spec::abi::Abi::Win64 { unwind }, - Abi::SysV64 { unwind } => rustc_target::spec::abi::Abi::SysV64 { unwind }, - Abi::PtxKernel => rustc_target::spec::abi::Abi::PtxKernel, - Abi::Msp430Interrupt => rustc_target::spec::abi::Abi::Msp430Interrupt, - Abi::X86Interrupt => rustc_target::spec::abi::Abi::X86Interrupt, - Abi::EfiApi => rustc_target::spec::abi::Abi::EfiApi, - Abi::AvrInterrupt => rustc_target::spec::abi::Abi::AvrInterrupt, - Abi::AvrNonBlockingInterrupt => rustc_target::spec::abi::Abi::AvrNonBlockingInterrupt, - Abi::CCmseNonSecureCall => rustc_target::spec::abi::Abi::CCmseNonSecureCall, - Abi::CCmseNonSecureEntry => rustc_target::spec::abi::Abi::CCmseNonSecureEntry, - Abi::System { unwind } => rustc_target::spec::abi::Abi::System { unwind }, - Abi::RustIntrinsic => rustc_target::spec::abi::Abi::RustIntrinsic, - Abi::RustCall => rustc_target::spec::abi::Abi::RustCall, - Abi::Unadjusted => rustc_target::spec::abi::Abi::Unadjusted, - Abi::RustCold => rustc_target::spec::abi::Abi::RustCold, - Abi::RiscvInterruptM => rustc_target::spec::abi::Abi::RiscvInterruptM, - Abi::RiscvInterruptS => rustc_target::spec::abi::Abi::RiscvInterruptS, + Abi::Rust => rustc_abi::ExternAbi::Rust, + Abi::C { unwind } => rustc_abi::ExternAbi::C { unwind }, + Abi::Cdecl { unwind } => rustc_abi::ExternAbi::Cdecl { unwind }, + Abi::Stdcall { unwind } => rustc_abi::ExternAbi::Stdcall { unwind }, + Abi::Fastcall { unwind } => rustc_abi::ExternAbi::Fastcall { unwind }, + Abi::Vectorcall { unwind } => rustc_abi::ExternAbi::Vectorcall { unwind }, + Abi::Thiscall { unwind } => rustc_abi::ExternAbi::Thiscall { unwind }, + Abi::Aapcs { unwind } => rustc_abi::ExternAbi::Aapcs { unwind }, + Abi::Win64 { unwind } => rustc_abi::ExternAbi::Win64 { unwind }, + Abi::SysV64 { unwind } => rustc_abi::ExternAbi::SysV64 { unwind }, + Abi::PtxKernel => rustc_abi::ExternAbi::PtxKernel, + Abi::Msp430Interrupt => rustc_abi::ExternAbi::Msp430Interrupt, + Abi::X86Interrupt => rustc_abi::ExternAbi::X86Interrupt, + Abi::EfiApi => rustc_abi::ExternAbi::EfiApi, + Abi::AvrInterrupt => rustc_abi::ExternAbi::AvrInterrupt, + Abi::AvrNonBlockingInterrupt => rustc_abi::ExternAbi::AvrNonBlockingInterrupt, + Abi::CCmseNonSecureCall => rustc_abi::ExternAbi::CCmseNonSecureCall, + Abi::CCmseNonSecureEntry => rustc_abi::ExternAbi::CCmseNonSecureEntry, + Abi::System { unwind } => rustc_abi::ExternAbi::System { unwind }, + Abi::RustIntrinsic => rustc_abi::ExternAbi::RustIntrinsic, + Abi::RustCall => rustc_abi::ExternAbi::RustCall, + Abi::Unadjusted => rustc_abi::ExternAbi::Unadjusted, + Abi::RustCold => rustc_abi::ExternAbi::RustCold, + Abi::RiscvInterruptM => rustc_abi::ExternAbi::RiscvInterruptM, + Abi::RiscvInterruptS => rustc_abi::ExternAbi::RiscvInterruptS, } } } @@ -503,7 +503,7 @@ impl RustcInternal for Span { } impl RustcInternal for Layout { - type T<'tcx> = rustc_target::abi::Layout<'tcx>; + type T<'tcx> = rustc_abi::Layout<'tcx>; fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { tcx.lift(tables.layouts[*self]).unwrap() diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 9514ec883ae..3db65692af7 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -34,7 +34,7 @@ use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, I use crate::rustc_internal::RustcInternal; use crate::rustc_smir::builder::BodyBuilder; -use crate::rustc_smir::{Stable, Tables, alloc, new_item_kind, smir_crate}; +use crate::rustc_smir::{Stable, Tables, alloc, filter_def_ids, new_item_kind, smir_crate}; impl<'tcx> Context for TablesWrapper<'tcx> { fn target_info(&self) -> MachineInfo { @@ -80,6 +80,20 @@ impl<'tcx> Context for TablesWrapper<'tcx> { .collect() } + fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let krate = crate_num.internal(&mut *tables, tcx); + filter_def_ids(tcx, krate, |def_id| tables.to_fn_def(def_id)) + } + + fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let krate = crate_num.internal(&mut *tables, tcx); + filter_def_ids(tcx, krate, |def_id| tables.to_static(def_id)) + } + fn foreign_module( &self, mod_def: stable_mir::ty::ForeignModuleDef, @@ -786,7 +800,7 @@ pub(crate) struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>); /// Implement error handling for extracting function ABI information. impl<'tcx> FnAbiOfHelpers<'tcx> for Tables<'tcx> { - type FnAbiOfResult = Result<&'tcx rustc_target::abi::call::FnAbi<'tcx, ty::Ty<'tcx>>, Error>; + type FnAbiOfResult = Result<&'tcx rustc_target::callconv::FnAbi<'tcx, ty::Ty<'tcx>>, Error>; #[inline] fn handle_fn_abi_err( diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index c9795fca399..4f8da08eff9 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -1,6 +1,6 @@ //! Conversion of internal Rust compiler items to stable ones. -use rustc_target::abi::FieldIdx; +use rustc_abi::FieldIdx; use crate::rustc_smir::{Stable, Tables}; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 8f05f859c07..a4f61313001 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -243,11 +243,11 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { use stable_mir::ty::BoundRegionKind; match self { - ty::BoundRegionKind::BrAnon => BoundRegionKind::BrAnon, - ty::BoundRegionKind::BrNamed(def_id, symbol) => { + ty::BoundRegionKind::Anon => BoundRegionKind::BrAnon, + ty::BoundRegionKind::Named(def_id, symbol) => { BoundRegionKind::BrNamed(tables.br_named_def(*def_id), symbol.to_string()) } - ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv, + ty::BoundRegionKind::ClosureEnv => BoundRegionKind::BrEnv, } } } @@ -418,7 +418,7 @@ pub(crate) fn mir_const_from_ty_const<'tcx>( ty: Ty<'tcx>, ) -> stable_mir::ty::MirConst { let kind = match ty_const.kind() { - ty::Value(ty, val) => { + ty::ConstKind::Value(ty, val) => { let val = match val { ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar), ty::ValTree::Branch(branch) => { @@ -435,19 +435,19 @@ pub(crate) fn mir_const_from_ty_const<'tcx>( )) } } - ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)), - ty::ErrorCt(_) => unreachable!(), - ty::InferCt(_) => unreachable!(), - ty::BoundCt(_, _) => unimplemented!(), - ty::PlaceholderCt(_) => unimplemented!(), - ty::Unevaluated(uv) => { + ty::ConstKind::Param(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)), + ty::ConstKind::Error(_) => unreachable!(), + ty::ConstKind::Infer(_) => unreachable!(), + ty::ConstKind::Bound(_, _) => unimplemented!(), + ty::ConstKind::Placeholder(_) => unimplemented!(), + ty::ConstKind::Unevaluated(uv) => { stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { def: tables.const_def(uv.def), args: uv.args.stable(tables), promoted: None, }) } - ty::ExprCt(_) => unimplemented!(), + ty::ConstKind::Expr(_) => unimplemented!(), }; let stable_ty = tables.intern_ty(ty); let id = tables.intern_mir_const(mir::Const::Ty(ty, ty_const)); @@ -459,7 +459,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { let kind = match self.kind() { - ty::Value(ty, val) => { + ty::ConstKind::Value(ty, val) => { let val = match val { ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar), ty::ValTree::Branch(branch) => { @@ -478,16 +478,16 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { ) } } - ty::ParamCt(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)), - ty::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated( + ty::ConstKind::Param(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)), + ty::ConstKind::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated( tables.const_def(uv.def), uv.args.stable(tables), ), - ty::ErrorCt(_) => unreachable!(), - ty::InferCt(_) => unreachable!(), - ty::BoundCt(_, _) => unimplemented!(), - ty::PlaceholderCt(_) => unimplemented!(), - ty::ExprCt(_) => unimplemented!(), + ty::ConstKind::Error(_) => unreachable!(), + ty::ConstKind::Infer(_) => unreachable!(), + ty::ConstKind::Bound(_, _) => unimplemented!(), + ty::ConstKind::Placeholder(_) => unimplemented!(), + ty::ConstKind::Expr(_) => unimplemented!(), }; let id = tables.intern_ty_const(tables.tcx.lift(*self).unwrap()); stable_mir::ty::TyConst::new(kind, id) @@ -891,38 +891,38 @@ impl<'tcx> Stable<'tcx> for ty::Movability { } } -impl<'tcx> Stable<'tcx> for rustc_target::spec::abi::Abi { +impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { type T = stable_mir::ty::Abi; fn stable(&self, _: &mut Tables<'_>) -> Self::T { - use rustc_target::spec::abi; + use rustc_abi::ExternAbi; use stable_mir::ty::Abi; match *self { - abi::Abi::Rust => Abi::Rust, - abi::Abi::C { unwind } => Abi::C { unwind }, - abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind }, - abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind }, - abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind }, - abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind }, - abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind }, - abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind }, - abi::Abi::Win64 { unwind } => Abi::Win64 { unwind }, - abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind }, - abi::Abi::PtxKernel => Abi::PtxKernel, - abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt, - abi::Abi::X86Interrupt => Abi::X86Interrupt, - abi::Abi::EfiApi => Abi::EfiApi, - abi::Abi::AvrInterrupt => Abi::AvrInterrupt, - abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, - abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall, - abi::Abi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry, - abi::Abi::System { unwind } => Abi::System { unwind }, - abi::Abi::RustIntrinsic => Abi::RustIntrinsic, - abi::Abi::RustCall => Abi::RustCall, - abi::Abi::Unadjusted => Abi::Unadjusted, - abi::Abi::RustCold => Abi::RustCold, - abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM, - abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS, + ExternAbi::Rust => Abi::Rust, + ExternAbi::C { unwind } => Abi::C { unwind }, + ExternAbi::Cdecl { unwind } => Abi::Cdecl { unwind }, + ExternAbi::Stdcall { unwind } => Abi::Stdcall { unwind }, + ExternAbi::Fastcall { unwind } => Abi::Fastcall { unwind }, + ExternAbi::Vectorcall { unwind } => Abi::Vectorcall { unwind }, + ExternAbi::Thiscall { unwind } => Abi::Thiscall { unwind }, + ExternAbi::Aapcs { unwind } => Abi::Aapcs { unwind }, + ExternAbi::Win64 { unwind } => Abi::Win64 { unwind }, + ExternAbi::SysV64 { unwind } => Abi::SysV64 { unwind }, + ExternAbi::PtxKernel => Abi::PtxKernel, + ExternAbi::Msp430Interrupt => Abi::Msp430Interrupt, + ExternAbi::X86Interrupt => Abi::X86Interrupt, + ExternAbi::EfiApi => Abi::EfiApi, + ExternAbi::AvrInterrupt => Abi::AvrInterrupt, + ExternAbi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, + ExternAbi::CCmseNonSecureCall => Abi::CCmseNonSecureCall, + ExternAbi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry, + ExternAbi::System { unwind } => Abi::System { unwind }, + ExternAbi::RustIntrinsic => Abi::RustIntrinsic, + ExternAbi::RustCall => Abi::RustCall, + ExternAbi::Unadjusted => Abi::Unadjusted, + ExternAbi::RustCold => Abi::RustCold, + ExternAbi::RiscvInterruptM => Abi::RiscvInterruptM, + ExternAbi::RiscvInterruptS => Abi::RiscvInterruptS, } } } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 9032156b257..c5d33f090a0 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -15,8 +15,8 @@ use rustc_middle::mir::interpret::AllocId; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use stable_mir::abi::Layout; -use stable_mir::mir::mono::InstanceDef; -use stable_mir::ty::{MirConstId, Span, TyConstId}; +use stable_mir::mir::mono::{InstanceDef, StaticDef}; +use stable_mir::ty::{FnDef, MirConstId, Span, TyConstId}; use stable_mir::{CtorKind, ItemKind}; use tracing::debug; @@ -79,6 +79,36 @@ impl<'tcx> Tables<'tcx> { }; !must_override && self.tcx.is_mir_available(def_id) } + + fn to_fn_def(&mut self, def_id: DefId) -> Option<FnDef> { + if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) { + Some(self.fn_def(def_id)) + } else { + None + } + } + + fn to_static(&mut self, def_id: DefId) -> Option<StaticDef> { + matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| self.static_def(def_id)) + } +} + +/// Iterate over the definitions of the given crate. +pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T> +where + F: FnMut(DefId) -> Option<T>, +{ + if krate == LOCAL_CRATE { + tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect() + } else { + let num_definitions = tcx.num_extern_def_ids(krate); + (0..num_definitions) + .filter_map(move |i| { + let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) }; + func(def_id) + }) + .collect() + } } /// Build a stable mir crate from a given crate number. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index fac2180d63b..82cfbd28fff 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1663,6 +1663,7 @@ symbols! { rustc_const_panic_str, rustc_const_stable, rustc_const_stable_indirect, + rustc_const_stable_intrinsic, rustc_const_unstable, rustc_conversion_suggestion, rustc_deallocator, @@ -1732,7 +1733,6 @@ symbols! { rustc_reallocator, rustc_regions, rustc_reservation_impl, - rustc_safe_intrinsic, rustc_serialize, rustc_skip_during_method_dispatch, rustc_specialization_trait, @@ -2174,6 +2174,7 @@ symbols! { yes, yield_expr, ymm_reg, + yreg, zfh, zfhmin, zmm_reg, diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index 644e710d1db..1fb647cab5b 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -15,6 +15,5 @@ rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_target = { path = "../rustc_target" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 868345c7594..05b4ff327a9 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -2,7 +2,7 @@ use std::fmt::Write; use std::iter; use std::ops::Range; -use rustc_abi::Integer; +use rustc_abi::{ExternAbi, Integer}; use rustc_data_structures::base_n::ToBaseN; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; @@ -18,7 +18,6 @@ use rustc_middle::ty::{ TyCtxt, TypeVisitable, TypeVisitableExt, UintTy, }; use rustc_span::symbol::kw; -use rustc_target::spec::abi::Abi; pub(super) fn mangle<'tcx>( tcx: TyCtxt<'tcx>, @@ -291,7 +290,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { // Bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) => { + ty::ReBound(debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + var.as_u32(); @@ -444,8 +443,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { cx.push("U"); } match sig.abi { - Abi::Rust => {} - Abi::C { unwind: false } => cx.push("KC"), + ExternAbi::Rust => {} + ExternAbi::C { unwind: false } => cx.push("KC"), abi => { cx.push("K"); let name = abi.name(); @@ -569,7 +568,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { // We may still encounter unevaluated consts due to the printing // logic sometimes passing identity-substituted impl headers. - ty::Unevaluated(ty::UnevaluatedConst { def, args, .. }) => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args, .. }) => { return self.print_def_path(def, args); } diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index c7d24154e8b..e33431ba122 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -8,9 +8,7 @@ edition = "2021" bitflags = "2.4.1" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } -rustc_feature = { path = "../rustc_feature" } rustc_fs_util = { path = "../rustc_fs_util" } -rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 4b539eb8e20..10778e9acf1 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -191,6 +191,7 @@ mod nvptx; mod powerpc; mod riscv; mod s390x; +mod sparc; mod spirv; mod wasm; mod x86; @@ -209,6 +210,7 @@ pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass}; pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass}; +pub use sparc::{SparcInlineAsmReg, SparcInlineAsmRegClass}; pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass}; pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass}; pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass}; @@ -230,6 +232,8 @@ pub enum InlineAsmArch { PowerPC, PowerPC64, S390x, + Sparc, + Sparc64, SpirV, Wasm32, Wasm64, @@ -260,6 +264,8 @@ impl FromStr for InlineAsmArch { "mips" | "mips32r6" => Ok(Self::Mips), "mips64" | "mips64r6" => Ok(Self::Mips64), "s390x" => Ok(Self::S390x), + "sparc" => Ok(Self::Sparc), + "sparc64" => Ok(Self::Sparc64), "spirv" => Ok(Self::SpirV), "wasm32" => Ok(Self::Wasm32), "wasm64" => Ok(Self::Wasm64), @@ -286,6 +292,7 @@ pub enum InlineAsmReg { LoongArch(LoongArchInlineAsmReg), Mips(MipsInlineAsmReg), S390x(S390xInlineAsmReg), + Sparc(SparcInlineAsmReg), SpirV(SpirVInlineAsmReg), Wasm(WasmInlineAsmReg), Bpf(BpfInlineAsmReg), @@ -309,6 +316,7 @@ impl InlineAsmReg { Self::LoongArch(r) => r.name(), Self::Mips(r) => r.name(), Self::S390x(r) => r.name(), + Self::Sparc(r) => r.name(), Self::Bpf(r) => r.name(), Self::Avr(r) => r.name(), Self::Msp430(r) => r.name(), @@ -329,6 +337,7 @@ impl InlineAsmReg { Self::LoongArch(r) => InlineAsmRegClass::LoongArch(r.reg_class()), Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()), + Self::Sparc(r) => InlineAsmRegClass::Sparc(r.reg_class()), Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()), Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()), @@ -361,6 +370,9 @@ impl InlineAsmReg { Self::Mips(MipsInlineAsmReg::parse(name)?) } InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?), + InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => { + Self::Sparc(SparcInlineAsmReg::parse(name)?) + } InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(name)?), InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { Self::Wasm(WasmInlineAsmReg::parse(name)?) @@ -393,6 +405,7 @@ impl InlineAsmReg { } Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::Sparc(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), @@ -420,6 +433,7 @@ impl InlineAsmReg { Self::LoongArch(r) => r.emit(out, arch, modifier), Self::Mips(r) => r.emit(out, arch, modifier), Self::S390x(r) => r.emit(out, arch, modifier), + Self::Sparc(r) => r.emit(out, arch, modifier), Self::Bpf(r) => r.emit(out, arch, modifier), Self::Avr(r) => r.emit(out, arch, modifier), Self::Msp430(r) => r.emit(out, arch, modifier), @@ -440,6 +454,7 @@ impl InlineAsmReg { Self::LoongArch(_) => cb(self), Self::Mips(_) => cb(self), Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))), + Self::Sparc(_) => cb(self), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), Self::Msp430(_) => cb(self), @@ -463,6 +478,7 @@ pub enum InlineAsmRegClass { LoongArch(LoongArchInlineAsmRegClass), Mips(MipsInlineAsmRegClass), S390x(S390xInlineAsmRegClass), + Sparc(SparcInlineAsmRegClass), SpirV(SpirVInlineAsmRegClass), Wasm(WasmInlineAsmRegClass), Bpf(BpfInlineAsmRegClass), @@ -487,6 +503,7 @@ impl InlineAsmRegClass { Self::LoongArch(r) => r.name(), Self::Mips(r) => r.name(), Self::S390x(r) => r.name(), + Self::Sparc(r) => r.name(), Self::SpirV(r) => r.name(), Self::Wasm(r) => r.name(), Self::Bpf(r) => r.name(), @@ -513,6 +530,7 @@ impl InlineAsmRegClass { Self::LoongArch(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::LoongArch), Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x), + Self::Sparc(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Sparc), Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm), Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf), @@ -542,6 +560,7 @@ impl InlineAsmRegClass { Self::LoongArch(r) => r.suggest_modifier(arch, ty), Self::Mips(r) => r.suggest_modifier(arch, ty), Self::S390x(r) => r.suggest_modifier(arch, ty), + Self::Sparc(r) => r.suggest_modifier(arch, ty), Self::SpirV(r) => r.suggest_modifier(arch, ty), Self::Wasm(r) => r.suggest_modifier(arch, ty), Self::Bpf(r) => r.suggest_modifier(arch, ty), @@ -571,6 +590,7 @@ impl InlineAsmRegClass { Self::LoongArch(r) => r.default_modifier(arch), Self::Mips(r) => r.default_modifier(arch), Self::S390x(r) => r.default_modifier(arch), + Self::Sparc(r) => r.default_modifier(arch), Self::SpirV(r) => r.default_modifier(arch), Self::Wasm(r) => r.default_modifier(arch), Self::Bpf(r) => r.default_modifier(arch), @@ -599,6 +619,7 @@ impl InlineAsmRegClass { Self::LoongArch(r) => r.supported_types(arch), Self::Mips(r) => r.supported_types(arch), Self::S390x(r) => r.supported_types(arch), + Self::Sparc(r) => r.supported_types(arch), Self::SpirV(r) => r.supported_types(arch), Self::Wasm(r) => r.supported_types(arch), Self::Bpf(r) => r.supported_types(arch), @@ -632,6 +653,9 @@ impl InlineAsmRegClass { Self::Mips(MipsInlineAsmRegClass::parse(name)?) } InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(name)?), + InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => { + Self::Sparc(SparcInlineAsmRegClass::parse(name)?) + } InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(name)?), InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { Self::Wasm(WasmInlineAsmRegClass::parse(name)?) @@ -658,6 +682,7 @@ impl InlineAsmRegClass { Self::LoongArch(r) => r.valid_modifiers(arch), Self::Mips(r) => r.valid_modifiers(arch), Self::S390x(r) => r.valid_modifiers(arch), + Self::Sparc(r) => r.valid_modifiers(arch), Self::SpirV(r) => r.valid_modifiers(arch), Self::Wasm(r) => r.valid_modifiers(arch), Self::Bpf(r) => r.valid_modifiers(arch), @@ -843,6 +868,11 @@ pub fn allocatable_registers( s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map); map } + InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => { + let mut map = sparc::regclass_map(); + sparc::fill_reg_map(arch, reloc_model, target_features, target, &mut map); + map + } InlineAsmArch::SpirV => { let mut map = spirv::regclass_map(); spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map); @@ -893,6 +923,7 @@ pub enum InlineAsmClobberAbi { Arm64EC, RiscV, LoongArch, + PowerPC, S390x, Msp430, } @@ -944,6 +975,10 @@ impl InlineAsmClobberAbi { "C" | "system" => Ok(InlineAsmClobberAbi::LoongArch), _ => Err(&["C", "system"]), }, + InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::PowerPC), + _ => Err(&["C", "system"]), + }, InlineAsmArch::S390x => match name { "C" | "system" => Ok(InlineAsmClobberAbi::S390x), _ => Err(&["C", "system"]), @@ -1121,6 +1156,44 @@ impl InlineAsmClobberAbi { f16, f17, f18, f19, f20, f21, f22, f23, } }, + InlineAsmClobberAbi::PowerPC => clobbered_regs! { + PowerPC PowerPCInlineAsmReg { + // Refs: + // - PPC32 SysV: "3.2. Function Calling Sequence" in Power Architecture® 32-bit Application Binary Interface Supplement 1.0 - Linux® & Embedded + // https://web.archive.org/web/20120608163804/https://www.power.org/resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Unified.pdf + // - PPC64 ELFv1: "3.2. Function Calling Sequence" in 64-bit PowerPC ELF Application Binary Interface Supplement 1.9 + // https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-CALL + // - PPC64 ELFv2: "2.2 Function Calling Sequence" in 64-Bit ELF V2 ABI Specification: Power Architecture, Revision 1.5 + // https://openpowerfoundation.org/specifications/64bitelfabi/ + // - AIX: + // - Register usage and conventions + // https://www.ibm.com/docs/en/aix/7.3?topic=overview-register-usage-conventions + // - Special registers in the PowerPC® + // https://www.ibm.com/docs/en/aix/7.3?topic=overview-special-registers-in-powerpc + // - AIX vector programming + // https://www.ibm.com/docs/en/aix/7.3?topic=concepts-aix-vector-programming + + // r0, r3-r12 + r0, + r3, r4, r5, r6, r7, + r8, r9, r10, r11, r12, + + // f0-f13 + f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, + + // v0-v19 + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, + + // cr0-cr1, cr5-cr7, xer + cr0, cr1, + cr5, cr6, cr7, + xer, + // lr and ctr are reserved + } + }, InlineAsmClobberAbi::S390x => clobbered_regs! { S390x S390xInlineAsmReg { r0, r1, r2, r3, r4, r5, diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index b2416466132..aa8b26170be 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -1,14 +1,17 @@ use std::fmt; +use rustc_data_structures::fx::FxIndexSet; use rustc_span::Symbol; use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; +use crate::spec::{RelocModel, Target}; def_reg_class! { PowerPC PowerPCInlineAsmRegClass { reg, reg_nonzero, freg, + vreg, cr, xer, } @@ -48,11 +51,44 @@ impl PowerPCInlineAsmRegClass { } } Self::freg => types! { _: F32, F64; }, + Self::vreg => &[], Self::cr | Self::xer => &[], } } } +fn reserved_r13( + arch: InlineAsmArch, + _reloc_model: RelocModel, + _target_features: &FxIndexSet<Symbol>, + target: &Target, + _is_clobber: bool, +) -> Result<(), &'static str> { + if target.is_like_aix && arch == InlineAsmArch::PowerPC { + Ok(()) + } else { + Err("r13 is a reserved register on this target") + } +} + +fn reserved_v20to31( + _arch: InlineAsmArch, + _reloc_model: RelocModel, + _target_features: &FxIndexSet<Symbol>, + target: &Target, + _is_clobber: bool, +) -> Result<(), &'static str> { + if target.is_like_aix { + match &*target.options.abi { + "vec-default" => Err("v20-v31 are reserved on vec-default ABI"), + "vec-extabi" => Ok(()), + _ => unreachable!("unrecognized AIX ABI"), + } + } else { + Ok(()) + } +} + def_regs! { PowerPC PowerPCInlineAsmReg PowerPCInlineAsmRegClass { r0: reg = ["r0", "0"], @@ -66,6 +102,7 @@ def_regs! { r10: reg, reg_nonzero = ["r10", "10"], r11: reg, reg_nonzero = ["r11", "11"], r12: reg, reg_nonzero = ["r12", "12"], + r13: reg, reg_nonzero = ["r13", "13"] % reserved_r13, r14: reg, reg_nonzero = ["r14", "14"], r15: reg, reg_nonzero = ["r15", "15"], r16: reg, reg_nonzero = ["r16", "16"], @@ -113,6 +150,38 @@ def_regs! { f29: freg = ["f29", "fr29"], f30: freg = ["f30", "fr30"], f31: freg = ["f31", "fr31"], + v0: vreg = ["v0"], + v1: vreg = ["v1"], + v2: vreg = ["v2"], + v3: vreg = ["v3"], + v4: vreg = ["v4"], + v5: vreg = ["v5"], + v6: vreg = ["v6"], + v7: vreg = ["v7"], + v8: vreg = ["v8"], + v9: vreg = ["v9"], + v10: vreg = ["v10"], + v11: vreg = ["v11"], + v12: vreg = ["v12"], + v13: vreg = ["v13"], + v14: vreg = ["v14"], + v15: vreg = ["v15"], + v16: vreg = ["v16"], + v17: vreg = ["v17"], + v18: vreg = ["v18"], + v19: vreg = ["v19"], + v20: vreg = ["v20"] % reserved_v20to31, + v21: vreg = ["v21"] % reserved_v20to31, + v22: vreg = ["v22"] % reserved_v20to31, + v23: vreg = ["v23"] % reserved_v20to31, + v24: vreg = ["v24"] % reserved_v20to31, + v25: vreg = ["v25"] % reserved_v20to31, + v26: vreg = ["v26"] % reserved_v20to31, + v27: vreg = ["v27"] % reserved_v20to31, + v28: vreg = ["v28"] % reserved_v20to31, + v29: vreg = ["v29"] % reserved_v20to31, + v30: vreg = ["v30"] % reserved_v20to31, + v31: vreg = ["v31"] % reserved_v20to31, cr: cr = ["cr"], cr0: cr = ["cr0"], cr1: cr = ["cr1"], @@ -127,8 +196,6 @@ def_regs! { "the stack pointer cannot be used as an operand for inline asm", #error = ["r2", "2"] => "r2 is a system reserved register and cannot be used as an operand for inline asm", - #error = ["r13", "13"] => - "r13 is a system reserved register and cannot be used as an operand for inline asm", #error = ["r29", "29"] => "r29 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["r30", "30"] => @@ -163,13 +230,17 @@ impl PowerPCInlineAsmReg { // Strip off the leading prefix. do_emit! { (r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7"); - (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r14, "14"), (r15, "15"); + (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r13, "13"), (r14, "14"), (r15, "15"); (r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23"); (r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28"); (f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7"); (f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15"); (f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23"); (f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31"); + (v0, "0"), (v1, "1"), (v2, "2"), (v3, "3"), (v4, "4"), (v5, "5"), (v6, "6"), (v7, "7"); + (v8, "8"), (v9, "9"), (v10, "10"), (v11, "11"), (v12, "12"), (v13, "13"), (v14, "14"), (v15, "15"); + (v16, "16"), (v17, "17"), (v18, "18"), (v19, "19"), (v20, "20"), (v21, "21"), (v22, "22"), (v23, "23"); + (v24, "24"), (v25, "25"), (v26, "26"), (v27, "27"), (v28, "28"), (v29, "29"), (v30, "30"), (v31, "31"); (cr, "cr"); (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7"); (xer, "xer"); @@ -201,5 +272,6 @@ impl PowerPCInlineAsmReg { reg_conflicts! { cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7; } + // f0-f31 (vsr0-vsr31) and v0-v31 (vsr32-vsr63) do not conflict. } } diff --git a/compiler/rustc_target/src/asm/sparc.rs b/compiler/rustc_target/src/asm/sparc.rs new file mode 100644 index 00000000000..6261708642b --- /dev/null +++ b/compiler/rustc_target/src/asm/sparc.rs @@ -0,0 +1,138 @@ +use std::fmt; + +use rustc_data_structures::fx::FxIndexSet; +use rustc_span::Symbol; + +use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; +use crate::spec::{RelocModel, Target}; + +def_reg_class! { + Sparc SparcInlineAsmRegClass { + reg, + yreg, + } +} + +impl SparcInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<ModifierInfo> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> { + None + } + + pub fn supported_types( + self, + arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option<Symbol>)] { + match self { + Self::reg => { + if arch == InlineAsmArch::Sparc { + types! { + _: I8, I16, I32; + // FIXME: i64 is ok for g*/o* registers on SPARC-V8+ ("h" constraint in GCC), + // but not yet supported in LLVM. + // v8plus: I64; + } + } else { + types! { _: I8, I16, I32, I64; } + } + } + Self::yreg => &[], + } + } +} + +fn reserved_g5( + arch: InlineAsmArch, + _reloc_model: RelocModel, + _target_features: &FxIndexSet<Symbol>, + _target: &Target, + _is_clobber: bool, +) -> Result<(), &'static str> { + if arch == InlineAsmArch::Sparc { + // FIXME: Section 2.1.5 "Function Registers with Unassigned Roles" of the V8+ Technical + // Specification says "%g5; no longer reserved for system software" [1], but LLVM always + // reserves it on SPARC32 [2]. + // [1]: https://temlib.org/pub/SparcStation/Standards/V8plus.pdf + // [2]: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L64-L66 + Err("g5 is reserved for system on SPARC32") + } else { + Ok(()) + } +} + +def_regs! { + Sparc SparcInlineAsmReg SparcInlineAsmRegClass { + // FIXME: + // - LLVM has reserve-{g,o,l,i}N feature to reserve each general-purpose registers. + // - g2-g4 are reserved for application (optional in both LLVM and GCC, and GCC has -mno-app-regs option to reserve them). + // There are currently no builtin targets that use them, but in the future they may need to + // be supported via options similar to AArch64's -Z fixed-x18. + r2: reg = ["r2", "g2"], // % reserved_g2 + r3: reg = ["r3", "g3"], // % reserved_g3 + r4: reg = ["r4", "g4"], // % reserved_g4 + r5: reg = ["r5", "g5"] % reserved_g5, + r8: reg = ["r8", "o0"], // % reserved_o0 + r9: reg = ["r9", "o1"], // % reserved_o1 + r10: reg = ["r10", "o2"], // % reserved_o2 + r11: reg = ["r11", "o3"], // % reserved_o3 + r12: reg = ["r12", "o4"], // % reserved_o4 + r13: reg = ["r13", "o5"], // % reserved_o5 + r15: reg = ["r15", "o7"], // % reserved_o7 + r16: reg = ["r16", "l0"], // % reserved_l0 + r17: reg = ["r17", "l1"], // % reserved_l1 + r18: reg = ["r18", "l2"], // % reserved_l2 + r19: reg = ["r19", "l3"], // % reserved_l3 + r20: reg = ["r20", "l4"], // % reserved_l4 + r21: reg = ["r21", "l5"], // % reserved_l5 + r22: reg = ["r22", "l6"], // % reserved_l6 + r23: reg = ["r23", "l7"], // % reserved_l7 + r24: reg = ["r24", "i0"], // % reserved_i0 + r25: reg = ["r25", "i1"], // % reserved_i1 + r26: reg = ["r26", "i2"], // % reserved_i2 + r27: reg = ["r27", "i3"], // % reserved_i3 + r28: reg = ["r28", "i4"], // % reserved_i4 + r29: reg = ["r29", "i5"], // % reserved_i5 + y: yreg = ["y"], + #error = ["r0", "g0"] => + "g0 is always zero and cannot be used as an operand for inline asm", + // FIXME: %g1 is volatile in ABI, but used internally by LLVM. + // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L55-L56 + // > FIXME: G1 reserved for now for large imm generation by frame code. + #error = ["r1", "g1"] => + "reserved by LLVM and cannot be used as an operand for inline asm", + #error = ["r6", "g6", "r7", "g7"] => + "reserved for system and cannot be used as an operand for inline asm", + #error = ["sp", "r14", "o6"] => + "the stack pointer cannot be used as an operand for inline asm", + #error = ["fp", "r30", "i6"] => + "the frame pointer cannot be used as an operand for inline asm", + #error = ["r31", "i7"] => + "the return address register cannot be used as an operand for inline asm", + } +} + +impl SparcInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + _modifier: Option<char>, + ) -> fmt::Result { + write!(out, "%{}", self.name()) + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 06408e0b210..321ab40403a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1595,11 +1595,10 @@ macro_rules! supported_targets { pub const TARGETS: &[&str] = &[$($tuple),+]; fn load_builtin(target: &str) -> Option<Target> { - let mut t = match target { + let t = match target { $( $tuple => targets::$module::target(), )+ _ => return None, }; - t.is_builtin = true; debug!("got builtin target: {:?}", t); Some(t) } @@ -1806,7 +1805,6 @@ supported_targets! { ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32v1-none", wasm32v1_none), - ("wasm32-wasi", wasm32_wasi), ("wasm32-wasip1", wasm32_wasip1), ("wasm32-wasip2", wasm32_wasip2), ("wasm32-wasip1-threads", wasm32_wasip1_threads), @@ -2128,9 +2126,6 @@ type StaticCow<T> = Cow<'static, T>; /// through `Deref` impls. #[derive(PartialEq, Clone, Debug)] pub struct TargetOptions { - /// Whether the target is built-in or loaded from a custom target specification. - pub is_builtin: bool, - /// Used as the `target_endian` `cfg` variable. Defaults to little endian. pub endian: Endian, /// Width of c_int type. Defaults to "32". @@ -2606,7 +2601,6 @@ impl Default for TargetOptions { /// incomplete, and if used for compilation, will certainly not work. fn default() -> TargetOptions { TargetOptions { - is_builtin: false, endian: Endian::Little, c_int_width: "32".into(), os: "none".into(), @@ -3349,7 +3343,6 @@ impl Target { } } - key!(is_builtin, bool); key!(c_int_width = "target-c-int-width"); key!(c_enum_min_bits, Option<u64>); // if None, matches c_int_width key!(os); @@ -3462,10 +3455,6 @@ impl Target { key!(entry_abi, Conv)?; key!(supports_xray, bool); - if base.is_builtin { - // This can cause unfortunate ICEs later down the line. - return Err("may not set is_builtin for targets not built-in".into()); - } base.update_from_cli(); // Each field should have been read using `Json::remove` so any keys remaining are unused. @@ -3635,7 +3624,6 @@ impl ToJson for Target { target_val!(arch); target_val!(data_layout); - target_option_val!(is_builtin); target_option_val!(endian, "target-endian"); target_option_val!(c_int_width, "target-c-int-width"); target_option_val!(os); diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs index ee69f9894ae..75447479e1c 100644 --- a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs @@ -14,7 +14,6 @@ pub(crate) fn target() -> Target { arch: "arm".into(), options: TargetOptions { abi: "eabihf".into(), - env: "gnu".into(), features: "+v6,+vfp2,-d32".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs index ed5fc8bcb64..11399b777a5 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs @@ -14,7 +14,6 @@ pub(crate) fn target() -> Target { arch: "arm".into(), options: TargetOptions { abi: "eabihf".into(), - env: "gnu".into(), features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index e83a43c1df2..b7415bf683d 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target { std: None, // ? }, pointer_width: 64, - data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), + data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { abi: "abi64".into(), diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs index 252d614e9ac..75da4abc6b6 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), + data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { abi: "abi64".into(), diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs index a1a596c9f1b..69af2da1100 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), + data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { abi: "abi64".into(), diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs index 35d2911fa9d..c7d24871225 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { abi: "abi64".into(), diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs index 9dab932aed4..4f50e8b7033 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs index 89ba7b889ec..c5948b745ff 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { std: None, // ? }, pointer_width: 64, - data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), + data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64r6".into(), options: TargetOptions { abi: "abi64".into(), diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs index 195894d9aac..60bda7a5996 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64r6".into(), options: TargetOptions { abi: "abi64".into(), diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs deleted file mode 100644 index c317ebd9592..00000000000 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! NB: This target is in the process of being renamed to -//! `wasm32-wasip1`. For more information see: -//! -//! * <https://github.com/rust-lang/compiler-team/issues/607> -//! * <https://github.com/rust-lang/compiler-team/issues/695> - -use crate::spec::Target; - -pub(crate) fn target() -> Target { - super::wasm32_wasip1::target() -} diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs index 89d0721bf35..1cd30f21bec 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs @@ -17,7 +17,7 @@ pub(crate) fn target() -> Target { options.os = "wasi".into(); options.env = "p1".into(); - options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]); + options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasip1"]); options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); @@ -47,7 +47,7 @@ pub(crate) fn target() -> Target { options.entry_name = "__main_void".into(); Target { - llvm_target: "wasm32-wasi".into(), + llvm_target: "wasm32-wasip1".into(), metadata: crate::spec::TargetMetadata { description: Some("WebAssembly with WASI".into()), tier: Some(2), diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs index bd6bba067ef..f06112160d1 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs @@ -1,5 +1,5 @@ //! The `wasm32-wasip2` target is the next evolution of the -//! wasm32-wasi target. While the wasi specification is still under +//! wasm32-wasip1 target. While the wasi specification is still under //! active development, the preview 2 iteration is considered an "island //! of stability" that should allow users to rely on it indefinitely. //! diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 94f771954e1..4dbaf1f7c95 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -1,10 +1,17 @@ +//! Declares Rust's target feature names for each target. +//! Note that these are similar to but not always identical to LLVM's feature names, +//! and Rust adds some features that do not correspond to LLVM features at all. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_span::symbol::{Symbol, sym}; /// Features that control behaviour of rustc, rather than the codegen. +/// These exist globally and are not in the target-specific lists below. pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; -/// Features that require special handling when passing to LLVM. +/// Features that require special handling when passing to LLVM: +/// these are target-specific (i.e., must also be listed in the target-specific list below) +/// but do not correspond to an LLVM target feature. pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"]; /// Stability information for target features. @@ -16,26 +23,47 @@ pub enum Stability { /// This target feature is unstable; using it in `#[target_feature]` or `#[cfg(target_feature)]` /// requires enabling the given nightly feature. Unstable(Symbol), + /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set in the basic + /// target definition. Used in particular for features that change the floating-point ABI. + Forbidden { reason: &'static str }, } use Stability::*; -impl Stability { - pub fn as_feature_name(self) -> Option<Symbol> { +impl<CTX> HashStable<CTX> for Stability { + #[inline] + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + std::mem::discriminant(self).hash_stable(hcx, hasher); match self { - Stable => None, - Unstable(s) => Some(s), + Stable => {} + Unstable(sym) => { + sym.hash_stable(hcx, hasher); + } + Forbidden { .. } => {} } } +} +impl Stability { pub fn is_stable(self) -> bool { matches!(self, Stable) } + + /// Forbidden features are not supported. + pub fn is_supported(self) -> bool { + !matches!(self, Forbidden { .. }) + } } // Here we list target features that rustc "understands": they can be used in `#[target_feature]` // and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with // `-Ctarget-feature`. // +// Note that even unstable (and even entirely unlisted) features can be used with `-Ctarget-feature` +// on stable. Using a feature not on the list of Rust target features only emits a warning. +// Only `cfg(target_feature)` and `#[target_feature]` actually do any stability gating. +// `cfg(target_feature)` for unstable features just works on nightly without any feature gate. +// `#[target_feature]` requires a feature gate. +// // When adding features to the below lists // check whether they're named already elsewhere in rust // e.g. in stdarch and whether the given name matches LLVM's @@ -46,17 +74,27 @@ impl Stability { // per-function level, since we would then allow safe calls from functions with `+soft-float` to // functions without that feature! // -// When adding a new feature, be particularly mindful of features that affect function ABIs. Those -// need to be treated very carefully to avoid introducing unsoundness! This often affects features -// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an -// example of this going wrong), but features enabling new SIMD registers are also a concern (see -// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong). +// It is important for soundness that features allowed here do *not* change the function call ABI. +// For example, disabling the `x87` feature on x86 changes how scalar floats are passed as +// arguments, so enabling toggling that feature would be unsound. In fact, since `-Ctarget-feature` +// will just allow unknown features (with a warning), we have to explicitly list features that change +// the ABI as `Forbidden` to ensure using them causes an error. Note that this is only effective if +// such features can never be toggled via `-Ctarget-cpu`! If that is ever a possibility, we will need +// extra checks ensuring that the LLVM-computed target features for a CPU did not (un)set a +// `Forbidden` feature. See https://github.com/rust-lang/rust/issues/116344 for some more context. +// FIXME: add such "forbidden" features for non-x86 targets. +// +// The one exception to features that change the ABI is features that enable larger vector +// registers. Those are permitted to be listed here. This is currently unsound (see +// https://github.com/rust-lang/rust/issues/116558); in the future we will have to ensure that +// functions can only use such vectors as arguments/return types if the corresponding target feature +// is enabled. // // Stabilizing a target feature requires t-lang approval. type ImpliedFeatures = &'static [&'static str]; -const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("aclass", Unstable(sym::arm_target_feature), &[]), ("aes", Unstable(sym::arm_target_feature), &["neon"]), @@ -70,6 +108,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("neon", Unstable(sym::arm_target_feature), &["vfp3"]), ("rclass", Unstable(sym::arm_target_feature), &[]), ("sha2", Unstable(sym::arm_target_feature), &["neon"]), + ("soft-float", Forbidden { reason: "unsound because it changes float ABI" }, &[]), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. @@ -87,9 +126,10 @@ const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]), ("virtualization", Unstable(sym::arm_target_feature), &[]), // tidy-alphabetical-end + // FIXME: need to also forbid turning off `fpregs` on hardfloat targets ]; -const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start // FEAT_AES & FEAT_PMULL ("aes", Stable, &["neon"]), @@ -277,7 +317,7 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[ &["paca", "pacg"], // Together these represent `pauth` in LLVM ]; -const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("adx", Stable, &[]), ("aes", Stable, &["sse2"]), @@ -328,6 +368,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]), ("sm3", Unstable(sym::sha512_sm_x86), &["avx"]), ("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]), + ("soft-float", Forbidden { reason: "unsound because it changes float ABI" }, &[]), ("sse", Stable, &[]), ("sse2", Stable, &["sse"]), ("sse3", Stable, &["sse2"]), @@ -344,16 +385,17 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("xsaveopt", Stable, &["xsave"]), ("xsaves", Stable, &["xsave"]), // tidy-alphabetical-end + // FIXME: need to also forbid turning off `x87` on hardfloat targets ]; -const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("hvx", Unstable(sym::hexagon_target_feature), &[]), ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]), // tidy-alphabetical-end ]; -const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("altivec", Unstable(sym::powerpc_target_feature), &[]), ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]), @@ -367,7 +409,7 @@ const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("fp64", Unstable(sym::mips_target_feature), &[]), ("msa", Unstable(sym::mips_target_feature), &[]), @@ -375,7 +417,7 @@ const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("a", Stable, &["zaamo", "zalrsc"]), ("c", Stable, &[]), @@ -415,7 +457,7 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("atomics", Unstable(sym::wasm_target_feature), &[]), ("bulk-memory", Stable, &[]), @@ -428,13 +470,14 @@ const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("relaxed-simd", Stable, &["simd128"]), ("sign-ext", Stable, &[]), ("simd128", Stable, &[]), + ("wide-arithmetic", Unstable(sym::wasm_target_feature), &[]), // tidy-alphabetical-end ]; -const BPF_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = +const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[("alu32", Unstable(sym::bpf_target_feature), &[])]; -const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("10e60", Unstable(sym::csky_target_feature), &["7e10"]), ("2e3", Unstable(sym::csky_target_feature), &["e2"]), @@ -481,7 +524,7 @@ const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("d", Unstable(sym::loongarch_target_feature), &["f"]), ("f", Unstable(sym::loongarch_target_feature), &[]), @@ -495,7 +538,7 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("backchain", Unstable(sym::s390x_target_feature), &[]), ("vector", Unstable(sym::s390x_target_feature), &[]), @@ -506,20 +549,20 @@ const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ /// primitives may be documented. /// /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! -pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> { +pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> { std::iter::empty() - .chain(ARM_ALLOWED_FEATURES.iter()) - .chain(AARCH64_ALLOWED_FEATURES.iter()) - .chain(X86_ALLOWED_FEATURES.iter()) - .chain(HEXAGON_ALLOWED_FEATURES.iter()) - .chain(POWERPC_ALLOWED_FEATURES.iter()) - .chain(MIPS_ALLOWED_FEATURES.iter()) - .chain(RISCV_ALLOWED_FEATURES.iter()) - .chain(WASM_ALLOWED_FEATURES.iter()) - .chain(BPF_ALLOWED_FEATURES.iter()) - .chain(CSKY_ALLOWED_FEATURES) - .chain(LOONGARCH_ALLOWED_FEATURES) - .chain(IBMZ_ALLOWED_FEATURES) + .chain(ARM_FEATURES.iter()) + .chain(AARCH64_FEATURES.iter()) + .chain(X86_FEATURES.iter()) + .chain(HEXAGON_FEATURES.iter()) + .chain(POWERPC_FEATURES.iter()) + .chain(MIPS_FEATURES.iter()) + .chain(RISCV_FEATURES.iter()) + .chain(WASM_FEATURES.iter()) + .chain(BPF_FEATURES.iter()) + .chain(CSKY_FEATURES) + .chain(LOONGARCH_FEATURES) + .chain(IBMZ_FEATURES) .cloned() .map(|(f, s, _)| (f, s)) } @@ -532,22 +575,20 @@ const X86_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = const AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "neon")]; impl super::spec::Target { - pub fn supported_target_features( - &self, - ) -> &'static [(&'static str, Stability, ImpliedFeatures)] { + pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] { match &*self.arch { - "arm" => ARM_ALLOWED_FEATURES, - "aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES, - "x86" | "x86_64" => X86_ALLOWED_FEATURES, - "hexagon" => HEXAGON_ALLOWED_FEATURES, - "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES, - "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, - "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, - "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, - "bpf" => BPF_ALLOWED_FEATURES, - "csky" => CSKY_ALLOWED_FEATURES, - "loongarch64" => LOONGARCH_ALLOWED_FEATURES, - "s390x" => IBMZ_ALLOWED_FEATURES, + "arm" => ARM_FEATURES, + "aarch64" | "arm64ec" => AARCH64_FEATURES, + "x86" | "x86_64" => X86_FEATURES, + "hexagon" => HEXAGON_FEATURES, + "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES, + "powerpc" | "powerpc64" => POWERPC_FEATURES, + "riscv32" | "riscv64" => RISCV_FEATURES, + "wasm32" | "wasm64" => WASM_FEATURES, + "bpf" => BPF_FEATURES, + "csky" => CSKY_FEATURES, + "loongarch64" => LOONGARCH_FEATURES, + "s390x" => IBMZ_FEATURES, _ => &[], } } @@ -574,7 +615,7 @@ impl super::spec::Target { base_features: impl Iterator<Item = Symbol>, ) -> FxHashSet<Symbol> { let implied_features = self - .supported_target_features() + .rust_target_features() .iter() .map(|(f, _, i)| (Symbol::intern(f), i)) .collect::<FxHashMap<_, _>>(); diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index d4bb84838cc..e29ed9a4b56 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start itertools = "0.12" +rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } @@ -18,11 +19,8 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_next_trait_solver = { path = "../rustc_next_trait_solver" } rustc_parse_format = { path = "../rustc_parse_format" } -rustc_query_system = { path = "../rustc_query_system" } -rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_target = { path = "../rustc_target" } rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 4725047090e..929fa559d75 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -50,6 +50,7 @@ use std::ops::ControlFlow; use std::path::PathBuf; use std::{cmp, fmt, iter}; +use rustc_abi::ExternAbi; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize}; use rustc_hir::def::DefKind; @@ -67,7 +68,6 @@ use rustc_middle::ty::{ TypeVisitableExt, }; use rustc_span::{BytePos, DesugaringKind, Pos, Span, sym}; -use rustc_target::spec::abi; use tracing::{debug, instrument}; use crate::error_reporting::TypeErrCtxt; @@ -686,10 +686,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^^^^^^^^^^ - if sig1.abi != abi::Abi::Rust { + if sig1.abi != ExternAbi::Rust { values.0.push(format!("extern {} ", sig1.abi), sig1.abi != sig2.abi); } - if sig2.abi != abi::Abi::Rust { + if sig2.abi != ExternAbi::Rust { values.1.push(format!("extern {} ", sig2.abi), sig1.abi != sig2.abi); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 2ecd28f4868..cd621fd1a39 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -100,7 +100,10 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // Find the index of the named region that was part of the // error. We will then search the function parameters for a bound // region at the right depth with the same index - (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { + ( + Some(rbv::ResolvedArg::EarlyBound(id)), + ty::BoundRegionKind::Named(def_id, _), + ) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); if id.to_def_id() == def_id { return ControlFlow::Break(arg); @@ -112,7 +115,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // region at the right depth with the same index ( Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), - ty::BrNamed(def_id, _), + ty::BoundRegionKind::Named(def_id, _), ) => { debug!( "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", @@ -191,14 +194,17 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result { match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) { // the lifetime of the TyPath! - (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { + (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BoundRegionKind::Named(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); if id.to_def_id() == def_id { return ControlFlow::Break(()); } } - (Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => { + ( + Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), + ty::BoundRegionKind::Named(def_id, _), + ) => { debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); debug!("id={:?}", id); debug!("def_id={:?}", def_id); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs index 7cf98183774..9fa5a8ac637 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let is_impl_item = region_info.is_impl_item; match br { - ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon => {} + ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime) | ty::BoundRegionKind::Anon => {} _ => { /* not an anonymous region */ debug!("try_report_named_anon_conflict: not an anonymous region"); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs index f2a7da707b8..7fcd3c847e3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs @@ -29,16 +29,16 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { )) => { let span = *span; let (sub_span, sub_symbol) = match sub_name { - ty::BrNamed(def_id, symbol) => { + ty::BoundRegionKind::Named(def_id, symbol) => { (Some(self.tcx().def_span(def_id)), Some(symbol)) } - ty::BrAnon | ty::BrEnv => (None, None), + ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None), }; let (sup_span, sup_symbol) = match sup_name { - ty::BrNamed(def_id, symbol) => { + ty::BoundRegionKind::Named(def_id, symbol) => { (Some(self.tcx().def_span(def_id)), Some(symbol)) } - ty::BrAnon | ty::BrEnv => (None, None), + ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None), }; let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) { (Some(sub_span), Some(sup_span), Some(&sub_symbol), Some(&sup_symbol)) => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 2b19db2c14e..808e6a50d85 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -59,11 +59,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let simple_ident = param.param.pat.simple_ident(); let (has_impl_path, impl_path) = match ctxt.assoc_item.container { - AssocItemContainer::TraitContainer => { + AssocItemContainer::Trait => { let id = ctxt.assoc_item.container_id(tcx); (true, tcx.def_path_str(id)) } - AssocItemContainer::ImplContainer => (false, String::new()), + AssocItemContainer::Impl => (false, String::new()), }; let mut err = self.tcx().dcx().create_err(ButCallingIntroduces { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 90b354305ff..75054b22153 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -46,7 +46,7 @@ pub fn find_param_with_region<'tcx>( ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region), ty::ReEarlyParam(ebr) => { let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id; - (tcx.parent(region_def), ty::BoundRegionKind::BrNamed(region_def, ebr.name)) + (tcx.parent(region_def), ty::BoundRegionKind::Named(region_def, ebr.name)) } _ => return None, // not a free region }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 438639e72f9..9fd7dccc57c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -993,7 +993,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'_> { let br_string = |br: ty::BoundRegionKind| { let mut s = match br { - ty::BrNamed(_, name) => name.to_string(), + ty::BoundRegionKind::Named(_, name) => name.to_string(), _ => String::new(), }; if !s.is_empty() { @@ -1103,7 +1103,7 @@ fn msg_span_from_named_region<'tcx>( ("the anonymous lifetime defined here".to_string(), Some(ty.span)) } else { match fr.bound_region { - ty::BoundRegionKind::BrNamed(param_def_id, name) => { + ty::BoundRegionKind::Named(param_def_id, name) => { let span = tcx.def_span(param_def_id); let text = if name == kw::UnderscoreLifetime { "the anonymous lifetime as defined here".to_string() @@ -1112,7 +1112,7 @@ fn msg_span_from_named_region<'tcx>( }; (text, Some(span)) } - ty::BrAnon => ( + ty::BoundRegionKind::Anon => ( "the anonymous lifetime as defined here".to_string(), Some(tcx.def_span(generic_param_scope)), ), @@ -1125,11 +1125,11 @@ fn msg_span_from_named_region<'tcx>( } ty::ReStatic => ("the static lifetime".to_owned(), alt_span), ty::RePlaceholder(ty::PlaceholderRegion { - bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, name), .. }, + bound: ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id, name), .. }, .. }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))), ty::RePlaceholder(ty::PlaceholderRegion { - bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon, .. }, + bound: ty::BoundRegion { kind: ty::BoundRegionKind::Anon, .. }, .. }) => ("an anonymous lifetime".to_owned(), None), _ => bug!("{:?}", region), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 524b4139600..1109b11d2a7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -471,6 +471,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } self.try_to_add_help_message( + &root_obligation, &obligation, leaf_trait_predicate, &mut err, @@ -538,7 +539,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => { - // FIXME(effects): We should recompute the predicate with `~const` + // FIXME(const_trait_impl): We should recompute the predicate with `~const` // if it's `const`, and if it holds, explain that this bound only // *conditionally* holds. If that fails, we should also do selection // to drill this down to an impl or built-in source, so we can @@ -1706,15 +1707,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // one crate version and the type comes from another crate version, even though they both // are from the same crate. let trait_def_id = trait_ref.def_id(); - if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind() - && let found_type = def.did() - && trait_def_id.krate != found_type.krate - && self.tcx.crate_name(trait_def_id.krate) == self.tcx.crate_name(found_type.krate) - { - let name = self.tcx.crate_name(trait_def_id.krate); - let spans: Vec<_> = [trait_def_id, found_type] - .into_iter() - .filter(|def_id| def_id.krate != LOCAL_CRATE) + let trait_name = self.tcx.item_name(trait_def_id); + let crate_name = self.tcx.crate_name(trait_def_id.krate); + if let Some(other_trait_def_id) = self.tcx.all_traits().find(|def_id| { + trait_name == self.tcx.item_name(trait_def_id) + && trait_def_id.krate != def_id.krate + && crate_name == self.tcx.crate_name(def_id.krate) + }) { + // We've found two different traits with the same name, same crate name, but + // different crate `DefId`. We highlight the traits. + + let found_type = + if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind() { + Some(def.did()) + } else { + None + }; + let candidates = if impl_candidates.is_empty() { + alternative_candidates(trait_def_id) + } else { + impl_candidates.into_iter().map(|cand| cand.trait_ref).collect() + }; + let mut span: MultiSpan = self.tcx.def_span(trait_def_id).into(); + span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait"); + for (sp, label) in [trait_def_id, other_trait_def_id] + .iter() .filter_map(|def_id| self.tcx.extern_crate(def_id.krate)) .map(|data| { let dependency = if data.dependency_of == LOCAL_CRATE { @@ -1725,57 +1742,86 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; ( data.span, - format!("one version of crate `{name}` is used here, as a {dependency}"), + format!( + "one version of crate `{crate_name}` is used here, as a {dependency}" + ), ) }) - .collect(); - let mut span: MultiSpan = spans.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into(); - for (sp, label) in spans.into_iter() { + { span.push_span_label(sp, label); } - err.highlighted_span_help(span, vec![ + let mut points_at_type = false; + if let Some(found_type) = found_type { + span.push_span_label( + self.tcx.def_span(found_type), + "this type doesn't implement the required trait", + ); + for trait_ref in candidates { + if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind() + && let candidate_def_id = def.did() + && let Some(name) = self.tcx.opt_item_name(candidate_def_id) + && let Some(found) = self.tcx.opt_item_name(found_type) + && name == found + && candidate_def_id.krate != found_type.krate + && self.tcx.crate_name(candidate_def_id.krate) + == self.tcx.crate_name(found_type.krate) + { + // A candidate was found of an item with the same name, from two separate + // versions of the same crate, let's clarify. + let candidate_span = self.tcx.def_span(candidate_def_id); + span.push_span_label( + candidate_span, + "this type implements the required trait", + ); + points_at_type = true; + } + } + } + span.push_span_label(self.tcx.def_span(other_trait_def_id), "this is the found trait"); + err.highlighted_span_note(span, vec![ StringPart::normal("there are ".to_string()), StringPart::highlighted("multiple different versions".to_string()), StringPart::normal(" of crate `".to_string()), - StringPart::highlighted(format!("{name}")), - StringPart::normal("` in the dependency graph".to_string()), + StringPart::highlighted(format!("{crate_name}")), + StringPart::normal("` in the dependency graph\n".to_string()), ]); - let candidates = if impl_candidates.is_empty() { - alternative_candidates(trait_def_id) - } else { - impl_candidates.into_iter().map(|cand| cand.trait_ref).collect() - }; - if let Some((sp_candidate, sp_found)) = candidates.iter().find_map(|trait_ref| { - if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind() - && let candidate_def_id = def.did() - && let Some(name) = self.tcx.opt_item_name(candidate_def_id) - && let Some(found) = self.tcx.opt_item_name(found_type) - && name == found - && candidate_def_id.krate != found_type.krate - && self.tcx.crate_name(candidate_def_id.krate) - == self.tcx.crate_name(found_type.krate) - { - // A candidate was found of an item with the same name, from two separate - // versions of the same crate, let's clarify. - Some((self.tcx.def_span(candidate_def_id), self.tcx.def_span(found_type))) - } else { - None - } - }) { - let mut span: MultiSpan = vec![sp_candidate, sp_found].into(); - span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait"); - span.push_span_label(sp_candidate, "this type implements the required trait"); - span.push_span_label(sp_found, "this type doesn't implement the required trait"); - err.highlighted_span_note(span, vec![ + if points_at_type { + // We only clarify that the same type from different crate versions are not the + // same when we *find* the same type coming from different crate versions, otherwise + // it could be that it was a type provided by a different crate than the one that + // provides the trait, and mentioning this adds verbosity without clarification. + err.highlighted_note(vec![ StringPart::normal( "two types coming from two different versions of the same crate are \ - different types " + different types " .to_string(), ), StringPart::highlighted("even if they look the same".to_string()), ]); } - err.help("you can use `cargo tree` to explore your dependency tree"); + err.highlighted_help(vec![ + StringPart::normal("you can use `".to_string()), + StringPart::highlighted("cargo tree".to_string()), + StringPart::normal("` to explore your dependency tree".to_string()), + ]); + + // FIXME: this is a giant hack for the benefit of this specific diagnostic. Because + // we're so nested in method calls before the error gets emitted, bubbling a single bit + // flag informing the top level caller to stop adding extra detail to the diagnostic, + // would actually be harder to follow. So we do something naughty here: we consume the + // diagnostic, emit it and leave in its place a "delayed bug" that will continue being + // modified but won't actually be printed to end users. This *is not ideal*, but allows + // us to reduce the verbosity of an error that is already quite verbose and increase its + // specificity. Below we modify the main message as well, in a way that *could* break if + // the implementation of Diagnostics change significantly, but that would be caught with + // a make test failure when this diagnostic is tested. + err.primary_message(format!( + "{} because the trait comes from a different crate version", + err.messages[0].0.as_str().unwrap(), + )); + let diag = err.clone(); + err.downgrade_to_delayed_bug(); + self.tcx.dcx().emit_diagnostic(diag); return true; } @@ -2488,6 +2534,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn try_to_add_help_message( &self, + root_obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>, trait_predicate: ty::PolyTraitPredicate<'tcx>, err: &mut Diag<'_>, @@ -2575,6 +2622,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { impl_candidates.as_slice(), span, ); + + self.suggest_tuple_wrapping(err, root_obligation, obligation); } } @@ -2641,7 +2690,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { _span: Span, ) -> UnsatisfiedConst { let unsatisfied_const = UnsatisfiedConst(false); - // FIXME(effects) + // FIXME(const_trait_impl) unsatisfied_const } @@ -3052,7 +3101,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Make a fresh inference variable so we can determine what the generic parameters // of the trait are. let var = self.next_ty_var(DUMMY_SP); - // FIXME(effects) + // FIXME(const_trait_impl) let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]); let obligation = Obligation::new( self.tcx, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 68aa9cffef2..86fd4c230f6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -6,6 +6,7 @@ use std::iter; use std::path::PathBuf; use itertools::{EitherOrBoth, Itertools}; +use rustc_abi::ExternAbi; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::codes::*; @@ -38,7 +39,6 @@ use rustc_middle::{bug, span_bug}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, ExpnKind, MacroKind, Span}; -use rustc_target::spec::abi; use tracing::{debug, instrument}; use super::{ @@ -1916,7 +1916,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infcx.next_ty_var(DUMMY_SP), false, hir::Safety::Safe, - abi::Abi::Rust, + ExternAbi::Rust, ) } _ => infcx.tcx.mk_fn_sig( @@ -1924,7 +1924,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infcx.next_ty_var(DUMMY_SP), false, hir::Safety::Safe, - abi::Abi::Rust, + ExternAbi::Rust, ), }; @@ -3751,7 +3751,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_pred.skip_binder().self_ty(), diagnostic_name, ), - // FIXME(effects, const_trait_impl) derive_const as suggestion? + // FIXME(const_trait_impl) derive_const as suggestion? format!("#[derive({diagnostic_name})]\n"), Applicability::MaybeIncorrect, ); @@ -3996,7 +3996,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let [self_ty, found_ty] = trait_ref.args.as_slice() && let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn()) && let fn_sig @ ty::FnSig { - abi: abi::Abi::Rust, + abi: ExternAbi::Rust, c_variadic: false, safety: hir::Safety::Safe, .. @@ -4452,6 +4452,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + /// If the type failed selection but the trait is implemented for `(T,)`, suggest that the user + /// creates a unary tuple + /// + /// This is a common gotcha when using libraries that emulate variadic functions with traits for tuples. + pub(super) fn suggest_tuple_wrapping( + &self, + err: &mut Diag<'_>, + root_obligation: &PredicateObligation<'tcx>, + obligation: &PredicateObligation<'tcx>, + ) { + let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() else { + return; + }; + + let Some(root_pred) = root_obligation.predicate.as_trait_clause() else { return }; + + let trait_ref = root_pred.map_bound(|root_pred| { + root_pred + .trait_ref + .with_self_ty(self.tcx, Ty::new_tup(self.tcx, &[root_pred.trait_ref.self_ty()])) + }); + + let obligation = + Obligation::new(self.tcx, obligation.cause.clone(), obligation.param_env, trait_ref); + + if self.predicate_must_hold_modulo_regions(&obligation) { + let arg_span = self.tcx.hir().span(*arg_hir_id); + err.multipart_suggestion_verbose( + format!("use a unary tuple instead"), + vec![(arg_span.shrink_to_lo(), "(".into()), (arg_span.shrink_to_hi(), ",)".into())], + Applicability::MaybeIncorrect, + ); + } + } + pub(super) fn explain_hrtb_projection( &self, diag: &mut Diag<'_>, diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 67463b9884c..cc0a637a78e 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -48,7 +48,7 @@ impl<'a> DescriptionCtx<'a> { } else { let scope = fr.scope.expect_local(); match fr.bound_region { - ty::BoundRegionKind::BrNamed(_, name) => { + ty::BoundRegionKind::Named(_, name) => { let span = if let Some(param) = tcx .hir() .get_generics(scope) @@ -64,7 +64,7 @@ impl<'a> DescriptionCtx<'a> { (Some(span), "as_defined", name.to_string()) } } - ty::BrAnon => { + ty::BoundRegionKind::Anon => { let span = Some(tcx.def_span(scope)); (span, "defined_here", String::new()) } diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index bacb3b1b1b8..8f1c8a29663 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -60,6 +60,24 @@ impl<'tcx> InferCtxt<'tcx> { /// /// Invokes `evaluate_obligation`, so in the event that evaluating /// `Ty: Trait` causes overflow, EvaluatedToAmbigStackDependent will be returned. + /// + /// `type_implements_trait` is a convenience function for simple cases like + /// + /// ```ignore (illustrative) + /// let copy_trait = infcx.tcx.require_lang_item(LangItem::Copy, span); + /// let implements_copy = infcx.type_implements_trait(copy_trait, [ty], param_env) + /// .must_apply_modulo_regions(); + /// ``` + /// + /// In most cases you should instead create an [Obligation] and check whether + /// it holds via [`evaluate_obligation`] or one of its helper functions like + /// [`predicate_must_hold_modulo_regions`], because it properly handles higher ranked traits + /// and it is more convenient and safer when your `params` are inside a [`Binder`]. + /// + /// [Obligation]: traits::Obligation + /// [`evaluate_obligation`]: crate::traits::query::evaluate_obligation::InferCtxtExt::evaluate_obligation + /// [`predicate_must_hold_modulo_regions`]: crate::traits::query::evaluate_obligation::InferCtxtExt::predicate_must_hold_modulo_regions + /// [`Binder`]: ty::Binder #[instrument(level = "debug", skip(self, params), ret)] fn type_implements_trait( &self, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 3cd11d7c8e8..a98871b2d60 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -540,7 +540,7 @@ fn plug_infer_with_placeholders<'tcx>( universe: self.universe, bound: ty::BoundRegion { var: self.next_var(), - kind: ty::BoundRegionKind::BrAnon, + kind: ty::BoundRegionKind::Anon, }, }), ) diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 0eaacbcfbea..c00246cfd7d 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -7,6 +7,7 @@ use std::iter; use std::ops::ControlFlow; +use rustc_abi::BackendRepr; use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -18,7 +19,6 @@ use rustc_middle::ty::{ }; use rustc_span::Span; use rustc_span::symbol::Symbol; -use rustc_target::abi::BackendRepr; use smallvec::SmallVec; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 29e60e3c428..21141f6e18f 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -374,7 +374,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::Coerce(_) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) - // FIXME(effects): We may need to do this using the higher-ranked + // FIXME(const_trait_impl): We may need to do this using the higher-ranked // pred instead of just instantiating it with placeholders b/c of // higher-ranked implied bound issues in the old solver. | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => { @@ -624,9 +624,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2); use rustc_hir::def::DefKind; - use ty::Unevaluated; match (c1.kind(), c2.kind()) { - (Unevaluated(a), Unevaluated(b)) + (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst => { if let Ok(new_obligations) = infcx @@ -644,7 +643,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { )); } } - (_, Unevaluated(_)) | (Unevaluated(_), _) => (), + (_, ty::ConstKind::Unevaluated(_)) + | (ty::ConstKind::Unevaluated(_), _) => (), (_, _) => { if let Ok(new_obligations) = infcx .at(&obligation.cause, obligation.param_env) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 03fde1d1598..bf3f83ec827 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1170,8 +1170,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - // FIXME(effects): Destruct is not const yet, and it is implemented - // by all types today in non-const setting. candidates.vec.push(BuiltinCandidate { has_nested: false }); } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index e7d3004aa20..041cfc21267 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -660,7 +660,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .into() } GenericParamDefKind::Lifetime => { - let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); + let kind = ty::BoundRegionKind::Named(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Region(kind); bound_vars.push(bound_var); ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { @@ -951,18 +951,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); // We must additionally check that the return type impls `Future`. - - // FIXME(async_closures): Investigate this before stabilization. - // We instantiate this binder eagerly because the `confirm_future_candidate` - // method doesn't support higher-ranked futures, which the `AsyncFn` - // traits expressly allow the user to write. To fix this correctly, - // we'd need to instantiate trait bounds before we get to selection, - // like the new trait solver does. let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None); - let placeholder_output_ty = self.infcx.enter_forall_and_leak_universe(sig.output()); nested.push(obligation.with( tcx, - ty::TraitRef::new(tcx, future_trait_def_id, [placeholder_output_ty]), + sig.output().map_bound(|output_ty| { + ty::TraitRef::new(tcx, future_trait_def_id, [output_ty]) + }), )); (trait_ref, Ty::from_closure_kind(tcx, ty::ClosureKind::Fn)) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b1e5e526315..cffb62ab559 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -890,9 +890,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); use rustc_hir::def::DefKind; - use ty::Unevaluated; match (c1.kind(), c2.kind()) { - (Unevaluated(a), Unevaluated(b)) + (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst => { if let Ok(InferOk { obligations, value: () }) = self @@ -912,7 +911,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } } - (_, Unevaluated(_)) | (Unevaluated(_), _) => (), + (_, ty::ConstKind::Unevaluated(_)) + | (ty::ConstKind::Unevaluated(_), _) => (), (_, _) => { if let Ok(InferOk { obligations, value: () }) = self .infcx @@ -1310,7 +1310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option<EvaluationResult> { let tcx = self.tcx(); - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, trait_pred) { if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) { return Some(res); } @@ -1331,7 +1331,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if self.can_use_global_caches(param_env) && !trait_pred.has_infer() { + if self.can_use_global_caches(param_env, trait_pred) && !trait_pred.has_infer() { debug!(?trait_pred, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values @@ -1476,7 +1476,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } /// Returns `true` if the global caches can be used. - fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool { + fn can_use_global_caches( + &self, + param_env: ty::ParamEnv<'tcx>, + pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { // If there are any inference variables in the `ParamEnv`, then we // always use a cache local to this particular scope. Otherwise, we // switch to a global cache. @@ -1494,7 +1498,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { TypingMode::Coherence => false, // Avoid using the global cache when we're defining opaque types // as their hidden type may impact the result of candidate selection. - TypingMode::Analysis { defining_opaque_types } => defining_opaque_types.is_empty(), + // + // HACK: This is still theoretically unsound. Goals can indirectly rely + // on opaques in the defining scope, and it's easier to do so with TAIT. + // However, if we disqualify *all* goals from being cached, perf suffers. + // This is likely fixed by better caching in general in the new solver. + // See: <https://github.com/rust-lang/rust/issues/132064>. + TypingMode::Analysis { defining_opaque_types } => { + defining_opaque_types.is_empty() || !pred.has_opaque_types() + } // The global cache is only used if there are no opaque types in // the defining scope or we're outside of analysis. // @@ -1512,7 +1524,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); let pred = cache_fresh_trait_pred.skip_binder(); - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) { return Some(res); } @@ -1562,7 +1574,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { if let Err(Overflow(OverflowError::Canonical)) = candidate { // Don't cache overflow globally; we only produce this in certain modes. } else if !pred.has_infer() && !candidate.has_infer() { @@ -3183,7 +3195,7 @@ fn bind_coroutine_hidden_types_above<'tcx>( ty::ReErased => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon, + kind: ty::BoundRegionKind::Anon, }; counter += 1; ty::Region::new_bound(tcx, current_depth, br) @@ -3196,9 +3208,11 @@ fn bind_coroutine_hidden_types_above<'tcx>( bty.instantiate(tcx, args) }) .collect(); - let bound_vars = - tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain( - (num_bound_variables..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon)), - )); + let bound_vars = tcx.mk_bound_variable_kinds_from_iter( + bound_vars.iter().chain( + (num_bound_variables..counter) + .map(|_| ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)), + ), + ); ty::Binder::bind_with_vars(hidden_types, bound_vars) } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 722ef5f4569..0184e93acf1 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -1,7 +1,7 @@ use std::iter; use rustc_abi::Primitive::Pointer; -use rustc_abi::{BackendRepr, PointerKind, Scalar, Size}; +use rustc_abi::{BackendRepr, ExternAbi, PointerKind, Scalar, Size}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_middle::bug; @@ -12,10 +12,9 @@ use rustc_middle::ty::layout::{ use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt}; use rustc_session::config::OptLevel; use rustc_span::def_id::DefId; -use rustc_target::abi::call::{ +use rustc_target::callconv::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, RiscvInterruptKind, }; -use rustc_target::spec::abi::Abi as SpecAbi; use tracing::debug; pub(crate) fn provide(providers: &mut Providers) { @@ -39,7 +38,7 @@ fn fn_sig_for_fn_abi<'tcx>( tcx.thread_local_ptr_ty(instance.def_id()), false, hir::Safety::Safe, - rustc_target::spec::abi::Abi::Unadjusted, + rustc_abi::ExternAbi::Unadjusted, )); } @@ -77,12 +76,13 @@ fn fn_sig_for_fn_abi<'tcx>( ty::Closure(def_id, args) => { let sig = args.as_closure().sig(); - let bound_vars = tcx.mk_bound_variable_kinds_from_iter( - sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), - ); + let bound_vars = + tcx.mk_bound_variable_kinds_from_iter(sig.bound_vars().iter().chain(iter::once( + ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv), + ))); let br = ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BoundRegionKind::BrEnv, + kind: ty::BoundRegionKind::ClosureEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); let env_ty = tcx.closure_env_ty( @@ -106,12 +106,13 @@ fn fn_sig_for_fn_abi<'tcx>( ty::CoroutineClosure(def_id, args) => { let coroutine_ty = Ty::new_coroutine_closure(tcx, def_id, args); let sig = args.as_coroutine_closure().coroutine_closure_sig(); - let bound_vars = tcx.mk_bound_variable_kinds_from_iter( - sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), - ); + let bound_vars = + tcx.mk_bound_variable_kinds_from_iter(sig.bound_vars().iter().chain(iter::once( + ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv), + ))); let br = ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BoundRegionKind::BrEnv, + kind: ty::BoundRegionKind::ClosureEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); // When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`, @@ -162,11 +163,11 @@ fn fn_sig_for_fn_abi<'tcx>( let sig = args.as_coroutine().sig(); let bound_vars = tcx.mk_bound_variable_kinds_from_iter(iter::once( - ty::BoundVariableKind::Region(ty::BrEnv), + ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv), )); let br = ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BoundRegionKind::BrEnv, + kind: ty::BoundRegionKind::ClosureEnv, }; let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); @@ -270,7 +271,7 @@ fn fn_sig_for_fn_abi<'tcx>( ret_ty, false, hir::Safety::Safe, - rustc_target::spec::abi::Abi::Rust, + rustc_abi::ExternAbi::Rust, ) } else { // `Iterator::next` doesn't have a `resume` argument. @@ -279,7 +280,7 @@ fn fn_sig_for_fn_abi<'tcx>( ret_ty, false, hir::Safety::Safe, - rustc_target::spec::abi::Abi::Rust, + rustc_abi::ExternAbi::Rust, ) }; ty::Binder::bind_with_vars(fn_sig, bound_vars) @@ -289,8 +290,8 @@ fn fn_sig_for_fn_abi<'tcx>( } #[inline] -fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv { - use rustc_target::spec::abi::Abi::*; +fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv { + use rustc_abi::ExternAbi::*; match tcx.sess.target.adjust_abi(abi, c_variadic) { RustIntrinsic | Rust | RustCall => Conv::Rust, @@ -453,52 +454,73 @@ fn adjust_for_rust_scalar<'tcx>( fn fn_abi_sanity_check<'tcx>( cx: &LayoutCx<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - spec_abi: SpecAbi, + spec_abi: ExternAbi, ) { fn fn_arg_sanity_check<'tcx>( cx: &LayoutCx<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - spec_abi: SpecAbi, + spec_abi: ExternAbi, arg: &ArgAbi<'tcx, Ty<'tcx>>, ) { let tcx = cx.tcx(); + + if spec_abi == ExternAbi::Rust + || spec_abi == ExternAbi::RustCall + || spec_abi == ExternAbi::RustCold + { + if arg.layout.is_zst() { + // Casting closures to function pointers depends on ZST closure types being + // omitted entirely in the calling convention. + assert!(arg.is_ignore()); + } + if let PassMode::Indirect { on_stack, .. } = arg.mode { + assert!(!on_stack, "rust abi shouldn't use on_stack"); + } + } + match &arg.mode { - PassMode::Ignore => {} + PassMode::Ignore => { + assert!(arg.layout.is_zst() || arg.layout.is_uninhabited()); + } PassMode::Direct(_) => { // Here the Rust type is used to determine the actual ABI, so we have to be very - // careful. Scalar/ScalarPair is fine, since backends will generally use - // `layout.abi` and ignore everything else. We should just reject `Aggregate` - // entirely here, but some targets need to be fixed first. - if matches!(arg.layout.backend_repr, BackendRepr::Memory { .. }) { - // For an unsized type we'd only pass the sized prefix, so there is no universe - // in which we ever want to allow this. - assert!( - arg.layout.is_sized(), - "`PassMode::Direct` for unsized type in ABI: {:#?}", - fn_abi - ); - // This really shouldn't happen even for sized aggregates, since - // `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an - // LLVM type. This means all sorts of Rust type details leak into the ABI. - // However wasm sadly *does* currently use this mode so we have to allow it -- - // but we absolutely shouldn't let any more targets do that. - // (Also see <https://github.com/rust-lang/rust/issues/115666>.) - // - // The unstable abi `PtxKernel` also uses Direct for now. - // It needs to switch to something else before stabilization can happen. - // (See issue: https://github.com/rust-lang/rust/issues/117271) - assert!( - matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") - || matches!(spec_abi, SpecAbi::PtxKernel | SpecAbi::Unadjusted), - "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\ + // careful. Scalar/Vector is fine, since backends will generally use + // `layout.backend_repr` and ignore everything else. We should just reject + //`Aggregate` entirely here, but some targets need to be fixed first. + match arg.layout.backend_repr { + BackendRepr::Uninhabited + | BackendRepr::Scalar(_) + | BackendRepr::Vector { .. } => {} + BackendRepr::ScalarPair(..) => { + panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty) + } + BackendRepr::Memory { sized } => { + // For an unsized type we'd only pass the sized prefix, so there is no universe + // in which we ever want to allow this. + assert!(sized, "`PassMode::Direct` for unsized type in ABI: {:#?}", fn_abi); + // This really shouldn't happen even for sized aggregates, since + // `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an + // LLVM type. This means all sorts of Rust type details leak into the ABI. + // However wasm sadly *does* currently use this mode so we have to allow it -- + // but we absolutely shouldn't let any more targets do that. + // (Also see <https://github.com/rust-lang/rust/issues/115666>.) + // + // The unstable abi `PtxKernel` also uses Direct for now. + // It needs to switch to something else before stabilization can happen. + // (See issue: https://github.com/rust-lang/rust/issues/117271) + assert!( + matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") + || matches!(spec_abi, ExternAbi::PtxKernel | ExternAbi::Unadjusted), + "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\ Problematic type: {:#?}", - arg.layout, - ); + arg.layout, + ); + } } } PassMode::Pair(_, _) => { - // Similar to `Direct`, we need to make sure that backends use `layout.abi` and - // ignore the rest of the layout. + // Similar to `Direct`, we need to make sure that backends use `layout.backend_repr` + // and ignore the rest of the layout. assert!( matches!(arg.layout.backend_repr, BackendRepr::ScalarPair(..)), "PassMode::Pair for type {}", @@ -556,7 +578,7 @@ fn fn_abi_new_uncached<'tcx>( let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); let mut inputs = sig.inputs(); - let extra_args = if sig.abi == SpecAbi::RustCall { + let extra_args = if sig.abi == ExternAbi::RustCall { assert!(!sig.c_variadic && extra_args.is_empty()); if let Some(input) = sig.inputs().last() { @@ -649,10 +671,10 @@ fn fn_abi_new_uncached<'tcx>( fn fn_abi_adjust_for_abi<'tcx>( cx: &LayoutCx<'tcx>, fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, - abi: SpecAbi, + abi: ExternAbi, fn_def_id: Option<DefId>, ) -> Result<(), &'tcx FnAbiError<'tcx>> { - if abi == SpecAbi::Unadjusted { + if abi == ExternAbi::Unadjusted { // The "unadjusted" ABI passes aggregates in "direct" mode. That's fragile but needed for // some LLVM intrinsics. fn unadjust<'tcx>(arg: &mut ArgAbi<'tcx, Ty<'tcx>>) { @@ -676,7 +698,7 @@ fn fn_abi_adjust_for_abi<'tcx>( let tcx = cx.tcx(); - if abi == SpecAbi::Rust || abi == SpecAbi::RustCall || abi == SpecAbi::RustIntrinsic { + if abi == ExternAbi::Rust || abi == ExternAbi::RustCall || abi == ExternAbi::RustIntrinsic { fn_abi.adjust_for_rust_abi(cx, abi); // Look up the deduced parameter attributes for this function, if we have its def ID and diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 3655fa5ae0e..f97e8d48c8e 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -140,7 +140,7 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty kind, def_id: owner_id.to_def_id(), trait_item_def_id: Some(owner_id.to_def_id()), - container: ty::TraitContainer, + container: ty::AssocItemContainer::Trait, fn_has_self_parameter: has_self, opt_rpitit_info: None, } @@ -159,7 +159,7 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A kind, def_id: def_id.to_def_id(), trait_item_def_id: impl_item_ref.trait_item_def_id, - container: ty::ImplContainer, + container: ty::AssocItemContainer::Impl, fn_has_self_parameter: has_self, opt_rpitit_info: None, } @@ -267,7 +267,7 @@ fn associated_type_for_impl_trait_in_trait( kind: ty::AssocKind::Type, def_id, trait_item_def_id: None, - container: ty::TraitContainer, + container: ty::AssocItemContainer::Trait, fn_has_self_parameter: false, opt_rpitit_info: Some(ImplTraitInTraitData::Trait { fn_def_id: fn_def_id.to_def_id(), @@ -319,7 +319,7 @@ fn associated_type_for_impl_trait_in_impl( kind: ty::AssocKind::Type, def_id, trait_item_def_id: Some(trait_assoc_def_id), - container: ty::ImplContainer, + container: ty::AssocItemContainer::Impl, fn_has_self_parameter: false, opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }), }); diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 4b770d9938c..637e239a570 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -1,5 +1,6 @@ use std::iter; +use rustc_abi::{FIRST_VARIANT, VariantIdx}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -11,7 +12,6 @@ use rustc_middle::ty::abstract_const::CastKind; use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, mir, thir}; use rustc_span::Span; -use rustc_target::abi::{FIRST_VARIANT, VariantIdx}; use tracing::{debug, instrument}; use crate::errors::{GenericConstantTooComplex, GenericConstantTooComplexSub}; diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index e258b6dae0b..1d8a0880760 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -81,7 +81,6 @@ fn resolve_instance_raw<'tcx>( } } else { debug!(" => free item"); - // FIXME(effects): we may want to erase the effect param if that is present on this item. ty::InstanceKind::Item(def_id) }; diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 5ca7afe2453..63421dfdce6 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -5,9 +5,9 @@ use hir::def_id::DefId; use rustc_abi::Integer::{I8, I32}; use rustc_abi::Primitive::{self, Float, Int, Pointer}; use rustc_abi::{ - AbiAndPrefAlign, AddressSpace, Align, BackendRepr, FieldsShape, HasDataLayout, - LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, - Variants, WrappingRange, + AbiAndPrefAlign, AddressSpace, Align, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, + HasDataLayout, Layout, LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, + StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; use rustc_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; @@ -24,7 +24,6 @@ use rustc_middle::ty::{ use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; use rustc_span::symbol::Symbol; -use rustc_target::abi::{FIRST_VARIANT, FieldIdx, Layout, VariantIdx}; use tracing::{debug, instrument, trace}; use {rustc_abi as abi, rustc_hir as hir}; diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index f43feb552b2..fc05dd8256b 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -1,8 +1,8 @@ use std::assert_matches::assert_matches; +use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, Variants}; use rustc_middle::bug; use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout}; -use rustc_target::abi::*; /// Enforce some basic invariants on layouts. pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 731d42fc006..2127ba8a423 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -135,7 +135,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { if tcx.def_kind(def_id) == DefKind::AssocFn && let assoc_item = tcx.associated_item(def_id) - && assoc_item.container == ty::AssocItemContainer::TraitContainer + && assoc_item.container == ty::AssocItemContainer::Trait && assoc_item.defaultness(tcx).has_value() { let sig = tcx.fn_sig(def_id).instantiate_identity(); diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 0cade1d6885..8a8e624e72a 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -174,7 +174,6 @@ impl<I: Interner> UpcastFrom<I, TraitRef<I>> for TraitPredicate<I> { impl<I: Interner> fmt::Debug for TraitPredicate<I> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // FIXME(effects) printing? write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity) } } diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 4b7707ebccf..a6f7c254583 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -34,6 +34,12 @@ pub trait Context { /// Check whether the body of a function is available. fn has_body(&self, item: DefId) -> bool; fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>; + + /// Retrieve all functions defined in this crate. + fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef>; + + /// Retrieve all static items defined in this crate. + fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef>; fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule; fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>; fn all_trait_decls(&self) -> TraitDecls; diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index b523e949cde..0b4cebadad1 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -25,8 +25,9 @@ use serde::Serialize; use crate::compiler_interface::with; pub use crate::crate_def::{CrateDef, CrateDefType, DefId}; pub use crate::error::*; +use crate::mir::mono::StaticDef; use crate::mir::{Body, Mutability}; -use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; +use crate::ty::{FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; pub mod abi; #[macro_use] @@ -96,6 +97,16 @@ impl Crate { pub fn trait_impls(&self) -> ImplTraitDecls { with(|cx| cx.trait_impls(self.id)) } + + /// Return a list of function definitions from this crate independent on their visibility. + pub fn fn_defs(&self) -> Vec<FnDef> { + with(|cx| cx.crate_functions(self.id)) + } + + /// Return a list of static items defined in this crate independent on their visibility. + pub fn statics(&self) -> Vec<StaticDef> { + with(|cx| cx.crate_statics(self.id)) + } } #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 13e3d229d06..01a50d46b2d 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -1,13 +1,14 @@ +//! Implement methods to pretty print stable MIR body. use std::fmt::Debug; use std::io::Write; use std::{fmt, io, iter}; use fmt::{Display, Formatter}; -use super::{AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind}; +use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind}; use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents}; -use crate::ty::{IndexedVal, MirConst, Ty, TyConst}; -use crate::{Body, Mutability, with}; +use crate::ty::{AdtKind, IndexedVal, MirConst, Ty, TyConst}; +use crate::{Body, CrateDef, Mutability, with}; impl Display for Ty { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -23,10 +24,11 @@ impl Debug for Place { pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -> io::Result<()> { write!(writer, "fn {name}(")?; - body.arg_locals() - .iter() - .enumerate() - .try_for_each(|(index, local)| write!(writer, "_{}: {}", index + 1, local.ty))?; + let mut sep = ""; + for (index, local) in body.arg_locals().iter().enumerate() { + write!(writer, "{}_{}: {}", sep, index + 1, local.ty)?; + sep = ", "; + } write!(writer, ")")?; let return_local = body.ret_local(); @@ -73,39 +75,40 @@ pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) - } fn pretty_statement<W: Write>(writer: &mut W, statement: &StatementKind) -> io::Result<()> { + const INDENT: &str = " "; match statement { StatementKind::Assign(place, rval) => { - write!(writer, " {place:?} = ")?; + write!(writer, "{INDENT}{place:?} = ")?; pretty_rvalue(writer, rval)?; writeln!(writer, ";") } // FIXME: Add rest of the statements StatementKind::FakeRead(cause, place) => { - writeln!(writer, "FakeRead({cause:?}, {place:?});") + writeln!(writer, "{INDENT}FakeRead({cause:?}, {place:?});") } StatementKind::SetDiscriminant { place, variant_index } => { - writeln!(writer, "discriminant({place:?} = {};", variant_index.to_index()) + writeln!(writer, "{INDENT}discriminant({place:?} = {};", variant_index.to_index()) } StatementKind::Deinit(place) => writeln!(writer, "Deinit({place:?};"), StatementKind::StorageLive(local) => { - writeln!(writer, "StorageLive(_{local});") + writeln!(writer, "{INDENT}StorageLive(_{local});") } StatementKind::StorageDead(local) => { - writeln!(writer, "StorageDead(_{local});") + writeln!(writer, "{INDENT}StorageDead(_{local});") } StatementKind::Retag(kind, place) => writeln!(writer, "Retag({kind:?}, {place:?});"), StatementKind::PlaceMention(place) => { - writeln!(writer, "PlaceMention({place:?};") + writeln!(writer, "{INDENT}PlaceMention({place:?};") } StatementKind::ConstEvalCounter => { - writeln!(writer, "ConstEvalCounter;") + writeln!(writer, "{INDENT}ConstEvalCounter;") } - StatementKind::Nop => writeln!(writer, "nop;"), + StatementKind::Nop => writeln!(writer, "{INDENT}nop;"), StatementKind::AscribeUserType { .. } | StatementKind::Coverage(_) | StatementKind::Intrinsic(_) => { // FIX-ME: Make them pretty. - writeln!(writer, "{statement:?};") + writeln!(writer, "{INDENT}{statement:?};") } } } @@ -322,15 +325,11 @@ fn pretty_ty_const(ct: &TyConst) -> String { fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> { match rval { Rvalue::AddressOf(mutability, place) => { - write!(writer, "&raw {}(*{:?})", pretty_mut(*mutability), place) + write!(writer, "&raw {} {:?}", pretty_mut(*mutability), place) } Rvalue::Aggregate(aggregate_kind, operands) => { // FIXME: Add pretty_aggregate function that returns a pretty string - write!(writer, "{aggregate_kind:?} (")?; - let mut op_iter = operands.iter(); - op_iter.next().map_or(Ok(()), |op| write!(writer, "{}", pretty_operand(op)))?; - op_iter.try_for_each(|op| write!(writer, ", {}", pretty_operand(op)))?; - write!(writer, ")") + pretty_aggregate(writer, aggregate_kind, operands) } Rvalue::BinaryOp(bin, op1, op2) => { write!(writer, "{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2)) @@ -360,22 +359,74 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> { write!(writer, "{kind}{place:?}") } Rvalue::Repeat(op, cnst) => { - write!(writer, "{} \" \" {}", pretty_operand(op), pretty_ty_const(cnst)) + write!(writer, "[{}; {}]", pretty_operand(op), pretty_ty_const(cnst)) } Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::ThreadLocalRef(item) => { write!(writer, "thread_local_ref{item:?}") } Rvalue::NullaryOp(nul, ty) => { - write!(writer, "{nul:?} {ty} \" \"") + write!(writer, "{nul:?}::<{ty}>() \" \"") } Rvalue::UnaryOp(un, op) => { - write!(writer, "{} \" \" {:?}", pretty_operand(op), un) + write!(writer, "{:?}({})", un, pretty_operand(op)) } Rvalue::Use(op) => write!(writer, "{}", pretty_operand(op)), } } +fn pretty_aggregate<W: Write>( + writer: &mut W, + aggregate_kind: &AggregateKind, + operands: &Vec<Operand>, +) -> io::Result<()> { + let suffix = match aggregate_kind { + AggregateKind::Array(_) => { + write!(writer, "[")?; + "]" + } + AggregateKind::Tuple => { + write!(writer, "(")?; + ")" + } + AggregateKind::Adt(def, var, _, _, _) => { + if def.kind() == AdtKind::Enum { + write!(writer, "{}::{}", def.name(), def.variant(*var).unwrap().name())?; + } else { + write!(writer, "{}", def.variant(*var).unwrap().name())?; + } + if operands.is_empty() { + return Ok(()); + } + // FIXME: Change this once we have CtorKind in StableMIR. + write!(writer, "(")?; + ")" + } + AggregateKind::Closure(def, _) => { + write!(writer, "{{closure@{}}}(", def.span().diagnostic())?; + ")" + } + AggregateKind::Coroutine(def, _, _) => { + write!(writer, "{{coroutine@{}}}(", def.span().diagnostic())?; + ")" + } + AggregateKind::RawPtr(ty, mutability) => { + write!( + writer, + "*{} {ty} from (", + if *mutability == Mutability::Mut { "mut" } else { "const" } + )?; + ")" + } + }; + let mut separator = ""; + for op in operands { + write!(writer, "{}{}", separator, pretty_operand(op))?; + separator = ", "; + } + write!(writer, "{suffix}") +} + fn pretty_mut(mutability: Mutability) -> &'static str { match mutability { Mutability::Not => " ", diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 8db1258b65f..9ce72f155f9 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -271,6 +271,14 @@ impl Span { pub fn get_lines(&self) -> LineInfo { with(|c| c.get_lines(self)) } + + /// Return the span location to be printed in diagnostic messages. + /// + /// This may leak local file paths and should not be used to build artifacts that may be + /// distributed. + pub fn diagnostic(&self) -> String { + with(|c| c.span_to_string(*self)) + } } #[derive(Clone, Copy, Debug, Serialize)] diff --git a/library/Cargo.lock b/library/Cargo.lock index 5defd2950e8..772f9b19695 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.136" +version = "0.1.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ccee9dd499d7ada4c81533382ce87e88c52b0676c7320b2e617d29e1bb3a3f" +checksum = "53f0ea7fff95b51f84371588f06062557e96bbe363d2b36218ddb806f3ca8611" dependencies = [ "cc", "rustc-std-workspace-core", @@ -167,9 +167,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", @@ -335,7 +335,6 @@ dependencies = [ "hashbrown", "hermit-abi", "libc", - "memchr", "miniz_oxide", "object", "panic_abort", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index a9c375b62bd..3464047d4ee 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.136", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.138", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs index 19a583ca546..4430fff6677 100644 --- a/library/alloc/src/boxed/convert.rs +++ b/library/alloc/src/boxed/convert.rs @@ -110,6 +110,29 @@ impl<T: Clone> From<&[T]> for Box<[T]> { } #[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl<T: Clone> From<&mut [T]> for Box<[T]> { + /// Converts a `&mut [T]` into a `Box<[T]>` + /// + /// This conversion allocates on the heap + /// and performs a copy of `slice` and its contents. + /// + /// # Examples + /// ```rust + /// // create a &mut [u8] which will be used to create a Box<[u8]> + /// let mut array = [104, 101, 108, 108, 111]; + /// let slice: &mut [u8] = &mut array; + /// let boxed_slice: Box<[u8]> = Box::from(slice); + /// + /// println!("{boxed_slice:?}"); + /// ``` + #[inline] + fn from(slice: &mut [T]) -> Box<[T]> { + Self::from(&*slice) + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_cow", since = "1.45.0")] impl<T: Clone> From<Cow<'_, [T]>> for Box<[T]> { /// Converts a `Cow<'_, [T]>` into a `Box<[T]>` @@ -148,6 +171,28 @@ impl From<&str> for Box<str> { } #[cfg(not(no_global_oom_handling))] +#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut str> for Box<str> { + /// Converts a `&mut str` into a `Box<str>` + /// + /// This conversion allocates on the heap + /// and performs a copy of `s`. + /// + /// # Examples + /// + /// ```rust + /// let mut original = String::from("hello"); + /// let original: &mut str = &mut original; + /// let boxed: Box<str> = Box::from(original); + /// println!("{boxed}"); + /// ``` + #[inline] + fn from(s: &mut str) -> Box<str> { + Self::from(&*s) + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_cow", since = "1.45.0")] impl From<Cow<'_, str>> for Box<str> { /// Converts a `Cow<'_, str>` into a `Box<str>` diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index d7e99f4a1a6..d91682b796e 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -772,6 +772,16 @@ impl From<&CStr> for Box<CStr> { } } +#[cfg(not(test))] +#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut CStr> for Box<CStr> { + /// Converts a `&mut CStr` into a `Box<CStr>`, + /// by copying the contents into a newly allocated [`Box`]. + fn from(s: &mut CStr) -> Box<CStr> { + Self::from(&*s) + } +} + #[stable(feature = "box_from_cow", since = "1.45.0")] impl From<Cow<'_, CStr>> for Box<CStr> { /// Converts a `Cow<'a, CStr>` into a `Box<CStr>`, @@ -910,6 +920,17 @@ impl From<&CStr> for Arc<CStr> { } } +#[cfg(target_has_atomic = "ptr")] +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut CStr> for Arc<CStr> { + /// Converts a `&mut CStr` into a `Arc<CStr>`, + /// by copying the contents into a newly allocated [`Arc`]. + #[inline] + fn from(s: &mut CStr) -> Arc<CStr> { + Arc::from(&*s) + } +} + #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<CString> for Rc<CStr> { /// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> by moving the [`CString`] @@ -932,6 +953,16 @@ impl From<&CStr> for Rc<CStr> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut CStr> for Rc<CStr> { + /// Converts a `&mut CStr` into a `Rc<CStr>`, + /// by copying the contents into a newly allocated [`Rc`]. + #[inline] + fn from(s: &mut CStr) -> Rc<CStr> { + Rc::from(&*s) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "more_rc_default_impls", since = "1.80.0")] impl Default for Rc<CStr> { diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 3da71038a5e..695dddb25ee 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -109,6 +109,16 @@ //! parameters (corresponding to `format_spec` in [the syntax](#syntax)). These //! parameters affect the string representation of what's being formatted. //! +//! The colon `:` in format syntax divides indentifier of the input data and +//! the formatting options, the colon itself does not change anything, only +//! introduces the options. +//! +//! ``` +//! let a = 5; +//! let b = &a; +//! println!("{a:e} {b:p}"); // => 5e0 0x7ffe37b7273c +//! ``` +//! //! ## Width //! //! ``` diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index fc8646e96d9..64b0520e983 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2658,6 +2658,26 @@ impl<T: Clone> From<&[T]> for Rc<[T]> { } #[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl<T: Clone> From<&mut [T]> for Rc<[T]> { + /// Allocates a reference-counted slice and fills it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let mut original = [1, 2, 3]; + /// let original: &mut [i32] = &mut original; + /// let shared: Rc<[i32]> = Rc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &mut [T]) -> Rc<[T]> { + Rc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&str> for Rc<str> { /// Allocates a reference-counted string slice and copies `v` into it. @@ -2677,6 +2697,26 @@ impl From<&str> for Rc<str> { } #[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut str> for Rc<str> { + /// Allocates a reference-counted string slice and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let mut original = String::from("statue"); + /// let original: &mut str = &mut original; + /// let shared: Rc<str> = Rc::from(original); + /// assert_eq!("statue", &shared[..]); + /// ``` + #[inline] + fn from(v: &mut str) -> Rc<str> { + Rc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<String> for Rc<str> { /// Allocates a reference-counted string slice and copies `v` into it. diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 26c1ba2a5c4..6fee8d3fe33 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -531,6 +531,7 @@ impl str { #[rustc_allow_incoherent_impl] #[must_use] #[stable(feature = "repeat_str", since = "1.16.0")] + #[inline] pub fn repeat(&self, n: usize) -> String { unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 98a2fe24257..f348fba6220 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3615,6 +3615,26 @@ impl<T: Clone> From<&[T]> for Arc<[T]> { } #[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl<T: Clone> From<&mut [T]> for Arc<[T]> { + /// Allocates a reference-counted slice and fills it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let mut original = [1, 2, 3]; + /// let original: &mut [i32] = &mut original; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &mut [T]) -> Arc<[T]> { + Arc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&str> for Arc<str> { /// Allocates a reference-counted `str` and copies `v` into it. @@ -3634,6 +3654,26 @@ impl From<&str> for Arc<str> { } #[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut str> for Arc<str> { + /// Allocates a reference-counted `str` and copies `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let mut original = String::from("eggplant"); + /// let original: &mut str = &mut original; + /// let shared: Arc<str> = Arc::from(original); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: &mut str) -> Arc<str> { + Arc::from(&*v) + } +} + +#[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<String> for Arc<str> { /// Allocates a reference-counted `str` and copies `v` into it. diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 7e6c042274d..ab76cd7a6be 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -2122,7 +2122,6 @@ impl<T: ?Sized> UnsafeCell<T> { /// # Examples /// /// ``` - /// # #![feature(unsafe_cell_from_mut)] /// use std::cell::UnsafeCell; /// /// let mut val = 42; @@ -2132,7 +2131,9 @@ impl<T: ?Sized> UnsafeCell<T> { /// assert_eq!(*uc.get_mut(), 41); /// ``` #[inline(always)] - #[unstable(feature = "unsafe_cell_from_mut", issue = "111645")] + #[stable(feature = "unsafe_cell_from_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(value: &mut T) -> &mut UnsafeCell<T> { // SAFETY: `UnsafeCell<T>` has the same memory layout as `T` due to #[repr(transparent)]. unsafe { &mut *(value as *mut T as *mut UnsafeCell<T>) } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index c37b9aa2aae..02cc0f9d770 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1,7 +1,7 @@ //! impl char {} use super::*; -use crate::intrinsics::const_eval_select; +use crate::panic::const_panic; use crate::slice; use crate::str::from_utf8_unchecked_mut; use crate::unicode::printable::is_printable; @@ -320,7 +320,7 @@ impl char { /// '1'.is_digit(37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_char_is_digit", issue = "132241")] + #[rustc_const_unstable(feature = "const_char_classify", issue = "132241")] #[inline] pub const fn is_digit(self, radix: u32) -> bool { self.to_digit(radix).is_some() @@ -711,7 +711,7 @@ impl char { /// '𝕊'.encode_utf16(&mut b); /// ``` #[stable(feature = "unicode_encode_char", since = "1.15.0")] - #[rustc_const_unstable(feature = "const_char_encode_utf16", issue = "130660")] + #[rustc_const_stable(feature = "const_char_encode_utf16", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] { encode_utf16_raw(self as u32, dst) @@ -856,8 +856,9 @@ impl char { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_char_classify", issue = "132241")] #[inline] - pub fn is_whitespace(self) -> bool { + pub const fn is_whitespace(self) -> bool { match self { ' ' | '\x09'..='\x0d' => true, c => c > '\x7f' && unicode::White_Space(c), @@ -1773,17 +1774,7 @@ const fn len_utf16(code: u32) -> usize { #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0"))] #[doc(hidden)] #[inline] -#[rustc_allow_const_fn_unstable(const_eval_select)] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { - const fn panic_at_const(_code: u32, _len: usize, _dst_len: usize) { - // Note that we cannot format in constant expressions. - panic!("encode_utf8: buffer does not have enough bytes to encode code point"); - } - fn panic_at_rt(code: u32, len: usize, dst_len: usize) { - panic!( - "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", - ); - } let len = len_utf8(code); match (len, &mut *dst) { (1, [a, ..]) => { @@ -1804,8 +1795,15 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { *c = (code >> 6 & 0x3F) as u8 | TAG_CONT; *d = (code & 0x3F) as u8 | TAG_CONT; } - // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. - _ => const_eval_select((code, len, dst.len()), panic_at_const, panic_at_rt), + _ => { + const_panic!( + "encode_utf8: buffer does not have enough bytes to encode code point", + "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", + code: u32 = code, + len: usize = len, + dst_len: usize = dst.len(), + ) + } }; // SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds. unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) } @@ -1822,19 +1820,13 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { /// Panics if the buffer is not large enough. /// A buffer of length 2 is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[rustc_const_unstable(feature = "const_char_encode_utf16", issue = "130660")] +#[cfg_attr( + bootstrap, + rustc_const_stable(feature = "const_char_encode_utf16", since = "CURRENT_RUSTC_VERSION") +)] #[doc(hidden)] #[inline] pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] { - const fn panic_at_const(_code: u32, _len: usize, _dst_len: usize) { - // Note that we cannot format in constant expressions. - panic!("encode_utf16: buffer does not have enough bytes to encode code point"); - } - fn panic_at_rt(code: u32, len: usize, dst_len: usize) { - panic!( - "encode_utf16: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", - ); - } let len = len_utf16(code); match (len, &mut *dst) { (1, [a, ..]) => { @@ -1845,8 +1837,15 @@ pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] { *a = (code >> 10) as u16 | 0xD800; *b = (code & 0x3FF) as u16 | 0xDC00; } - // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. - _ => const_eval_select((code, len, dst.len()), panic_at_const, panic_at_rt), + _ => { + const_panic!( + "encode_utf16: buffer does not have enough bytes to encode code point", + "encode_utf16: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", + code: u32 = code, + len: usize = len, + dst_len: usize = dst.len(), + ) + } }; // SAFETY: `<&mut [u16]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds. unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) } diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 93dd351b029..85571222b5c 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -3,11 +3,12 @@ use crate::cmp::Ordering; use crate::error::Error; use crate::ffi::c_char; +use crate::intrinsics::const_eval_select; use crate::iter::FusedIterator; use crate::marker::PhantomData; use crate::ptr::NonNull; use crate::slice::memchr; -use crate::{fmt, intrinsics, ops, slice, str}; +use crate::{fmt, ops, slice, str}; // FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link // depends on where the item is being documented. however, since this is libcore, we can't @@ -411,37 +412,35 @@ impl CStr { #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")] #[rustc_allow_const_fn_unstable(const_eval_select)] pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { - #[inline] - fn rt_impl(bytes: &[u8]) -> &CStr { - // Chance at catching some UB at runtime with debug builds. - debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0); - - // SAFETY: Casting to CStr is safe because its internal representation - // is a [u8] too (safe only inside std). - // Dereferencing the obtained pointer is safe because it comes from a - // reference. Making a reference is then safe because its lifetime - // is bound by the lifetime of the given `bytes`. - unsafe { &*(bytes as *const [u8] as *const CStr) } - } - - const fn const_impl(bytes: &[u8]) -> &CStr { - // Saturating so that an empty slice panics in the assert with a good - // message, not here due to underflow. - let mut i = bytes.len().saturating_sub(1); - assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated"); - - // Ending nul byte exists, skip to the rest. - while i != 0 { - i -= 1; - let byte = bytes[i]; - assert!(byte != 0, "input contained interior nul"); + const_eval_select!( + @capture { bytes: &[u8] } -> &CStr: + if const { + // Saturating so that an empty slice panics in the assert with a good + // message, not here due to underflow. + let mut i = bytes.len().saturating_sub(1); + assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated"); + + // Ending nul byte exists, skip to the rest. + while i != 0 { + i -= 1; + let byte = bytes[i]; + assert!(byte != 0, "input contained interior nul"); + } + + // SAFETY: See runtime cast comment below. + unsafe { &*(bytes as *const [u8] as *const CStr) } + } else { + // Chance at catching some UB at runtime with debug builds. + debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0); + + // SAFETY: Casting to CStr is safe because its internal representation + // is a [u8] too (safe only inside std). + // Dereferencing the obtained pointer is safe because it comes from a + // reference. Making a reference is then safe because its lifetime + // is bound by the lifetime of the given `bytes`. + unsafe { &*(bytes as *const [u8] as *const CStr) } } - - // SAFETY: See `rt_impl` cast. - unsafe { &*(bytes as *const [u8] as *const CStr) } - } - - intrinsics::const_eval_select((bytes,), const_impl, rt_impl) + ) } /// Returns the inner pointer to this C string. @@ -510,7 +509,7 @@ impl CStr { #[inline] #[must_use] const fn as_non_null_ptr(&self) -> NonNull<c_char> { - // FIXME(effects) replace with `NonNull::from` + // FIXME(const_trait_impl) replace with `NonNull::from` // SAFETY: a reference is never null unsafe { NonNull::new_unchecked(&self.inner as *const [c_char] as *mut [c_char]) } .as_non_null_ptr() @@ -735,29 +734,27 @@ impl AsRef<CStr> for CStr { #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))] #[rustc_allow_const_fn_unstable(const_eval_select)] const unsafe fn strlen(ptr: *const c_char) -> usize { - const fn strlen_ct(s: *const c_char) -> usize { - let mut len = 0; - - // SAFETY: Outer caller has provided a pointer to a valid C string. - while unsafe { *s.add(len) } != 0 { - len += 1; - } + const_eval_select!( + @capture { s: *const c_char = ptr } -> usize: + if const { + let mut len = 0; + + // SAFETY: Outer caller has provided a pointer to a valid C string. + while unsafe { *s.add(len) } != 0 { + len += 1; + } - len - } + len + } else { + extern "C" { + /// Provided by libc or compiler_builtins. + fn strlen(s: *const c_char) -> usize; + } - #[inline] - fn strlen_rt(s: *const c_char) -> usize { - extern "C" { - /// Provided by libc or compiler_builtins. - fn strlen(s: *const c_char) -> usize; + // SAFETY: Outer caller has provided a pointer to a valid C string. + unsafe { strlen(s) } } - - // SAFETY: Outer caller has provided a pointer to a valid C string. - unsafe { strlen(s) } - } - - intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt) + ) } /// An iterator over the bytes of a [`CStr`], without the nul terminator. diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index f3b54230bc1..2b1692a195e 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -438,10 +438,9 @@ impl<'a> Arguments<'a> { /// assert_eq!(format_args!("{:?}", std::env::current_dir()).as_str(), None); /// ``` #[stable(feature = "fmt_as_str", since = "1.52.0")] - #[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")] + #[rustc_const_stable(feature = "const_arguments_as_str", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] pub const fn as_str(&self) -> Option<&'static str> { match (self.pieces, self.args) { ([], []) => Some(""), diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index f1540803f97..d43f25d9fd1 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -88,7 +88,10 @@ unsafe trait GenericRadix: Sized { }; } } - let buf = &buf[curr..]; + // SAFETY: `curr` is initialized to `buf.len()` and is only decremented, so it can't overflow. It is + // decremented exactly once for each digit. Since u128 is the widest fixed width integer format supported, + // the maximum number of digits (bits) is 128 for base-2, so `curr` won't underflow as well. + let buf = unsafe { buf.get_unchecked(curr..) }; // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be // valid UTF-8 let buf = unsafe { diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 17f2caaa0c0..6ea3241c593 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -147,9 +147,8 @@ impl SipHasher { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] - pub const fn new() -> SipHasher { + pub fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) } @@ -157,9 +156,8 @@ impl SipHasher { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] - pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher { + pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) }) } } @@ -169,8 +167,7 @@ impl SipHasher13 { #[inline] #[unstable(feature = "hashmap_internals", issue = "none")] #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - pub const fn new() -> SipHasher13 { + pub fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) } @@ -178,8 +175,7 @@ impl SipHasher13 { #[inline] #[unstable(feature = "hashmap_internals", issue = "none")] #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { + pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } } } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics/mod.rs index fc09da7bcbc..b6e22c42eee 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics/mod.rs @@ -8,16 +8,16 @@ //! Note: any changes to the constness of intrinsics should be discussed with the language team. //! This includes changes in the stability of the constness. //! -//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation -//! from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics> to -//! <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs> and add a -//! `#[rustc_const_unstable(feature = "const_such_and_such", issue = "01234")]` to the intrinsic declaration. +//! In order to make an intrinsic usable at compile-time, it needs to be declared in the "new" +//! style, i.e. as a `#[rustc_intrinsic]` function, not inside an `extern` block. Then copy the +//! implementation from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics> to +//! <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs> +//! and make the intrinsic declaration a `const fn`. //! //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, -//! `#[rustc_const_stable_indirect]` needs to be added to the intrinsic (`#[rustc_const_unstable]` -//! can be removed then). Such a change should not be done without T-lang consultation, because it -//! may bake a feature into the language that cannot be replicated in user code without compiler -//! support. +//! `#[rustc_const_stable_intrinsic]` needs to be added to the intrinsic. Such a change requires +//! T-lang approval, because it may bake a feature into the language that cannot be replicated in +//! user code without compiler support. //! //! # Volatiles //! @@ -904,53 +904,69 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn prefetch_write_instruction<T>(data: *const T, locality: i32); - /// Magic intrinsic that derives its meaning from attributes - /// attached to the function. - /// - /// For example, dataflow uses this to inject static assertions so - /// that `rustc_peek(potentially_uninitialized)` would actually - /// double-check that dataflow did indeed compute that it is - /// uninitialized at that point in the control flow. + /// Executes a breakpoint trap, for inspection by a debugger. /// - /// This intrinsic should not be used outside of the compiler. - #[rustc_safe_intrinsic] + /// This intrinsic does not have a stable counterpart. #[rustc_nounwind] - pub fn rustc_peek<T>(_: T) -> T; + pub fn breakpoint(); +} - /// Aborts the execution of the process. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible, - /// as its behavior is more user-friendly and more stable. - /// - /// The current implementation of `intrinsics::abort` is to invoke an invalid instruction, - /// on most platforms. - /// On Unix, the - /// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or - /// `SIGBUS`. The precise behavior is not guaranteed and not stable. - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn abort() -> !; +/// Magic intrinsic that derives its meaning from attributes +/// attached to the function. +/// +/// For example, dataflow uses this to inject static assertions so +/// that `rustc_peek(potentially_uninitialized)` would actually +/// double-check that dataflow did indeed compute that it is +/// uninitialized at that point in the control flow. +/// +/// This intrinsic should not be used outside of the compiler. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn rustc_peek<T>(_: T) -> T { + unreachable!() +} - /// Informs the optimizer that this point in the code is not reachable, - /// enabling further optimizations. - /// - /// N.B., this is very different from the `unreachable!()` macro: Unlike the - /// macro, which panics when it is executed, it is *undefined behavior* to - /// reach code marked with this function. - /// - /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`]. - #[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0") - )] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn unreachable() -> !; +/// Aborts the execution of the process. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible, +/// as its behavior is more user-friendly and more stable. +/// +/// The current implementation of `intrinsics::abort` is to invoke an invalid instruction, +/// on most platforms. +/// On Unix, the +/// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or +/// `SIGBUS`. The precise behavior is not guaranteed and not stable. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn abort() -> ! { + unreachable!() +} + +/// Informs the optimizer that this point in the code is not reachable, +/// enabling further optimizations. +/// +/// N.B., this is very different from the `unreachable!()` macro: Unlike the +/// macro, which panics when it is executed, it is *undefined behavior* to +/// reach code marked with this function. +/// +/// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`]. +#[cfg_attr( + bootstrap, + rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0") +)] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unreachable() -> ! { + unreachable!() } /// Informs the optimizer that a condition is always true. @@ -964,7 +980,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`]. #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assume", since = "1.77.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -990,7 +1006,7 @@ pub const unsafe fn assume(b: bool) { bootstrap, rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION") )] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] @@ -1014,7 +1030,7 @@ pub const fn likely(b: bool) -> bool { bootstrap, rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION") )] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] @@ -1044,449 +1060,480 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T { if b { true_val } else { false_val } } -extern "rust-intrinsic" { - /// Executes a breakpoint trap, for inspection by a debugger. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn breakpoint(); +/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: +/// This will statically either panic, or do nothing. +/// +/// This intrinsic does not have a stable counterpart. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn assert_inhabited<T>() { + unreachable!() +} - /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: - /// This will statically either panic, or do nothing. - /// - /// This intrinsic does not have a stable counterpart. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn assert_inhabited<T>(); +/// A guard for unsafe functions that cannot ever be executed if `T` does not permit +/// zero-initialization: This will statically either panic, or do nothing. +/// +/// This intrinsic does not have a stable counterpart. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn assert_zero_valid<T>() { + unreachable!() +} - /// A guard for unsafe functions that cannot ever be executed if `T` does not permit - /// zero-initialization: This will statically either panic, or do nothing. - /// - /// This intrinsic does not have a stable counterpart. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn assert_zero_valid<T>(); +/// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. +/// +/// This intrinsic does not have a stable counterpart. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn assert_mem_uninitialized_valid<T>() { + unreachable!() +} - /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. - /// - /// This intrinsic does not have a stable counterpart. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn assert_mem_uninitialized_valid<T>(); +/// Gets a reference to a static `Location` indicating where it was called. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// Consider using [`core::panic::Location::caller`] instead. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn caller_location() -> &'static crate::panic::Location<'static> { + unreachable!() +} - /// Gets a reference to a static `Location` indicating where it was called. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// Consider using [`core::panic::Location::caller`] instead. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn caller_location() -> &'static crate::panic::Location<'static>; - - /// Moves a value out of scope without running drop glue. - /// - /// This exists solely for [`crate::mem::forget_unsized`]; normal `forget` uses - /// `ManuallyDrop` instead. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn forget<T: ?Sized>(_: T); - - /// Reinterprets the bits of a value of one type as another type. - /// - /// Both types must have the same size. Compilation will fail if this is not guaranteed. - /// - /// `transmute` is semantically equivalent to a bitwise move of one type - /// into another. It copies the bits from the source value into the - /// destination value, then forgets the original. Note that source and destination - /// are passed by-value, which means if `Src` or `Dst` contain padding, that padding - /// is *not* guaranteed to be preserved by `transmute`. - /// - /// Both the argument and the result must be [valid](../../nomicon/what-unsafe-does.html) at - /// their given type. Violating this condition leads to [undefined behavior][ub]. The compiler - /// will generate code *assuming that you, the programmer, ensure that there will never be - /// undefined behavior*. It is therefore your responsibility to guarantee that every value - /// passed to `transmute` is valid at both types `Src` and `Dst`. Failing to uphold this condition - /// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly - /// unsafe**. `transmute` should be the absolute last resort. - /// - /// Because `transmute` is a by-value operation, alignment of the *transmuted values - /// themselves* is not a concern. As with any other function, the compiler already ensures - /// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point - /// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper - /// alignment of the pointed-to values. - /// - /// The [nomicon](../../nomicon/transmutes.html) has additional documentation. - /// - /// [ub]: ../../reference/behavior-considered-undefined.html - /// - /// # Transmutation between pointers and integers - /// - /// Special care has to be taken when transmuting between pointers and integers, e.g. - /// transmuting between `*const ()` and `usize`. - /// - /// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless - /// the pointer was originally created *from* an integer. (That includes this function - /// specifically, integer-to-pointer casts, and helpers like [`dangling`][crate::ptr::dangling], - /// but also semantically-equivalent conversions such as punning through `repr(C)` union - /// fields.) Any attempt to use the resulting value for integer operations will abort - /// const-evaluation. (And even outside `const`, such transmutation is touching on many - /// unspecified aspects of the Rust memory model and should be avoided. See below for - /// alternatives.) - /// - /// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not* - /// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed - /// this way is currently considered undefined behavior. - /// - /// All this also applies when the integer is nested inside an array, tuple, struct, or enum. - /// However, `MaybeUninit<usize>` is not considered an integer type for the purpose of this - /// section. Transmuting `*const ()` to `MaybeUninit<usize>` is fine---but then calling - /// `assume_init()` on that result is considered as completing the pointer-to-integer transmute - /// and thus runs into the issues discussed above. - /// - /// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a - /// lossless process. If you want to round-trip a pointer through an integer in a way that you - /// can get back the original pointer, you need to use `as` casts, or replace the integer type - /// by `MaybeUninit<$int>` (and never call `assume_init()`). If you are looking for a way to - /// store data of arbitrary type, also use `MaybeUninit<T>` (that will also handle uninitialized - /// memory due to padding). If you specifically need to store something that is "either an - /// integer or a pointer", use `*mut ()`: integers can be converted to pointers and back without - /// any loss (via `as` casts or via `transmute`). - /// - /// # Examples - /// - /// There are a few things that `transmute` is really useful for. - /// - /// Turning a pointer into a function pointer. This is *not* portable to - /// machines where function pointers and data pointers have different sizes. - /// - /// ``` - /// fn foo() -> i32 { - /// 0 - /// } - /// // Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer. - /// // This avoids an integer-to-pointer `transmute`, which can be problematic. - /// // Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine. - /// let pointer = foo as *const (); - /// let function = unsafe { - /// std::mem::transmute::<*const (), fn() -> i32>(pointer) - /// }; - /// assert_eq!(function(), 0); - /// ``` - /// - /// Extending a lifetime, or shortening an invariant lifetime. This is - /// advanced, very unsafe Rust! - /// - /// ``` - /// struct R<'a>(&'a i32); - /// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> { - /// std::mem::transmute::<R<'b>, R<'static>>(r) - /// } - /// - /// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>) - /// -> &'b mut R<'c> { - /// std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r) - /// } - /// ``` - /// - /// # Alternatives - /// - /// Don't despair: many uses of `transmute` can be achieved through other means. - /// Below are common applications of `transmute` which can be replaced with safer - /// constructs. - /// - /// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.: - /// - /// ``` - /// let raw_bytes = [0x78, 0x56, 0x34, 0x12]; - /// - /// let num = unsafe { - /// std::mem::transmute::<[u8; 4], u32>(raw_bytes) - /// }; - /// - /// // use `u32::from_ne_bytes` instead - /// let num = u32::from_ne_bytes(raw_bytes); - /// // or use `u32::from_le_bytes` or `u32::from_be_bytes` to specify the endianness - /// let num = u32::from_le_bytes(raw_bytes); - /// assert_eq!(num, 0x12345678); - /// let num = u32::from_be_bytes(raw_bytes); - /// assert_eq!(num, 0x78563412); - /// ``` - /// - /// Turning a pointer into a `usize`: - /// - /// ```no_run - /// let ptr = &0; - /// let ptr_num_transmute = unsafe { - /// std::mem::transmute::<&i32, usize>(ptr) - /// }; - /// - /// // Use an `as` cast instead - /// let ptr_num_cast = ptr as *const i32 as usize; - /// ``` - /// - /// Note that using `transmute` to turn a pointer to a `usize` is (as noted above) [undefined - /// behavior][ub] in `const` contexts. Also outside of consts, this operation might not behave - /// as expected -- this is touching on many unspecified aspects of the Rust memory model. - /// Depending on what the code is doing, the following alternatives are preferable to - /// pointer-to-integer transmutation: - /// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a - /// type for that buffer, it can use [`MaybeUninit`][crate::mem::MaybeUninit]. - /// - If the code actually wants to work on the address the pointer points to, it can use `as` - /// casts or [`ptr.addr()`][pointer::addr]. - /// - /// Turning a `*mut T` into a `&mut T`: - /// - /// ``` - /// let ptr: *mut i32 = &mut 0; - /// let ref_transmuted = unsafe { - /// std::mem::transmute::<*mut i32, &mut i32>(ptr) - /// }; - /// - /// // Use a reborrow instead - /// let ref_casted = unsafe { &mut *ptr }; - /// ``` - /// - /// Turning a `&mut T` into a `&mut U`: - /// - /// ``` - /// let ptr = &mut 0; - /// let val_transmuted = unsafe { - /// std::mem::transmute::<&mut i32, &mut u32>(ptr) - /// }; - /// - /// // Now, put together `as` and reborrowing - note the chaining of `as` - /// // `as` is not transitive - /// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) }; - /// ``` - /// - /// Turning a `&str` into a `&[u8]`: - /// - /// ``` - /// // this is not a good way to do this. - /// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") }; - /// assert_eq!(slice, &[82, 117, 115, 116]); - /// - /// // You could use `str::as_bytes` - /// let slice = "Rust".as_bytes(); - /// assert_eq!(slice, &[82, 117, 115, 116]); - /// - /// // Or, just use a byte string, if you have control over the string - /// // literal - /// assert_eq!(b"Rust", &[82, 117, 115, 116]); - /// ``` - /// - /// Turning a `Vec<&T>` into a `Vec<Option<&T>>`. - /// - /// To transmute the inner type of the contents of a container, you must make sure to not - /// violate any of the container's invariants. For `Vec`, this means that both the size - /// *and alignment* of the inner types have to match. Other containers might rely on the - /// size of the type, alignment, or even the `TypeId`, in which case transmuting wouldn't - /// be possible at all without violating the container invariants. - /// - /// ``` - /// let store = [0, 1, 2, 3]; - /// let v_orig = store.iter().collect::<Vec<&i32>>(); - /// - /// // clone the vector as we will reuse them later - /// let v_clone = v_orig.clone(); - /// - /// // Using transmute: this relies on the unspecified data layout of `Vec`, which is a - /// // bad idea and could cause Undefined Behavior. - /// // However, it is no-copy. - /// let v_transmuted = unsafe { - /// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone) - /// }; - /// - /// let v_clone = v_orig.clone(); - /// - /// // This is the suggested, safe way. - /// // It may copy the entire vector into a new one though, but also may not. - /// let v_collected = v_clone.into_iter() - /// .map(Some) - /// .collect::<Vec<Option<&i32>>>(); - /// - /// let v_clone = v_orig.clone(); - /// - /// // This is the proper no-copy, unsafe way of "transmuting" a `Vec`, without relying on the - /// // data layout. Instead of literally calling `transmute`, we perform a pointer cast, but - /// // in terms of converting the original inner type (`&i32`) to the new one (`Option<&i32>`), - /// // this has all the same caveats. Besides the information provided above, also consult the - /// // [`from_raw_parts`] documentation. - /// let v_from_raw = unsafe { - // FIXME Update this when vec_into_raw_parts is stabilized - /// // Ensure the original vector is not dropped. - /// let mut v_clone = std::mem::ManuallyDrop::new(v_clone); - /// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>, - /// v_clone.len(), - /// v_clone.capacity()) - /// }; - /// ``` - /// - /// [`from_raw_parts`]: ../../std/vec/struct.Vec.html#method.from_raw_parts - /// - /// Implementing `split_at_mut`: - /// - /// ``` - /// use std::{slice, mem}; - /// - /// // There are multiple ways to do this, and there are multiple problems - /// // with the following (transmute) way. - /// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize) - /// -> (&mut [T], &mut [T]) { - /// let len = slice.len(); - /// assert!(mid <= len); - /// unsafe { - /// let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice); - /// // first: transmute is not type safe; all it checks is that T and - /// // U are of the same size. Second, right here, you have two - /// // mutable references pointing to the same memory. - /// (&mut slice[0..mid], &mut slice2[mid..len]) - /// } - /// } - /// - /// // This gets rid of the type safety problems; `&mut *` will *only* give - /// // you a `&mut T` from a `&mut T` or `*mut T`. - /// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize) - /// -> (&mut [T], &mut [T]) { - /// let len = slice.len(); - /// assert!(mid <= len); - /// unsafe { - /// let slice2 = &mut *(slice as *mut [T]); - /// // however, you still have two mutable references pointing to - /// // the same memory. - /// (&mut slice[0..mid], &mut slice2[mid..len]) - /// } - /// } - /// - /// // This is how the standard library does it. This is the best method, if - /// // you need to do something like this - /// fn split_at_stdlib<T>(slice: &mut [T], mid: usize) - /// -> (&mut [T], &mut [T]) { - /// let len = slice.len(); - /// assert!(mid <= len); - /// unsafe { - /// let ptr = slice.as_mut_ptr(); - /// // This now has three mutable references pointing at the same - /// // memory. `slice`, the rvalue ret.0, and the rvalue ret.1. - /// // `slice` is never used after `let ptr = ...`, and so one can - /// // treat it as "dead", and therefore, you only have two real - /// // mutable slices. - /// (slice::from_raw_parts_mut(ptr, mid), - /// slice::from_raw_parts_mut(ptr.add(mid), len - mid)) - /// } - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_allowed_through_unstable_modules] - #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] - #[rustc_diagnostic_item = "transmute"] - #[rustc_nounwind] - pub fn transmute<Src, Dst>(src: Src) -> Dst; - - /// Like [`transmute`], but even less checked at compile-time: rather than - /// giving an error for `size_of::<Src>() != size_of::<Dst>()`, it's - /// **Undefined Behavior** at runtime. - /// - /// Prefer normal `transmute` where possible, for the extra checking, since - /// both do exactly the same thing at runtime, if they both compile. - /// - /// This is not expected to ever be exposed directly to users, rather it - /// may eventually be exposed through some more-constrained API. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn transmute_unchecked<Src, Dst>(src: Src) -> Dst; - - /// Returns `true` if the actual type given as `T` requires drop - /// glue; returns `false` if the actual type provided for `T` - /// implements `Copy`. - /// - /// If the actual type neither requires drop glue nor implements - /// `Copy`, then the return value of this function is unspecified. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn needs_drop<T: ?Sized>() -> bool; - - /// Calculates the offset from a pointer. - /// - /// This is implemented as an intrinsic to avoid converting to and from an - /// integer, since the conversion would throw away aliasing information. - /// - /// This can only be used with `Ptr` as a raw pointer type (`*mut` or `*const`) - /// to a `Sized` pointee and with `Delta` as `usize` or `isize`. Any other - /// instantiations may arbitrarily misbehave, and that's *not* a compiler bug. - /// - /// # Safety - /// - /// If the computed offset is non-zero, then both the starting and resulting pointer must be - /// either in bounds or at the end of an allocated object. If either pointer is out - /// of bounds or arithmetic overflow occurs then this operation is undefined behavior. - /// - /// The stabilized version of this intrinsic is [`pointer::offset`]. - #[must_use = "returns a new pointer rather than modifying its argument"] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr; - - /// Calculates the offset from a pointer, potentially wrapping. - /// - /// This is implemented as an intrinsic to avoid converting to and from an - /// integer, since the conversion inhibits certain optimizations. - /// - /// # Safety - /// - /// Unlike the `offset` intrinsic, this intrinsic does not restrict the - /// resulting pointer to point into or at the end of an allocated - /// object, and it wraps with two's complement arithmetic. The resulting - /// value is not necessarily valid to be used to actually access memory. - /// - /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. - #[must_use = "returns a new pointer rather than modifying its argument"] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T; +/// Moves a value out of scope without running drop glue. +/// +/// This exists solely for [`crate::mem::forget_unsized`]; normal `forget` uses +/// `ManuallyDrop` instead. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn forget<T: ?Sized>(_: T) { + unreachable!() +} - /// Masks out bits of the pointer according to a mask. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// Consider using [`pointer::mask`] instead. - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T; +/// Reinterprets the bits of a value of one type as another type. +/// +/// Both types must have the same size. Compilation will fail if this is not guaranteed. +/// +/// `transmute` is semantically equivalent to a bitwise move of one type +/// into another. It copies the bits from the source value into the +/// destination value, then forgets the original. Note that source and destination +/// are passed by-value, which means if `Src` or `Dst` contain padding, that padding +/// is *not* guaranteed to be preserved by `transmute`. +/// +/// Both the argument and the result must be [valid](../../nomicon/what-unsafe-does.html) at +/// their given type. Violating this condition leads to [undefined behavior][ub]. The compiler +/// will generate code *assuming that you, the programmer, ensure that there will never be +/// undefined behavior*. It is therefore your responsibility to guarantee that every value +/// passed to `transmute` is valid at both types `Src` and `Dst`. Failing to uphold this condition +/// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly +/// unsafe**. `transmute` should be the absolute last resort. +/// +/// Because `transmute` is a by-value operation, alignment of the *transmuted values +/// themselves* is not a concern. As with any other function, the compiler already ensures +/// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point +/// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper +/// alignment of the pointed-to values. +/// +/// The [nomicon](../../nomicon/transmutes.html) has additional documentation. +/// +/// [ub]: ../../reference/behavior-considered-undefined.html +/// +/// # Transmutation between pointers and integers +/// +/// Special care has to be taken when transmuting between pointers and integers, e.g. +/// transmuting between `*const ()` and `usize`. +/// +/// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless +/// the pointer was originally created *from* an integer. (That includes this function +/// specifically, integer-to-pointer casts, and helpers like [`dangling`][crate::ptr::dangling], +/// but also semantically-equivalent conversions such as punning through `repr(C)` union +/// fields.) Any attempt to use the resulting value for integer operations will abort +/// const-evaluation. (And even outside `const`, such transmutation is touching on many +/// unspecified aspects of the Rust memory model and should be avoided. See below for +/// alternatives.) +/// +/// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not* +/// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed +/// this way is currently considered undefined behavior. +/// +/// All this also applies when the integer is nested inside an array, tuple, struct, or enum. +/// However, `MaybeUninit<usize>` is not considered an integer type for the purpose of this +/// section. Transmuting `*const ()` to `MaybeUninit<usize>` is fine---but then calling +/// `assume_init()` on that result is considered as completing the pointer-to-integer transmute +/// and thus runs into the issues discussed above. +/// +/// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a +/// lossless process. If you want to round-trip a pointer through an integer in a way that you +/// can get back the original pointer, you need to use `as` casts, or replace the integer type +/// by `MaybeUninit<$int>` (and never call `assume_init()`). If you are looking for a way to +/// store data of arbitrary type, also use `MaybeUninit<T>` (that will also handle uninitialized +/// memory due to padding). If you specifically need to store something that is "either an +/// integer or a pointer", use `*mut ()`: integers can be converted to pointers and back without +/// any loss (via `as` casts or via `transmute`). +/// +/// # Examples +/// +/// There are a few things that `transmute` is really useful for. +/// +/// Turning a pointer into a function pointer. This is *not* portable to +/// machines where function pointers and data pointers have different sizes. +/// +/// ``` +/// fn foo() -> i32 { +/// 0 +/// } +/// // Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer. +/// // This avoids an integer-to-pointer `transmute`, which can be problematic. +/// // Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine. +/// let pointer = foo as *const (); +/// let function = unsafe { +/// std::mem::transmute::<*const (), fn() -> i32>(pointer) +/// }; +/// assert_eq!(function(), 0); +/// ``` +/// +/// Extending a lifetime, or shortening an invariant lifetime. This is +/// advanced, very unsafe Rust! +/// +/// ``` +/// struct R<'a>(&'a i32); +/// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> { +/// std::mem::transmute::<R<'b>, R<'static>>(r) +/// } +/// +/// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>) +/// -> &'b mut R<'c> { +/// std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r) +/// } +/// ``` +/// +/// # Alternatives +/// +/// Don't despair: many uses of `transmute` can be achieved through other means. +/// Below are common applications of `transmute` which can be replaced with safer +/// constructs. +/// +/// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.: +/// +/// ``` +/// let raw_bytes = [0x78, 0x56, 0x34, 0x12]; +/// +/// let num = unsafe { +/// std::mem::transmute::<[u8; 4], u32>(raw_bytes) +/// }; +/// +/// // use `u32::from_ne_bytes` instead +/// let num = u32::from_ne_bytes(raw_bytes); +/// // or use `u32::from_le_bytes` or `u32::from_be_bytes` to specify the endianness +/// let num = u32::from_le_bytes(raw_bytes); +/// assert_eq!(num, 0x12345678); +/// let num = u32::from_be_bytes(raw_bytes); +/// assert_eq!(num, 0x78563412); +/// ``` +/// +/// Turning a pointer into a `usize`: +/// +/// ```no_run +/// let ptr = &0; +/// let ptr_num_transmute = unsafe { +/// std::mem::transmute::<&i32, usize>(ptr) +/// }; +/// +/// // Use an `as` cast instead +/// let ptr_num_cast = ptr as *const i32 as usize; +/// ``` +/// +/// Note that using `transmute` to turn a pointer to a `usize` is (as noted above) [undefined +/// behavior][ub] in `const` contexts. Also outside of consts, this operation might not behave +/// as expected -- this is touching on many unspecified aspects of the Rust memory model. +/// Depending on what the code is doing, the following alternatives are preferable to +/// pointer-to-integer transmutation: +/// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a +/// type for that buffer, it can use [`MaybeUninit`][crate::mem::MaybeUninit]. +/// - If the code actually wants to work on the address the pointer points to, it can use `as` +/// casts or [`ptr.addr()`][pointer::addr]. +/// +/// Turning a `*mut T` into a `&mut T`: +/// +/// ``` +/// let ptr: *mut i32 = &mut 0; +/// let ref_transmuted = unsafe { +/// std::mem::transmute::<*mut i32, &mut i32>(ptr) +/// }; +/// +/// // Use a reborrow instead +/// let ref_casted = unsafe { &mut *ptr }; +/// ``` +/// +/// Turning a `&mut T` into a `&mut U`: +/// +/// ``` +/// let ptr = &mut 0; +/// let val_transmuted = unsafe { +/// std::mem::transmute::<&mut i32, &mut u32>(ptr) +/// }; +/// +/// // Now, put together `as` and reborrowing - note the chaining of `as` +/// // `as` is not transitive +/// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) }; +/// ``` +/// +/// Turning a `&str` into a `&[u8]`: +/// +/// ``` +/// // this is not a good way to do this. +/// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") }; +/// assert_eq!(slice, &[82, 117, 115, 116]); +/// +/// // You could use `str::as_bytes` +/// let slice = "Rust".as_bytes(); +/// assert_eq!(slice, &[82, 117, 115, 116]); +/// +/// // Or, just use a byte string, if you have control over the string +/// // literal +/// assert_eq!(b"Rust", &[82, 117, 115, 116]); +/// ``` +/// +/// Turning a `Vec<&T>` into a `Vec<Option<&T>>`. +/// +/// To transmute the inner type of the contents of a container, you must make sure to not +/// violate any of the container's invariants. For `Vec`, this means that both the size +/// *and alignment* of the inner types have to match. Other containers might rely on the +/// size of the type, alignment, or even the `TypeId`, in which case transmuting wouldn't +/// be possible at all without violating the container invariants. +/// +/// ``` +/// let store = [0, 1, 2, 3]; +/// let v_orig = store.iter().collect::<Vec<&i32>>(); +/// +/// // clone the vector as we will reuse them later +/// let v_clone = v_orig.clone(); +/// +/// // Using transmute: this relies on the unspecified data layout of `Vec`, which is a +/// // bad idea and could cause Undefined Behavior. +/// // However, it is no-copy. +/// let v_transmuted = unsafe { +/// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone) +/// }; +/// +/// let v_clone = v_orig.clone(); +/// +/// // This is the suggested, safe way. +/// // It may copy the entire vector into a new one though, but also may not. +/// let v_collected = v_clone.into_iter() +/// .map(Some) +/// .collect::<Vec<Option<&i32>>>(); +/// +/// let v_clone = v_orig.clone(); +/// +/// // This is the proper no-copy, unsafe way of "transmuting" a `Vec`, without relying on the +/// // data layout. Instead of literally calling `transmute`, we perform a pointer cast, but +/// // in terms of converting the original inner type (`&i32`) to the new one (`Option<&i32>`), +/// // this has all the same caveats. Besides the information provided above, also consult the +/// // [`from_raw_parts`] documentation. +/// let v_from_raw = unsafe { +// FIXME Update this when vec_into_raw_parts is stabilized +/// // Ensure the original vector is not dropped. +/// let mut v_clone = std::mem::ManuallyDrop::new(v_clone); +/// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>, +/// v_clone.len(), +/// v_clone.capacity()) +/// }; +/// ``` +/// +/// [`from_raw_parts`]: ../../std/vec/struct.Vec.html#method.from_raw_parts +/// +/// Implementing `split_at_mut`: +/// +/// ``` +/// use std::{slice, mem}; +/// +/// // There are multiple ways to do this, and there are multiple problems +/// // with the following (transmute) way. +/// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize) +/// -> (&mut [T], &mut [T]) { +/// let len = slice.len(); +/// assert!(mid <= len); +/// unsafe { +/// let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice); +/// // first: transmute is not type safe; all it checks is that T and +/// // U are of the same size. Second, right here, you have two +/// // mutable references pointing to the same memory. +/// (&mut slice[0..mid], &mut slice2[mid..len]) +/// } +/// } +/// +/// // This gets rid of the type safety problems; `&mut *` will *only* give +/// // you a `&mut T` from a `&mut T` or `*mut T`. +/// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize) +/// -> (&mut [T], &mut [T]) { +/// let len = slice.len(); +/// assert!(mid <= len); +/// unsafe { +/// let slice2 = &mut *(slice as *mut [T]); +/// // however, you still have two mutable references pointing to +/// // the same memory. +/// (&mut slice[0..mid], &mut slice2[mid..len]) +/// } +/// } +/// +/// // This is how the standard library does it. This is the best method, if +/// // you need to do something like this +/// fn split_at_stdlib<T>(slice: &mut [T], mid: usize) +/// -> (&mut [T], &mut [T]) { +/// let len = slice.len(); +/// assert!(mid <= len); +/// unsafe { +/// let ptr = slice.as_mut_ptr(); +/// // This now has three mutable references pointing at the same +/// // memory. `slice`, the rvalue ret.0, and the rvalue ret.1. +/// // `slice` is never used after `let ptr = ...`, and so one can +/// // treat it as "dead", and therefore, you only have two real +/// // mutable slices. +/// (slice::from_raw_parts_mut(ptr, mid), +/// slice::from_raw_parts_mut(ptr.add(mid), len - mid)) +/// } +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_allowed_through_unstable_modules] +#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] +#[rustc_diagnostic_item = "transmute"] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn transmute<Src, Dst>(_src: Src) -> Dst { + unreachable!() +} + +/// Like [`transmute`], but even less checked at compile-time: rather than +/// giving an error for `size_of::<Src>() != size_of::<Dst>()`, it's +/// **Undefined Behavior** at runtime. +/// +/// Prefer normal `transmute` where possible, for the extra checking, since +/// both do exactly the same thing at runtime, if they both compile. +/// +/// This is not expected to ever be exposed directly to users, rather it +/// may eventually be exposed through some more-constrained API. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn transmute_unchecked<Src, Dst>(_src: Src) -> Dst { + unreachable!() +} + +/// Returns `true` if the actual type given as `T` requires drop +/// glue; returns `false` if the actual type provided for `T` +/// implements `Copy`. +/// +/// If the actual type neither requires drop glue nor implements +/// `Copy`, then the return value of this function is unspecified. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn needs_drop<T: ?Sized>() -> bool { + unreachable!() +} + +/// Calculates the offset from a pointer. +/// +/// This is implemented as an intrinsic to avoid converting to and from an +/// integer, since the conversion would throw away aliasing information. +/// +/// This can only be used with `Ptr` as a raw pointer type (`*mut` or `*const`) +/// to a `Sized` pointee and with `Delta` as `usize` or `isize`. Any other +/// instantiations may arbitrarily misbehave, and that's *not* a compiler bug. +/// +/// # Safety +/// +/// If the computed offset is non-zero, then both the starting and resulting pointer must be +/// either in bounds or at the end of an allocated object. If either pointer is out +/// of bounds or arithmetic overflow occurs then this operation is undefined behavior. +/// +/// The stabilized version of this intrinsic is [`pointer::offset`]. +#[must_use = "returns a new pointer rather than modifying its argument"] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn offset<Ptr, Delta>(_dst: Ptr, _offset: Delta) -> Ptr { + unreachable!() +} + +/// Calculates the offset from a pointer, potentially wrapping. +/// +/// This is implemented as an intrinsic to avoid converting to and from an +/// integer, since the conversion inhibits certain optimizations. +/// +/// # Safety +/// +/// Unlike the `offset` intrinsic, this intrinsic does not restrict the +/// resulting pointer to point into or at the end of an allocated +/// object, and it wraps with two's complement arithmetic. The resulting +/// value is not necessarily valid to be used to actually access memory. +/// +/// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. +#[must_use = "returns a new pointer rather than modifying its argument"] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn arith_offset<T>(_dst: *const T, _offset: isize) -> *const T { + unreachable!() +} +/// Masks out bits of the pointer according to a mask. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// Consider using [`pointer::mask`] instead. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn ptr_mask<T>(_ptr: *const T, _mask: usize) -> *const T { + unreachable!() +} + +extern "rust-intrinsic" { /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with /// a size of `count` * `size_of::<T>()` and an alignment of /// `min_align_of::<T>()` @@ -2102,515 +2149,625 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn frem_fast<T: Copy>(a: T, b: T) -> T; - /// Float addition that allows optimizations based on algebraic rules. + /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range + /// (<https://github.com/rust-lang/rust/issues/10184>) /// - /// This intrinsic does not have a stable counterpart. + /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. #[rustc_nounwind] - #[rustc_safe_intrinsic] - pub fn fadd_algebraic<T: Copy>(a: T, b: T) -> T; + pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; +} - /// Float subtraction that allows optimizations based on algebraic rules. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - #[rustc_safe_intrinsic] - pub fn fsub_algebraic<T: Copy>(a: T, b: T) -> T; +/// Float addition that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn fadd_algebraic<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} - /// Float multiplication that allows optimizations based on algebraic rules. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - #[rustc_safe_intrinsic] - pub fn fmul_algebraic<T: Copy>(a: T, b: T) -> T; +/// Float subtraction that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn fsub_algebraic<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} - /// Float division that allows optimizations based on algebraic rules. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - #[rustc_safe_intrinsic] - pub fn fdiv_algebraic<T: Copy>(a: T, b: T) -> T; +/// Float multiplication that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn fmul_algebraic<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} - /// Float remainder that allows optimizations based on algebraic rules. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - #[rustc_safe_intrinsic] - pub fn frem_algebraic<T: Copy>(a: T, b: T) -> T; +/// Float division that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn fdiv_algebraic<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} - /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range - /// (<https://github.com/rust-lang/rust/issues/10184>) - /// - /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. - #[rustc_nounwind] - pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; +/// Float remainder that allows optimizations based on algebraic rules. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn frem_algebraic<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} - /// Returns the number of bits set in an integer type `T` - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `count_ones` method. For example, - /// [`u32::count_ones`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn ctpop<T: Copy>(x: T) -> u32; +/// Returns the number of bits set in an integer type `T` +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `count_ones` method. For example, +/// [`u32::count_ones`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn ctpop<T: Copy>(_x: T) -> u32 { + unimplemented!() +} - /// Returns the number of leading unset bits (zeroes) in an integer type `T`. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `leading_zeros` method. For example, - /// [`u32::leading_zeros`] - /// - /// # Examples - /// - /// ``` - /// #![feature(core_intrinsics)] - /// # #![allow(internal_features)] - /// - /// use std::intrinsics::ctlz; - /// - /// let x = 0b0001_1100_u8; - /// let num_leading = ctlz(x); - /// assert_eq!(num_leading, 3); - /// ``` - /// - /// An `x` with value `0` will return the bit width of `T`. - /// - /// ``` - /// #![feature(core_intrinsics)] - /// # #![allow(internal_features)] - /// - /// use std::intrinsics::ctlz; - /// - /// let x = 0u16; - /// let num_leading = ctlz(x); - /// assert_eq!(num_leading, 16); - /// ``` - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn ctlz<T: Copy>(x: T) -> u32; +/// Returns the number of leading unset bits (zeroes) in an integer type `T`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `leading_zeros` method. For example, +/// [`u32::leading_zeros`] +/// +/// # Examples +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::ctlz; +/// +/// let x = 0b0001_1100_u8; +/// let num_leading = ctlz(x); +/// assert_eq!(num_leading, 3); +/// ``` +/// +/// An `x` with value `0` will return the bit width of `T`. +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::ctlz; +/// +/// let x = 0u16; +/// let num_leading = ctlz(x); +/// assert_eq!(num_leading, 16); +/// ``` +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn ctlz<T: Copy>(_x: T) -> u32 { + unimplemented!() +} - /// Like `ctlz`, but extra-unsafe as it returns `undef` when - /// given an `x` with value `0`. - /// - /// This intrinsic does not have a stable counterpart. - /// - /// # Examples - /// - /// ``` - /// #![feature(core_intrinsics)] - /// # #![allow(internal_features)] - /// - /// use std::intrinsics::ctlz_nonzero; - /// - /// let x = 0b0001_1100_u8; - /// let num_leading = unsafe { ctlz_nonzero(x) }; - /// assert_eq!(num_leading, 3); - /// ``` - #[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn ctlz_nonzero<T: Copy>(x: T) -> u32; +/// Like `ctlz`, but extra-unsafe as it returns `undef` when +/// given an `x` with value `0`. +/// +/// This intrinsic does not have a stable counterpart. +/// +/// # Examples +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::ctlz_nonzero; +/// +/// let x = 0b0001_1100_u8; +/// let num_leading = unsafe { ctlz_nonzero(x) }; +/// assert_eq!(num_leading, 3); +/// ``` +#[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn ctlz_nonzero<T: Copy>(_x: T) -> u32 { + unimplemented!() +} - /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `trailing_zeros` method. For example, - /// [`u32::trailing_zeros`] - /// - /// # Examples - /// - /// ``` - /// #![feature(core_intrinsics)] - /// # #![allow(internal_features)] - /// - /// use std::intrinsics::cttz; - /// - /// let x = 0b0011_1000_u8; - /// let num_trailing = cttz(x); - /// assert_eq!(num_trailing, 3); - /// ``` - /// - /// An `x` with value `0` will return the bit width of `T`: - /// - /// ``` - /// #![feature(core_intrinsics)] - /// # #![allow(internal_features)] - /// - /// use std::intrinsics::cttz; - /// - /// let x = 0u16; - /// let num_trailing = cttz(x); - /// assert_eq!(num_trailing, 16); - /// ``` - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn cttz<T: Copy>(x: T) -> u32; +/// Returns the number of trailing unset bits (zeroes) in an integer type `T`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `trailing_zeros` method. For example, +/// [`u32::trailing_zeros`] +/// +/// # Examples +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::cttz; +/// +/// let x = 0b0011_1000_u8; +/// let num_trailing = cttz(x); +/// assert_eq!(num_trailing, 3); +/// ``` +/// +/// An `x` with value `0` will return the bit width of `T`: +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::cttz; +/// +/// let x = 0u16; +/// let num_trailing = cttz(x); +/// assert_eq!(num_trailing, 16); +/// ``` +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn cttz<T: Copy>(_x: T) -> u32 { + unimplemented!() +} - /// Like `cttz`, but extra-unsafe as it returns `undef` when - /// given an `x` with value `0`. - /// - /// This intrinsic does not have a stable counterpart. - /// - /// # Examples - /// - /// ``` - /// #![feature(core_intrinsics)] - /// # #![allow(internal_features)] - /// - /// use std::intrinsics::cttz_nonzero; - /// - /// let x = 0b0011_1000_u8; - /// let num_trailing = unsafe { cttz_nonzero(x) }; - /// assert_eq!(num_trailing, 3); - /// ``` - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn cttz_nonzero<T: Copy>(x: T) -> u32; +/// Like `cttz`, but extra-unsafe as it returns `undef` when +/// given an `x` with value `0`. +/// +/// This intrinsic does not have a stable counterpart. +/// +/// # Examples +/// +/// ``` +/// #![feature(core_intrinsics)] +/// # #![allow(internal_features)] +/// +/// use std::intrinsics::cttz_nonzero; +/// +/// let x = 0b0011_1000_u8; +/// let num_trailing = unsafe { cttz_nonzero(x) }; +/// assert_eq!(num_trailing, 3); +/// ``` +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn cttz_nonzero<T: Copy>(_x: T) -> u32 { + unimplemented!() +} - /// Reverses the bytes in an integer type `T`. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `swap_bytes` method. For example, - /// [`u32::swap_bytes`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn bswap<T: Copy>(x: T) -> T; +/// Reverses the bytes in an integer type `T`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `swap_bytes` method. For example, +/// [`u32::swap_bytes`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn bswap<T: Copy>(_x: T) -> T { + unimplemented!() +} - /// Reverses the bits in an integer type `T`. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `reverse_bits` method. For example, - /// [`u32::reverse_bits`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn bitreverse<T: Copy>(x: T) -> T; +/// Reverses the bits in an integer type `T`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `reverse_bits` method. For example, +/// [`u32::reverse_bits`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn bitreverse<T: Copy>(_x: T) -> T { + unimplemented!() +} - /// Does a three-way comparison between the two integer arguments. - /// - /// This is included as an intrinsic as it's useful to let it be one thing - /// in MIR, rather than the multiple checks and switches that make its IR - /// large and difficult to optimize. - /// - /// The stabilized version of this intrinsic is [`Ord::cmp`]. - #[rustc_const_unstable(feature = "const_three_way_compare", issue = "none")] - #[rustc_safe_intrinsic] - pub fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> crate::cmp::Ordering; +/// Does a three-way comparison between the two integer arguments. +/// +/// This is included as an intrinsic as it's useful to let it be one thing +/// in MIR, rather than the multiple checks and switches that make its IR +/// large and difficult to optimize. +/// +/// The stabilized version of this intrinsic is [`Ord::cmp`]. +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_three_way_compare", issue = "none"))] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn three_way_compare<T: Copy>(_lhs: T, _rhss: T) -> crate::cmp::Ordering { + unimplemented!() +} - /// Performs checked integer addition. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `overflowing_add` method. For example, - /// [`u32::overflowing_add`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool); +/// Performs checked integer addition. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `overflowing_add` method. For example, +/// [`u32::overflowing_add`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn add_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) { + unimplemented!() +} - /// Performs checked integer subtraction - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `overflowing_sub` method. For example, - /// [`u32::overflowing_sub`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool); +/// Performs checked integer subtraction +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `overflowing_sub` method. For example, +/// [`u32::overflowing_sub`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn sub_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) { + unimplemented!() +} - /// Performs checked integer multiplication - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `overflowing_mul` method. For example, - /// [`u32::overflowing_mul`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool); +/// Performs checked integer multiplication +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `overflowing_mul` method. For example, +/// [`u32::overflowing_mul`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn mul_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) { + unimplemented!() +} - /// Performs an exact division, resulting in undefined behavior where - /// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1` - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_exact_div", issue = "none")] - #[rustc_nounwind] - pub fn exact_div<T: Copy>(x: T, y: T) -> T; +/// Performs an exact division, resulting in undefined behavior where +/// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1` +/// +/// This intrinsic does not have a stable counterpart. +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_exact_div", issue = "none"))] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn exact_div<T: Copy>(_x: T, _y: T) -> T { + unimplemented!() +} - /// Performs an unchecked division, resulting in undefined behavior - /// where `y == 0` or `x == T::MIN && y == -1` - /// - /// Safe wrappers for this intrinsic are available on the integer - /// primitives via the `checked_div` method. For example, - /// [`u32::checked_div`] - #[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0") - )] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn unchecked_div<T: Copy>(x: T, y: T) -> T; - /// Returns the remainder of an unchecked division, resulting in - /// undefined behavior when `y == 0` or `x == T::MIN && y == -1` - /// - /// Safe wrappers for this intrinsic are available on the integer - /// primitives via the `checked_rem` method. For example, - /// [`u32::checked_rem`] - #[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0") - )] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T; +/// Performs an unchecked division, resulting in undefined behavior +/// where `y == 0` or `x == T::MIN && y == -1` +/// +/// Safe wrappers for this intrinsic are available on the integer +/// primitives via the `checked_div` method. For example, +/// [`u32::checked_div`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_div<T: Copy>(_x: T, _y: T) -> T { + unimplemented!() +} +/// Returns the remainder of an unchecked division, resulting in +/// undefined behavior when `y == 0` or `x == T::MIN && y == -1` +/// +/// Safe wrappers for this intrinsic are available on the integer +/// primitives via the `checked_rem` method. For example, +/// [`u32::checked_rem`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_rem<T: Copy>(_x: T, _y: T) -> T { + unimplemented!() +} - /// Performs an unchecked left shift, resulting in undefined behavior when - /// `y < 0` or `y >= N`, where N is the width of T in bits. - /// - /// Safe wrappers for this intrinsic are available on the integer - /// primitives via the `checked_shl` method. For example, - /// [`u32::checked_shl`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T; - /// Performs an unchecked right shift, resulting in undefined behavior when - /// `y < 0` or `y >= N`, where N is the width of T in bits. - /// - /// Safe wrappers for this intrinsic are available on the integer - /// primitives via the `checked_shr` method. For example, - /// [`u32::checked_shr`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T; - - /// Returns the result of an unchecked addition, resulting in - /// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`. - /// - /// The stable counterpart of this intrinsic is `unchecked_add` on the various - /// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`]. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn unchecked_add<T: Copy>(x: T, y: T) -> T; +/// Performs an unchecked left shift, resulting in undefined behavior when +/// `y < 0` or `y >= N`, where N is the width of T in bits. +/// +/// Safe wrappers for this intrinsic are available on the integer +/// primitives via the `checked_shl` method. For example, +/// [`u32::checked_shl`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_shl<T: Copy, U: Copy>(_x: T, _y: U) -> T { + unimplemented!() +} +/// Performs an unchecked right shift, resulting in undefined behavior when +/// `y < 0` or `y >= N`, where N is the width of T in bits. +/// +/// Safe wrappers for this intrinsic are available on the integer +/// primitives via the `checked_shr` method. For example, +/// [`u32::checked_shr`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_shr<T: Copy, U: Copy>(_x: T, _y: U) -> T { + unimplemented!() +} - /// Returns the result of an unchecked subtraction, resulting in - /// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`. - /// - /// The stable counterpart of this intrinsic is `unchecked_sub` on the various - /// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`]. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T; - - /// Returns the result of an unchecked multiplication, resulting in - /// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`. - /// - /// The stable counterpart of this intrinsic is `unchecked_mul` on the various - /// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`]. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T; - - /// Performs rotate left. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `rotate_left` method. For example, - /// [`u32::rotate_left`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn rotate_left<T: Copy>(x: T, shift: u32) -> T; - - /// Performs rotate right. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `rotate_right` method. For example, - /// [`u32::rotate_right`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn rotate_right<T: Copy>(x: T, shift: u32) -> T; - - /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_add` method. For example, - /// [`u32::wrapping_add`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn wrapping_add<T: Copy>(a: T, b: T) -> T; - /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_sub` method. For example, - /// [`u32::wrapping_sub`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T; - /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_mul` method. For example, - /// [`u32::wrapping_mul`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T; +/// Returns the result of an unchecked addition, resulting in +/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`. +/// +/// The stable counterpart of this intrinsic is `unchecked_add` on the various +/// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`]. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_add<T: Copy>(_x: T, _y: T) -> T { + unimplemented!() +} - /// Computes `a + b`, saturating at numeric bounds. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `saturating_add` method. For example, - /// [`u32::saturating_add`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn saturating_add<T: Copy>(a: T, b: T) -> T; - /// Computes `a - b`, saturating at numeric bounds. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `saturating_sub` method. For example, - /// [`u32::saturating_sub`] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn saturating_sub<T: Copy>(a: T, b: T) -> T; - - /// This is an implementation detail of [`crate::ptr::read`] and should - /// not be used anywhere else. See its comments for why this exists. - /// - /// This intrinsic can *only* be called where the pointer is a local without - /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it - /// trivially obeys runtime-MIR rules about derefs in operands. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn read_via_copy<T>(ptr: *const T) -> T; - - /// This is an implementation detail of [`crate::ptr::write`] and should - /// not be used anywhere else. See its comments for why this exists. - /// - /// This intrinsic can *only* be called where the pointer is a local without - /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so - /// that it trivially obeys runtime-MIR rules about derefs in operands. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn write_via_move<T>(ptr: *mut T, value: T); +/// Returns the result of an unchecked subtraction, resulting in +/// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`. +/// +/// The stable counterpart of this intrinsic is `unchecked_sub` on the various +/// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`]. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_sub<T: Copy>(_x: T, _y: T) -> T { + unimplemented!() +} - /// Returns the value of the discriminant for the variant in 'v'; - /// if `T` has no discriminant, returns `0`. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant; +/// Returns the result of an unchecked multiplication, resulting in +/// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`. +/// +/// The stable counterpart of this intrinsic is `unchecked_mul` on the various +/// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`]. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn unchecked_mul<T: Copy>(_x: T, _y: T) -> T { + unimplemented!() +} + +/// Performs rotate left. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `rotate_left` method. For example, +/// [`u32::rotate_left`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn rotate_left<T: Copy>(_x: T, _shift: u32) -> T { + unimplemented!() +} + +/// Performs rotate right. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `rotate_right` method. For example, +/// [`u32::rotate_right`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn rotate_right<T: Copy>(_x: T, _shift: u32) -> T { + unimplemented!() +} +/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `wrapping_add` method. For example, +/// [`u32::wrapping_add`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn wrapping_add<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} +/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `wrapping_sub` method. For example, +/// [`u32::wrapping_sub`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn wrapping_sub<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} +/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `wrapping_mul` method. For example, +/// [`u32::wrapping_mul`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn wrapping_mul<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} + +/// Computes `a + b`, saturating at numeric bounds. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `saturating_add` method. For example, +/// [`u32::saturating_add`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn saturating_add<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} +/// Computes `a - b`, saturating at numeric bounds. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized versions of this intrinsic are available on the integer +/// primitives via the `saturating_sub` method. For example, +/// [`u32::saturating_sub`] +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn saturating_sub<T: Copy>(_a: T, _b: T) -> T { + unimplemented!() +} + +/// This is an implementation detail of [`crate::ptr::read`] and should +/// not be used anywhere else. See its comments for why this exists. +/// +/// This intrinsic can *only* be called where the pointer is a local without +/// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it +/// trivially obeys runtime-MIR rules about derefs in operands. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn read_via_copy<T>(_ptr: *const T) -> T { + unimplemented!() +} + +/// This is an implementation detail of [`crate::ptr::write`] and should +/// not be used anywhere else. See its comments for why this exists. +/// +/// This intrinsic can *only* be called where the pointer is a local without +/// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so +/// that it trivially obeys runtime-MIR rules about derefs in operands. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn write_via_move<T>(_ptr: *mut T, _value: T) { + unimplemented!() +} + +/// Returns the value of the discriminant for the variant in 'v'; +/// if `T` has no discriminant, returns `0`. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is [`core::mem::discriminant`]. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn discriminant_value<T>(_v: &T) -> <T as DiscriminantKind>::Discriminant { + unimplemented!() +} + +extern "rust-intrinsic" { /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs. /// @@ -2638,25 +2795,32 @@ extern "rust-intrinsic" { /// in ways that are not allowed for regular writes). #[rustc_nounwind] pub fn nontemporal_store<T>(ptr: *mut T, val: T); +} - /// See documentation of `<*const T>::offset_from` for details. - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize; +/// See documentation of `<*const T>::offset_from` for details. +#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn ptr_offset_from<T>(_ptr: *const T, _base: *const T) -> isize { + unimplemented!() +} - /// See documentation of `<*const T>::sub_ptr` for details. - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] - #[rustc_nounwind] - pub fn ptr_offset_from_unsigned<T>(ptr: *const T, base: *const T) -> usize; +/// See documentation of `<*const T>::sub_ptr` for details. +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892"))] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn ptr_offset_from_unsigned<T>(_ptr: *const T, _base: *const T) -> usize { + unimplemented!() } /// See documentation of `<*const T>::guaranteed_eq` for details. /// Returns `2` if the result is unknown. /// Returns `1` if the pointers are guaranteed equal /// Returns `0` if the pointers are guaranteed inequal -#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] -#[unstable(feature = "core_intrinsics", issue = "none")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))] #[rustc_intrinsic] #[rustc_nounwind] #[rustc_do_not_const_check] @@ -2666,59 +2830,71 @@ pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 { (ptr == other) as u8 } -extern "rust-intrinsic" { - /// Determines whether the raw bytes of the two values are equal. - /// - /// This is particularly handy for arrays, since it allows things like just - /// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`. - /// - /// Above some backend-decided threshold this will emit calls to `memcmp`, - /// like slice equality does, instead of causing massive code size. - /// - /// Since this works by comparing the underlying bytes, the actual `T` is - /// not particularly important. It will be used for its size and alignment, - /// but any validity restrictions will be ignored, not enforced. - /// - /// # Safety - /// - /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized. - /// Note that this is a stricter criterion than just the *values* being - /// fully-initialized: if `T` has padding, it's UB to call this intrinsic. - /// - /// At compile-time, it is furthermore UB to call this if any of the bytes - /// in `*a` or `*b` have provenance. - /// - /// (The implementation is allowed to branch on the results of comparisons, - /// which is UB if any of their inputs are `undef`.) - #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")] - #[rustc_nounwind] - pub fn raw_eq<T>(a: &T, b: &T) -> bool; +/// Determines whether the raw bytes of the two values are equal. +/// +/// This is particularly handy for arrays, since it allows things like just +/// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`. +/// +/// Above some backend-decided threshold this will emit calls to `memcmp`, +/// like slice equality does, instead of causing massive code size. +/// +/// Since this works by comparing the underlying bytes, the actual `T` is +/// not particularly important. It will be used for its size and alignment, +/// but any validity restrictions will be ignored, not enforced. +/// +/// # Safety +/// +/// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized. +/// Note that this is a stricter criterion than just the *values* being +/// fully-initialized: if `T` has padding, it's UB to call this intrinsic. +/// +/// At compile-time, it is furthermore UB to call this if any of the bytes +/// in `*a` or `*b` have provenance. +/// +/// (The implementation is allowed to branch on the results of comparisons, +/// which is UB if any of their inputs are `undef`.) +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none"))] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn raw_eq<T>(_a: &T, _b: &T) -> bool { + unimplemented!() +} - /// Lexicographically compare `[left, left + bytes)` and `[right, right + bytes)` - /// as unsigned bytes, returning negative if `left` is less, zero if all the - /// bytes match, or positive if `left` is greater. - /// - /// This underlies things like `<[u8]>::cmp`, and will usually lower to `memcmp`. - /// - /// # Safety - /// - /// `left` and `right` must each be [valid] for reads of `bytes` bytes. - /// - /// Note that this applies to the whole range, not just until the first byte - /// that differs. That allows optimizations that can read in large chunks. - /// - /// [valid]: crate::ptr#safety - #[rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none")] - #[rustc_nounwind] - pub fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32; +/// Lexicographically compare `[left, left + bytes)` and `[right, right + bytes)` +/// as unsigned bytes, returning negative if `left` is less, zero if all the +/// bytes match, or positive if `left` is greater. +/// +/// This underlies things like `<[u8]>::cmp`, and will usually lower to `memcmp`. +/// +/// # Safety +/// +/// `left` and `right` must each be [valid] for reads of `bytes` bytes. +/// +/// Note that this applies to the whole range, not just until the first byte +/// that differs. That allows optimizations that can read in large chunks. +/// +/// [valid]: crate::ptr#safety +#[cfg_attr( + bootstrap, + rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none") +)] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: usize) -> i32 { + unimplemented!() +} - /// See documentation of [`std::hint::black_box`] for details. - /// - /// [`std::hint::black_box`]: crate::hint::black_box - #[rustc_const_unstable(feature = "const_black_box", issue = "none")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn black_box<T>(dummy: T) -> T; +/// See documentation of [`std::hint::black_box`] for details. +/// +/// [`std::hint::black_box`]: crate::hint::black_box +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_black_box", issue = "none"))] +#[rustc_nounwind] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn black_box<T>(_dummy: T) -> T { + unimplemented!() } /// Selects which function to call depending on the context. @@ -2788,6 +2964,68 @@ where unreachable!() } +/// A macro to make it easier to invoke const_eval_select. Use as follows: +/// ```rust,ignore (just a macro example) +/// const_eval_select!( +/// @capture { arg1: i32 = some_expr, arg2: T = other_expr } -> U: +/// if const #[attributes_for_const_arm] { +/// // Compile-time code goes here. +/// } else #[attributes_for_runtime_arm] { +/// // Run-time code goes here. +/// } +/// ) +/// ``` +/// The `@capture` block declares which surrounding variables / expressions can be +/// used inside the `if const`. +/// Note that the two arms of this `if` really each become their own function, which is why the +/// macro supports setting attributes for those functions. The runtime function is always +/// markes as `#[inline]`. +/// +/// See [`const_eval_select()`] for the rules and requirements around that intrinsic. +pub(crate) macro const_eval_select { + ( + @capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? : + if const + $(#[$compiletime_attr:meta])* $compiletime:block + else + $(#[$runtime_attr:meta])* $runtime:block + ) => {{ + #[inline] // avoid the overhead of an extra fn call + $(#[$runtime_attr])* + fn runtime($($arg: $ty),*) $( -> $ret )? { + $runtime + } + + #[inline] // prevent codegen on this function + $(#[$compiletime_attr])* + const fn compiletime($($arg: $ty),*) $( -> $ret )? { + // Don't warn if one of the arguments is unused. + $(let _ = $arg;)* + + $compiletime + } + + const_eval_select(($($val,)*), compiletime, runtime) + }}, + // We support leaving away the `val` expressions for *all* arguments + // (but not for *some* arguments, that's too tricky). + ( + @capture { $($arg:ident : $ty:ty),* $(,)? } $( -> $ret:ty )? : + if const + $(#[$compiletime_attr:meta])* $compiletime:block + else + $(#[$runtime_attr:meta])* $runtime:block + ) => { + $crate::intrinsics::const_eval_select!( + @capture { $($arg : $ty = $arg),* } $(-> $ret)? : + if const + $(#[$compiletime_attr])* $compiletime + else + $(#[$runtime_attr])* $runtime + ) + }, +} + /// Returns whether the argument's value is statically known at /// compile-time. /// @@ -2830,7 +3068,7 @@ where /// # Stability concerns /// /// While it is safe to call, this intrinsic may behave differently in -/// a `const` context than otherwise. See the [`const_eval_select`] +/// a `const` context than otherwise. See the [`const_eval_select()`] /// documentation for an explanation of the issues this can cause. Unlike /// `const_eval_select`, this intrinsic isn't guaranteed to behave /// deterministically even in a `const` context. @@ -2886,7 +3124,7 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool { #[rustc_nounwind] #[inline] #[rustc_intrinsic] -// This has fallback `const fn` MIR, so shouldn't need stability, see #122652 +// Const-unstable because `swap_nonoverlapping` is const-unstable. #[rustc_const_unstable(feature = "const_typed_swap", issue = "none")] pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { // SAFETY: The caller provided single non-overlapping items behind @@ -2908,8 +3146,7 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is /// primarily used by [`ub_checks::assert_unsafe_precondition`]. #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // just for UB checks -#[unstable(feature = "core_intrinsics", issue = "none")] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] // just for UB checks #[inline(always)] #[rustc_intrinsic] pub const fn ub_checks() -> bool { @@ -2925,7 +3162,6 @@ pub const fn ub_checks() -> bool { /// - At compile time, a compile error occurs if this constraint is violated. /// - At runtime, it is not checked. #[rustc_const_unstable(feature = "const_heap", issue = "79597")] -#[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[rustc_intrinsic] #[miri::intrinsic_fallback_is_spec] @@ -2994,7 +3230,7 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize { #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_size_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn size_of<T>() -> usize { @@ -3012,7 +3248,7 @@ pub const fn size_of<T>() -> usize { #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_min_align_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn min_align_of<T>() -> usize { @@ -3025,7 +3261,7 @@ pub const fn min_align_of<T>() -> usize { /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971). #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_pref_align_of", issue = "91971"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn pref_align_of<T>() -> usize { @@ -3043,7 +3279,7 @@ pub const unsafe fn pref_align_of<T>() -> usize { /// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_unstable(feature = "variant_count", issue = "73662")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "variant_count", issue = "73662"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn variant_count<T>() -> usize { @@ -3059,7 +3295,7 @@ pub const fn variant_count<T>() -> usize { /// See [`crate::mem::size_of_val_raw`] for safety conditions. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_size_of_val", issue = "46571"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize { @@ -3075,7 +3311,7 @@ pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize { /// See [`crate::mem::align_of_val_raw`] for safety conditions. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_align_of_val", issue = "46571"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize { @@ -3092,7 +3328,7 @@ pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize { /// The stabilized version of this intrinsic is [`core::any::type_name`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_unstable(feature = "const_type_name", issue = "63084")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_name", issue = "63084"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn type_name<T: ?Sized>() -> &'static str { @@ -3111,7 +3347,7 @@ pub const fn type_name<T: ?Sized>() -> &'static str { /// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_unstable(feature = "const_type_id", issue = "77125")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_id", issue = "77125"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn type_id<T: ?Sized + 'static>() -> u128 { @@ -3126,7 +3362,7 @@ pub const fn type_id<T: ?Sized + 'static>() -> u128 { #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(_data: D, _meta: M) -> P { @@ -3155,7 +3391,7 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P { bootstrap, cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")) )] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M { @@ -3261,18 +3497,13 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) { - extern "rust-intrinsic" { - #[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0") - )] - #[cfg_attr( - not(bootstrap), - rustc_const_unstable(feature = "core_intrinsics", issue = "none") - )] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); + #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] + #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + const unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize) { + unreachable!() } ub_checks::assert_unsafe_precondition!( @@ -3373,18 +3604,13 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { - extern "rust-intrinsic" { - #[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0") - )] - #[cfg_attr( - not(bootstrap), - rustc_const_unstable(feature = "core_intrinsics", issue = "none") - )] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - fn copy<T>(src: *const T, dst: *mut T, count: usize); + #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] + #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + const unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize) { + unreachable!() } // SAFETY: the safety contract for `copy` must be upheld by the caller. @@ -3462,11 +3688,13 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { - extern "rust-intrinsic" { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] - #[rustc_nounwind] - fn write_bytes<T>(dst: *mut T, val: u8, count: usize); + #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] + #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] + #[rustc_nounwind] + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + const unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize) { + unreachable!() } // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. @@ -3494,8 +3722,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { /// The stabilized version of this intrinsic is /// [`f16::min`] #[rustc_nounwind] -// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] -#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf16(_x: f16, _y: f16) -> f16 { @@ -3512,7 +3739,7 @@ pub const fn minnumf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::min`] #[rustc_nounwind] -#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf32(_x: f32, _y: f32) -> f32 { @@ -3529,7 +3756,7 @@ pub const fn minnumf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::min`] #[rustc_nounwind] -#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf64(_x: f64, _y: f64) -> f64 { @@ -3546,8 +3773,7 @@ pub const fn minnumf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::min`] #[rustc_nounwind] -// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] -#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf128(_x: f128, _y: f128) -> f128 { @@ -3564,8 +3790,7 @@ pub const fn minnumf128(_x: f128, _y: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::max`] #[rustc_nounwind] -// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] -#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { @@ -3582,7 +3807,7 @@ pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::max`] #[rustc_nounwind] -#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { @@ -3599,7 +3824,7 @@ pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::max`] #[rustc_nounwind] -#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { @@ -3616,8 +3841,7 @@ pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::max`] #[rustc_nounwind] -// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] -#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { @@ -3629,8 +3853,7 @@ pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::abs`](../../std/primitive.f16.html#method.abs) #[rustc_nounwind] -// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] -#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf16(_x: f16) -> f16 { @@ -3642,7 +3865,7 @@ pub const unsafe fn fabsf16(_x: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::abs`](../../std/primitive.f32.html#method.abs) #[rustc_nounwind] -#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf32(_x: f32) -> f32 { @@ -3654,7 +3877,7 @@ pub const unsafe fn fabsf32(_x: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::abs`](../../std/primitive.f64.html#method.abs) #[rustc_nounwind] -#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf64(_x: f64) -> f64 { @@ -3666,8 +3889,7 @@ pub const unsafe fn fabsf64(_x: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::abs`](../../std/primitive.f128.html#method.abs) #[rustc_nounwind] -// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] -#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf128(_x: f128) -> f128 { @@ -3679,8 +3901,7 @@ pub const unsafe fn fabsf128(_x: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) #[rustc_nounwind] -// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] -#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { @@ -3692,7 +3913,7 @@ pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) #[rustc_nounwind] -#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { @@ -3703,7 +3924,7 @@ pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) #[rustc_nounwind] -#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { @@ -3715,8 +3936,7 @@ pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) #[rustc_nounwind] -// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] -#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 { @@ -3734,14 +3954,15 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize fn miri_promise_symbolic_alignment(ptr: *const (), align: usize); } - fn runtime(ptr: *const (), align: usize) { - // SAFETY: this call is always safe. - unsafe { - miri_promise_symbolic_alignment(ptr, align); + const_eval_select!( + @capture { ptr: *const (), align: usize}: + if const { + // Do nothing. + } else { + // SAFETY: this call is always safe. + unsafe { + miri_promise_symbolic_alignment(ptr, align); + } } - } - - const fn compiletime(_ptr: *const (), _align: usize) {} - - const_eval_select((ptr, align), compiletime, runtime); + ) } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 686378fc5cf..2f4f33dcc85 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -107,19 +107,17 @@ // // Library features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(const_exact_div))] #![cfg_attr(bootstrap, feature(const_fmt_arguments_new))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] #![feature(const_alloc_layout)] -#![feature(const_arguments_as_str)] #![feature(const_black_box)] -#![feature(const_char_encode_utf16)] +#![feature(const_eq_ignore_ascii_case)] #![feature(const_eval_select)] -#![feature(const_exact_div)] #![feature(const_float_methods)] -#![feature(const_hash)] #![feature(const_heap)] #![feature(const_nonnull_new)] #![feature(const_option_ext)] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index e8161cce2fe..0484611958d 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -16,6 +16,7 @@ use crate::convert::FloatToInt; use crate::intrinsics; use crate::mem; use crate::num::FpCategory; +use crate::panic::const_assert; /// Basic mathematical constants. #[unstable(feature = "f128", issue = "116909")] @@ -1263,17 +1264,14 @@ impl f128 { #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn clamp(mut self, min: f128, max: f128) -> f128 { - #[inline] // inline to avoid LLVM crash - const fn assert_at_const(min: f128, max: f128) { - // Note that we cannot format in constant expressions. - assert!(min <= max, "min > max, or either was NaN"); - } - #[inline] // inline to avoid codegen regression - fn assert_at_rt(min: f128, max: f128) { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); - } - // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. - intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); + const_assert!( + min <= max, + "min > max, or either was NaN", + "min > max, or either was NaN. min = {min:?}, max = {max:?}", + min: f128, + max: f128, + ); + if self < min { self = min; } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 8b3f3b7d19b..898caf835bf 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -16,6 +16,7 @@ use crate::convert::FloatToInt; use crate::intrinsics; use crate::mem; use crate::num::FpCategory; +use crate::panic::const_assert; /// Basic mathematical constants. #[unstable(feature = "f16", issue = "116909")] @@ -1238,17 +1239,14 @@ impl f16 { #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn clamp(mut self, min: f16, max: f16) -> f16 { - #[inline] // inline to avoid LLVM crash - const fn assert_at_const(min: f16, max: f16) { - // Note that we cannot format in constant expressions. - assert!(min <= max, "min > max, or either was NaN"); - } - #[inline] // inline to avoid codegen regression - fn assert_at_rt(min: f16, max: f16) { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); - } - // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. - intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); + const_assert!( + min <= max, + "min > max, or either was NaN", + "min > max, or either was NaN. min = {min:?}, max = {max:?}", + min: f16, + max: f16, + ); + if self < min { self = min; } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 2672fe773c2..20ece883da6 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -16,6 +16,7 @@ use crate::convert::FloatToInt; use crate::intrinsics; use crate::mem; use crate::num::FpCategory; +use crate::panic::const_assert; /// The radix or base of the internal representation of `f32`. /// Use [`f32::RADIX`] instead. @@ -1407,16 +1408,14 @@ impl f32 { #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] pub const fn clamp(mut self, min: f32, max: f32) -> f32 { - const fn assert_at_const(min: f32, max: f32) { - // Note that we cannot format in constant expressions. - assert!(min <= max, "min > max, or either was NaN"); - } - #[inline] // inline to avoid codegen regression - fn assert_at_rt(min: f32, max: f32) { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); - } - // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. - intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); + const_assert!( + min <= max, + "min > max, or either was NaN", + "min > max, or either was NaN. min = {min:?}, max = {max:?}", + min: f32, + max: f32, + ); + if self < min { self = min; } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 86082650e55..5640e71788b 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -16,6 +16,7 @@ use crate::convert::FloatToInt; use crate::intrinsics; use crate::mem; use crate::num::FpCategory; +use crate::panic::const_assert; /// The radix or base of the internal representation of `f64`. /// Use [`f64::RADIX`] instead. @@ -1407,16 +1408,14 @@ impl f64 { #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] pub const fn clamp(mut self, min: f64, max: f64) -> f64 { - const fn assert_at_const(min: f64, max: f64) { - // Note that we cannot format in constant expressions. - assert!(min <= max, "min > max, or either was NaN"); - } - #[inline] // inline to avoid codegen regression - fn assert_at_rt(min: f64, max: f64) { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); - } - // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. - intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); + const_assert!( + min <= max, + "min > max, or either was NaN", + "min > max, or either was NaN. min = {min:?}, max = {max:?}", + min: f64, + max: f64, + ); + if self < min { self = min; } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 9e0af8b2ace..5a69dc0c724 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -2,6 +2,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::panic::const_panic; use crate::str::FromStr; use crate::ub_checks::assert_unsafe_precondition; use crate::{ascii, intrinsics, mem}; @@ -1452,24 +1453,16 @@ pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize } -#[track_caller] -const fn from_str_radix_panic_ct(_radix: u32) -> ! { - panic!("from_str_radix_int: must lie in the range `[2, 36]`"); -} - -#[track_caller] -fn from_str_radix_panic_rt(radix: u32) -> ! { - panic!("from_str_radix_int: must lie in the range `[2, 36]` - found {}", radix); -} - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_allow_const_fn_unstable(const_eval_select)] -const fn from_str_radix_panic(radix: u32) { - // The only difference between these two functions is their panic message. - intrinsics::const_eval_select((radix,), from_str_radix_panic_ct, from_str_radix_panic_rt); +const fn from_str_radix_panic(radix: u32) -> ! { + const_panic!( + "from_str_radix_int: must lie in the range `[2, 36]`", + "from_str_radix_int: must lie in the range `[2, 36]` - found {radix}", + radix: u32 = radix, + ) } macro_rules! from_str_radix { diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index e2560f48e59..c7eb9d0f3fd 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -110,26 +110,40 @@ impl_zeroable_primitive!( pub struct NonZero<T: ZeroablePrimitive>(T::NonZeroInner); macro_rules! impl_nonzero_fmt { - ($Trait:ident) => { - #[stable(feature = "nonzero", since = "1.28.0")] - impl<T> fmt::$Trait for NonZero<T> - where - T: ZeroablePrimitive + fmt::$Trait, - { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.get().fmt(f) + ($(#[$Attribute:meta] $Trait:ident)*) => { + $( + #[$Attribute] + impl<T> fmt::$Trait for NonZero<T> + where + T: ZeroablePrimitive + fmt::$Trait, + { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.get().fmt(f) + } } - } + )* }; } -impl_nonzero_fmt!(Debug); -impl_nonzero_fmt!(Display); -impl_nonzero_fmt!(Binary); -impl_nonzero_fmt!(Octal); -impl_nonzero_fmt!(LowerHex); -impl_nonzero_fmt!(UpperHex); +impl_nonzero_fmt! { + #[stable(feature = "nonzero", since = "1.28.0")] + Debug + #[stable(feature = "nonzero", since = "1.28.0")] + Display + #[stable(feature = "nonzero", since = "1.28.0")] + Binary + #[stable(feature = "nonzero", since = "1.28.0")] + Octal + #[stable(feature = "nonzero", since = "1.28.0")] + LowerHex + #[stable(feature = "nonzero", since = "1.28.0")] + UpperHex + #[stable(feature = "nonzero_fmt_exp", since = "CURRENT_RUSTC_VERSION")] + LowerExp + #[stable(feature = "nonzero_fmt_exp", since = "CURRENT_RUSTC_VERSION")] + UpperExp +} macro_rules! impl_nonzero_auto_trait { (unsafe $Trait:ident) => { @@ -458,7 +472,15 @@ macro_rules! nonzero_integer { reversed = $reversed:literal, leading_zeros_test = $leading_zeros_test:expr, ) => { - /// An integer that is known not to equal zero. + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("An [`", stringify!($Int), "`] that is known not to equal zero.") + } + if unsigned { + concat!("A [`", stringify!($Int), "`] that is known not to equal zero.") + } + }] /// /// This enables some memory layout optimization. #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] @@ -1192,6 +1214,35 @@ macro_rules! nonzero_integer_signedness_dependent_impls { *self = *self % other; } } + + impl NonZero<$Int> { + /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity. + /// + /// The result is guaranteed to be non-zero. + /// + /// # Examples + /// + /// ``` + /// # #![feature(unsigned_nonzero_div_ceil)] + /// # use std::num::NonZero; + #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ").unwrap();")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX).unwrap();")] + /// assert_eq!(one.div_ceil(max), one); + /// + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ").unwrap();")] + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ").unwrap();")] + /// assert_eq!(three.div_ceil(two), two); + /// ``` + #[unstable(feature = "unsigned_nonzero_div_ceil", issue = "none")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn div_ceil(self, rhs: Self) -> Self { + let v = self.get().div_ceil(rhs.get()); + // SAFETY: ceiled division of two positive integers can never be zero. + unsafe { Self::new_unchecked(v) } + } + } }; // Impls for signed nonzero types only. (signed $Int:ty) => { diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index c6083a121d1..a6f63ad68d6 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -203,7 +203,7 @@ /// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] -// FIXME(effects) #[const_trait] +// FIXME(const_trait_impl) #[const_trait] pub trait Drop { /// Executes the destructor for this type. /// diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 3a3d3fcf1da..e9014458b48 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -72,7 +72,7 @@ use crate::marker::Tuple; )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -// FIXME(effects) #[const_trait] +// FIXME(const_trait_impl) #[const_trait] pub trait Fn<Args: Tuple>: FnMut<Args> { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -159,7 +159,7 @@ pub trait Fn<Args: Tuple>: FnMut<Args> { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -// FIXME(effects) #[const_trait] +// FIXME(const_trait_impl) #[const_trait] pub trait FnMut<Args: Tuple>: FnOnce<Args> { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -238,7 +238,7 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -// FIXME(effects) #[const_trait] +// FIXME(const_trait_impl) #[const_trait] pub trait FnOnce<Args: Tuple> { /// The returned type after the call operator is used. #[lang = "fn_once_output"] diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index c95a000561c..f8f3962ce55 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -189,3 +189,59 @@ pub unsafe trait PanicPayload: crate::fmt::Display { None } } + +/// Helper macro for panicking in a `const fn`. +/// Invoke as: +/// ```rust,ignore (just an example) +/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar); +/// ``` +/// where the first message will be printed in const-eval, +/// and the second message will be printed at runtime. +// All uses of this macro are FIXME(const-hack). +#[unstable(feature = "panic_internals", issue = "none")] +#[doc(hidden)] +pub macro const_panic { + ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{ + // Wrap call to `const_eval_select` in a function so that we can + // add the `rustc_allow_const_fn_unstable`. This is okay to do + // because both variants will panic, just with different messages. + #[rustc_allow_const_fn_unstable(const_eval_select)] + #[inline(always)] + #[track_caller] + #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "CURRENT_RUSTC_VERSION"))] + const fn do_panic($($arg: $ty),*) -> ! { + $crate::intrinsics::const_eval_select!( + @capture { $($arg: $ty),* } -> !: + if const #[track_caller] { + $crate::panic!($const_msg) + } else #[track_caller] { + $crate::panic!($runtime_msg) + } + ) + } + + do_panic($($val),*) + }}, + // We support leaving away the `val` expressions for *all* arguments + // (but not for *some* arguments, that's too tricky). + ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => { + $crate::panic::const_panic!( + $const_msg, + $runtime_msg, + $($arg: $ty = $arg),* + ) + }, +} + +/// A version of `assert` that prints a non-formatting message in const contexts. +/// +/// See [`const_panic!`]. +#[unstable(feature = "panic_internals", issue = "none")] +#[doc(hidden)] +pub macro const_assert { + ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{ + if !$crate::intrinsics::likely($condition) { + $crate::panic::const_panic!($const_msg, $runtime_msg, $($arg)*) + } + }} +} diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 1d950eb3625..230a9918dbf 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -165,10 +165,9 @@ impl<'a> PanicMessage<'a> { /// /// See [`fmt::Arguments::as_str`] for details. #[stable(feature = "panic_info_message", since = "1.81.0")] - #[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")] + #[rustc_const_stable(feature = "const_arguments_as_str", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] pub const fn as_str(&self) -> Option<&'static str> { self.message.as_str() } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 9071d6719a3..f603eb2971f 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -29,6 +29,7 @@ )] use crate::fmt; +use crate::intrinsics::const_eval_select; use crate::panic::{Location, PanicInfo}; #[cfg(feature = "panic_immediate_abort")] @@ -89,40 +90,35 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable #[rustc_allow_const_fn_unstable(const_eval_select)] pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { - #[inline] // this should always be inlined into `panic_nounwind_fmt` - #[track_caller] - fn runtime(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { - if cfg!(feature = "panic_immediate_abort") { - super::intrinsics::abort() + const_eval_select!( + @capture { fmt: fmt::Arguments<'_>, force_no_backtrace: bool } -> !: + if const #[track_caller] { + // We don't unwind anyway at compile-time so we can call the regular `panic_fmt`. + panic_fmt(fmt) + } else #[track_caller] { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } + + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + // PanicInfo with the `can_unwind` flag set to false forces an abort. + let pi = PanicInfo::new( + &fmt, + Location::caller(), + /* can_unwind */ false, + force_no_backtrace, + ); + + // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. + unsafe { panic_impl(&pi) } } - - // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - // that gets resolved to the `#[panic_handler]` function. - extern "Rust" { - #[lang = "panic_impl"] - fn panic_impl(pi: &PanicInfo<'_>) -> !; - } - - // PanicInfo with the `can_unwind` flag set to false forces an abort. - let pi = PanicInfo::new( - &fmt, - Location::caller(), - /* can_unwind */ false, - force_no_backtrace, - ); - - // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. - unsafe { panic_impl(&pi) } - } - - #[inline] - #[track_caller] - const fn comptime(fmt: fmt::Arguments<'_>, _force_no_backtrace: bool) -> ! { - // We don't unwind anyway at compile-time so we can call the regular `panic_fmt`. - panic_fmt(fmt); - } - - super::intrinsics::const_eval_select((fmt, force_no_backtrace), comptime, runtime); + ) } // Next we define a bunch of higher-level wrappers that all bottom out in the two core functions diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index a4e8e373e04..2d7507e2d53 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -33,26 +33,23 @@ impl<T: ?Sized> *const T { #[rustc_diagnostic_item = "ptr_const_is_null"] #[inline] pub const fn is_null(self) -> bool { - #[inline] - fn runtime_impl(ptr: *const u8) -> bool { - ptr.addr() == 0 - } - - #[inline] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] - const fn const_impl(ptr: *const u8) -> bool { - match (ptr).guaranteed_eq(null_mut()) { - Some(res) => res, - // To remain maximally convervative, we stop execution when we don't - // know whether the pointer is null or not. - // We can *not* return `false` here, that would be unsound in `NonNull::new`! - None => panic!("null-ness of this pointer cannot be determined in const context"), - } - } - // Compare via a cast to a thin pointer, so fat pointers are only // considering their "data" part for null-ness. - const_eval_select((self as *const u8,), const_impl, runtime_impl) + let ptr = self as *const u8; + const_eval_select!( + @capture { ptr: *const u8 } -> bool: + if const #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] { + match (ptr).guaranteed_eq(null_mut()) { + Some(res) => res, + // To remain maximally convervative, we stop execution when we don't + // know whether the pointer is null or not. + // We can *not* return `false` here, that would be unsound in `NonNull::new`! + None => panic!("null-ness of this pointer cannot be determined in const context"), + } + } else { + ptr.addr() == 0 + } + ) } /// Casts to a pointer of another type. @@ -410,22 +407,21 @@ impl<T: ?Sized> *const T { #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool { - #[inline] - fn runtime(this: *const (), count: isize, size: usize) -> bool { - // We know `size <= isize::MAX` so the `as` cast here is not lossy. - let Some(byte_offset) = count.checked_mul(size as isize) else { - return false; - }; - let (_, overflow) = this.addr().overflowing_add_signed(byte_offset); - !overflow - } - - const fn comptime(_: *const (), _: isize, _: usize) -> bool { - true - } - // We can use const_eval_select here because this is only for UB checks. - intrinsics::const_eval_select((this, count, size), comptime, runtime) + const_eval_select!( + @capture { this: *const (), count: isize, size: usize } -> bool: + if const { + true + } else { + // `size` is the size of a Rust type, so we know that + // `size <= isize::MAX` and thus `as` cast here is not lossy. + let Some(byte_offset) = count.checked_mul(size as isize) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add_signed(byte_offset); + !overflow + } + ) } ub_checks::assert_unsafe_precondition!( @@ -763,14 +759,14 @@ impl<T: ?Sized> *const T { { #[rustc_allow_const_fn_unstable(const_eval_select)] const fn runtime_ptr_ge(this: *const (), origin: *const ()) -> bool { - fn runtime(this: *const (), origin: *const ()) -> bool { - this >= origin - } - const fn comptime(_: *const (), _: *const ()) -> bool { - true - } - - intrinsics::const_eval_select((this, origin), comptime, runtime) + const_eval_select!( + @capture { this: *const (), origin: *const () } -> bool: + if const { + true + } else { + this >= origin + } + ) } ub_checks::assert_unsafe_precondition!( @@ -924,20 +920,18 @@ impl<T: ?Sized> *const T { #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool { - #[inline] - fn runtime(this: *const (), count: usize, size: usize) -> bool { - let Some(byte_offset) = count.checked_mul(size) else { - return false; - }; - let (_, overflow) = this.addr().overflowing_add(byte_offset); - byte_offset <= (isize::MAX as usize) && !overflow - } - - const fn comptime(_: *const (), _: usize, _: usize) -> bool { - true - } - - intrinsics::const_eval_select((this, count, size), comptime, runtime) + const_eval_select!( + @capture { this: *const (), count: usize, size: usize } -> bool: + if const { + true + } else { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add(byte_offset); + byte_offset <= (isize::MAX as usize) && !overflow + } + ) } #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. @@ -1033,19 +1027,17 @@ impl<T: ?Sized> *const T { #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool { - #[inline] - fn runtime(this: *const (), count: usize, size: usize) -> bool { - let Some(byte_offset) = count.checked_mul(size) else { - return false; - }; - byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset - } - - const fn comptime(_: *const (), _: usize, _: usize) -> bool { - true - } - - intrinsics::const_eval_select((this, count, size), comptime, runtime) + const_eval_select!( + @capture { this: *const (), count: usize, size: usize } -> bool: + if const { + true + } else { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset + } + ) } #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 0d94a7f491c..344ba46a50e 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1,5 +1,6 @@ use super::*; use crate::cmp::Ordering::{Equal, Greater, Less}; +use crate::intrinsics::const_eval_select; use crate::mem::SizedTypeProperties; use crate::slice::{self, SliceIndex}; @@ -404,23 +405,21 @@ impl<T: ?Sized> *mut T { #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool { - #[inline] - fn runtime(this: *const (), count: isize, size: usize) -> bool { - // `size` is the size of a Rust type, so we know that - // `size <= isize::MAX` and thus `as` cast here is not lossy. - let Some(byte_offset) = count.checked_mul(size as isize) else { - return false; - }; - let (_, overflow) = this.addr().overflowing_add_signed(byte_offset); - !overflow - } - - const fn comptime(_: *const (), _: isize, _: usize) -> bool { - true - } - // We can use const_eval_select here because this is only for UB checks. - intrinsics::const_eval_select((this, count, size), comptime, runtime) + const_eval_select!( + @capture { this: *const (), count: isize, size: usize } -> bool: + if const { + true + } else { + // `size` is the size of a Rust type, so we know that + // `size <= isize::MAX` and thus `as` cast here is not lossy. + let Some(byte_offset) = count.checked_mul(size as isize) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add_signed(byte_offset); + !overflow + } + ) } ub_checks::assert_unsafe_precondition!( @@ -1002,20 +1001,18 @@ impl<T: ?Sized> *mut T { #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool { - #[inline] - fn runtime(this: *const (), count: usize, size: usize) -> bool { - let Some(byte_offset) = count.checked_mul(size) else { - return false; - }; - let (_, overflow) = this.addr().overflowing_add(byte_offset); - byte_offset <= (isize::MAX as usize) && !overflow - } - - const fn comptime(_: *const (), _: usize, _: usize) -> bool { - true - } - - intrinsics::const_eval_select((this, count, size), comptime, runtime) + const_eval_select!( + @capture { this: *const (), count: usize, size: usize } -> bool: + if const { + true + } else { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add(byte_offset); + byte_offset <= (isize::MAX as usize) && !overflow + } + ) } #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. @@ -1111,19 +1108,17 @@ impl<T: ?Sized> *mut T { #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool { - #[inline] - fn runtime(this: *const (), count: usize, size: usize) -> bool { - let Some(byte_offset) = count.checked_mul(size) else { - return false; - }; - byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset - } - - const fn comptime(_: *const (), _: usize, _: usize) -> bool { - true - } - - intrinsics::const_eval_select((this, count, size), comptime, runtime) + const_eval_select!( + @capture { this: *const (), count: usize, size: usize } -> bool: + if const { + true + } else { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset + } + ) } #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 8dcd34929e1..17ad4fd8f67 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -52,10 +52,30 @@ impl [u8] { /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, /// but without allocating and copying temporaries. #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")] #[must_use] #[inline] - pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { - self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) + pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool { + if self.len() != other.len() { + return false; + } + + // FIXME(const-hack): This implementation can be reverted when + // `core::iter::zip` is allowed in const. The original implementation: + // self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) + let mut a = self; + let mut b = other; + + while let ([first_a, rest_a @ ..], [first_b, rest_b @ ..]) = (a, b) { + if first_a.eq_ignore_ascii_case(&first_b) { + a = rest_a; + b = rest_b; + } else { + return false; + } + } + + true } /// Converts this slice to its ASCII upper case equivalent in-place. @@ -351,89 +371,87 @@ pub const fn is_ascii_simple(mut bytes: &[u8]) -> bool { const fn is_ascii(s: &[u8]) -> bool { // The runtime version behaves the same as the compiletime version, it's // just more optimized. - return const_eval_select((s,), compiletime, runtime); - - const fn compiletime(s: &[u8]) -> bool { - is_ascii_simple(s) - } - - #[inline] - fn runtime(s: &[u8]) -> bool { - const USIZE_SIZE: usize = mem::size_of::<usize>(); - - let len = s.len(); - let align_offset = s.as_ptr().align_offset(USIZE_SIZE); - - // If we wouldn't gain anything from the word-at-a-time implementation, fall - // back to a scalar loop. - // - // We also do this for architectures where `size_of::<usize>()` isn't - // sufficient alignment for `usize`, because it's a weird edge case. - if len < USIZE_SIZE || len < align_offset || USIZE_SIZE < mem::align_of::<usize>() { - return is_ascii_simple(s); - } + const_eval_select!( + @capture { s: &[u8] } -> bool: + if const { + is_ascii_simple(s) + } else { + const USIZE_SIZE: usize = mem::size_of::<usize>(); + + let len = s.len(); + let align_offset = s.as_ptr().align_offset(USIZE_SIZE); + + // If we wouldn't gain anything from the word-at-a-time implementation, fall + // back to a scalar loop. + // + // We also do this for architectures where `size_of::<usize>()` isn't + // sufficient alignment for `usize`, because it's a weird edge case. + if len < USIZE_SIZE || len < align_offset || USIZE_SIZE < mem::align_of::<usize>() { + return is_ascii_simple(s); + } - // We always read the first word unaligned, which means `align_offset` is - // 0, we'd read the same value again for the aligned read. - let offset_to_aligned = if align_offset == 0 { USIZE_SIZE } else { align_offset }; + // We always read the first word unaligned, which means `align_offset` is + // 0, we'd read the same value again for the aligned read. + let offset_to_aligned = if align_offset == 0 { USIZE_SIZE } else { align_offset }; - let start = s.as_ptr(); - // SAFETY: We verify `len < USIZE_SIZE` above. - let first_word = unsafe { (start as *const usize).read_unaligned() }; + let start = s.as_ptr(); + // SAFETY: We verify `len < USIZE_SIZE` above. + let first_word = unsafe { (start as *const usize).read_unaligned() }; - if contains_nonascii(first_word) { - return false; - } - // We checked this above, somewhat implicitly. Note that `offset_to_aligned` - // is either `align_offset` or `USIZE_SIZE`, both of are explicitly checked - // above. - debug_assert!(offset_to_aligned <= len); - - // SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the - // middle chunk of the slice. - let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize }; - - // `byte_pos` is the byte index of `word_ptr`, used for loop end checks. - let mut byte_pos = offset_to_aligned; - - // Paranoia check about alignment, since we're about to do a bunch of - // unaligned loads. In practice this should be impossible barring a bug in - // `align_offset` though. - // While this method is allowed to spuriously fail in CTFE, if it doesn't - // have alignment information it should have given a `usize::MAX` for - // `align_offset` earlier, sending things through the scalar path instead of - // this one, so this check should pass if it's reachable. - debug_assert!(word_ptr.is_aligned_to(mem::align_of::<usize>())); - - // Read subsequent words until the last aligned word, excluding the last - // aligned word by itself to be done in tail check later, to ensure that - // tail is always one `usize` at most to extra branch `byte_pos == len`. - while byte_pos < len - USIZE_SIZE { - // Sanity check that the read is in bounds - debug_assert!(byte_pos + USIZE_SIZE <= len); - // And that our assumptions about `byte_pos` hold. - debug_assert!(word_ptr.cast::<u8>() == start.wrapping_add(byte_pos)); - - // SAFETY: We know `word_ptr` is properly aligned (because of - // `align_offset`), and we know that we have enough bytes between `word_ptr` and the end - let word = unsafe { word_ptr.read() }; - if contains_nonascii(word) { + if contains_nonascii(first_word) { return false; } + // We checked this above, somewhat implicitly. Note that `offset_to_aligned` + // is either `align_offset` or `USIZE_SIZE`, both of are explicitly checked + // above. + debug_assert!(offset_to_aligned <= len); + + // SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the + // middle chunk of the slice. + let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize }; + + // `byte_pos` is the byte index of `word_ptr`, used for loop end checks. + let mut byte_pos = offset_to_aligned; + + // Paranoia check about alignment, since we're about to do a bunch of + // unaligned loads. In practice this should be impossible barring a bug in + // `align_offset` though. + // While this method is allowed to spuriously fail in CTFE, if it doesn't + // have alignment information it should have given a `usize::MAX` for + // `align_offset` earlier, sending things through the scalar path instead of + // this one, so this check should pass if it's reachable. + debug_assert!(word_ptr.is_aligned_to(mem::align_of::<usize>())); + + // Read subsequent words until the last aligned word, excluding the last + // aligned word by itself to be done in tail check later, to ensure that + // tail is always one `usize` at most to extra branch `byte_pos == len`. + while byte_pos < len - USIZE_SIZE { + // Sanity check that the read is in bounds + debug_assert!(byte_pos + USIZE_SIZE <= len); + // And that our assumptions about `byte_pos` hold. + debug_assert!(word_ptr.cast::<u8>() == start.wrapping_add(byte_pos)); + + // SAFETY: We know `word_ptr` is properly aligned (because of + // `align_offset`), and we know that we have enough bytes between `word_ptr` and the end + let word = unsafe { word_ptr.read() }; + if contains_nonascii(word) { + return false; + } + + byte_pos += USIZE_SIZE; + // SAFETY: We know that `byte_pos <= len - USIZE_SIZE`, which means that + // after this `add`, `word_ptr` will be at most one-past-the-end. + word_ptr = unsafe { word_ptr.add(1) }; + } - byte_pos += USIZE_SIZE; - // SAFETY: We know that `byte_pos <= len - USIZE_SIZE`, which means that - // after this `add`, `word_ptr` will be at most one-past-the-end. - word_ptr = unsafe { word_ptr.add(1) }; - } - - // Sanity check to ensure there really is only one `usize` left. This should - // be guaranteed by our loop condition. - debug_assert!(byte_pos <= len && len - byte_pos <= USIZE_SIZE); + // Sanity check to ensure there really is only one `usize` left. This should + // be guaranteed by our loop condition. + debug_assert!(byte_pos <= len && len - byte_pos <= USIZE_SIZE); - // SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start. - let last_word = unsafe { (start.add(len - USIZE_SIZE) as *const usize).read_unaligned() }; + // SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start. + let last_word = unsafe { (start.add(len - USIZE_SIZE) as *const usize).read_unaligned() }; - !contains_nonascii(last_word) - } + !contains_nonascii(last_word) + } + ) } diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 231ab7396ad..aafa19c0dd3 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -1,6 +1,6 @@ //! Indexing implementations for `[T]`. -use crate::intrinsics::const_eval_select; +use crate::panic::const_panic; use crate::ub_checks::assert_unsafe_precondition; use crate::{ops, range}; @@ -31,67 +31,37 @@ where #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_allow_const_fn_unstable(const_eval_select)] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { - // FIXME(const-hack): once integer formatting in panics is possible, we - // should use the same implementation at compiletime and runtime. - const_eval_select((index, len), slice_start_index_len_fail_ct, slice_start_index_len_fail_rt) -} - -#[inline] -#[track_caller] -fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! { - panic!("range start index {index} out of range for slice of length {len}"); -} - -#[inline] -#[track_caller] -const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { - panic!("slice start index is out of range for slice"); + const_panic!( + "slice start index is out of range for slice", + "range start index {index} out of range for slice of length {len}", + index: usize, + len: usize, + ) } #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_allow_const_fn_unstable(const_eval_select)] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { - // FIXME(const-hack): once integer formatting in panics is possible, we - // should use the same implementation at compiletime and runtime. - const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt) -} - -#[inline] -#[track_caller] -fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! { - panic!("range end index {index} out of range for slice of length {len}"); -} - -#[inline] -#[track_caller] -const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { - panic!("slice end index is out of range for slice"); + const_panic!( + "slice end index is out of range for slice", + "range end index {index} out of range for slice of length {len}", + index: usize, + len: usize, + ) } #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_allow_const_fn_unstable(const_eval_select)] const fn slice_index_order_fail(index: usize, end: usize) -> ! { - // FIXME(const-hack): once integer formatting in panics is possible, we - // should use the same implementation at compiletime and runtime. - const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) -} - -#[inline] -#[track_caller] -fn slice_index_order_fail_rt(index: usize, end: usize) -> ! { - panic!("slice index starts at {index} but ends at {end}"); -} - -#[inline] -#[track_caller] -const fn slice_index_order_fail_ct(_: usize, _: usize) -> ! { - panic!("slice index start is larger than end"); + const_panic!( + "slice index start is larger than end", + "slice index starts at {index} but ends at {end}", + index: usize, + end: usize, + ) } #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index b7c4a1f6f08..339adad1b17 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -56,61 +56,59 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> { const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> { // The runtime version behaves the same as the compiletime version, it's // just more optimized. - return const_eval_select((x, text), compiletime, runtime); - - const fn compiletime(x: u8, text: &[u8]) -> Option<usize> { - memchr_naive(x, text) - } - - #[inline] - fn runtime(x: u8, text: &[u8]) -> Option<usize> { - // Scan for a single byte value by reading two `usize` words at a time. - // - // Split `text` in three parts - // - unaligned initial part, before the first word aligned address in text - // - body, scan by 2 words at a time - // - the last remaining part, < 2 word size - - // search up to an aligned boundary - let len = text.len(); - let ptr = text.as_ptr(); - let mut offset = ptr.align_offset(USIZE_BYTES); - - if offset > 0 { - offset = offset.min(len); - let slice = &text[..offset]; - if let Some(index) = memchr_naive(x, slice) { - return Some(index); + const_eval_select!( + @capture { x: u8, text: &[u8] } -> Option<usize>: + if const { + memchr_naive(x, text) + } else { + // Scan for a single byte value by reading two `usize` words at a time. + // + // Split `text` in three parts + // - unaligned initial part, before the first word aligned address in text + // - body, scan by 2 words at a time + // - the last remaining part, < 2 word size + + // search up to an aligned boundary + let len = text.len(); + let ptr = text.as_ptr(); + let mut offset = ptr.align_offset(USIZE_BYTES); + + if offset > 0 { + offset = offset.min(len); + let slice = &text[..offset]; + if let Some(index) = memchr_naive(x, slice) { + return Some(index); + } } - } - // search the body of the text - let repeated_x = usize::repeat_u8(x); - while offset <= len - 2 * USIZE_BYTES { - // SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes - // between the offset and the end of the slice. - unsafe { - let u = *(ptr.add(offset) as *const usize); - let v = *(ptr.add(offset + USIZE_BYTES) as *const usize); - - // break if there is a matching byte - let zu = contains_zero_byte(u ^ repeated_x); - let zv = contains_zero_byte(v ^ repeated_x); - if zu || zv { - break; + // search the body of the text + let repeated_x = usize::repeat_u8(x); + while offset <= len - 2 * USIZE_BYTES { + // SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes + // between the offset and the end of the slice. + unsafe { + let u = *(ptr.add(offset) as *const usize); + let v = *(ptr.add(offset + USIZE_BYTES) as *const usize); + + // break if there is a matching byte + let zu = contains_zero_byte(u ^ repeated_x); + let zv = contains_zero_byte(v ^ repeated_x); + if zu || zv { + break; + } } + offset += USIZE_BYTES * 2; } - offset += USIZE_BYTES * 2; - } - // Find the byte after the point the body loop stopped. - // FIXME(const-hack): Use `?` instead. - // FIXME(const-hack, fee1-dead): use range slicing - let slice = - // SAFETY: offset is within bounds - unsafe { super::from_raw_parts(text.as_ptr().add(offset), text.len() - offset) }; - if let Some(i) = memchr_naive(x, slice) { Some(offset + i) } else { None } - } + // Find the byte after the point the body loop stopped. + // FIXME(const-hack): Use `?` instead. + // FIXME(const-hack, fee1-dead): use range slicing + let slice = + // SAFETY: offset is within bounds + unsafe { super::from_raw_parts(text.as_ptr().add(offset), text.len() - offset) }; + if let Some(i) = memchr_naive(x, slice) { Some(offset + i) } else { None } + } + ) } /// Returns the last index matching the byte `x` in `text`. diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs index 6adf779a72f..09f898309bd 100644 --- a/library/core/src/slice/sort/shared/smallsort.rs +++ b/library/core/src/slice/sort/shared/smallsort.rs @@ -102,7 +102,7 @@ impl<T: FreezeMarker> UnstableSmallSortTypeImpl for T { } } -/// FIXME(effects) use original ipnsort approach with choose_unstable_small_sort, +/// FIXME(const_trait_impl) use original ipnsort approach with choose_unstable_small_sort, /// as found here <https://github.com/Voultapher/sort-research-rs/blob/438fad5d0495f65d4b72aa87f0b62fc96611dff3/ipnsort/src/smallsort.rs#L83C10-L83C36>. pub(crate) trait UnstableSmallSortFreezeTypeImpl: Sized + FreezeMarker { fn small_sort_threshold() -> usize; diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 58d6e07de8d..0f7c2c999d0 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2474,9 +2474,10 @@ impl str { /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS")); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")] #[must_use] #[inline] - pub fn eq_ignore_ascii_case(&self, other: &str) -> bool { + pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool { self.as_bytes().eq_ignore_ascii_case(other.as_bytes()) } diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 665c9fc67d0..52e2364893e 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -886,8 +886,8 @@ impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {} /// # Examples /// /// ``` -/// assert_eq!("Hello world".find(&['l', 'l'] as &[_]), Some(2)); -/// assert_eq!("Hello world".find(&['l', 'l'][..]), Some(2)); +/// assert_eq!("Hello world".find(&['o', 'l'][..]), Some(2)); +/// assert_eq!("Hello world".find(&['h', 'w'][..]), Some(6)); /// ``` impl<'b> Pattern for &'b [char] { pattern_methods!('a, CharSliceSearcher<'a, 'b>, MultiCharEqPattern, CharSliceSearcher); diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs index 6095b589e18..0f724dd9613 100644 --- a/library/core/src/str/validations.rs +++ b/library/core/src/str/validations.rs @@ -132,19 +132,16 @@ pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { let ascii_block_size = 2 * USIZE_BYTES; let blocks_end = if len >= ascii_block_size { len - ascii_block_size + 1 } else { 0 }; - let align = { - const fn compiletime(_v: &[u8]) -> usize { + // Below, we safely fall back to a slower codepath if the offset is `usize::MAX`, + // so the end-to-end behavior is the same at compiletime and runtime. + let align = const_eval_select!( + @capture { v: &[u8] } -> usize: + if const { usize::MAX - } - - fn runtime(v: &[u8]) -> usize { + } else { v.as_ptr().align_offset(USIZE_BYTES) } - - // Below, we safely fall back to a slower codepath if the offset is `usize::MAX`, - // so the end-to-end behavior is the same at compiletime and runtime. - const_eval_select((v,), compiletime, runtime) - }; + ); while index < len { let old_offset = index; diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index dd1454f401e..8fcbda141da 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -95,20 +95,18 @@ pub use intrinsics::ub_checks as check_library_ub; #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] pub(crate) const fn check_language_ub() -> bool { - #[inline] - fn runtime() -> bool { - // Disable UB checks in Miri. - !cfg!(miri) - } - - #[inline] - const fn comptime() -> bool { - // Always disable UB checks. - false - } - // Only used for UB checks so we may const_eval_select. - intrinsics::ub_checks() && const_eval_select((), comptime, runtime) + intrinsics::ub_checks() + && const_eval_select!( + @capture { } -> bool: + if const { + // Always disable UB checks. + false + } else { + // Disable UB checks in Miri. + !cfg!(miri) + } + ) } /// Checks whether `ptr` is properly aligned with respect to the given alignment, and @@ -120,19 +118,15 @@ pub(crate) const fn check_language_ub() -> bool { #[inline] #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool { - #[inline] - fn runtime(ptr: *const (), align: usize, is_zst: bool) -> bool { - ptr.is_aligned_to(align) && (is_zst || !ptr.is_null()) - } - - #[inline] - #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] - const fn comptime(ptr: *const (), _align: usize, is_zst: bool) -> bool { - is_zst || !ptr.is_null() - } - // This is just for safety checks so we can const_eval_select. - const_eval_select((ptr, align, is_zst), comptime, runtime) + const_eval_select!( + @capture { ptr: *const (), align: usize, is_zst: bool } -> bool: + if const #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] { + is_zst || !ptr.is_null() + } else { + ptr.is_aligned_to(align) && (is_zst || !ptr.is_null()) + } + ) } #[inline] @@ -154,26 +148,23 @@ pub(crate) const fn is_nonoverlapping( size: usize, count: usize, ) -> bool { - #[inline] - fn runtime(src: *const (), dst: *const (), size: usize, count: usize) -> bool { - let src_usize = src.addr(); - let dst_usize = dst.addr(); - let Some(size) = size.checked_mul(count) else { - crate::panicking::panic_nounwind( - "is_nonoverlapping: `size_of::<T>() * count` overflows a usize", - ) - }; - let diff = src_usize.abs_diff(dst_usize); - // If the absolute distance between the ptrs is at least as big as the size of the buffer, - // they do not overlap. - diff >= size - } - - #[inline] - const fn comptime(_: *const (), _: *const (), _: usize, _: usize) -> bool { - true - } - // This is just for safety checks so we can const_eval_select. - const_eval_select((src, dst, size, count), comptime, runtime) + const_eval_select!( + @capture { src: *const (), dst: *const (), size: usize, count: usize } -> bool: + if const { + true + } else { + let src_usize = src.addr(); + let dst_usize = dst.addr(); + let Some(size) = size.checked_mul(count) else { + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::<T>() * count` overflows a usize", + ) + }; + let diff = src_usize.abs_diff(dst_usize); + // If the absolute distance between the ptrs is at least as big as the size of the buffer, + // they do not overlap. + diff >= size + } + ) } diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 4101aa5292e..4655d35e9c4 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -1,4 +1,4 @@ -///! This file is generated by src/tools/unicode-table-generator; do not edit manually! +///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually! #[inline(always)] const fn bitset_search< @@ -572,7 +572,7 @@ pub mod white_space { 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; #[inline] - pub fn lookup(c: char) -> bool { + pub const fn lookup(c: char) -> bool { match c as u32 >> 8 { 0 => WHITESPACE_MAP[c as usize & 0xff] & 1 != 0, 22 => c as u32 == 0x1680, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 5f14baf96ae..b9706ea2a9e 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,4 +1,5 @@ // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(const_three_way_compare))] #![cfg_attr(bootstrap, feature(strict_provenance))] #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] @@ -18,12 +19,10 @@ #![feature(const_align_of_val_raw)] #![feature(const_black_box)] #![feature(const_eval_select)] -#![feature(const_hash)] #![feature(const_heap)] #![feature(const_nonnull_new)] #![feature(const_option_ext)] #![feature(const_pin_2)] -#![feature(const_three_way_compare)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index d728513a4e2..43c279053d8 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -354,3 +354,14 @@ fn test_signed_nonzero_neg() { assert_eq!((-NonZero::<i128>::new(1).unwrap()).get(), -1); assert_eq!((-NonZero::<i128>::new(-1).unwrap()).get(), 1); } + +#[test] +fn test_nonzero_fmt() { + let i = format!("{0}, {0:?}, {0:x}, {0:X}, {0:#x}, {0:#X}, {0:o}, {0:b}, {0:e}, {0:E}", 42); + let nz = format!( + "{0}, {0:?}, {0:x}, {0:X}, {0:#x}, {0:#X}, {0:o}, {0:b}, {0:e}, {0:E}", + NonZero::new(42).unwrap() + ); + + assert_eq!(i, nz); +} diff --git a/library/rustc-std-workspace-core/README.md b/library/rustc-std-workspace-core/README.md index 40e0b62afab..55a36e74106 100644 --- a/library/rustc-std-workspace-core/README.md +++ b/library/rustc-std-workspace-core/README.md @@ -27,3 +27,6 @@ it'll look like when Cargo invokes the compiler, satisfying the implicit `extern crate core` directive injected by the compiler. + +The sources for the crates.io version can be found in +[`src/rustc-std-workspace`](../../src/rustc-std-workspace). diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 9b66fc8f921..b732fdf1696 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,15 +17,11 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.136" } +compiler_builtins = { version = "=0.1.138" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', ] } -# FIXME(#127890): `object` depends on `memchr`, but `memchr` > v2.5 causes -# issues with LTO. This dependency is not used directly, but pin it here so -# it resolves to 2.5. To be removed once rust-lang/rust#127890 is fixed. -memchr = { version = "=2.5.0", default-features = false, features = ["rustc-dep-of-std"] } std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = [ 'rustc-dep-of-std', ] } diff --git a/library/std/build.rs b/library/std/build.rs index 032326556bd..8dc326a3dde 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -122,19 +122,24 @@ fn main() { _ if is_miri => true, // Unsupported <https://github.com/llvm/llvm-project/issues/94434> ("arm64ec", _) => false, - // ABI and precision bugs <https://github.com/rust-lang/rust/issues/125109> - // <https://github.com/rust-lang/rust/issues/125102> - ("powerpc" | "powerpc64", _) => false, + // Selection bug <https://github.com/llvm/llvm-project/issues/96432> + ("mips64" | "mips64r6", _) => false, // Selection bug <https://github.com/llvm/llvm-project/issues/95471> ("nvptx64", _) => false, + // ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full + // list at <https://github.com/rust-lang/rust/issues/116909>) + ("powerpc" | "powerpc64", _) => false, // ABI unsupported <https://github.com/llvm/llvm-project/issues/41838> ("sparc", _) => false, + // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may + // not fail if our compiler-builtins is linked. + ("x86", _) => false, // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054> ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false, - // 64-bit Linux is about the only platform to have f128 symbols by default - (_, "linux") if target_pointer_width == 64 => true, - // Almost all OSs are missing symbol. compiler-builtins will have to add them. - _ => false, + // There are no known problems on other platforms, so the only requirement is that symbols + // are available. `compiler-builtins` provides all symbols required for core `f128` + // support, so this should work for everything else. + _ => true, }; // Configure platforms that have reliable basics but may have unreliable math. diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs index b79ad1c3119..a275488a556 100644 --- a/library/std/src/collections/hash/map/tests.rs +++ b/library/std/src/collections/hash/map/tests.rs @@ -5,7 +5,7 @@ use super::Entry::{Occupied, Vacant}; use super::HashMap; use crate::assert_matches::assert_matches; use crate::cell::RefCell; -use crate::hash::RandomState; +use crate::hash::{BuildHasher, BuildHasherDefault, DefaultHasher, RandomState}; use crate::test_helpers::test_rng; // https://github.com/rust-lang/rust/issues/62301 @@ -1124,6 +1124,26 @@ fn from_array() { #[test] fn const_with_hasher() { - const X: HashMap<(), (), ()> = HashMap::with_hasher(()); - assert_eq!(X.len(), 0); + const X: HashMap<(), (), BuildHasherDefault<DefaultHasher>> = + HashMap::with_hasher(BuildHasherDefault::new()); + let mut x = X; + assert_eq!(x.len(), 0); + x.insert((), ()); + assert_eq!(x.len(), 1); + + // It *is* possible to do this without using the `BuildHasherDefault` type. + struct MyBuildDefaultHasher; + impl BuildHasher for MyBuildDefaultHasher { + type Hasher = DefaultHasher; + + fn build_hasher(&self) -> Self::Hasher { + DefaultHasher::new() + } + } + + const Y: HashMap<(), (), MyBuildDefaultHasher> = HashMap::with_hasher(MyBuildDefaultHasher); + let mut y = Y; + assert_eq!(y.len(), 0); + y.insert((), ()); + assert_eq!(y.len(), 1); } diff --git a/library/std/src/f128/tests.rs b/library/std/src/f128/tests.rs index 7051c051bf7..cbcf9f96239 100644 --- a/library/std/src/f128/tests.rs +++ b/library/std/src/f128/tests.rs @@ -2,7 +2,10 @@ #![cfg(reliable_f128)] use crate::f128::consts; -use crate::num::{FpCategory as Fp, *}; +use crate::num::FpCategory as Fp; +#[cfg(reliable_f128_math)] +use crate::ops::Rem; +use crate::ops::{Add, Div, Mul, Sub}; // Note these tolerances make sense around zero, but not for more extreme exponents. @@ -53,7 +56,22 @@ macro_rules! assert_f128_biteq { #[test] fn test_num_f128() { - test_num(10f128, 2f128); + // FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128` + // function is available on all platforms. + let ten = 10f128; + let two = 2f128; + assert_eq!(ten.add(two), ten + two); + assert_eq!(ten.sub(two), ten - two); + assert_eq!(ten.mul(two), ten * two); + assert_eq!(ten.div(two), ten / two); +} + +#[test] +#[cfg(reliable_f128_math)] +fn test_num_f128_rem() { + let ten = 10f128; + let two = 2f128; + assert_eq!(ten.rem(two), ten % two); } #[test] diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 2243f100643..b19d482feaa 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1225,6 +1225,15 @@ impl From<&OsStr> for Box<OsStr> { } } +#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut OsStr> for Box<OsStr> { + /// Copies the string into a newly allocated <code>[Box]<[OsStr]></code>. + #[inline] + fn from(s: &mut OsStr) -> Box<OsStr> { + Self::from(&*s) + } +} + #[stable(feature = "box_from_cow", since = "1.45.0")] impl From<Cow<'_, OsStr>> for Box<OsStr> { /// Converts a `Cow<'a, OsStr>` into a <code>[Box]<[OsStr]></code>, @@ -1296,6 +1305,15 @@ impl From<&OsStr> for Arc<OsStr> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut OsStr> for Arc<OsStr> { + /// Copies the string into a newly allocated <code>[Arc]<[OsStr]></code>. + #[inline] + fn from(s: &mut OsStr) -> Arc<OsStr> { + Arc::from(&*s) + } +} + #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<OsString> for Rc<OsStr> { /// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> by moving the [`OsString`] @@ -1317,6 +1335,15 @@ impl From<&OsStr> for Rc<OsStr> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut OsStr> for Rc<OsStr> { + /// Copies the string into a newly allocated <code>[Rc]<[OsStr]></code>. + #[inline] + fn from(s: &mut OsStr) -> Rc<OsStr> { + Rc::from(&*s) + } +} + #[stable(feature = "cow_from_osstr", since = "1.28.0")] impl<'a> From<OsString> for Cow<'a, OsStr> { /// Moves the string into a [`Cow::Owned`]. diff --git a/library/std/src/hash/random.rs b/library/std/src/hash/random.rs index 40f3a90f60c..236803b24a2 100644 --- a/library/std/src/hash/random.rs +++ b/library/std/src/hash/random.rs @@ -105,9 +105,8 @@ impl DefaultHasher { #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[inline] #[allow(deprecated)] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] - pub const fn new() -> DefaultHasher { + pub fn new() -> DefaultHasher { DefaultHasher(SipHasher13::new_with_keys(0, 0)) } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d0dd991a933..5b94f036248 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -32,14 +32,12 @@ //! //! Once you are familiar with the contents of the standard library you may //! begin to find the verbosity of the prose distracting. At this stage in your -//! development you may want to press the <code> -//! <svg style="width:0.75rem;height:0.75rem" viewBox="0 0 12 12" -//! stroke="currentColor" fill="none"> -//! <path d="M2,2l4,4l4,-4M2,6l4,4l4,-4"/></svg> Summary</code> button near the -//! top of the page to collapse it into a more skimmable view. +//! development you may want to press the +//! "<svg style="width:0.75rem;height:0.75rem" viewBox="0 0 12 12" stroke="currentColor" fill="none"><path d="M2,2l4,4l4,-4M2,6l4,4l4,-4"/></svg> Summary" +//! button near the top of the page to collapse it into a more skimmable view. //! //! While you are looking at the top of the page, also notice the -//! <code>source</code> link. Rust's API documentation comes with the source +//! "Source" link. Rust's API documentation comes with the source //! code and you are encouraged to read it. The standard library source is //! generally high quality and a peek behind the curtains is //! often enlightening. @@ -328,6 +326,7 @@ // Library features (core): // tidy-alphabetical-start #![feature(array_chunks)] +#![feature(build_hasher_default_const_new)] #![feature(c_str_module)] #![feature(char_internals)] #![feature(clone_to_uninit)] @@ -415,7 +414,6 @@ // Only for const-ness: // tidy-alphabetical-start #![feature(const_collections_with_hasher)] -#![feature(const_hash)] #![feature(thread_local_internals)] // tidy-alphabetical-end // diff --git a/library/std/src/os/darwin/fs.rs b/library/std/src/os/darwin/fs.rs index 2d154b214b5..5740c86e621 100644 --- a/library/std/src/os/darwin/fs.rs +++ b/library/std/src/os/darwin/fs.rs @@ -1,7 +1,8 @@ -#![allow(dead_code)] +//! Darwin-specific extension traits to [`fs`]. +//! +//! [`fs`]: crate::fs +#![stable(feature = "metadata_ext", since = "1.1.0")] -#[allow(deprecated)] -use super::raw; use crate::fs::{self, Metadata}; use crate::sealed::Sealed; use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; @@ -25,7 +26,10 @@ pub trait MetadataExt { methods of this trait" )] #[allow(deprecated)] - fn as_raw_stat(&self) -> &raw::stat; + // Only available on macOS and iOS, since they were stably exposed there. + #[cfg(any(doc, target_os = "macos", target_os = "ios"))] + #[doc(cfg(any(target_os = "macos", target_os = "ios")))] + fn as_raw_stat(&self) -> &super::raw::stat; #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_dev(&self) -> u64; @@ -77,8 +81,9 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for Metadata { #[allow(deprecated)] - fn as_raw_stat(&self) -> &raw::stat { - unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) } + #[cfg(any(doc, target_os = "macos", target_os = "ios"))] + fn as_raw_stat(&self) -> &super::raw::stat { + unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const super::raw::stat) } } fn st_dev(&self) -> u64 { self.as_inner().as_inner().st_dev as u64 diff --git a/library/std/src/os/darwin/mod.rs b/library/std/src/os/darwin/mod.rs index 03401fe8895..7a057ddb861 100644 --- a/library/std/src/os/darwin/mod.rs +++ b/library/std/src/os/darwin/mod.rs @@ -13,7 +13,10 @@ //! `aarch64-apple-darwin` target names, which are mostly named that way for //! legacy reasons. -pub(crate) mod fs; +#![stable(feature = "os_darwin", since = "CURRENT_RUSTC_VERSION")] +#![doc(cfg(target_vendor = "apple"))] + +pub mod fs; // deprecated, but used for public reexport under `std::os::unix::raw`, as // well as `std::os::macos`/`std::os::ios`, because those modules precede the // decision to remove these. diff --git a/library/std/src/os/ios/mod.rs b/library/std/src/os/ios/mod.rs index 52d592ed95a..bd18fc2fa0c 100644 --- a/library/std/src/os/ios/mod.rs +++ b/library/std/src/os/ios/mod.rs @@ -4,10 +4,8 @@ #[stable(feature = "metadata_ext", since = "1.1.0")] pub mod fs { - #[doc(inline)] #[stable(feature = "file_set_times", since = "1.75.0")] pub use crate::os::darwin::fs::FileTimesExt; - #[doc(inline)] #[stable(feature = "metadata_ext", since = "1.1.0")] pub use crate::os::darwin::fs::MetadataExt; } diff --git a/library/std/src/os/macos/mod.rs b/library/std/src/os/macos/mod.rs index 59fe90834c2..0681c9b7148 100644 --- a/library/std/src/os/macos/mod.rs +++ b/library/std/src/os/macos/mod.rs @@ -4,10 +4,8 @@ #[stable(feature = "metadata_ext", since = "1.1.0")] pub mod fs { - #[doc(inline)] #[stable(feature = "file_set_times", since = "1.75.0")] pub use crate::os::darwin::fs::FileTimesExt; - #[doc(inline)] #[stable(feature = "metadata_ext", since = "1.1.0")] pub use crate::os::darwin::fs::MetadataExt; } diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 6701173d1e0..e28a1c3e6d5 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -15,7 +15,16 @@ pub mod raw; // documented don't compile (missing things in `libc` which is empty), // so just omit them with an empty module and add the "unstable" attribute. -// unix, linux, wasi and windows are handled a bit differently. +// darwin, unix, linux, wasi and windows are handled a bit differently. +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod darwin {} #[cfg(all( doc, any( @@ -53,6 +62,17 @@ pub mod wasi {} #[unstable(issue = "none", feature = "std_internals")] pub mod windows {} +// darwin +#[cfg(not(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +)))] +#[cfg(any(target_vendor = "apple", doc))] +pub mod darwin; + // unix #[cfg(not(all( doc, @@ -105,8 +125,6 @@ pub mod windows; pub mod aix; #[cfg(target_os = "android")] pub mod android; -#[cfg(target_vendor = "apple")] -pub(crate) mod darwin; #[cfg(target_os = "dragonfly")] pub mod dragonfly; #[cfg(target_os = "emscripten")] diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 5c2ec8ef994..2f9dffe8c65 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -42,7 +42,7 @@ mod platform { #[cfg(target_os = "android")] pub use crate::os::android::*; #[cfg(target_vendor = "apple")] - pub(super) use crate::os::darwin::*; + pub use crate::os::darwin::*; #[cfg(target_os = "dragonfly")] pub use crate::os::dragonfly::*; #[cfg(target_os = "emscripten")] diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index ef5adaf2290..7c3fa7d6507 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -143,7 +143,7 @@ pub trait CommandExt: Sealed { /// /// This function, unlike `spawn`, will **not** `fork` the process to create /// a new child. Like spawn, however, the default behavior for the stdio - /// descriptors will be to inherited from the current process. + /// descriptors will be to inherit them from the current process. /// /// # Notes /// diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 62125f885b2..5662a44d832 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1762,6 +1762,16 @@ impl From<&Path> for Box<Path> { } } +#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut Path> for Box<Path> { + /// Creates a boxed [`Path`] from a reference. + /// + /// This will allocate and clone `path` to it. + fn from(path: &mut Path) -> Box<Path> { + Self::from(&*path) + } +} + #[stable(feature = "box_from_cow", since = "1.45.0")] impl From<Cow<'_, Path>> for Box<Path> { /// Creates a boxed [`Path`] from a clone-on-write pointer. @@ -1990,6 +2000,15 @@ impl From<&Path> for Arc<Path> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut Path> for Arc<Path> { + /// Converts a [`Path`] into an [`Arc`] by copying the [`Path`] data into a new [`Arc`] buffer. + #[inline] + fn from(s: &mut Path) -> Arc<Path> { + Arc::from(&*s) + } +} + #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<PathBuf> for Rc<Path> { /// Converts a [`PathBuf`] into an <code>[Rc]<[Path]></code> by moving the [`PathBuf`] data into @@ -2011,6 +2030,15 @@ impl From<&Path> for Rc<Path> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut Path> for Rc<Path> { + /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer. + #[inline] + fn from(s: &mut Path) -> Rc<Path> { + Rc::from(&*s) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for Path { type Owned = PathBuf; diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index b05615035d7..40510f56134 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -226,7 +226,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { } impl<T, F> LazyLock<T, F> { - /// Returns a reference to the value if initialized, or `None` if not. + /// Returns a mutable reference to the value if initialized, or `None` if not. /// /// # Examples /// @@ -255,7 +255,7 @@ impl<T, F> LazyLock<T, F> { } } - /// Returns a mutable reference to the value if initialized, or `None` if not. + /// Returns a reference to the value if initialized, or `None` if not. /// /// # Examples /// diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index 88a8c75f7c8..523e6d2f3bb 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -63,14 +63,14 @@ struct Block<T> { impl<T> Block<T> { /// Creates an empty block. - fn new() -> Block<T> { + fn new() -> Box<Block<T>> { // SAFETY: This is safe because: // [1] `Block::next` (AtomicPtr) may be safely zero initialized. // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. // [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it // holds a MaybeUninit. // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. - unsafe { MaybeUninit::zeroed().assume_init() } + unsafe { Box::new_zeroed().assume_init() } } /// Waits until the next pointer is set. @@ -199,13 +199,13 @@ impl<T> Channel<T> { // If we're going to have to install the next block, allocate it in advance in order to // make the wait for other threads as short as possible. if offset + 1 == BLOCK_CAP && next_block.is_none() { - next_block = Some(Box::new(Block::<T>::new())); + next_block = Some(Block::<T>::new()); } // If this is the first message to be sent into the channel, we need to allocate the // first block and install it. if block.is_null() { - let new = Box::into_raw(Box::new(Block::<T>::new())); + let new = Box::into_raw(Block::<T>::new()); if self .tail diff --git a/library/std/src/sys/alloc/windows.rs b/library/std/src/sys/alloc/windows.rs index a77dda6e817..7e2402afab9 100644 --- a/library/std/src/sys/alloc/windows.rs +++ b/library/std/src/sys/alloc/windows.rs @@ -3,7 +3,6 @@ use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ffi::c_void; use crate::mem::MaybeUninit; use crate::ptr; -use crate::sync::atomic::{AtomicPtr, Ordering}; use crate::sys::c; #[cfg(test)] @@ -81,40 +80,18 @@ windows_targets::link!("kernel32.dll" "system" fn HeapReAlloc( // See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-heapfree windows_targets::link!("kernel32.dll" "system" fn HeapFree(hheap: c::HANDLE, dwflags: u32, lpmem: *const c_void) -> c::BOOL); -// Cached handle to the default heap of the current process. -// Either a non-null handle returned by `GetProcessHeap`, or null when not yet initialized or `GetProcessHeap` failed. -static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut()); - -// Get a handle to the default heap of the current process, or null if the operation fails. -// If this operation is successful, `HEAP` will be successfully initialized and contain -// a non-null handle returned by `GetProcessHeap`. -#[inline] -fn init_or_get_process_heap() -> c::HANDLE { - // `HEAP` has not yet been successfully initialized - let heap = unsafe { GetProcessHeap() }; - if !heap.is_null() { - // SAFETY: No locking is needed because within the same process, - // successful calls to `GetProcessHeap` will always return the same value, even on different threads. - HEAP.store(heap, Ordering::Release); - - // SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap` - heap - } else { - // Could not get the current process heap. - ptr::null_mut() - } +fn get_process_heap() -> *mut c_void { + // SAFETY: GetProcessHeap simply returns a valid handle or NULL so is always safe to call. + unsafe { GetProcessHeap() } } -/// This is outlined from `process_heap_alloc` so that `process_heap_alloc` -/// does not need any stack allocations. #[inline(never)] -#[cold] -extern "C" fn process_heap_init_and_alloc( - _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc` +fn process_heap_alloc( + _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`, flags: u32, bytes: usize, ) -> *mut c_void { - let heap = init_or_get_process_heap(); + let heap = get_process_heap(); if core::intrinsics::unlikely(heap.is_null()) { return ptr::null_mut(); } @@ -122,28 +99,6 @@ extern "C" fn process_heap_init_and_alloc( unsafe { HeapAlloc(heap, flags, bytes) } } -#[inline(never)] -fn process_heap_alloc( - _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`, - flags: u32, - bytes: usize, -) -> *mut c_void { - let heap = HEAP.load(Ordering::Relaxed); - if core::intrinsics::likely(!heap.is_null()) { - // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`. - unsafe { HeapAlloc(heap, flags, bytes) } - } else { - process_heap_init_and_alloc(MaybeUninit::uninit(), flags, bytes) - } -} - -// Get a non-null handle to the default heap of the current process. -// SAFETY: `HEAP` must have been successfully initialized. -#[inline] -unsafe fn get_process_heap() -> c::HANDLE { - HEAP.load(Ordering::Acquire) -} - // Header containing a pointer to the start of an allocated block. // SAFETY: Size and alignment must be <= `MIN_ALIGN`. #[repr(C)] @@ -232,9 +187,9 @@ unsafe impl GlobalAlloc for System { } }; - // SAFETY: because `ptr` has been successfully allocated with this allocator, - // `HEAP` must have been successfully initialized. - let heap = unsafe { get_process_heap() }; + // because `ptr` has been successfully allocated with this allocator, + // there must be a valid process heap. + let heap = get_process_heap(); // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, // `block` is a pointer to the start of an allocated block. @@ -244,9 +199,9 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { if layout.align() <= MIN_ALIGN { - // SAFETY: because `ptr` has been successfully allocated with this allocator, - // `HEAP` must have been successfully initialized. - let heap = unsafe { get_process_heap() }; + // because `ptr` has been successfully allocated with this allocator, + // there must be a valid process heap. + let heap = get_process_heap(); // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, // `ptr` is a pointer to the start of an allocated block. diff --git a/rustfmt.toml b/rustfmt.toml index 4d48236a393..16a0d67ab52 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -26,8 +26,6 @@ ignore = [ "/tests/ui-fulldeps/", # Some are whitespace-sensitive (e.g. `// ~ERROR` comments). # Do not format submodules. - # FIXME: sync submodule list with tidy/bootstrap/etc - # tidy/src/walk.rs:filter_dirs "library/backtrace", "library/portable-simd", "library/stdarch", @@ -41,6 +39,7 @@ ignore = [ "src/llvm-project", "src/tools/cargo", "src/tools/clippy", + "src/tools/enzyme", "src/tools/miri", "src/tools/rust-analyzer", "src/tools/rustc-perf", diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 2e173c9e6df..70f4e70962a 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -3,6 +3,7 @@ # ignore-tidy-linelength from __future__ import absolute_import, division, print_function +import shlex import sys import os rust_dir = os.path.dirname(os.path.abspath(__file__)) @@ -288,8 +289,9 @@ def build(known_args): def set(key, value, config): if isinstance(value, list): - # Remove empty values, which value.split(',') tends to generate. - value = [v for v in value if v] + # Remove empty values, which value.split(',') tends to generate and + # replace single quotes for double quotes to ensure correct parsing. + value = [v.replace('\'', '"') for v in value if v] s = "{:20} := {}".format(key, value) if len(s) < 70 or VERBOSE: @@ -298,7 +300,13 @@ def set(key, value, config): p(s[:70] + " ...") arr = config - parts = key.split('.') + + # Split `key` on periods using shell semantics. + lexer = shlex.shlex(key, posix=True) + lexer.whitespace = "." + lexer.wordchars += "-" + parts = list(lexer) + for i, part in enumerate(parts): if i == len(parts) - 1: if is_value_list(part) and isinstance(value, str): diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index e9ec79e417b..409a644b9be 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -33,7 +33,7 @@ fn main() { // Display PID of process holding the lock // PID will be stored in a lock file let lock_path = config.out.join("lock"); - let pid = fs::read_to_string(&lock_path).unwrap_or_default(); + let pid = fs::read_to_string(&lock_path); build_lock = fd_lock::RwLock::new(t!(fs::OpenOptions::new() .write(true) @@ -47,7 +47,11 @@ fn main() { } err => { drop(err); - println!("WARNING: build directory locked by process {pid}, waiting for lock"); + if let Ok(pid) = pid { + println!("WARNING: build directory locked by process {pid}, waiting for lock"); + } else { + println!("WARNING: build directory locked, waiting for lock"); + } let mut lock = t!(build_lock.write()); t!(lock.write(process::id().to_string().as_ref())); lock diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index f419bebdc12..d46c0ab7fef 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -91,8 +91,8 @@ impl Step for Std { // We skip populating the sysroot in non-zero stage because that'll lead // to rlib/rmeta conflicts if std gets built during this session. if compiler.stage == 0 { - let libdir = builder.sysroot_libdir(compiler, target); - let hostdir = builder.sysroot_libdir(compiler, compiler.host); + let libdir = builder.sysroot_target_libdir(compiler, target); + let hostdir = builder.sysroot_target_libdir(compiler, compiler.host); add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); } drop(_guard); @@ -257,8 +257,8 @@ impl Step for Rustc { false, ); - let libdir = builder.sysroot_libdir(compiler, target); - let hostdir = builder.sysroot_libdir(compiler, compiler.host); + let libdir = builder.sysroot_target_libdir(compiler, target); + let hostdir = builder.sysroot_target_libdir(compiler, compiler.host); add_to_sysroot(builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target)); } } diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 4ab4e60773f..3394f2a84a0 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -219,8 +219,7 @@ impl Step for Std { .join(compiler.host) .join("bin"); if src_sysroot_bin.exists() { - let target_sysroot_bin = - builder.sysroot_libdir(compiler, target).parent().unwrap().join("bin"); + let target_sysroot_bin = builder.sysroot_target_bindir(compiler, target); t!(fs::create_dir_all(&target_sysroot_bin)); builder.cp_link_r(&src_sysroot_bin, &target_sysroot_bin); } @@ -334,7 +333,7 @@ fn copy_third_party_objects( && (target.contains("linux") || target.contains("fuchsia")) { let libunwind_path = - copy_llvm_libunwind(builder, target, &builder.sysroot_libdir(*compiler, target)); + copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target)); target_deps.push((libunwind_path, DependencyType::Target)); } @@ -347,7 +346,8 @@ fn copy_self_contained_objects( compiler: &Compiler, target: TargetSelection, ) -> Vec<(PathBuf, DependencyType)> { - let libdir_self_contained = builder.sysroot_libdir(*compiler, target).join("self-contained"); + let libdir_self_contained = + builder.sysroot_target_libdir(*compiler, target).join("self-contained"); t!(fs::create_dir_all(&libdir_self_contained)); let mut target_deps = vec![]; @@ -655,8 +655,8 @@ impl Step for StdLink { let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib"); (libdir, hostdir) } else { - let libdir = builder.sysroot_libdir(target_compiler, target); - let hostdir = builder.sysroot_libdir(target_compiler, compiler.host); + let libdir = builder.sysroot_target_libdir(target_compiler, target); + let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host); (libdir, hostdir) }; @@ -723,7 +723,7 @@ fn copy_sanitizers( } let mut target_deps = Vec::new(); - let libdir = builder.sysroot_libdir(*compiler, target); + let libdir = builder.sysroot_target_libdir(*compiler, target); for runtime in &runtimes { let dst = libdir.join(&runtime.name); @@ -801,7 +801,7 @@ impl Step for StartupObjects { let src_dir = &builder.src.join("library").join("rtstartup"); let dst_dir = &builder.native_dir(target).join("rtstartup"); - let sysroot_dir = &builder.sysroot_libdir(for_compiler, target); + let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target); t!(fs::create_dir_all(dst_dir)); for file in &["rsbegin", "rsend"] { @@ -1287,10 +1287,17 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect } } +/// `RustcLink` copies all of the rlibs from the rustc build into the previous stage's sysroot. +/// This is necessary for tools using `rustc_private`, where the previous compiler will build +/// a tool against the next compiler. +/// To build a tool against a compiler, the rlibs of that compiler that it links against +/// must be in the sysroot of the compiler that's doing the compiling. #[derive(Debug, Clone, PartialEq, Eq, Hash)] struct RustcLink { + /// The compiler whose rlibs we are copying around. pub compiler: Compiler, - pub target_compiler: Compiler, + /// This is the compiler into whose sysroot we want to copy the rlibs into. + pub previous_stage_compiler: Compiler, pub target: TargetSelection, /// Not actually used; only present to make sure the cache invalidation is correct. crates: Vec<String>, @@ -1300,7 +1307,7 @@ impl RustcLink { fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self { Self { compiler: host_compiler, - target_compiler: rustc.compiler, + previous_stage_compiler: rustc.compiler, target: rustc.target, crates: rustc.crates, } @@ -1317,12 +1324,12 @@ impl Step for RustcLink { /// Same as `std_link`, only for librustc fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; - let target_compiler = self.target_compiler; + let previous_stage_compiler = self.previous_stage_compiler; let target = self.target; add_to_sysroot( builder, - &builder.sysroot_libdir(target_compiler, target), - &builder.sysroot_libdir(target_compiler, compiler.host), + &builder.sysroot_target_libdir(previous_stage_compiler, target), + &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host), &librustc_stamp(builder, compiler, target), ); } @@ -1770,7 +1777,7 @@ impl Step for Assemble { // We prepend this bin directory to the user PATH when linking Rust binaries. To // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`. - let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); + let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host); let libdir_bin = libdir.parent().unwrap().join("bin"); t!(fs::create_dir_all(&libdir_bin)); @@ -1854,8 +1861,9 @@ impl Step for Assemble { if let Some(enzyme_install) = enzyme_install { let lib_ext = std::env::consts::DLL_EXTENSION; let src_lib = enzyme_install.join("build/Enzyme/libEnzyme-19").with_extension(lib_ext); - let libdir = builder.sysroot_libdir(build_compiler, build_compiler.host); - let target_libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); + let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host); + let target_libdir = + builder.sysroot_target_libdir(target_compiler, target_compiler.host); let dst_lib = libdir.join("libEnzyme-19").with_extension(lib_ext); let target_dst_lib = target_libdir.join("libEnzyme-19").with_extension(lib_ext); builder.copy_link(&src_lib, &dst_lib); @@ -1923,7 +1931,7 @@ impl Step for Assemble { let sysroot = builder.sysroot(target_compiler); let rustc_libdir = builder.rustc_libdir(target_compiler); t!(fs::create_dir_all(&rustc_libdir)); - let src_libdir = builder.sysroot_libdir(build_compiler, host); + let src_libdir = builder.sysroot_target_libdir(build_compiler, host); for f in builder.read_dir(&src_libdir) { let filename = f.file_name().into_string().unwrap(); @@ -1968,6 +1976,14 @@ impl Step for Assemble { } } + { + // `llvm-strip` is used by rustc, which is actually just a symlink to `llvm-objcopy`, + // so copy and rename `llvm-objcopy`. + let src_exe = exe("llvm-objcopy", target_compiler.host); + let dst_exe = exe("rust-objcopy", target_compiler.host); + builder.copy_link(&libdir_bin.join(src_exe), &libdir_bin.join(dst_exe)); + } + // In addition to `rust-lld` also install `wasm-component-ld` when // LLD is enabled. This is a relatively small binary that primarily // delegates to the `rust-lld` binary for linking and then runs diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 80ba9f44448..c022285211f 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -459,7 +459,7 @@ impl Step for Rustc { // Copy over lld if it's there if builder.config.lld_enabled { - let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin"); + let src_dir = builder.sysroot_target_bindir(compiler, host); let rust_lld = exe("rust-lld", compiler.host); builder.copy_link(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld)); let self_contained_lld_src_dir = src_dir.join("gcc-ld"); @@ -473,8 +473,16 @@ impl Step for Rustc { ); } } + + { + let src_dir = builder.sysroot_target_bindir(compiler, host); + let llvm_objcopy = exe("llvm-objcopy", compiler.host); + let rust_objcopy = exe("rust-objcopy", compiler.host); + builder.copy_link(&src_dir.join(&llvm_objcopy), &dst_dir.join(&rust_objcopy)); + } + if builder.tool_enabled("wasm-component-ld") { - let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin"); + let src_dir = builder.sysroot_target_bindir(compiler, host); let ld = exe("wasm-component-ld", compiler.host); builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld)); } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 0a290a697e6..2c36d8bab82 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -800,7 +800,7 @@ impl Step for RustdocTheme { .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap()) .env("RUSTC_STAGE", self.compiler.stage.to_string()) .env("RUSTC_SYSROOT", builder.sysroot(self.compiler)) - .env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host)) + .env("RUSTDOC_LIBDIR", builder.sysroot_target_libdir(self.compiler, self.compiler.host)) .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("RUSTDOC_REAL", builder.rustdoc(self.compiler)) .env("RUSTC_BOOTSTRAP", "1"); @@ -1722,7 +1722,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // of them! cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler)); - cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target)); + cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(compiler, target)); cmd.arg("--rustc-path").arg(builder.rustc(compiler)); // Minicore auxiliary lib for `no_core` tests that need `core` stubs in cross-compilation @@ -1938,9 +1938,13 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--json"); - if builder.config.rust_debug_assertions_std { - cmd.arg("--with-debug-assertions"); - }; + if builder.config.rustc_debug_assertions { + cmd.arg("--with-rustc-debug-assertions"); + } + + if builder.config.std_debug_assertions { + cmd.arg("--with-std-debug-assertions"); + } let mut llvm_components_passed = false; let mut copts_passed = false; @@ -2583,7 +2587,7 @@ fn prepare_cargo_test( // by `Cargo::new` and that actually makes things go wrong. if builder.kind != Kind::Miri { let mut dylib_path = dylib_path(); - dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target))); + dylib_path.insert(0, PathBuf::from(&*builder.sysroot_target_libdir(compiler, target))); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); } @@ -2818,7 +2822,7 @@ impl Step for CrateRustdoc { let libdir = if builder.download_rustc() { builder.rustc_libdir(compiler) } else { - builder.sysroot_libdir(compiler, target).to_path_buf() + builder.sysroot_target_libdir(compiler, target).to_path_buf() }; let mut dylib_path = dylib_path(); dylib_path.insert(0, PathBuf::from(&*libdir)); @@ -2943,7 +2947,7 @@ impl Step for RemoteCopyLibs { cmd.run(builder); // Push all our dylibs to the emulator - for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) { + for f in t!(builder.sysroot_target_libdir(compiler, target).read_dir()) { let f = t!(f); let name = f.file_name().into_string().unwrap(); if helpers::is_dylib(&name) { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index bb837eb8137..3cfbef27f87 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -466,7 +466,7 @@ impl ErrorIndex { let compiler = builder.compiler_for(builder.top_stage, host, host); let mut cmd = command(builder.ensure(ErrorIndex { compiler })); let mut dylib_paths = builder.rustc_lib_paths(compiler); - dylib_paths.push(PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))); + dylib_paths.push(PathBuf::from(&builder.sysroot_target_libdir(compiler, compiler.host))); add_dylib_path(dylib_paths, &mut cmd); cmd } diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index c3d0994f164..134da5db96d 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -833,9 +833,9 @@ impl Builder<'_> { cargo.env( profile_var("DEBUG_ASSERTIONS"), if mode == Mode::Std { - self.config.rust_debug_assertions_std.to_string() + self.config.std_debug_assertions.to_string() } else { - self.config.rust_debug_assertions.to_string() + self.config.rustc_debug_assertions.to_string() }, ); cargo.env( diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 8f8ab112857..f1b3cf6da13 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1161,9 +1161,14 @@ impl<'a> Builder<'a> { self.ensure(compile::Sysroot::new(compiler)) } + /// Returns the bindir for a compiler's sysroot. + pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { + self.sysroot_target_libdir(compiler, target).parent().unwrap().join("bin") + } + /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. - pub fn sysroot_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { + pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { #[derive(Debug, Clone, Hash, PartialEq, Eq)] struct Libdir { compiler: Compiler, @@ -1211,7 +1216,7 @@ impl<'a> Builder<'a> { } pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf { - self.sysroot_libdir(compiler, compiler.host).with_file_name("codegen-backends") + self.sysroot_target_libdir(compiler, compiler.host).with_file_name("codegen-backends") } /// Returns the compiler's libdir where it stores the dynamic libraries that diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 8115aea033d..f977c285a74 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -263,8 +263,10 @@ pub struct Config { pub rust_optimize: RustOptimize, pub rust_codegen_units: Option<u32>, pub rust_codegen_units_std: Option<u32>, - pub rust_debug_assertions: bool, - pub rust_debug_assertions_std: bool, + + pub rustc_debug_assertions: bool, + pub std_debug_assertions: bool, + pub rust_overflow_checks: bool, pub rust_overflow_checks_std: bool, pub rust_debug_logging: bool, @@ -1115,9 +1117,9 @@ define_config! { debug: Option<bool> = "debug", codegen_units: Option<u32> = "codegen-units", codegen_units_std: Option<u32> = "codegen-units-std", - debug_assertions: Option<bool> = "debug-assertions", + rustc_debug_assertions: Option<bool> = "debug-assertions", randomize_layout: Option<bool> = "randomize-layout", - debug_assertions_std: Option<bool> = "debug-assertions-std", + std_debug_assertions: Option<bool> = "debug-assertions-std", overflow_checks: Option<bool> = "overflow-checks", overflow_checks_std: Option<bool> = "overflow-checks-std", debug_logging: Option<bool> = "debug-logging", @@ -1652,8 +1654,8 @@ impl Config { let mut llvm_offload = None; let mut llvm_plugins = None; let mut debug = None; - let mut debug_assertions = None; - let mut debug_assertions_std = None; + let mut rustc_debug_assertions = None; + let mut std_debug_assertions = None; let mut overflow_checks = None; let mut overflow_checks_std = None; let mut debug_logging = None; @@ -1675,8 +1677,8 @@ impl Config { debug: debug_toml, codegen_units, codegen_units_std, - debug_assertions: debug_assertions_toml, - debug_assertions_std: debug_assertions_std_toml, + rustc_debug_assertions: rustc_debug_assertions_toml, + std_debug_assertions: std_debug_assertions_toml, overflow_checks: overflow_checks_toml, overflow_checks_std: overflow_checks_std_toml, debug_logging: debug_logging_toml, @@ -1734,8 +1736,8 @@ impl Config { config.download_ci_rustc_commit(download_rustc, config.llvm_assertions); debug = debug_toml; - debug_assertions = debug_assertions_toml; - debug_assertions_std = debug_assertions_std_toml; + rustc_debug_assertions = rustc_debug_assertions_toml; + std_debug_assertions = std_debug_assertions_toml; overflow_checks = overflow_checks_toml; overflow_checks_std = overflow_checks_std_toml; debug_logging = debug_logging_toml; @@ -2148,14 +2150,13 @@ impl Config { config.rust_std_features = std_features.unwrap_or(default_std_features); let default = debug == Some(true); - config.rust_debug_assertions = debug_assertions.unwrap_or(default); - config.rust_debug_assertions_std = - debug_assertions_std.unwrap_or(config.rust_debug_assertions); + config.rustc_debug_assertions = rustc_debug_assertions.unwrap_or(default); + config.std_debug_assertions = std_debug_assertions.unwrap_or(config.rustc_debug_assertions); config.rust_overflow_checks = overflow_checks.unwrap_or(default); config.rust_overflow_checks_std = overflow_checks_std.unwrap_or(config.rust_overflow_checks); - config.rust_debug_logging = debug_logging.unwrap_or(config.rust_debug_assertions); + config.rust_debug_logging = debug_logging.unwrap_or(config.rustc_debug_assertions); let with_defaults = |debuginfo_level_specific: Option<_>| { debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) { @@ -3075,8 +3076,8 @@ fn check_incompatible_options_for_ci_rustc( debug: _, codegen_units: _, codegen_units_std: _, - debug_assertions: _, - debug_assertions_std: _, + rustc_debug_assertions: _, + std_debug_assertions: _, overflow_checks: _, overflow_checks_std: _, debuginfo_level: _, diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index ece5f174d06..c40de76abbf 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -114,7 +114,6 @@ ENV CARGO_TARGET_AARCH64_UNKNOWN_FUCHSIA_RUSTFLAGS \ ENV TARGETS=x86_64-unknown-fuchsia ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV TARGETS=$TARGETS,wasm32-unknown-unknown -ENV TARGETS=$TARGETS,wasm32-wasi ENV TARGETS=$TARGETS,wasm32-wasip1 ENV TARGETS=$TARGETS,wasm32-wasip1-threads ENV TARGETS=$TARGETS,wasm32-wasip2 diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index c0ce358486b..340dfd67b7d 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -6,6 +6,8 @@ runners: - &job-linux-4c os: ubuntu-20.04 + # Free some disk space to avoid running out of space during the build. + free_disk: true <<: *base-job # Large runner used mainly for its bigger disk capacity @@ -135,7 +137,7 @@ auto: - image: dist-aarch64-linux env: CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - image: dist-android <<: *job-linux-4c @@ -156,28 +158,28 @@ auto: <<: *job-linux-4c - image: dist-loongarch64-linux - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - image: dist-loongarch64-musl - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - image: dist-ohos <<: *job-linux-4c - image: dist-powerpc-linux - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - image: dist-powerpc64-linux - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - image: dist-powerpc64le-linux - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - image: dist-riscv64-linux <<: *job-linux-4c - image: dist-s390x-linux - <<: *job-linux-4c-largedisk + <<: *job-linux-4c - image: dist-various-1 <<: *job-linux-4c diff --git a/src/doc/edition-guide b/src/doc/edition-guide -Subproject 1f07c242f8162a711a5ac5a4ea8fa7ec884ee7a +Subproject 2d482e203eb6d6e353814cf1415c5f94e590b9e diff --git a/src/doc/reference b/src/doc/reference -Subproject 23ce619966541bf2c80d45fdfeecf3393e360a1 +Subproject da0f6dad767670da0e8cd5af8a7090db3272f62 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 8bede1b919a81ab7d0c961f6bbf68d3efa297bd +Subproject 9db78608b17d5f4a6c033b8a3038466b87d6320 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 59d94ea75a0b157e148af14c73c2dd60efb7b60 +Subproject 6a5accdaf10255882b1e6c59dfe5f1c79ac9548 diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 04bb40d750c..500eaafb63f 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -192,8 +192,8 @@ target | std | notes [`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat [`wasm32-unknown-emscripten`](platform-support/wasm32-unknown-emscripten.md) | ✓ | WebAssembly via Emscripten [`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly -`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename]) -[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI +[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASIp1 +[`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ | WebAssembly with WASIp2 [`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads [`wasm32v1-none`](platform-support/wasm32v1-none.md) | * | WebAssembly limited to 1.0 features and no imports [`x86_64-apple-ios`](platform-support/apple-ios.md) | ✓ | 64-bit x86 iOS @@ -377,7 +377,6 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ✓ | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.3 -[`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ | | WebAssembly [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index 0e4def6768d..e5e8d554ecf 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -98,10 +98,6 @@ the target with: rustup target add wasm32-wasip1 ``` -> **Note**: the `wasm32-wasip1` target is new and may only be available -> on nightly by the time you're reading this. If `wasm32-wasip1` isn't -> available on stable Rust then `wasm32-wasi` should be available instead. - Rust programs can be built for that target: ```text diff --git a/src/doc/unstable-book/src/compiler-flags/branch-protection.md b/src/doc/unstable-book/src/compiler-flags/branch-protection.md index 9276220f447..f0cc44a07f3 100644 --- a/src/doc/unstable-book/src/compiler-flags/branch-protection.md +++ b/src/doc/unstable-book/src/compiler-flags/branch-protection.md @@ -9,11 +9,12 @@ This option is only accepted when targeting AArch64 architectures. It takes some combination of the following values, separated by a `,`. - `pac-ret` - Enable pointer authentication for non-leaf functions. +- `pc` - Use PC as a diversifier using PAuthLR instructions - `leaf` - Enable pointer authentication for all functions, including leaf functions. - `b-key` - Sign return addresses with key B, instead of the default key A. - `bti` - Enable branch target identification. -`leaf` and `b-key` are only valid if `pac-ret` was previously specified. +`leaf`, `b-key` and `pc` are only valid if `pac-ret` was previously specified. For example, `-Z branch-protection=bti,pac-ret,leaf` is valid, but `-Z branch-protection=bti,leaf,pac-ret` is not. diff --git a/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md b/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md index 138a98dbe3d..4dd8d9707d4 100644 --- a/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md +++ b/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md @@ -3,8 +3,8 @@ This option controls whether Rust uses the spec-compliant C ABI when compiling for the `wasm32-unknown-unknown` target. -This makes it possible to be ABI-compatible with all other spec-compliant Wasm -like Rusts `wasm32-wasi`. +This makes it possible to be ABI-compatible with all other spec-compliant Wasm targets +like `wasm32-wasip1`. This compiler flag is perma-unstable, as it will be enabled by default in the future with no option to fall back to the old non-spec-compliant ABI. diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index b1c429c7676..3029c3989c9 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -20,6 +20,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - CSKY - s390x - Arm64EC +- SPARC ## Register classes @@ -31,9 +32,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | NVPTX | `reg32` | None\* | `r` | | NVPTX | `reg64` | None\* | `l` | | Hexagon | `reg` | `r[0-28]` | `r` | -| PowerPC | `reg` | `r[0-31]` | `r` | -| PowerPC | `reg_nonzero` | `r[1-31]` | `b` | +| PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` | +| PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` | | PowerPC | `freg` | `f[0-31]` | `f` | +| PowerPC | `vreg` | `v[0-31]` | Only clobbers | | PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | | PowerPC | `xer` | `xer` | Only clobbers | | wasm32 | `local` | None\* | `r` | @@ -55,6 +57,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | s390x | `freg` | `f[0-15]` | `f` | | s390x | `vreg` | `v[0-31]` | Only clobbers | | s390x | `areg` | `a[2-15]` | Only clobbers | +| SPARC | `reg` | `r[2-29]` | `r` | +| SPARC | `yreg` | `y` | Only clobbers | | Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` | | Arm64EC | `vreg` | `v[0-15]` | `w` | | Arm64EC | `vreg_low16` | `v[0-15]` | `x` | @@ -76,9 +80,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | | NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | -| PowerPC | `reg` | None | `i8`, `i16`, `i32` | -| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` | +| PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | +| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `freg` | None | `f32`, `f64` | +| PowerPC | `vreg` | N/A | Only clobbers | | PowerPC | `cr` | N/A | Only clobbers | | PowerPC | `xer` | N/A | Only clobbers | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | @@ -95,6 +100,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | s390x | `freg` | None | `f32`, `f64` | | s390x | `vreg` | N/A | Only clobbers | | s390x | `areg` | N/A | Only clobbers | +| SPARC | `reg` | None | `i8`, `i16`, `i32`, `i64` (SPARC64 only) | +| SPARC | `yreg` | N/A | Only clobbers | | Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | Arm64EC | `vreg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | @@ -105,6 +112,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | Hexagon | `r29` | `sp` | | Hexagon | `r30` | `fr` | | Hexagon | `r31` | `lr` | +| PowerPC | `r1` | `sp` | +| PowerPC | `r31` | `fp` | +| PowerPC | `r[0-31]` | `[0-31]` | +| PowerPC | `f[0-31]` | `fr[0-31]`| | BPF | `r[0-10]` | `w[0-10]` | | AVR | `XH` | `r27` | | AVR | `XL` | `r26` | @@ -129,6 +140,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `r29` | `rtb` | | CSKY | `r30` | `svbr` | | CSKY | `r31` | `tls` | +| SPARC | `r[0-7]` | `g[0-7]` | +| SPARC | `r[8-15]` | `o[0-7]` | +| SPARC | `r[16-23]` | `l[0-7]` | +| SPARC | `r[24-31]` | `i[0-7]` | | Arm64EC | `x[0-30]` | `w[0-30]` | | Arm64EC | `x29` | `fp` | | Arm64EC | `x30` | `lr` | @@ -144,15 +159,19 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | Architecture | Unsupported register | Reason | | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. | -| All | `r19` (Hexagon), `x19` (Arm64EC) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | +| All | `sp`, `r15` (s390x), `r14`/`o6` (SPARC) | The stack pointer must be restored to its original value at the end of an asm code block. | +| All | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `r30`/`i6` (SPARC), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. | +| All | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC), `x19` (Arm64EC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames. | | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | | MIPS | `$1` or `$at` | Reserved for assembler. | | MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. | | MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. | | MIPS | `$ra` | Return address cannot be used as inputs or outputs. | | Hexagon | `lr` | This is the link register which cannot be used as an input or output. | +| PowerPC | `r2`, `r13` | These are system reserved registers. | +| PowerPC | `lr` | The link register cannot be used as an input or output. | +| PowerPC | `ctr` | The counter register cannot be used as an input or output. | +| PowerPC | `vrsave` | The vrsave register cannot be used as an input or output. | | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | |MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | | M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. | @@ -164,6 +183,11 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `r31` | This is the TLS register. | | s390x | `c[0-15]` | Reserved by the kernel. | | s390x | `a[0-1]` | Reserved for system use. | +| SPARC | `r0`/`g0` | This is always zero and cannot be used as inputs or outputs. | +| SPARC | `r1`/`g1` | Used internally by LLVM. | +| SPARC | `r5`/`g5` | Reserved for system. (SPARC32 only) | +| SPARC | `r6`/`g6`, `r7`/`g7` | Reserved for system. | +| SPARC | `r31`/`i7` | Return address cannot be used as inputs or outputs. | | Arm64EC | `xzr` | This is a constant zero register which can't be modified. | | Arm64EC | `x18` | This is an OS-reserved register. | | Arm64EC | `x13`, `x14`, `x23`, `x24`, `x28`, `v[16-31]` | These are AArch64 registers that are not supported for Arm64EC. | @@ -185,6 +209,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | s390x | `reg` | None | `%r0` | None | | s390x | `reg_addr` | None | `%r1` | None | | s390x | `freg` | None | `%f0` | None | +| SPARC | `reg` | None | `%o0` | None | | CSKY | `reg` | None | `r0` | None | | CSKY | `freg` | None | `f0` | None | | Arm64EC | `reg` | None | `x0` | `x` | @@ -209,6 +234,9 @@ These flags registers must be restored upon exiting the asm block if the `preser - The condition code register `ccr`. - s390x - The condition code register `cc`. +- SPARC + - Integer condition codes (`icc` and `xcc`) + - Floating-point condition codes (`fcc[0-3]`) - Arm64EC - Condition flags (`NZCV` register). - Floating-point status (`FPSR` register). diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md index c262d3f6da1..13a6814d31b 100644 --- a/src/doc/unstable-book/src/language-features/intrinsics.md +++ b/src/doc/unstable-book/src/language-features/intrinsics.md @@ -18,7 +18,7 @@ All intrinsic fallback bodies are automatically made cross-crate inlineable (lik by the codegen backend, but not the MIR inliner. ```rust -#![feature(rustc_attrs)] +#![feature(intrinsics)] #![allow(internal_features)] #[rustc_intrinsic] @@ -28,7 +28,7 @@ const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} Since these are just regular functions, it is perfectly ok to create the intrinsic twice: ```rust -#![feature(rustc_attrs)] +#![feature(intrinsics)] #![allow(internal_features)] #[rustc_intrinsic] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 58663fcbafe..6b6142a6eaa 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -304,7 +304,9 @@ pub(crate) fn clean_middle_region(region: ty::Region<'_>) -> Option<Lifetime> { match *region { ty::ReStatic => Some(Lifetime::statik()), _ if !region.has_name() => None, - ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => Some(Lifetime(name)), + ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) => { + Some(Lifetime(name)) + } ty::ReEarlyParam(ref data) => Some(Lifetime(data.name)), ty::ReBound(..) | ty::ReLateParam(..) @@ -369,7 +371,7 @@ pub(crate) fn clean_predicate<'tcx>( ty::ClauseKind::ConstEvaluatable(..) | ty::ClauseKind::WellFormed(..) | ty::ClauseKind::ConstArgHasType(..) - // FIXME(effects): We can probably use this `HostEffect` pred to render `~const`. + // FIXME(const_trait_impl): We can probably use this `HostEffect` pred to render `~const`. | ty::ClauseKind::HostEffect(_) => None, } } @@ -379,7 +381,7 @@ fn clean_poly_trait_predicate<'tcx>( cx: &mut DocContext<'tcx>, ) -> Option<WherePredicate> { // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. - // FIXME(effects) check constness + // FIXME(const_trait_impl) check constness if Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() { return None; } @@ -1317,8 +1319,8 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo simplify::move_bounds_to_generic_parameters(&mut generics); let provided = match assoc_item.container { - ty::ImplContainer => true, - ty::TraitContainer => tcx.defaultness(assoc_item.def_id).has_value(), + ty::AssocItemContainer::Impl => true, + ty::AssocItemContainer::Trait => tcx.defaultness(assoc_item.def_id).has_value(), }; if provided { AssocConstItem(Box::new(Constant { @@ -1335,10 +1337,10 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo if assoc_item.fn_has_self_parameter { let self_ty = match assoc_item.container { - ty::ImplContainer => { + ty::AssocItemContainer::Impl => { tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity() } - ty::TraitContainer => tcx.types.self_param, + ty::AssocItemContainer::Trait => tcx.types.self_param, }; let self_arg_ty = tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder(); @@ -1355,13 +1357,13 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } let provided = match assoc_item.container { - ty::ImplContainer => true, - ty::TraitContainer => assoc_item.defaultness(tcx).has_value(), + ty::AssocItemContainer::Impl => true, + ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(), }; if provided { let defaultness = match assoc_item.container { - ty::ImplContainer => Some(assoc_item.defaultness(tcx)), - ty::TraitContainer => None, + ty::AssocItemContainer::Impl => Some(assoc_item.defaultness(tcx)), + ty::AssocItemContainer::Trait => None, }; MethodItem(item, defaultness) } else { @@ -1392,7 +1394,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; - if let ty::TraitContainer = assoc_item.container { + if let ty::AssocItemContainer::Trait = assoc_item.container { let bounds = tcx.explicit_item_bounds(assoc_item.def_id).iter_identity_copied(); predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); } @@ -1403,7 +1405,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo }); simplify::move_bounds_to_generic_parameters(&mut generics); - if let ty::TraitContainer = assoc_item.container { + if let ty::AssocItemContainer::Trait = assoc_item.container { // Move bounds that are (likely) directly attached to the associated type // from the where-clause to the associated type. // There is no guarantee that this is what the user actually wrote but we have @@ -1896,7 +1898,9 @@ fn clean_trait_object_lifetime_bound<'tcx>( match *region { ty::ReStatic => Some(Lifetime::statik()), ty::ReEarlyParam(region) if region.name != kw::Empty => Some(Lifetime(region.name)), - ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) if name != kw::Empty => { + ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) + if name != kw::Empty => + { Some(Lifetime(name)) } ty::ReEarlyParam(_) @@ -2141,7 +2145,7 @@ pub(crate) fn clean_middle_ty<'tcx>( .iter() .flat_map(|pred| pred.bound_vars()) .filter_map(|var| match var { - ty::BoundVariableKind::Region(ty::BrNamed(def_id, name)) + ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name)) if name != kw::UnderscoreLifetime => { Some(GenericParamDef::lifetime(def_id, name)) @@ -2907,7 +2911,7 @@ fn clean_extern_crate<'tcx>( None => false, } }) - && !cx.output_format.is_json(); + && !cx.is_json_output(); let krate_owner_def_id = krate.owner_id.def_id; if please_inline { @@ -3000,7 +3004,7 @@ fn clean_use_statement_inner<'tcx>( // forcefully don't inline if this is not public or if the // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. - let mut denied = cx.output_format.is_json() + let mut denied = cx.is_json_output() || !(visibility.is_public() || (cx.render_options.document_private && is_visible_from_parent_mod)) || pub_underscore @@ -3118,7 +3122,7 @@ fn clean_bound_vars(bound_vars: &ty::List<ty::BoundVariableKind>) -> Vec<Generic bound_vars .into_iter() .filter_map(|var| match var { - ty::BoundVariableKind::Region(ty::BrNamed(def_id, name)) + ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name)) if name != kw::UnderscoreLifetime => { Some(GenericParamDef::lifetime(def_id, name)) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d49b4320db6..e5c9539b5e7 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -703,8 +703,8 @@ impl Item { | TyMethodItem(..) | MethodItem(..) => { let assoc_item = tcx.associated_item(def_id); let is_trait_item = match assoc_item.container { - ty::TraitContainer => true, - ty::ImplContainer => { + ty::AssocItemContainer::Trait => true, + ty::AssocItemContainer::Impl => { // Trait impl items always inherit the impl's visibility -- // we don't want to show `pub`. tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some() diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index d3a545fe0b6..560831197f0 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -206,7 +206,7 @@ fn clean_middle_generic_args_with_constraints<'tcx>( ) -> GenericArgs { let args = clean_middle_generic_args(cx, ty_args.map_bound(|args| &args[..]), has_self, did); - if cx.tcx.fn_trait_kind_from_def_id(did).is_some() { + if cx.tcx.is_trait(did) && cx.tcx.trait_def(did).paren_sugar { let ty = ty_args .iter() .nth(if has_self { 1 } else { 0 }) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0f7d4d3e8f3..7ba3cfb66bd 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -121,6 +121,13 @@ impl<'tcx> DocContext<'tcx> { _ => None, } } + + /// Returns `true` if the JSON output format is enabled for generating the crate content. + /// + /// If another option like `--show-coverage` is enabled, it will return `false`. + pub(crate) fn is_json_output(&self) -> bool { + self.output_format.is_json() && !self.show_coverage + } } /// Creates a new `DiagCtxt` that can be used to emit warnings and errors. diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index d27e737764d..9f9a093da8a 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -132,6 +132,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> { fn print_results(&self) { let output_format = self.ctx.output_format; + // In this case we want to ensure that the `OutputFormat` is JSON and NOT the `DocContext`. if output_format.is_json() { println!("{}", self.to_json()); return; diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index aba04283e59..4ef5f7f20a9 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -23,7 +23,7 @@ pub(crate) const STRIP_HIDDEN: Pass = Pass { /// Strip items marked `#[doc(hidden)]` pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { let mut retained = ItemIdSet::default(); - let is_json_output = cx.output_format.is_json() && !cx.show_coverage; + let is_json_output = cx.is_json_output(); // strip all #[doc(hidden)] items let krate = { diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs index 2e9f06bd0a3..b9b2431f06f 100644 --- a/src/librustdoc/passes/strip_priv_imports.rs +++ b/src/librustdoc/passes/strip_priv_imports.rs @@ -13,7 +13,7 @@ pub(crate) const STRIP_PRIV_IMPORTS: Pass = Pass { }; pub(crate) fn strip_priv_imports(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { - let is_json_output = cx.output_format.is_json() && !cx.show_coverage; + let is_json_output = cx.is_json_output(); ImportStripper { tcx: cx.tcx, is_json_output, diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 78f0ad27740..1bd8a7838ec 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -18,7 +18,7 @@ pub(crate) const STRIP_PRIVATE: Pass = Pass { pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { // This stripper collects all *retained* nodes. let mut retained = ItemIdSet::default(); - let is_json_output = cx.output_format.is_json() && !cx.show_coverage; + let is_json_output = cx.is_json_output(); // strip all private items { diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index a59c43bfbf9..980a9f7a47c 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -9,7 +9,6 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir}; use rustc_interface::interface; use rustc_macros::{Decodable, Encodable}; -use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; use rustc_serialize::opaque::{FileEncoder, MemDecoder}; @@ -43,10 +42,16 @@ impl ScrapeExamplesOptions { scrape_tests, }), (Some(_), false, _) | (None, true, _) => { - dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate together"); + dcx.fatal( + "must use --scrape-examples-output-path and --scrape-examples-target-crate \ + together", + ); } (None, false, true) => { - dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests"); + dcx.fatal( + "must use --scrape-examples-output-path and \ + --scrape-examples-target-crate with --scrape-tests", + ); } (None, false, false) => None, } @@ -107,8 +112,6 @@ pub(crate) type AllCallLocations = FxIndexMap<DefPathHash, FnCallLocations>; /// Visitor for traversing a crate and finding instances of function calls. struct FindCalls<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - map: Map<'tcx>, cx: Context<'tcx>, target_crates: Vec<CrateNum>, calls: &'a mut AllCallLocations, @@ -122,13 +125,13 @@ where type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { - self.map + self.cx.tcx().hir() } fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { intravisit::walk_expr(self, ex); - let tcx = self.tcx; + let tcx = self.cx.tcx(); // If we visit an item that contains an expression outside a function body, // then we need to exit before calling typeck (which will panic). See @@ -166,14 +169,15 @@ where }; // If this span comes from a macro expansion, then the source code may not actually show - // a use of the given item, so it would be a poor example. Hence, we skip all uses in macros. + // a use of the given item, so it would be a poor example. Hence, we skip all uses in + // macros. if call_span.from_expansion() { trace!("Rejecting expr from macro: {call_span:?}"); return; } - // If the enclosing item has a span coming from a proc macro, then we also don't want to include - // the example. + // If the enclosing item has a span coming from a proc macro, then we also don't want to + // include the example. let enclosing_item_span = tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id).into()); if enclosing_item_span.from_expansion() { @@ -181,11 +185,12 @@ where return; } - // If the enclosing item doesn't actually enclose the call, this means we probably have a weird - // macro issue even though the spans aren't tagged as being from an expansion. + // If the enclosing item doesn't actually enclose the call, this means we probably have a + // weird macro issue even though the spans aren't tagged as being from an expansion. if !enclosing_item_span.contains(call_span) { warn!( - "Attempted to scrape call at [{call_span:?}] whose enclosing item [{enclosing_item_span:?}] doesn't contain the span of the call." + "Attempted to scrape call at [{call_span:?}] whose enclosing item \ + [{enclosing_item_span:?}] doesn't contain the span of the call." ); return; } @@ -193,7 +198,8 @@ where // Similarly for the call w/ the function ident. if !call_span.contains(ident_span) { warn!( - "Attempted to scrape call at [{call_span:?}] whose identifier [{ident_span:?}] was not contained in the span of the call." + "Attempted to scrape call at [{call_span:?}] whose identifier [{ident_span:?}] was \ + not contained in the span of the call." ); return; } @@ -227,7 +233,8 @@ where Some(url) => url, None => { trace!( - "Rejecting expr ({call_span:?}) whose clean span ({clean_span:?}) cannot be turned into a link" + "Rejecting expr ({call_span:?}) whose clean span ({clean_span:?}) \ + cannot be turned into a link" ); return; } @@ -275,7 +282,8 @@ pub(crate) fn run( let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?; // Collect CrateIds corresponding to provided target crates - // If two different versions of the crate in the dependency tree, then examples will be collected from both. + // If two different versions of the crate in the dependency tree, then examples will be + // collected from both. let all_crates = tcx .crates(()) .iter() @@ -294,8 +302,7 @@ pub(crate) fn run( // Run call-finder on all items let mut calls = FxIndexMap::default(); - let mut finder = - FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates, bin_crate }; + let mut finder = FindCalls { calls: &mut calls, cx, target_crates, bin_crate }; tcx.hir().visit_all_item_likes_in_crate(&mut finder); // The visitor might have found a type error, which we need to diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index f789aca7378..31c33fbf497 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -235,7 +235,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { return false; } - if self.cx.output_format.is_json() { + if self.cx.is_json_output() { return false; } diff --git a/src/rustc-std-workspace/README.md b/src/rustc-std-workspace/README.md new file mode 100644 index 00000000000..a8e925f243d --- /dev/null +++ b/src/rustc-std-workspace/README.md @@ -0,0 +1,4 @@ +See [`library/rustc-std-workspace-core/README.md`](../../library/rustc-std-workspace-core/README.md) for context. + +These are the crates.io versions of these crates, as opposed to the versions +in `library` which are the ones used inside the rustc workspace. diff --git a/src/rustc-std-workspace/rustc-std-workspace-alloc/Cargo.toml b/src/rustc-std-workspace/rustc-std-workspace-alloc/Cargo.toml new file mode 100644 index 00000000000..1a8ebdcfeae --- /dev/null +++ b/src/rustc-std-workspace/rustc-std-workspace-alloc/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rustc-std-workspace-alloc" +version = "1.0.1" +authors = ["Alex Crichton <alex@alexcrichton.com>"] +edition = "2021" +license = 'MIT/Apache-2.0' +description = """ +crate for integration of crates.io crates into rust-lang/rust standard library workspace +""" + +repository = "https://github.com/rust-lang/rust/tree/master/src/rustc-std-workspace" diff --git a/src/rustc-std-workspace/rustc-std-workspace-alloc/src/lib.rs b/src/rustc-std-workspace/rustc-std-workspace-alloc/src/lib.rs new file mode 100644 index 00000000000..938b8bb29b6 --- /dev/null +++ b/src/rustc-std-workspace/rustc-std-workspace-alloc/src/lib.rs @@ -0,0 +1,3 @@ +#![no_std] +extern crate alloc as the_alloc; +pub use the_alloc::*; diff --git a/src/rustc-std-workspace/rustc-std-workspace-core/Cargo.toml b/src/rustc-std-workspace/rustc-std-workspace-core/Cargo.toml new file mode 100644 index 00000000000..116cf3fb6bc --- /dev/null +++ b/src/rustc-std-workspace/rustc-std-workspace-core/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rustc-std-workspace-core" +version = "1.0.1" +authors = ["Alex Crichton <alex@alexcrichton.com>"] +edition = "2021" +license = "MIT/Apache-2.0" +description = """ +crate for integration of crates.io crates into rust-lang/rust standard library workspace +""" + +repository = "https://github.com/rust-lang/rust/tree/master/src/rustc-std-workspace" diff --git a/src/rustc-std-workspace/rustc-std-workspace-core/src/lib.rs b/src/rustc-std-workspace/rustc-std-workspace-core/src/lib.rs new file mode 100644 index 00000000000..38b1615a024 --- /dev/null +++ b/src/rustc-std-workspace/rustc-std-workspace-core/src/lib.rs @@ -0,0 +1,3 @@ +#![no_std] +extern crate core as the_core; +pub use the_core::*; diff --git a/src/rustc-std-workspace/rustc-std-workspace-std/Cargo.toml b/src/rustc-std-workspace/rustc-std-workspace-std/Cargo.toml new file mode 100644 index 00000000000..fcd1ca3deaf --- /dev/null +++ b/src/rustc-std-workspace/rustc-std-workspace-std/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rustc-std-workspace-std" +version = "1.0.1" +authors = ["Alex Crichton <alex@alexcrichton.com>"] +edition = "2021" +license = "MIT/Apache-2.0" +description = """ +crate for integration of crates.io crates into rust-lang/rust standard library workspace +""" + +repository = "https://github.com/rust-lang/rust/tree/master/src/rustc-std-workspace" diff --git a/src/rustc-std-workspace/rustc-std-workspace-std/src/lib.rs b/src/rustc-std-workspace/rustc-std-workspace-std/src/lib.rs new file mode 100644 index 00000000000..f40d09cafbb --- /dev/null +++ b/src/rustc-std-workspace/rustc-std-workspace-std/src/lib.rs @@ -0,0 +1 @@ +pub use std::*; diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 925cbfe09a4..39d9158a1ff 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -157,7 +157,6 @@ static TARGETS: &[&str] = &[ "thumbv8m.main-none-eabihf", "wasm32-unknown-emscripten", "wasm32-unknown-unknown", - "wasm32-wasi", "wasm32-wasip1", "wasm32-wasip1-threads", "wasm32-wasip2", diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml index cf0a8bde202..bcb3193ad67 100644 --- a/src/tools/clippy/.github/workflows/clippy_dev.yml +++ b/src/tools/clippy/.github/workflows/clippy_dev.yml @@ -1,17 +1,8 @@ name: Clippy Dev Test on: - push: - branches: - - auto - - try + merge_group: pull_request: - # Only run on paths, that get checked by the clippy_dev tool - paths: - - 'CHANGELOG.md' - - 'README.md' - - '**.stderr' - - '**.rs' env: RUST_BACKTRACE: 1 @@ -47,28 +38,21 @@ jobs: cargo check git reset --hard HEAD - # These jobs doesn't actually test anything, but they're only used to tell - # bors the build completed, as there is no practical way to detect when a - # workflow is successful listening to webhooks only. - # - # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! - - end-success: - name: bors dev test finished - if: github.event.pusher.name == 'bors' && success() - runs-on: ubuntu-latest - needs: [clippy_dev] - - steps: - - name: Mark the job as successful - run: exit 0 - - end-failure: - name: bors dev test finished - if: github.event.pusher.name == 'bors' && (failure() || cancelled()) + conclusion_dev: + needs: [ clippy_dev ] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + if: ${{ !cancelled() }} runs-on: ubuntu-latest - needs: [clippy_dev] - steps: - - name: Mark the job as a failure - run: exit 1 + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_mq.yml index 026771e6fcf..49622048050 100644 --- a/src/tools/clippy/.github/workflows/clippy_bors.yml +++ b/src/tools/clippy/.github/workflows/clippy_mq.yml @@ -1,10 +1,7 @@ -name: Clippy Test (bors) +name: Clippy Test (merge queue) on: - push: - branches: - - auto - - try + merge_group: env: RUST_BACKTRACE: 1 @@ -13,11 +10,6 @@ env: CARGO_INCREMENTAL: 0 RUSTFLAGS: -D warnings -concurrency: - # For a given workflow, if we push to the same branch, cancel all previous builds on that branch. - group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" - cancel-in-progress: true - defaults: run: shell: bash @@ -218,28 +210,21 @@ jobs: env: INTEGRATION: ${{ matrix.integration }} - # These jobs doesn't actually test anything, but they're only used to tell - # bors the build completed, as there is no practical way to detect when a - # workflow is successful listening to webhooks only. - # - # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! - - end-success: - name: bors test finished - if: github.event.pusher.name == 'bors' && success() + conclusion: + needs: [ changelog, base, metadata_collection, integration_build, integration ] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + if: ${{ !cancelled() }} runs-on: ubuntu-latest - needs: [changelog, base, metadata_collection, integration_build, integration] - - steps: - - name: Mark the job as successful - run: exit 0 - - end-failure: - name: bors test finished - if: github.event.pusher.name == 'bors' && (failure() || cancelled()) - runs-on: ubuntu-latest - needs: [changelog, base, metadata_collection, integration_build, integration] - steps: - - name: Mark the job as a failure - run: exit 1 + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy_pr.yml index 0a0538490cc..2e5b5bd41df 100644 --- a/src/tools/clippy/.github/workflows/clippy.yml +++ b/src/tools/clippy/.github/workflows/clippy_pr.yml @@ -1,24 +1,7 @@ name: Clippy Test on: - push: - # Ignore bors branches, since they are covered by `clippy_bors.yml` - branches-ignore: - - auto - - try - # Don't run Clippy tests, when only text files were modified - paths-ignore: - - 'COPYRIGHT' - - 'LICENSE-*' - - '**.md' - - '**.txt' pull_request: - # Don't run Clippy tests, when only text files were modified - paths-ignore: - - 'COPYRIGHT' - - 'LICENSE-*' - - '**.md' - - '**.txt' env: RUST_BACKTRACE: 1 @@ -35,7 +18,7 @@ concurrency: jobs: base: - # NOTE: If you modify this job, make sure you copy the changes to clippy_bors.yml + # NOTE: If you modify this job, make sure you copy the changes to clippy_mq.yml runs-on: ubuntu-latest steps: @@ -73,3 +56,24 @@ jobs: run: .github/driver.sh env: OS: ${{ runner.os }} + + # We need to have the "conclusion" job also on PR CI, to make it possible + # to add PRs to a merge queue. + conclusion: + needs: [ base ] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/src/tools/clippy/.github/workflows/deploy.yml b/src/tools/clippy/.github/workflows/deploy.yml index 94f494b65c4..32dc251c836 100644 --- a/src/tools/clippy/.github/workflows/deploy.yml +++ b/src/tools/clippy/.github/workflows/deploy.yml @@ -52,7 +52,7 @@ jobs: run: cargo generate-lockfile - name: Cache - uses: Swatinem/rust-cache@v2.7.0 + uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/master' }} diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml index a1b011dc32d..0d402fe7064 100644 --- a/src/tools/clippy/.github/workflows/remark.yml +++ b/src/tools/clippy/.github/workflows/remark.yml @@ -1,13 +1,8 @@ name: Remark on: - push: - branches: - - auto - - try + merge_group: pull_request: - paths: - - '**.md' jobs: remark: @@ -45,28 +40,21 @@ jobs: - name: Build mdbook run: mdbook build book - # These jobs doesn't actually test anything, but they're only used to tell - # bors the build completed, as there is no practical way to detect when a - # workflow is successful listening to webhooks only. - # - # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! - - end-success: - name: bors remark test finished - if: github.event.pusher.name == 'bors' && success() - runs-on: ubuntu-latest - needs: [remark] - - steps: - - name: Mark the job as successful - run: exit 0 - - end-failure: - name: bors remark test finished - if: github.event.pusher.name == 'bors' && (failure() || cancelled()) + conclusion_remark: + needs: [ remark ] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + if: ${{ !cancelled() }} runs-on: ubuntu-latest - needs: [remark] - steps: - - name: Mark the job as a failure - run: exit 1 + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 4bdbc91db93..161fa630ed4 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -5331,6 +5331,7 @@ Released 2018-09-13 [`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant +[`arbitrary_source_item_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering [`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects [`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions @@ -5689,6 +5690,7 @@ Released 2018-09-13 [`manual_unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or_default [`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_while_let_some [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names +[`map_all_any_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_all_any_identity [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone [`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_collect_result_unit [`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry @@ -5696,6 +5698,7 @@ Released 2018-09-13 [`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten [`map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_identity [`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or +[`map_with_unused_argument_over_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_with_unused_argument_over_ranges [`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref [`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool [`match_like_matches_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro @@ -5761,6 +5764,7 @@ Released 2018-09-13 [`mutex_integer`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_integer [`naive_bytecount`]: https://rust-lang.github.io/rust-clippy/master/index.html#naive_bytecount [`needless_arbitrary_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_arbitrary_self_type +[`needless_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_as_bytes [`needless_bitwise_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bitwise_bool [`needless_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool [`needless_bool_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool_assign @@ -6205,12 +6209,14 @@ Released 2018-09-13 [`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold [`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items +[`module-item-order-groupings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#module-item-order-groupings [`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv [`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit [`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior [`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline [`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline [`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold +[`source-item-ordering`]: https://doc.rust-lang.org/clippy/lint_configuration.html#source-item-ordering [`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold [`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces [`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold @@ -6218,6 +6224,7 @@ Released 2018-09-13 [`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack [`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold [`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold +[`trait-assoc-item-kinds-order`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trait-assoc-item-kinds-order [`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit [`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold [`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md index b1a59238c82..1f6c918fc6c 100644 --- a/src/tools/clippy/CONTRIBUTING.md +++ b/src/tools/clippy/CONTRIBUTING.md @@ -21,7 +21,6 @@ All contributors are expected to follow the [Rust Code of Conduct]. - [Rust Analyzer](#rust-analyzer) - [How Clippy works](#how-clippy-works) - [Issue and PR triage](#issue-and-pr-triage) - - [Bors and Homu](#bors-and-homu) - [Contributions](#contributions) - [License](#license) @@ -213,16 +212,6 @@ We have prioritization labels and a sync-blocker label, which are described belo Or rather: before the sync this should be addressed, e.g. by removing a lint again, so it doesn't hit beta/stable. -## Bors and Homu - -We use a bot powered by [Homu][homu] to help automate testing and landing of pull -requests in Clippy. The bot's username is @bors. - -You can find the Clippy bors queue [here][homu_queue]. - -If you have @bors permissions, you can find an overview of the available -commands [here][homu_instructions]. - [triage]: https://forge.rust-lang.org/release/triage-procedure.html [l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash [l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug @@ -230,9 +219,6 @@ commands [here][homu_instructions]. [p-medium]: https://github.com/rust-lang/rust-clippy/labels/P-medium [p-high]: https://github.com/rust-lang/rust-clippy/labels/P-high [l-sync-blocker]: https://github.com/rust-lang/rust-clippy/labels/L-sync-blocker -[homu]: https://github.com/rust-lang/homu -[homu_instructions]: https://bors.rust-lang.org/ -[homu_queue]: https://bors.rust-lang.org/queue/clippy ## Contributions @@ -244,7 +230,7 @@ All PRs should include a `changelog` entry with a short comment explaining the c "what do you believe is important from an outsider's perspective?" Often, PRs are only related to a single property of a lint, and then it's good to mention that one. Otherwise, it's better to include too much detail than too little. -Clippy's [changelog] is created from these comments. Every release, someone gets all commits from bors with a +Clippy's [changelog] is created from these comments. Every release, someone gets all merge commits with a `changelog: XYZ` entry and combines them into the changelog. This is a manual process. Examples: diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 1f7784fc489..50a2afbfc07 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -39,7 +39,7 @@ toml = "0.7.3" walkdir = "2.3" filetime = "0.2.9" itertools = "0.12" -pulldown-cmark = "0.11" +pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] } rinja = { version = "0.3", default-features = false, features = ["config"] } # UI test dependencies diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index ec76a6dfb08..cb3a22d4288 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -1,11 +1,10 @@ # Clippy -[/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test+(bors)%22+event%3Apush+branch%3Aauto) [](#license) A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 750 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. diff --git a/src/tools/clippy/book/src/README.md b/src/tools/clippy/book/src/README.md index 7bdfb97c3ac..5d2c3972b06 100644 --- a/src/tools/clippy/book/src/README.md +++ b/src/tools/clippy/book/src/README.md @@ -1,12 +1,11 @@ # Clippy -[/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test+(bors)%22+event%3Apush+branch%3Aauto) [](https://github.com/rust-lang/rust-clippy#license) A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 750 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how diff --git a/src/tools/clippy/book/src/development/README.md b/src/tools/clippy/book/src/development/README.md index 8f09f66f595..b33cdc00ead 100644 --- a/src/tools/clippy/book/src/development/README.md +++ b/src/tools/clippy/book/src/development/README.md @@ -53,7 +53,6 @@ book](../lints.md). > - IDE setup > - High level overview on how Clippy works > - Triage procedure -> - Bors and Homu [ast]: https://rustc-dev-guide.rust-lang.org/syntax-intro.html [hir]: https://rustc-dev-guide.rust-lang.org/hir.html diff --git a/src/tools/clippy/book/src/development/common_tools_writing_lints.md b/src/tools/clippy/book/src/development/common_tools_writing_lints.md index 09171d86a20..77910917963 100644 --- a/src/tools/clippy/book/src/development/common_tools_writing_lints.md +++ b/src/tools/clippy/book/src/development/common_tools_writing_lints.md @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for MyStructLint { // Check our expr is calling a method if let hir::ExprKind::MethodCall(path, _, _self_arg, ..) = &expr.kind // Check the name of this method is `some_method` - && path.ident.name == sym!(some_method) + && path.ident.name.as_str() == "some_method" // Optionally, check the type of the self argument. // - See "Checking for a specific type" { @@ -167,7 +167,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl { // Check if item is a method/function if let ImplItemKind::Fn(ref signature, _) = impl_item.kind // Check the method is named `some_method` - && impl_item.ident.name == sym!(some_method) + && impl_item.ident.name.as_str() == "some_method" // We can also check it has a parameter `self` && signature.decl.implicit_self.has_implicit_self() // We can go further and even check if its return type is `String` diff --git a/src/tools/clippy/book/src/development/method_checking.md b/src/tools/clippy/book/src/development/method_checking.md index 56d1be37519..9c5d4b516db 100644 --- a/src/tools/clippy/book/src/development/method_checking.md +++ b/src/tools/clippy/book/src/development/method_checking.md @@ -3,8 +3,8 @@ In some scenarios we might want to check for methods when developing a lint. There are two kinds of questions that we might be curious about: -- Invocation: Does an expression call a specific method? -- Definition: Does an `impl` define a method? +- Invocation: Does an expression call a specific method? +- Definition: Does an `impl` define a method? ## Checking if an `expr` is calling a specific method @@ -23,7 +23,7 @@ impl<'tcx> LateLintPass<'tcx> for OurFancyMethodLint { // Check our expr is calling a method with pattern matching if let hir::ExprKind::MethodCall(path, _, [self_arg, ..]) = &expr.kind // Check if the name of this method is `our_fancy_method` - && path.ident.name == sym!(our_fancy_method) + && path.ident.name.as_str() == "our_fancy_method" // We can check the type of the self argument whenever necessary. // (It's necessary if we want to check that method is specifically belonging to a specific trait, // for example, a `map` method could belong to user-defined trait instead of to `Iterator`) @@ -41,10 +41,6 @@ information on the pattern matching. As mentioned in [Define Lints](defining_lints.md#lint-types), the `methods` lint type is full of pattern matching with `MethodCall` in case the reader wishes to explore more. -Additionally, we use the [`clippy_utils::sym!`][sym] macro to conveniently -convert an input `our_fancy_method` into a `Symbol` and compare that symbol to -the [`Ident`]'s name in the [`PathSegment`] in the [`MethodCall`]. - ## Checking if a `impl` block implements a method While sometimes we want to check whether a method is being called or not, other @@ -71,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl { // Check if item is a method/function if let ImplItemKind::Fn(ref signature, _) = impl_item.kind // Check the method is named `our_fancy_method` - && impl_item.ident.name == sym!(our_fancy_method) + && impl_item.ident.name.as_str() == "our_fancy_method" // We can also check it has a parameter `self` && signature.decl.implicit_self.has_implicit_self() // We can go even further and even check if its return type is `String` @@ -85,9 +81,6 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl { [`check_impl_item`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_lint/trait.LateLintPass.html#method.check_impl_item [`ExprKind`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/hir/enum.ExprKind.html -[`Ident`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/struct.Ident.html [`ImplItem`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_hir/hir/struct.ImplItem.html [`LateLintPass`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_lint/trait.LateLintPass.html [`MethodCall`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/hir/enum.ExprKind.html#variant.MethodCall -[`PathSegment`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/hir/struct.PathSegment.html -[sym]: https://doc.rust-lang.org/stable/nightly-rustc/clippy_utils/macro.sym.html diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 43b551ae216..670b5cbef82 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -456,7 +456,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "AccessKit", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** @@ -666,6 +666,16 @@ crate. For example, `pub(crate)` items. * [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) +## `module-item-order-groupings` +The named groupings of different source item kinds within modules. + +**Default Value:** `[["modules", ["extern_crate", "mod", "foreign_mod"]], ["use", ["use"]], ["macros", ["macro"]], ["global_asm", ["global_asm"]], ["UPPER_SNAKE_CASE", ["static", "const"]], ["PascalCase", ["ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl"]], ["lower_snake_case", ["fn"]]]` + +--- +**Affected lints:** +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) + + ## `msrv` The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` @@ -710,6 +720,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) * [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) * [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) +* [`map_with_unused_argument_over_ranges`](https://rust-lang.github.io/rust-clippy/master/index.html#map_with_unused_argument_over_ranges) * [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) * [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) * [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) @@ -783,6 +794,16 @@ The maximum number of single char bindings a scope may have * [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) +## `source-item-ordering` +Which kind of elements should be ordered internally, possible values being `enum`, `impl`, `module`, `struct`, `trait`. + +**Default Value:** `["enum", "impl", "module", "struct", "trait"]` + +--- +**Affected lints:** +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) + + ## `stack-size-threshold` The maximum allowed stack size for functions in bytes @@ -862,6 +883,16 @@ The maximum number of lines a function or method can have * [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) +## `trait-assoc-item-kinds-order` +The order of associated items in traits. + +**Default Value:** `["const", "type", "fn"]` + +--- +**Affected lints:** +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) + + ## `trivial-copy-size-limit` The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference. By default there is no limit diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 4757c0b1339..600d5b6e2c8 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -1,6 +1,10 @@ use crate::ClippyConfiguration; use crate::msrvs::Msrv; -use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename}; +use crate::types::{ + DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, + SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, + SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, +}; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::edit_distance::edit_distance; @@ -17,8 +21,9 @@ use std::{cmp, env, fmt, fs, io}; #[rustfmt::skip] const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", + "MHz", "GHz", "THz", "AccessKit", - "CoreFoundation", "CoreGraphics", "CoreText", + "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", @@ -46,6 +51,29 @@ const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z const DEFAULT_ALLOWED_PREFIXES: &[&str] = &["to", "as", "into", "from", "try_into", "try_from"]; const DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS: &[&str] = &["core::convert::From", "core::convert::TryFrom", "core::str::FromStr"]; +const DEFAULT_MODULE_ITEM_ORDERING_GROUPS: &[(&str, &[SourceItemOrderingModuleItemKind])] = { + #[allow(clippy::enum_glob_use)] // Very local glob use for legibility. + use SourceItemOrderingModuleItemKind::*; + &[ + ("modules", &[ExternCrate, Mod, ForeignMod]), + ("use", &[Use]), + ("macros", &[Macro]), + ("global_asm", &[GlobalAsm]), + ("UPPER_SNAKE_CASE", &[Static, Const]), + ("PascalCase", &[TyAlias, Enum, Struct, Union, Trait, TraitAlias, Impl]), + ("lower_snake_case", &[Fn]), + ] +}; +const DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER: &[SourceItemOrderingTraitAssocItemKind] = { + #[allow(clippy::enum_glob_use)] // Very local glob use for legibility. + use SourceItemOrderingTraitAssocItemKind::*; + &[Const, Type, Fn] +}; +const DEFAULT_SOURCE_ITEM_ORDERING: &[SourceItemOrderingCategory] = { + #[allow(clippy::enum_glob_use)] // Very local glob use for legibility. + use SourceItemOrderingCategory::*; + &[Enum, Impl, Module, Struct, Trait] +}; /// Conf with parse errors #[derive(Default)] @@ -102,7 +130,9 @@ pub fn sanitize_explanation(raw_docs: &str) -> String { // Remove tags and hidden code: let mut explanation = String::with_capacity(128); let mut in_code = false; - for line in raw_docs.lines().map(str::trim) { + for line in raw_docs.lines() { + let line = line.strip_prefix(' ').unwrap_or(line); + if let Some(lang) = line.strip_prefix("```") { let tag = lang.split_once(',').map_or(lang, |(left, _)| left); if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { @@ -530,6 +560,9 @@ define_Conf! { /// crate. For example, `pub(crate)` items. #[lints(missing_docs_in_private_items)] missing_docs_in_crate_items: bool = false, + /// The named groupings of different source item kinds within modules. + #[lints(arbitrary_source_item_ordering)] + module_item_order_groupings: SourceItemOrderingModuleItemGroupings = DEFAULT_MODULE_ITEM_ORDERING_GROUPS.into(), /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = "current version"] #[lints( @@ -570,6 +603,7 @@ define_Conf! { manual_try_fold, map_clone, map_unwrap_or, + map_with_unused_argument_over_ranges, match_like_matches_macro, mem_replace_with_default, missing_const_for_fn, @@ -608,6 +642,9 @@ define_Conf! { /// The maximum number of single char bindings a scope may have #[lints(many_single_char_names)] single_char_binding_names_threshold: u64 = 4, + /// Which kind of elements should be ordered internally, possible values being `enum`, `impl`, `module`, `struct`, `trait`. + #[lints(arbitrary_source_item_ordering)] + source_item_ordering: SourceItemOrdering = DEFAULT_SOURCE_ITEM_ORDERING.into(), /// The maximum allowed stack size for functions in bytes #[lints(large_stack_frames)] stack_size_threshold: u64 = 512_000, @@ -637,6 +674,9 @@ define_Conf! { /// The maximum number of lines a function or method can have #[lints(too_many_lines)] too_many_lines_threshold: u64 = 100, + /// The order of associated items in traits. + #[lints(arbitrary_source_item_ordering)] + trait_assoc_item_kinds_order: SourceItemOrderingTraitAssocItemKinds = DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER.into(), /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by /// reference. By default there is no limit #[default_text = "target_pointer_width * 2"] diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs index 42651521f8d..1c3f32c2514 100644 --- a/src/tools/clippy/clippy_config/src/lib.rs +++ b/src/tools/clippy/clippy_config/src/lib.rs @@ -20,6 +20,7 @@ extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_session; extern crate rustc_span; +extern crate smallvec; mod conf; mod metadata; diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index 2f4da4cba3d..764ca8fb50a 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -3,6 +3,7 @@ use rustc_attr::parse_version; use rustc_session::{RustcVersion, Session}; use rustc_span::{Symbol, sym}; use serde::Deserialize; +use smallvec::{SmallVec, smallvec}; use std::fmt; macro_rules! msrv_aliases { @@ -18,7 +19,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { 1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY } - 1,82,0 { IS_NONE_OR } + 1,82,0 { IS_NONE_OR, REPEAT_N } 1,81,0 { LINT_REASONS_STABILIZATION } 1,80,0 { BOX_INTO_ITER} 1,77,0 { C_STR_LITERALS } @@ -54,7 +55,7 @@ msrv_aliases! { 1,33,0 { UNDERSCORE_IMPORTS } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,29,0 { ITER_FLATTEN } - 1,28,0 { FROM_BOOL } + 1,28,0 { FROM_BOOL, REPEAT_WITH } 1,27,0 { ITERATOR_TRY_FOLD } 1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN } 1,24,0 { IS_ASCII_DIGIT } @@ -67,7 +68,7 @@ msrv_aliases! { /// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]` #[derive(Debug, Clone)] pub struct Msrv { - stack: Vec<RustcVersion>, + stack: SmallVec<[RustcVersion; 2]>, } impl fmt::Display for Msrv { @@ -87,14 +88,14 @@ impl<'de> Deserialize<'de> for Msrv { { let v = String::deserialize(deserializer)?; parse_version(Symbol::intern(&v)) - .map(|v| Msrv { stack: vec![v] }) + .map(|v| Msrv { stack: smallvec![v] }) .ok_or_else(|| serde::de::Error::custom("not a valid Rust version")) } } impl Msrv { pub fn empty() -> Msrv { - Msrv { stack: Vec::new() } + Msrv { stack: SmallVec::new() } } pub fn read_cargo(&mut self, sess: &Session) { @@ -103,7 +104,7 @@ impl Msrv { .and_then(|v| parse_version(Symbol::intern(&v))); match (self.current(), cargo_msrv) { - (None, Some(cargo_msrv)) => self.stack = vec![cargo_msrv], + (None, Some(cargo_msrv)) => self.stack = smallvec![cargo_msrv], (Some(clippy_msrv), Some(cargo_msrv)) => { if clippy_msrv != cargo_msrv { sess.dcx().warn(format!( diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs index bab63911182..fe576424148 100644 --- a/src/tools/clippy/clippy_config/src/types.rs +++ b/src/tools/clippy/clippy_config/src/types.rs @@ -1,5 +1,6 @@ use serde::de::{self, Deserializer, Visitor}; use serde::{Deserialize, Serialize, ser}; +use std::collections::HashMap; use std::fmt; #[derive(Debug, Deserialize)] @@ -102,6 +103,306 @@ impl<'de> Deserialize<'de> for MacroMatcher { } } +/// Represents the item categories that can be ordered by the source ordering lint. +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum SourceItemOrderingCategory { + Enum, + Impl, + Module, + Struct, + Trait, +} + +/// Represents which item categories are enabled for ordering. +/// +/// The [`Deserialize`] implementation checks that there are no duplicates in +/// the user configuration. +pub struct SourceItemOrdering(Vec<SourceItemOrderingCategory>); + +impl SourceItemOrdering { + pub fn contains(&self, category: &SourceItemOrderingCategory) -> bool { + self.0.contains(category) + } +} + +impl<T> From<T> for SourceItemOrdering +where + T: Into<Vec<SourceItemOrderingCategory>>, +{ + fn from(value: T) -> Self { + Self(value.into()) + } +} + +impl core::fmt::Debug for SourceItemOrdering { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl<'de> Deserialize<'de> for SourceItemOrdering { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let items = Vec::<SourceItemOrderingCategory>::deserialize(deserializer)?; + let mut items_set = std::collections::HashSet::new(); + + for item in &items { + if items_set.contains(item) { + return Err(de::Error::custom(format!( + "The category \"{item:?}\" was enabled more than once in the source ordering configuration." + ))); + } + items_set.insert(item); + } + + Ok(Self(items)) + } +} + +impl Serialize for SourceItemOrdering { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + self.0.serialize(serializer) + } +} + +/// Represents the items that can occur within a module. +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum SourceItemOrderingModuleItemKind { + ExternCrate, + Mod, + ForeignMod, + Use, + Macro, + GlobalAsm, + Static, + Const, + TyAlias, + Enum, + Struct, + Union, + Trait, + TraitAlias, + Impl, + Fn, +} + +impl SourceItemOrderingModuleItemKind { + pub fn all_variants() -> Vec<Self> { + #[allow(clippy::enum_glob_use)] // Very local glob use for legibility. + use SourceItemOrderingModuleItemKind::*; + vec![ + ExternCrate, + Mod, + ForeignMod, + Use, + Macro, + GlobalAsm, + Static, + Const, + TyAlias, + Enum, + Struct, + Union, + Trait, + TraitAlias, + Impl, + Fn, + ] + } +} + +/// Represents the configured ordering of items within a module. +/// +/// The [`Deserialize`] implementation checks that no item kinds have been +/// omitted and that there are no duplicates in the user configuration. +#[derive(Clone)] +pub struct SourceItemOrderingModuleItemGroupings { + groups: Vec<(String, Vec<SourceItemOrderingModuleItemKind>)>, + lut: HashMap<SourceItemOrderingModuleItemKind, usize>, +} + +impl SourceItemOrderingModuleItemGroupings { + fn build_lut( + groups: &[(String, Vec<SourceItemOrderingModuleItemKind>)], + ) -> HashMap<SourceItemOrderingModuleItemKind, usize> { + let mut lut = HashMap::new(); + for (group_index, (_, items)) in groups.iter().enumerate() { + for item in items { + lut.insert(item.clone(), group_index); + } + } + lut + } + + pub fn module_level_order_of(&self, item: &SourceItemOrderingModuleItemKind) -> Option<usize> { + self.lut.get(item).copied() + } +} + +impl From<&[(&str, &[SourceItemOrderingModuleItemKind])]> for SourceItemOrderingModuleItemGroupings { + fn from(value: &[(&str, &[SourceItemOrderingModuleItemKind])]) -> Self { + let groups: Vec<(String, Vec<SourceItemOrderingModuleItemKind>)> = + value.iter().map(|item| (item.0.to_string(), item.1.to_vec())).collect(); + let lut = Self::build_lut(&groups); + Self { groups, lut } + } +} + +impl core::fmt::Debug for SourceItemOrderingModuleItemGroupings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.groups.fmt(f) + } +} + +impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let groups = Vec::<(String, Vec<SourceItemOrderingModuleItemKind>)>::deserialize(deserializer)?; + let items_total: usize = groups.iter().map(|(_, v)| v.len()).sum(); + let lut = Self::build_lut(&groups); + + let mut expected_items = SourceItemOrderingModuleItemKind::all_variants(); + for item in lut.keys() { + expected_items.retain(|i| i != item); + } + + let all_items = SourceItemOrderingModuleItemKind::all_variants(); + if expected_items.is_empty() && items_total == all_items.len() { + let Some(use_group_index) = lut.get(&SourceItemOrderingModuleItemKind::Use) else { + return Err(de::Error::custom("Error in internal LUT.")); + }; + let Some((_, use_group_items)) = groups.get(*use_group_index) else { + return Err(de::Error::custom("Error in internal LUT.")); + }; + if use_group_items.len() > 1 { + return Err(de::Error::custom( + "The group containing the \"use\" item kind may not contain any other item kinds. \ + The \"use\" items will (generally) be sorted by rustfmt already. \ + Therefore it makes no sense to implement linting rules that may conflict with rustfmt.", + )); + } + + Ok(Self { groups, lut }) + } else if items_total != all_items.len() { + Err(de::Error::custom(format!( + "Some module item kinds were configured more than once, or were missing, in the source ordering configuration. \ + The module item kinds are: {all_items:?}" + ))) + } else { + Err(de::Error::custom(format!( + "Not all module item kinds were part of the configured source ordering rule. \ + All item kinds must be provided in the config, otherwise the required source ordering would remain ambiguous. \ + The module item kinds are: {all_items:?}" + ))) + } + } +} + +impl Serialize for SourceItemOrderingModuleItemGroupings { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + self.groups.serialize(serializer) + } +} + +/// Represents all kinds of trait associated items. +#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum SourceItemOrderingTraitAssocItemKind { + Const, + Fn, + Type, +} + +impl SourceItemOrderingTraitAssocItemKind { + pub fn all_variants() -> Vec<Self> { + #[allow(clippy::enum_glob_use)] // Very local glob use for legibility. + use SourceItemOrderingTraitAssocItemKind::*; + vec![Const, Fn, Type] + } +} + +/// Represents the order in which associated trait items should be ordered. +/// +/// The reason to wrap a `Vec` in a newtype is to be able to implement +/// [`Deserialize`]. Implementing `Deserialize` allows for implementing checks +/// on configuration completeness at the time of loading the clippy config, +/// letting the user know if there's any issues with the config (e.g. not +/// listing all item kinds that should be sorted). +#[derive(Clone)] +pub struct SourceItemOrderingTraitAssocItemKinds(Vec<SourceItemOrderingTraitAssocItemKind>); + +impl SourceItemOrderingTraitAssocItemKinds { + pub fn index_of(&self, item: &SourceItemOrderingTraitAssocItemKind) -> Option<usize> { + self.0.iter().position(|i| i == item) + } +} + +impl<T> From<T> for SourceItemOrderingTraitAssocItemKinds +where + T: Into<Vec<SourceItemOrderingTraitAssocItemKind>>, +{ + fn from(value: T) -> Self { + Self(value.into()) + } +} + +impl core::fmt::Debug for SourceItemOrderingTraitAssocItemKinds { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl<'de> Deserialize<'de> for SourceItemOrderingTraitAssocItemKinds { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let items = Vec::<SourceItemOrderingTraitAssocItemKind>::deserialize(deserializer)?; + + let mut expected_items = SourceItemOrderingTraitAssocItemKind::all_variants(); + for item in &items { + expected_items.retain(|i| i != item); + } + + let all_items = SourceItemOrderingTraitAssocItemKind::all_variants(); + if expected_items.is_empty() && items.len() == all_items.len() { + Ok(Self(items)) + } else if items.len() != all_items.len() { + Err(de::Error::custom(format!( + "Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. \ + The trait associated item kinds are: {all_items:?}", + ))) + } else { + Err(de::Error::custom(format!( + "Not all trait associated item kinds were part of the configured source ordering rule. \ + All item kinds must be provided in the config, otherwise the required source ordering would remain ambiguous. \ + The trait associated item kinds are: {all_items:?}" + ))) + } + } +} + +impl Serialize for SourceItemOrderingTraitAssocItemKinds { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + self.0.serialize(serializer) + } +} + // these impls are never actually called but are used by the various config options that default to // empty lists macro_rules! unimplemented_serialize { diff --git a/src/tools/clippy/clippy_dev/src/serve.rs b/src/tools/clippy/clippy_dev/src/serve.rs index d367fefec61..a2d1236629f 100644 --- a/src/tools/clippy/clippy_dev/src/serve.rs +++ b/src/tools/clippy/clippy_dev/src/serve.rs @@ -20,8 +20,14 @@ pub fn run(port: u16, lint: Option<String>) -> ! { loop { let index_time = mtime("util/gh-pages/index.html"); + let times = [ + "clippy_lints/src", + "util/gh-pages/index_template.html", + "tests/compile-test.rs", + ] + .map(mtime); - if index_time < mtime("clippy_lints/src") || index_time < mtime("util/gh-pages/index_template.html") { + if times.iter().any(|&time| index_time < time) { Command::new(env::var("CARGO").unwrap_or("cargo".into())) .arg("collect-metadata") .spawn() diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index d6ed36d52f4..795456ad3c5 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -762,13 +762,19 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) { Literal{..}(desc) ); - if let Some(LintDeclSearchResult { - token_kind: TokenKind::CloseBrace, - range, - .. - }) = iter.next() - { - lints.push(Lint::new(name, group, desc, module, start..range.end)); + if let Some(end) = iter.find_map(|t| { + if let LintDeclSearchResult { + token_kind: TokenKind::CloseBrace, + range, + .. + } = t + { + Some(range.end) + } else { + None + } + }) { + lints.push(Lint::new(name, group, desc, module, start..end)); } } } diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs new file mode 100644 index 00000000000..8719f61a890 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -0,0 +1,531 @@ +use clippy_config::Conf; +use clippy_config::types::{ + SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, + SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, +}; +use clippy_utils::diagnostics::span_lint_and_note; +use rustc_hir::{ + AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, UseKind, + Variant, VariantData, +}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::impl_lint_pass; + +declare_clippy_lint! { + /// ### What it does + /// + /// Confirms that items are sorted in source files as per configuration. + /// + /// ### Why restrict this? + /// + /// Keeping a consistent ordering throughout the codebase helps with working + /// as a team, and possibly improves maintainability of the codebase. The + /// idea is that by defining a consistent and enforceable rule for how + /// source files are structured, less time will be wasted during reviews on + /// a topic that is (under most circumstances) not relevant to the logic + /// implemented in the code. Sometimes this will be referred to as + /// "bikeshedding". + /// + /// ### Default Ordering and Configuration + /// + /// As there is no generally applicable rule, and each project may have + /// different requirements, the lint can be configured with high + /// granularity. The configuration is split into two stages: + /// + /// 1. Which item kinds that should have an internal order enforced. + /// 2. Individual ordering rules per item kind. + /// + /// The item kinds that can be linted are: + /// - Module (with customized groupings, alphabetical within) + /// - Trait (with customized order of associated items, alphabetical within) + /// - Enum, Impl, Struct (purely alphabetical) + /// + /// #### Module Item Order + /// + /// Due to the large variation of items within modules, the ordering can be + /// configured on a very granular level. Item kinds can be grouped together + /// arbitrarily, items within groups will be ordered alphabetically. The + /// following table shows the default groupings: + /// + /// | Group | Item Kinds | + /// |--------------------|----------------------| + /// | `modules` | "mod", "foreign_mod" | + /// | `use` | "use" | + /// | `macros` | "macro" | + /// | `global_asm` | "global_asm" | + /// | `UPPER_SNAKE_CASE` | "static", "const" | + /// | `PascalCase` | "ty_alias", "opaque_ty", "enum", "struct", "union", "trait", "trait_alias", "impl" | + /// | `lower_snake_case` | "fn" | + /// + /// All item kinds must be accounted for to create an enforceable linting + /// rule set. + /// + /// ### Known Problems + /// + /// #### Performance Impact + /// + /// Keep in mind, that ordering source code alphabetically can lead to + /// reduced performance in cases where the most commonly used enum variant + /// isn't the first entry anymore, and similar optimizations that can reduce + /// branch misses, cache locality and such. Either don't use this lint if + /// that's relevant, or disable the lint in modules or items specifically + /// where it matters. Other solutions can be to use profile guided + /// optimization (PGO), post-link optimization (e.g. using BOLT for LLVM), + /// or other advanced optimization methods. A good starting point to dig + /// into optimization is [cargo-pgo][cargo-pgo]. + /// + /// #### Lints on a Contains basis + /// + /// The lint can be disabled only on a "contains" basis, but not per element + /// within a "container", e.g. the lint works per-module, per-struct, + /// per-enum, etc. but not for "don't order this particular enum variant". + /// + /// #### Module documentation + /// + /// Module level rustdoc comments are not part of the resulting syntax tree + /// and as such cannot be linted from within `check_mod`. Instead, the + /// `rustdoc::missing_documentation` lint may be used. + /// + /// #### Module Tests + /// + /// This lint does not implement detection of module tests (or other feature + /// dependent elements for that matter). To lint the location of mod tests, + /// the lint `items_after_test_module` can be used instead. + /// + /// ### Example + /// + /// ```no_run + /// trait TraitUnordered { + /// const A: bool; + /// const C: bool; + /// const B: bool; + /// + /// type SomeType; + /// + /// fn a(); + /// fn c(); + /// fn b(); + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// trait TraitOrdered { + /// const A: bool; + /// const B: bool; + /// const C: bool; + /// + /// type SomeType; + /// + /// fn a(); + /// fn b(); + /// fn c(); + /// } + /// ``` + /// + /// [cargo-pgo]: https://github.com/Kobzol/cargo-pgo/blob/main/README.md + /// + #[clippy::version = "1.82.0"] + pub ARBITRARY_SOURCE_ITEM_ORDERING, + restriction, + "arbitrary source item ordering" +} + +impl_lint_pass!(ArbitrarySourceItemOrdering => [ARBITRARY_SOURCE_ITEM_ORDERING]); + +#[derive(Debug)] +#[allow(clippy::struct_excessive_bools)] // Bools are cached feature flags. +pub struct ArbitrarySourceItemOrdering { + assoc_types_order: SourceItemOrderingTraitAssocItemKinds, + enable_ordering_for_enum: bool, + enable_ordering_for_impl: bool, + enable_ordering_for_module: bool, + enable_ordering_for_struct: bool, + enable_ordering_for_trait: bool, + module_item_order_groupings: SourceItemOrderingModuleItemGroupings, +} + +impl ArbitrarySourceItemOrdering { + pub fn new(conf: &'static Conf) -> Self { + #[allow(clippy::enum_glob_use)] // Very local glob use for legibility. + use SourceItemOrderingCategory::*; + Self { + assoc_types_order: conf.trait_assoc_item_kinds_order.clone(), + enable_ordering_for_enum: conf.source_item_ordering.contains(&Enum), + enable_ordering_for_impl: conf.source_item_ordering.contains(&Impl), + enable_ordering_for_module: conf.source_item_ordering.contains(&Module), + enable_ordering_for_struct: conf.source_item_ordering.contains(&Struct), + enable_ordering_for_trait: conf.source_item_ordering.contains(&Trait), + module_item_order_groupings: conf.module_item_order_groupings.clone(), + } + } + + /// Produces a linting warning for incorrectly ordered impl items. + fn lint_impl_item<T: LintContext>(&self, cx: &T, item: &ImplItemRef, before_item: &ImplItemRef) { + span_lint_and_note( + cx, + ARBITRARY_SOURCE_ITEM_ORDERING, + item.span, + format!( + "incorrect ordering of impl items (defined order: {:?})", + self.assoc_types_order + ), + Some(before_item.span), + format!("should be placed before `{}`", before_item.ident.as_str(),), + ); + } + + /// Produces a linting warning for incorrectly ordered item members. + fn lint_member_name<T: LintContext>( + cx: &T, + ident: &rustc_span::symbol::Ident, + before_ident: &rustc_span::symbol::Ident, + ) { + span_lint_and_note( + cx, + ARBITRARY_SOURCE_ITEM_ORDERING, + ident.span, + "incorrect ordering of items (must be alphabetically ordered)", + Some(before_ident.span), + format!("should be placed before `{}`", before_ident.as_str(),), + ); + } + + fn lint_member_item<T: LintContext>(cx: &T, item: &Item<'_>, before_item: &Item<'_>) { + let span = if item.ident.as_str().is_empty() { + &item.span + } else { + &item.ident.span + }; + + let (before_span, note) = if before_item.ident.as_str().is_empty() { + ( + &before_item.span, + "should be placed before the following item".to_owned(), + ) + } else { + ( + &before_item.ident.span, + format!("should be placed before `{}`", before_item.ident.as_str(),), + ) + }; + + // This catches false positives where generated code gets linted. + if span == before_span { + return; + } + + span_lint_and_note( + cx, + ARBITRARY_SOURCE_ITEM_ORDERING, + *span, + "incorrect ordering of items (must be alphabetically ordered)", + Some(*before_span), + note, + ); + } + + /// Produces a linting warning for incorrectly ordered trait items. + fn lint_trait_item<T: LintContext>(&self, cx: &T, item: &TraitItemRef, before_item: &TraitItemRef) { + span_lint_and_note( + cx, + ARBITRARY_SOURCE_ITEM_ORDERING, + item.span, + format!( + "incorrect ordering of trait items (defined order: {:?})", + self.assoc_types_order + ), + Some(before_item.span), + format!("should be placed before `{}`", before_item.ident.as_str(),), + ); + } +} + +impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + match &item.kind { + ItemKind::Enum(enum_def, _generics) if self.enable_ordering_for_enum => { + let mut cur_v: Option<&Variant<'_>> = None; + for variant in enum_def.variants { + if in_external_macro(cx.sess(), variant.span) { + continue; + } + + if let Some(cur_v) = cur_v { + if cur_v.ident.name.as_str() > variant.ident.name.as_str() && cur_v.span != variant.span { + Self::lint_member_name(cx, &variant.ident, &cur_v.ident); + } + } + cur_v = Some(variant); + } + }, + ItemKind::Struct(VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => { + let mut cur_f: Option<&FieldDef<'_>> = None; + for field in *fields { + if in_external_macro(cx.sess(), field.span) { + continue; + } + + if let Some(cur_f) = cur_f { + if cur_f.ident.name.as_str() > field.ident.name.as_str() && cur_f.span != field.span { + Self::lint_member_name(cx, &field.ident, &cur_f.ident); + } + } + cur_f = Some(field); + } + }, + ItemKind::Trait(is_auto, _safety, _generics, _generic_bounds, item_ref) + if self.enable_ordering_for_trait && *is_auto == IsAuto::No => + { + let mut cur_t: Option<&TraitItemRef> = None; + + for item in *item_ref { + if in_external_macro(cx.sess(), item.span) { + continue; + } + + if let Some(cur_t) = cur_t { + let cur_t_kind = convert_assoc_item_kind(cur_t.kind); + let cur_t_kind_index = self.assoc_types_order.index_of(&cur_t_kind); + let item_kind = convert_assoc_item_kind(item.kind); + let item_kind_index = self.assoc_types_order.index_of(&item_kind); + + if cur_t_kind == item_kind && cur_t.ident.name.as_str() > item.ident.name.as_str() { + Self::lint_member_name(cx, &item.ident, &cur_t.ident); + } else if cur_t_kind_index > item_kind_index { + self.lint_trait_item(cx, item, cur_t); + } + } + cur_t = Some(item); + } + }, + ItemKind::Impl(trait_impl) if self.enable_ordering_for_impl => { + let mut cur_t: Option<&ImplItemRef> = None; + + for item in trait_impl.items { + if in_external_macro(cx.sess(), item.span) { + continue; + } + + if let Some(cur_t) = cur_t { + let cur_t_kind = convert_assoc_item_kind(cur_t.kind); + let cur_t_kind_index = self.assoc_types_order.index_of(&cur_t_kind); + let item_kind = convert_assoc_item_kind(item.kind); + let item_kind_index = self.assoc_types_order.index_of(&item_kind); + + if cur_t_kind == item_kind && cur_t.ident.name.as_str() > item.ident.name.as_str() { + Self::lint_member_name(cx, &item.ident, &cur_t.ident); + } else if cur_t_kind_index > item_kind_index { + self.lint_impl_item(cx, item, cur_t); + } + } + cur_t = Some(item); + } + }, + _ => {}, // Catch-all for `ItemKinds` that don't have fields. + } + } + + fn check_mod(&mut self, cx: &LateContext<'tcx>, module: &'tcx Mod<'tcx>, _: HirId) { + struct CurItem<'a> { + item: &'a Item<'a>, + order: usize, + name: String, + } + let mut cur_t: Option<CurItem<'_>> = None; + + if !self.enable_ordering_for_module { + return; + } + + let items = module.item_ids.iter().map(|&id| cx.tcx.hir().item(id)); + + // Iterates over the items within a module. + // + // As of 2023-05-09, the Rust compiler will hold the entries in the same + // order as they appear in the source code, which is convenient for us, + // as no sorting by source map/line of code has to be applied. + // + for item in items { + if in_external_macro(cx.sess(), item.span) { + continue; + } + + // The following exceptions (skipping with `continue;`) may not be + // complete, edge cases have not been explored further than what + // appears in the existing code base. + if item.ident.name == rustc_span::symbol::kw::Empty { + if let ItemKind::Impl(_) = item.kind { + // Sorting trait impls for unnamed types makes no sense. + if get_item_name(item).is_empty() { + continue; + } + } else if let ItemKind::ForeignMod { .. } = item.kind { + continue; + } else if let ItemKind::GlobalAsm(_) = item.kind { + continue; + } else if let ItemKind::Use(path, use_kind) = item.kind { + if path.segments.is_empty() { + // Use statements that contain braces get caught here. + // They will still be linted internally. + continue; + } else if path.segments.len() >= 2 + && (path.segments[0].ident.name == rustc_span::sym::std + || path.segments[0].ident.name == rustc_span::sym::core) + && path.segments[1].ident.name == rustc_span::sym::prelude + { + // Filters the autogenerated prelude use statement. + // e.g. `use std::prelude::rustc_2021` + } else if use_kind == UseKind::Glob { + // Filters glob kinds of uses. + // e.g. `use std::sync::*` + } else { + // This can be used for debugging. + // println!("Unknown autogenerated use statement: {:?}", item); + } + continue; + } + } + + if item.ident.name.as_str().starts_with('_') { + // Filters out unnamed macro-like impls for various derives, + // e.g. serde::Serialize or num_derive::FromPrimitive. + continue; + } + + if item.ident.name == rustc_span::sym::std && item.span.is_dummy() { + if let ItemKind::ExternCrate(None) = item.kind { + // Filters the auto-included Rust standard library. + continue; + } + println!("Unknown item: {item:?}"); + } + + let item_kind = convert_module_item_kind(&item.kind); + let module_level_order = self + .module_item_order_groupings + .module_level_order_of(&item_kind) + .unwrap_or_default(); + + if let Some(cur_t) = cur_t.as_ref() { + use std::cmp::Ordering; // Better legibility. + match module_level_order.cmp(&cur_t.order) { + Ordering::Less => { + Self::lint_member_item(cx, item, cur_t.item); + }, + Ordering::Equal if item_kind == SourceItemOrderingModuleItemKind::Use => { + // Skip ordering use statements, as these should be ordered by rustfmt. + }, + Ordering::Equal if cur_t.name > get_item_name(item) => { + Self::lint_member_item(cx, item, cur_t.item); + }, + Ordering::Equal | Ordering::Greater => { + // Nothing to do in this case, they're already in the right order. + }, + } + } + + // Makes a note of the current item for comparison with the next. + cur_t = Some(CurItem { + order: module_level_order, + item, + name: get_item_name(item), + }); + } + } +} + +/// Converts a [`rustc_hir::AssocItemKind`] to a +/// [`SourceItemOrderingTraitAssocItemKind`]. +/// +/// This is implemented here because `rustc_hir` is not a dependency of +/// `clippy_config`. +fn convert_assoc_item_kind(value: AssocItemKind) -> SourceItemOrderingTraitAssocItemKind { + #[allow(clippy::enum_glob_use)] // Very local glob use for legibility. + use SourceItemOrderingTraitAssocItemKind::*; + match value { + AssocItemKind::Const { .. } => Const, + AssocItemKind::Type { .. } => Type, + AssocItemKind::Fn { .. } => Fn, + } +} + +/// Converts a [`rustc_hir::ItemKind`] to a +/// [`SourceItemOrderingModuleItemKind`]. +/// +/// This is implemented here because `rustc_hir` is not a dependency of +/// `clippy_config`. +fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleItemKind { + #[allow(clippy::enum_glob_use)] // Very local glob use for legibility. + use SourceItemOrderingModuleItemKind::*; + match value { + ItemKind::ExternCrate(..) => ExternCrate, + ItemKind::Use(..) => Use, + ItemKind::Static(..) => Static, + ItemKind::Const(..) => Const, + ItemKind::Fn(..) => Fn, + ItemKind::Macro(..) => Macro, + ItemKind::Mod(..) => Mod, + ItemKind::ForeignMod { .. } => ForeignMod, + ItemKind::GlobalAsm(..) => GlobalAsm, + ItemKind::TyAlias(..) => TyAlias, + ItemKind::Enum(..) => Enum, + ItemKind::Struct(..) => Struct, + ItemKind::Union(..) => Union, + ItemKind::Trait(..) => Trait, + ItemKind::TraitAlias(..) => TraitAlias, + ItemKind::Impl(..) => Impl, + } +} + +/// Gets the item name for sorting purposes, which in the general case is +/// `item.ident.name`. +/// +/// For trait impls, the name used for sorting will be the written path of +/// `item.self_ty` plus the written path of `item.of_trait`, joined with +/// exclamation marks. Exclamation marks are used because they are the first +/// printable ASCII character. +/// +/// Trait impls generated using a derive-macro will have their path rewritten, +/// such that for example `Default` is `$crate::default::Default`, and +/// `std::clone::Clone` is `$crate::clone::Clone`. This behaviour is described +/// further in the [Rust Reference, Paths Chapter][rust_ref]. +/// +/// [rust_ref]: https://doc.rust-lang.org/reference/paths.html#crate-1 +fn get_item_name(item: &Item<'_>) -> String { + match item.kind { + ItemKind::Impl(im) => { + if let TyKind::Path(path) = im.self_ty.kind { + match path { + QPath::Resolved(_, path) => { + let segs = path.segments.iter(); + let mut segs: Vec<String> = segs.map(|s| s.ident.name.as_str().to_owned()).collect(); + + if let Some(of_trait) = im.of_trait { + let mut trait_segs: Vec<String> = of_trait + .path + .segments + .iter() + .map(|s| s.ident.name.as_str().to_owned()) + .collect(); + segs.append(&mut trait_segs); + } + + segs.push(String::new()); + segs.join("!!") + }, + QPath::TypeRelative(_, _path_seg) => { + // This case doesn't exist in the clippy tests codebase. + String::new() + }, + QPath::LangItem(_, _) => String::new(), + } + } else { + // Impls for anything that isn't a named type can be skipped. + String::new() + } + }, + _ => item.ident.name.as_str().to_owned(), + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs index a5a7b9f74a6..1879391ec29 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs @@ -3,11 +3,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use rustc_ast::{AttrStyle, Attribute}; use rustc_errors::Applicability; -use rustc_lint::{LateContext, LintContext}; +use rustc_lint::{EarlyContext, LintContext}; use rustc_middle::lint::in_external_macro; // Separate each crate's features. -pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) { +pub fn check<'cx>(cx: &EarlyContext<'cx>, attr: &'cx Attribute) { if !in_external_macro(cx.sess(), attr.span) && let AttrStyle::Outer = attr.style && let Some(ident) = attr.ident() diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs index 5d4e864b9b0..788377fe83c 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs @@ -2,12 +2,12 @@ use super::{ALLOW_ATTRIBUTES_WITHOUT_REASON, Attribute}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use rustc_ast::{MetaItemInner, MetaItemKind}; -use rustc_lint::{LateContext, LintContext}; +use rustc_lint::{EarlyContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_span::sym; use rustc_span::symbol::Symbol; -pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) { +pub(super) fn check<'cx>(cx: &EarlyContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) { // Check if the reason is present if let Some(item) = items.last().and_then(MetaItemInner::meta_item) && let MetaItemKind::NameValue(_) = &item.kind diff --git a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs index 0baf889faa0..fecf3166406 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs @@ -2,11 +2,11 @@ use super::BLANKET_CLIPPY_RESTRICTION_LINTS; use super::utils::extract_clippy_lint; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use rustc_ast::MetaItemInner; -use rustc_lint::{LateContext, Level, LintContext}; +use rustc_lint::{EarlyContext, Level, LintContext}; use rustc_span::symbol::Symbol; use rustc_span::{DUMMY_SP, sym}; -pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner]) { +pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) { for lint in items { if let Some(lint_name) = extract_clippy_lint(lint) { if lint_name.as_str() == "restriction" && name != sym::allow { @@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner]) } } -pub(super) fn check_command_line(cx: &LateContext<'_>) { +pub(super) fn check_command_line(cx: &EarlyContext<'_>) { for (name, level) in &cx.sess().opts.lint_opts { if name == "clippy::restriction" && *level > Level::Allow { span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs index 1898c145c76..d3153ec6613 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs @@ -1,11 +1,11 @@ use super::DEPRECATED_SEMVER; use clippy_utils::diagnostics::span_lint; use rustc_ast::{LitKind, MetaItemLit}; -use rustc_lint::LateContext; +use rustc_lint::EarlyContext; use rustc_span::Span; use semver::Version; -pub(super) fn check(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) { +pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) { if let LitKind::Str(is, _) = lit.kind { if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() { return; diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs index 55f8e1072db..2ddbc7a6a76 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs @@ -2,12 +2,12 @@ use super::DUPLICATED_ATTRIBUTES; use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::{Attribute, MetaItem}; use rustc_data_structures::fx::FxHashMap; -use rustc_lint::LateContext; +use rustc_lint::EarlyContext; use rustc_span::{Span, sym}; use std::collections::hash_map::Entry; fn emit_if_duplicated( - cx: &LateContext<'_>, + cx: &EarlyContext<'_>, attr: &MetaItem, attr_paths: &mut FxHashMap<String, Span>, complete_path: String, @@ -26,7 +26,7 @@ fn emit_if_duplicated( } fn check_duplicated_attr( - cx: &LateContext<'_>, + cx: &EarlyContext<'_>, attr: &MetaItem, attr_paths: &mut FxHashMap<String, Span>, parent: &mut Vec<String>, @@ -65,7 +65,7 @@ fn check_duplicated_attr( } } -pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { +pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) { let mut attr_paths = FxHashMap::default(); for attr in attrs { diff --git a/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs b/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs index 5d2ea36b366..32c28c09c36 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::{AttrKind, AttrStyle, Attribute}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; -use rustc_lint::{LateContext, LintContext}; +use rustc_lint::{EarlyContext, LintContext}; use rustc_span::source_map::SourceMap; use rustc_span::{SourceFile, Span, Symbol}; @@ -32,7 +32,7 @@ impl From<&AttrKind> for SimpleAttrKind { } } -pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) { +pub(super) fn check(cx: &EarlyContext<'_>, item_span: Span, attrs: &[Attribute]) { let mut inner_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default(); let mut outer_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default(); @@ -64,7 +64,7 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) } } -fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) { +fn lint_mixed_attrs(cx: &EarlyContext<'_>, attrs: &[Attribute]) { let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion()); let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) { first.span.with_hi(last.span.hi()) diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index 1a34ca99fc2..c29c9f08cf7 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -14,8 +14,8 @@ mod utils; use clippy_config::Conf; use clippy_config::msrvs::{self, Msrv}; -use rustc_ast::{Attribute, MetaItemInner, MetaItemKind}; -use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; +use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind}; +use rustc_hir::{ImplItem, Item, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::sym; @@ -414,15 +414,7 @@ pub struct Attributes { } impl_lint_pass!(Attributes => [ - ALLOW_ATTRIBUTES, - ALLOW_ATTRIBUTES_WITHOUT_REASON, INLINE_ALWAYS, - DEPRECATED_SEMVER, - USELESS_ATTRIBUTE, - BLANKET_CLIPPY_RESTRICTION_LINTS, - SHOULD_PANIC_WITHOUT_EXPECT, - MIXED_ATTRIBUTES_STYLE, - DUPLICATED_ATTRIBUTES, ]); impl Attributes { @@ -434,53 +426,11 @@ impl Attributes { } impl<'tcx> LateLintPass<'tcx> for Attributes { - fn check_crate(&mut self, cx: &LateContext<'tcx>) { - blanket_clippy_restriction_lints::check_command_line(cx); - duplicated_attributes::check(cx, cx.tcx.hir().krate_attrs()); - } - - fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) { - if let Some(items) = &attr.meta_item_list() { - if let Some(ident) = attr.ident() { - if is_lint_level(ident.name, attr.id) { - blanket_clippy_restriction_lints::check(cx, ident.name, items); - } - if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) { - allow_attributes::check(cx, attr); - } - if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) - { - allow_attributes_without_reason::check(cx, ident.name, items, attr); - } - if items.is_empty() || !attr.has_name(sym::deprecated) { - return; - } - for item in items { - if let MetaItemInner::MetaItem(mi) = &item - && let MetaItemKind::NameValue(lit) = &mi.kind - && mi.has_name(sym::since) - { - deprecated_semver::check(cx, item.span(), lit); - } - } - } - } - if attr.has_name(sym::should_panic) { - should_panic_without_expect::check(cx, attr); - } - } - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { let attrs = cx.tcx.hir().attrs(item.hir_id()); if is_relevant_item(cx, item) { inline_always::check(cx, item.span, item.ident.name, attrs); } - match item.kind { - ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs), - _ => {}, - } - mixed_attributes_style::check(cx, item.span, attrs); - duplicated_attributes::check(cx, attrs); } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { @@ -526,3 +476,77 @@ impl EarlyLintPass for EarlyAttributes { extract_msrv_attr!(EarlyContext); } + +pub struct PostExpansionEarlyAttributes { + msrv: Msrv, +} + +impl PostExpansionEarlyAttributes { + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } + } +} + +impl_lint_pass!(PostExpansionEarlyAttributes => [ + ALLOW_ATTRIBUTES, + ALLOW_ATTRIBUTES_WITHOUT_REASON, + DEPRECATED_SEMVER, + USELESS_ATTRIBUTE, + BLANKET_CLIPPY_RESTRICTION_LINTS, + SHOULD_PANIC_WITHOUT_EXPECT, + MIXED_ATTRIBUTES_STYLE, + DUPLICATED_ATTRIBUTES, +]); + +impl EarlyLintPass for PostExpansionEarlyAttributes { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) { + blanket_clippy_restriction_lints::check_command_line(cx); + duplicated_attributes::check(cx, &krate.attrs); + } + + fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { + if let Some(items) = &attr.meta_item_list() { + if let Some(ident) = attr.ident() { + if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) { + allow_attributes::check(cx, attr); + } + if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) + { + allow_attributes_without_reason::check(cx, ident.name, items, attr); + } + if is_lint_level(ident.name, attr.id) { + blanket_clippy_restriction_lints::check(cx, ident.name, items); + } + if items.is_empty() || !attr.has_name(sym::deprecated) { + return; + } + for item in items { + if let MetaItemInner::MetaItem(mi) = &item + && let MetaItemKind::NameValue(lit) = &mi.kind + && mi.has_name(sym::since) + { + deprecated_semver::check(cx, item.span(), lit); + } + } + } + } + + if attr.has_name(sym::should_panic) { + should_panic_without_expect::check(cx, attr); + } + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &'_ ast::Item) { + match item.kind { + ast::ItemKind::ExternCrate(..) | ast::ItemKind::Use(..) => useless_attribute::check(cx, item, &item.attrs), + _ => {}, + } + + mixed_attributes_style::check(cx, item.span, &item.attrs); + duplicated_attributes::check(cx, &item.attrs); + } + + extract_msrv_attr!(EarlyContext); +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs index 2d45cbbf621..fadd5272880 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -4,12 +4,12 @@ use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::TokenTree; use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind}; use rustc_errors::Applicability; -use rustc_lint::LateContext; +use rustc_lint::EarlyContext; use rustc_span::sym; -pub(super) fn check(cx: &LateContext<'_>, attr: &Attribute) { +pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { if let AttrKind::Normal(normal_attr) = &attr.kind { - if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args { + if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args { // `#[should_panic = ".."]` found, good return; } diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs index 72e6ce59d59..dc5a6857089 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs @@ -1,15 +1,14 @@ +use super::USELESS_ATTRIBUTE; use super::utils::{extract_clippy_lint, is_lint_level, is_word}; -use super::{Attribute, USELESS_ATTRIBUTE}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{SpanRangeExt, first_line_of_span}; -use rustc_ast::MetaItemInner; +use rustc_ast::{Attribute, Item, ItemKind, MetaItemInner}; use rustc_errors::Applicability; -use rustc_hir::{Item, ItemKind}; -use rustc_lint::{LateContext, LintContext}; +use rustc_lint::{EarlyContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_span::sym; -pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) { +pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use)); for attr in attrs { diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs index 9952d0af99e..6948cf560a5 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs @@ -15,7 +15,7 @@ declare_clippy_lint! { /// `MutexGuard`. /// /// ### Why is this bad? - /// The Mutex types found in [`std::sync`][https://doc.rust-lang.org/stable/std/sync/] and + /// The Mutex types found in [`std::sync`](https://doc.rust-lang.org/stable/std/sync/) and /// [`parking_lot`](https://docs.rs/parking_lot/latest/parking_lot/) are /// not designed to operate in an async context across await points. /// diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 26888f7e3a0..26a20bc99a0 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -203,6 +203,21 @@ fn check_simplify_not(cx: &LateContext<'_>, msrv: &Msrv, expr: &Expr<'_>) { && let Some(suggestion) = simplify_not(cx, msrv, inner) && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow { + use clippy_utils::sugg::{Sugg, has_enclosing_paren}; + let maybe_par = if let Some(sug) = Sugg::hir_opt(cx, inner) { + match sug { + Sugg::BinOp(..) => true, + Sugg::MaybeParen(sug) if !has_enclosing_paren(&sug) => true, + _ => false, + } + } else { + false + }; + let suggestion = if maybe_par { + format!("({suggestion})") + } else { + suggestion + }; span_lint_and_sugg( cx, NONMINIMAL_BOOL, diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs index cba8224b84c..f2551a05b1a 100644 --- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs +++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs @@ -4,7 +4,7 @@ use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed}; use rustc_errors::Applicability; -use rustc_hir::{ExprKind, UnOp}; +use rustc_hir::{BorrowKind, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::Mutability; use rustc_middle::ty; @@ -49,7 +49,7 @@ declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]); impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) { - if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind + if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, addrof_target) = e.kind && let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind && !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..)) && !e.span.from_expansion() diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs index b11b967f8bc..205357afd84 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { ); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); } else if let ExprKind::MethodCall(method_path, self_arg, [], _) = &expr.kind { - if method_path.ident.name == sym!(cast) + if method_path.ident.name.as_str() == "cast" && let Some(generic_args) = method_path.args && let [GenericArg::Type(cast_to)] = generic_args.args // There probably is no obvious reason to do this, just to be consistent with `as` cases. diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index 811d33c8bde..abd80abffe6 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -268,8 +268,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx if !snippet .split("->") .skip(1) - .map(|s| snippet_eq_ty(s, cast_from) || s.split("where").any(|ty| snippet_eq_ty(ty, cast_from))) - .any(|a| a) + .any(|s| snippet_eq_ty(s, cast_from) || s.split("where").any(|ty| snippet_eq_ty(ty, cast_from))) { return ControlFlow::Break(()); } diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index 2e7f91a842e..f76e399517c 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -232,7 +232,7 @@ fn get_types_from_cast<'a>( // or `to_type::MAX as from_type` let call_from_cast: Option<(&Expr<'_>, &str)> = if let ExprKind::Cast(limit, from_type) = &expr.kind // to_type::max_value(), from_type - && let TyKind::Path(ref from_type_path) = &from_type.kind + && let TyKind::Path(from_type_path) = &from_type.kind && let Some(from_sym) = int_ty_to_sym(from_type_path) { Some((limit, from_sym)) @@ -245,7 +245,7 @@ fn get_types_from_cast<'a>( if let ExprKind::Call(from_func, [limit]) = &expr.kind // `from_type::from, to_type::max_value()` // `from_type::from` - && let ExprKind::Path(ref path) = &from_func.kind + && let ExprKind::Path(path) = &from_func.kind && let Some(from_sym) = get_implementing_type(path, INTS, "from") { Some((limit, from_sym)) diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs index 477435236a5..383fae7992b 100644 --- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs @@ -30,7 +30,7 @@ declare_clippy_lint! { #[clippy::version = "1.35.0"] pub COGNITIVE_COMPLEXITY, nursery, - "functions that should be split up into multiple functions" + "functions that should be split up into multiple functions", @eval_always = true } diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index d90a22bb62a..c4afdc757d8 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -540,24 +540,22 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo .iter() .filter(|&&(_, name)| !name.as_str().starts_with('_')) .any(|&(_, name)| { - let mut walker = ContainsName { - name, - result: false, - cx, - }; + let mut walker = ContainsName { name, cx }; // Scan block - block + let mut res = block .stmts .iter() .filter(|stmt| !ignore_span.overlaps(stmt.span)) - .for_each(|stmt| intravisit::walk_stmt(&mut walker, stmt)); + .try_for_each(|stmt| intravisit::walk_stmt(&mut walker, stmt)); if let Some(expr) = block.expr { - intravisit::walk_expr(&mut walker, expr); + if res.is_continue() { + res = intravisit::walk_expr(&mut walker, expr); + } } - walker.result + res.is_break() }) }) } diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs index 50fd76a3a47..4ecf3e41611 100644 --- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs @@ -37,7 +37,7 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]); impl<'tcx> LateLintPass<'tcx> for CopyIterator { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), + of_trait: Some(trait_ref), .. }) = item.kind && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() diff --git a/src/tools/clippy/clippy_lints/src/ctfe.rs b/src/tools/clippy/clippy_lints/src/ctfe.rs index 2fe37a64db6..589b99518a0 100644 --- a/src/tools/clippy/clippy_lints/src/ctfe.rs +++ b/src/tools/clippy/clippy_lints/src/ctfe.rs @@ -1,29 +1,15 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; -use rustc_lint::Level::Deny; -use rustc_lint::{LateContext, LateLintPass, Lint}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::Span; -/// Ensures that Constant-time Function Evaluation is being done (specifically, MIR lint passes). -/// As Clippy deactivates codegen, this lint ensures that CTFE (used in hard errors) is still ran. -pub static CLIPPY_CTFE: &Lint = &Lint { - name: &"clippy::CLIPPY_CTFE", - default_level: Deny, - desc: "Ensure CTFE is being made", - edition_lint_opts: None, - report_in_external_macro: true, - future_incompatible: None, - is_externally_loaded: true, - crate_level_only: false, - eval_always: true, - ..Lint::default_fields_for_macro() -}; - -// No static CLIPPY_CTFE_INFO because we want this lint to be invisible - -declare_lint_pass! { ClippyCtfe => [CLIPPY_CTFE] } +declare_lint_pass! { + /// Ensures that Constant-time Function Evaluation is being done (specifically, MIR lint passes). + /// As Clippy deactivates codegen, this lint ensures that CTFE (used in hard errors) is still ran. + ClippyCtfe => [] +} impl<'tcx> LateLintPass<'tcx> for ClippyCtfe { fn check_fn( diff --git a/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs b/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs index a785a9d377c..4d908af4084 100644 --- a/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs +++ b/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs @@ -4,7 +4,7 @@ macro_rules! declare_clippy_lint { (@ $(#[doc = $lit:literal])* pub $lint_name:ident, - $category:ident, + $level:ident, $lintcategory:expr, $desc:literal, $version_expr:expr, @@ -15,7 +15,7 @@ macro_rules! declare_clippy_lint { $(#[doc = $lit])* #[clippy::version = $version_lit] pub clippy::$lint_name, - $category, + $level, $desc, report_in_external_macro:true $(, @eval_always = $eval_always)? @@ -35,12 +35,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, restriction, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Allow, crate::LintCategory::Restriction, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; ( @@ -49,12 +50,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, style, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Warn, crate::LintCategory::Style, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; ( @@ -63,12 +65,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, correctness, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Deny, crate::LintCategory::Correctness, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; @@ -78,12 +81,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, perf, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Warn, crate::LintCategory::Perf, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; ( @@ -92,12 +96,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, complexity, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Warn, crate::LintCategory::Complexity, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; ( @@ -106,12 +111,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, suspicious, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Warn, crate::LintCategory::Suspicious, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; ( @@ -120,12 +126,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, nursery, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Allow, crate::LintCategory::Nursery, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; ( @@ -134,12 +141,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, pedantic, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Allow, crate::LintCategory::Pedantic, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; ( @@ -148,12 +156,13 @@ macro_rules! declare_clippy_lint { pub $lint_name:ident, cargo, $desc:literal - $(@eval_always = $eval_always: literal)? + $(, @eval_always = $eval_always: literal)? ) => { declare_clippy_lint! {@ $(#[doc = $lit])* pub $lint_name, Allow, crate::LintCategory::Cargo, $desc, - Some($version), $version $(, $eval_always)? + Some($version), $version + $(, $eval_always)? } }; diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 3c4e75df8ab..edb52851e0c 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -28,12 +28,15 @@ pub static LINTS: &[&crate::LintInfo] = &[ #[cfg(feature = "internal")] crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO, #[cfg(feature = "internal")] + crate::utils::internal_lints::slow_symbol_comparisons::SLOW_SYMBOL_COMPARISONS_INFO, + #[cfg(feature = "internal")] crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO, #[cfg(feature = "internal")] crate::utils::internal_lints::unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS_INFO, crate::absolute_paths::ABSOLUTE_PATHS_INFO, crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO, crate::approx_const::APPROX_CONSTANT_INFO, + crate::arbitrary_source_item_ordering::ARBITRARY_SOURCE_ITEM_ORDERING_INFO, crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO, crate::as_conversions::AS_CONVERSIONS_INFO, crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO, @@ -414,14 +417,17 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::methods::MANUAL_SPLIT_ONCE_INFO, crate::methods::MANUAL_STR_REPEAT_INFO, crate::methods::MANUAL_TRY_FOLD_INFO, + crate::methods::MAP_ALL_ANY_IDENTITY_INFO, crate::methods::MAP_CLONE_INFO, crate::methods::MAP_COLLECT_RESULT_UNIT_INFO, crate::methods::MAP_ERR_IGNORE_INFO, crate::methods::MAP_FLATTEN_INFO, crate::methods::MAP_IDENTITY_INFO, crate::methods::MAP_UNWRAP_OR_INFO, + crate::methods::MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES_INFO, crate::methods::MUT_MUTEX_LOCK_INFO, crate::methods::NAIVE_BYTECOUNT_INFO, + crate::methods::NEEDLESS_AS_BYTES_INFO, crate::methods::NEEDLESS_CHARACTER_ITERATION_INFO, crate::methods::NEEDLESS_COLLECT_INFO, crate::methods::NEEDLESS_OPTION_AS_DEREF_INFO, diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index 2920bbb4c81..2b6bfafe695 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -187,7 +187,7 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex impl<'tcx> LateLintPass<'tcx> for DerivableImpls { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), + of_trait: Some(trait_ref), items: [child], self_ty, .. diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index e8e21edd494..e569c4dc786 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy}; use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths}; @@ -202,7 +204,7 @@ declare_lint_pass!(Derive => [ impl<'tcx> LateLintPass<'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), + of_trait: Some(trait_ref), .. }) = item.kind { @@ -371,9 +373,8 @@ fn check_unsafe_derive_deserialize<'tcx>( ty: Ty<'tcx>, ) { fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool { - let mut visitor = UnsafeVisitor { cx, has_unsafe: false }; - walk_item(&mut visitor, item); - visitor.has_unsafe + let mut visitor = UnsafeVisitor { cx }; + walk_item(&mut visitor, item).is_break() } if let Some(trait_def_id) = trait_ref.trait_def_id() @@ -406,38 +407,37 @@ fn check_unsafe_derive_deserialize<'tcx>( struct UnsafeVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - has_unsafe: bool, } impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { + type Result = ControlFlow<()>; type NestedFilter = nested_filter::All; - fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, _: Span, id: LocalDefId) { - if self.has_unsafe { - return; - } - + fn visit_fn( + &mut self, + kind: FnKind<'tcx>, + decl: &'tcx FnDecl<'_>, + body_id: BodyId, + _: Span, + id: LocalDefId, + ) -> Self::Result { if let Some(header) = kind.header() && header.safety == Safety::Unsafe { - self.has_unsafe = true; + ControlFlow::Break(()) + } else { + walk_fn(self, kind, decl, body_id, id) } - - walk_fn(self, kind, decl, body_id, id); } - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if self.has_unsafe { - return; - } - + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> Self::Result { if let ExprKind::Block(block, _) = expr.kind { if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) { - self.has_unsafe = true; + return ControlFlow::Break(()); } } - walk_expr(self, expr); + walk_expr(self, expr) } fn nested_visit_map(&mut self) -> Self::Map { diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs index b51d343132b..bdd49bf8aa7 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs @@ -2,7 +2,6 @@ use clippy_config::Conf; use clippy_utils::create_disallowed_map; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::macros::macro_backtrace; -use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diag; use rustc_hir::def_id::DefIdMap; @@ -14,6 +13,8 @@ use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; use rustc_span::{ExpnId, MacroKind, Span}; +use crate::utils::attr_collector::AttrStorage; + declare_clippy_lint! { /// ### What it does /// Denies the configured macros in clippy.toml @@ -64,14 +65,19 @@ pub struct DisallowedMacros { // Track the most recently seen node that can have a `derive` attribute. // Needed to use the correct lint level. derive_src: Option<OwnerId>, + + // When a macro is disallowed in an early pass, it's stored + // and emitted during the late pass. This happens for attributes. + earlies: AttrStorage, } impl DisallowedMacros { - pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf, earlies: AttrStorage) -> Self { Self { disallowed: create_disallowed_map(tcx, &conf.disallowed_macros), seen: FxHashSet::default(), derive_src: None, + earlies, } } @@ -114,6 +120,15 @@ impl DisallowedMacros { impl_lint_pass!(DisallowedMacros => [DISALLOWED_MACROS]); impl LateLintPass<'_> for DisallowedMacros { + fn check_crate(&mut self, cx: &LateContext<'_>) { + // once we check a crate in the late pass we can emit the early pass lints + if let Some(attr_spans) = self.earlies.clone().0.get() { + for span in attr_spans { + self.check(cx, *span, None); + } + } + } + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { self.check(cx, expr.span, None); // `$t + $t` can have the context of $t, check also the span of the binary operator @@ -164,8 +179,4 @@ impl LateLintPass<'_> for DisallowedMacros { fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, _: HirId) { self.check(cx, path.span, None); } - - fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &Attribute) { - self.check(cx, attr.span, self.derive_src); - } } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs index f79264e6b04..53c24a3faf1 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs @@ -80,7 +80,7 @@ impl EarlyLintPass for DisallowedScriptIdents { let mut symbols: Vec<_> = symbols.iter().collect(); symbols.sort_unstable_by_key(|k| k.1); - for (symbol, &span) in &symbols { + for &(symbol, &span) in &symbols { // Note: `symbol.as_str()` is an expensive operation, thus should not be called // more than once for a single symbol. let symbol_str = symbol.as_str(); diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index 89c6a4e08dc..df7c37a192a 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -427,11 +427,11 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks if the first line in the documentation of items listed in module page is too long. + /// Checks if the first paragraph in the documentation of items listed in the module page is too long. /// /// ### Why is this bad? - /// Documentation will show the first paragraph of the doscstring in the summary page of a - /// module, so having a nice, short summary in the first paragraph is part of writing good docs. + /// Documentation will show the first paragraph of the docstring in the summary page of a + /// module. Having a nice, short summary in the first paragraph is part of writing good docs. /// /// ### Example /// ```no_run @@ -453,7 +453,7 @@ declare_clippy_lint! { #[clippy::version = "1.82.0"] pub TOO_LONG_FIRST_DOC_PARAGRAPH, nursery, - "ensure that the first line of a documentation paragraph isn't too long" + "ensure the first documentation paragraph is short" } declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/empty_drop.rs b/src/tools/clippy/clippy_lints/src/empty_drop.rs index b66dd2108fc..10a84b1b2ff 100644 --- a/src/tools/clippy/clippy_lints/src/empty_drop.rs +++ b/src/tools/clippy/clippy_lints/src/empty_drop.rs @@ -36,7 +36,7 @@ declare_lint_pass!(EmptyDrop => [EMPTY_DROP]); impl LateLintPass<'_> for EmptyDrop { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), + of_trait: Some(trait_ref), items: [child], .. }) = item.kind diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 6ca599ed361..de10b7bf533 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -9,8 +9,7 @@ use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Saf use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ - self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, - TypeckResults, + self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults, }; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; @@ -204,11 +203,16 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc // 'cuz currently nothing changes after deleting this check. local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr) }) { - match cx.tcx.infer_ctxt().build(cx.typing_mode()).err_ctxt().type_implements_fn_trait( - cx.param_env, - Binder::bind_with_vars(callee_ty_adjusted, List::empty()), - ty::PredicatePolarity::Positive, - ) { + match cx + .tcx + .infer_ctxt() + .build(cx.typing_mode()) + .err_ctxt() + .type_implements_fn_trait( + cx.param_env, + Binder::bind_with_vars(callee_ty_adjusted, List::empty()), + ty::PredicatePolarity::Positive, + ) { // Mutable closure is used after current expr; we cannot consume it. Ok((ClosureKind::FnMut, _)) => snippet = format!("&mut {snippet}"), Ok((ClosureKind::Fn, _)) if !callee_ty_raw.is_ref() => { diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index 4e4434ec7d1..0550c22761a 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { // match call to write_fmt && let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = *look_in_block(cx, &write_call.kind) && let ExprKind::Call(write_recv_path, []) = write_recv.kind - && write_fun.ident.name == sym!(write_fmt) + && write_fun.ident.name.as_str() == "write_fmt" && let Some(def_id) = path_def_id(cx, write_recv_path) { // match calls to std::io::stdout() / std::io::stderr () diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index d5a2e06863d..14da0b515a5 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use clippy_config::Conf; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; @@ -115,25 +117,26 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { } /// Finds the occurrences of `Self` and `self` +/// +/// Returns `ControlFlow::break` if any of the `self`/`Self` usages were from an expansion, or the +/// body contained a binding already named `val`. struct SelfFinder<'a, 'tcx> { cx: &'a LateContext<'tcx>, /// Occurrences of `Self` upper: Vec<Span>, /// Occurrences of `self` lower: Vec<Span>, - /// If any of the `self`/`Self` usages were from an expansion, or the body contained a binding - /// already named `val` - invalid: bool, } impl<'tcx> Visitor<'tcx> for SelfFinder<'_, 'tcx> { + type Result = ControlFlow<()>; type NestedFilter = OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { self.cx.tcx.hir() } - fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) { + fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) -> Self::Result { for segment in path.segments { match segment.ident.name { kw::SelfLower => self.lower.push(segment.ident.span), @@ -141,17 +144,19 @@ impl<'tcx> Visitor<'tcx> for SelfFinder<'_, 'tcx> { _ => continue, } - self.invalid |= segment.ident.span.from_expansion(); + if segment.ident.span.from_expansion() { + return ControlFlow::Break(()); + } } - if !self.invalid { - walk_path(self, path); - } + walk_path(self, path) } - fn visit_name(&mut self, name: Symbol) { + fn visit_name(&mut self, name: Symbol) -> Self::Result { if name == sym::val { - self.invalid = true; + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) } } } @@ -209,11 +214,9 @@ fn convert_to_from( cx, upper: Vec::new(), lower: Vec::new(), - invalid: false, }; - finder.visit_expr(body.value); - if finder.invalid { + if finder.visit_expr(body.value).is_break() { return None; } diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs index d62d008d480..c8828c93615 100644 --- a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs @@ -41,7 +41,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if let ExprKind::Call(box_from_raw, [arg]) = expr.kind && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_from_raw.kind - && seg.ident.name == sym!(from_raw) + && seg.ident.name.as_str() == "from_raw" && let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id)) && let arg_kind = cx.typeck_results().expr_ty(arg).kind() && let ty::RawPtr(ty, _) = arg_kind diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs index 91d73c2a9c9..be3d0f7ad63 100644 --- a/src/tools/clippy/clippy_lints/src/functions/mod.rs +++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs @@ -441,7 +441,7 @@ declare_clippy_lint! { /// fn bar(&self) -> Option<&String> { None } /// # } /// ``` - #[clippy::version = "1.82.0"] + #[clippy::version = "1.83.0"] pub REF_OPTION, pedantic, "function signature uses `&Option<T>` instead of `Option<&T>`" diff --git a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs index 373ecd74cb3..aba0fbcb9fe 100644 --- a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs +++ b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs @@ -15,9 +15,9 @@ use rustc_span::{Span, sym}; fn check_ty<'a>(cx: &LateContext<'a>, param: &rustc_hir::Ty<'a>, param_ty: Ty<'a>, fixes: &mut Vec<(Span, String)>) { if let ty::Ref(_, opt_ty, Mutability::Not) = param_ty.kind() && is_type_diagnostic_item(cx, *opt_ty, sym::Option) - && let ty::Adt(_, opt_gen) = opt_ty.kind() - && let [gen] = opt_gen.as_slice() - && let GenericArgKind::Type(gen_ty) = gen.unpack() + && let ty::Adt(_, opt_gen_args) = opt_ty.kind() + && let [gen_arg] = opt_gen_args.as_slice() + && let GenericArgKind::Type(gen_ty) = gen_arg.unpack() && !gen_ty.is_ref() // Need to gen the original spans, so first parsing mid, and hir parsing afterward && let hir::TyKind::Ref(lifetime, hir::MutTy { ty, .. }) = param.kind diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 4c5375730b8..c370f206c8f 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -340,7 +340,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { if self.cx.tcx.is_diagnostic_item(sym::HashMap, ty_did) { if method.ident.name == sym::new { self.suggestions.insert(e.span, "HashMap::default()".to_string()); - } else if method.ident.name == sym!(with_capacity) { + } else if method.ident.name.as_str() == "with_capacity" { self.suggestions.insert( e.span, format!( @@ -352,7 +352,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { } else if self.cx.tcx.is_diagnostic_item(sym::HashSet, ty_did) { if method.ident.name == sym::new { self.suggestions.insert(e.span, "HashSet::default()".to_string()); - } else if method.ident.name == sym!(with_capacity) { + } else if method.ident.name.as_str() == "with_capacity" { self.suggestions.insert( e.span, format!( diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index 71c317552ee..48874d6064b 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -157,7 +157,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { .and(cap); } } - if method.ident.name == sym!(flat_map) && args.len() == 1 { + if method.ident.name.as_str() == "flat_map" && args.len() == 1 { if let ExprKind::Closure(&Closure { body, .. }) = args[0].kind { let body = cx.tcx.hir().body(body); return is_infinite(cx, body.value); @@ -224,7 +224,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { return MaybeInfinite.and(is_infinite(cx, receiver)); } } - if method.ident.name == sym!(last) && args.is_empty() { + if method.ident.name.as_str() == "last" && args.is_empty() { let not_double_ended = cx .tcx .get_diagnostic_item(sym::DoubleEndedIterator) @@ -234,7 +234,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { if not_double_ended { return is_infinite(cx, receiver); } - } else if method.ident.name == sym!(collect) { + } else if method.ident.name.as_str() == "collect" { let ty = cx.typeck_results().expr_ty(expr); if matches!( get_type_diagnostic_name(cx, ty), diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 1e6404190d3..314d0dfa26c 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -142,7 +142,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter { ty.peel_refs().is_slice() || get_adt_inherent_method(cx, ty, expected_method_name).is_some() }) && let Some(iter_assoc_span) = imp.items.iter().find_map(|item| { - if item.ident.name == sym!(IntoIter) { + if item.ident.name.as_str() == "IntoIter" { Some(cx.tcx.hir().impl_item(item.id).expect_type().span) } else { None @@ -247,8 +247,8 @@ impl {self_ty_without_ref} {{ let sugg = format!( " impl IntoIterator for {self_ty_snippet} {{ - type IntoIter = {ret_ty}; type Item = {iter_ty}; + type IntoIter = {ret_ty}; fn into_iter(self) -> Self::IntoIter {{ self.iter() }} diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 5d2b521b250..aa8b4d88d2f 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, ConstKind}; +use rustc_middle::ty::{self, ParamEnv}; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, Span}; @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { && !item.span.from_expansion() && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Array(element_type, cst) = ty.kind() - && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind() + && let Ok((_, ty::ValTree::Leaf(element_count))) = cst.eval_valtree(cx.tcx, ParamEnv::empty(), item.span) && let element_count = element_count.to_target_usize(cx.tcx) && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size) diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs index f2f841dcec3..ab3d19f89c3 100644 --- a/src/tools/clippy/clippy_lints/src/large_include_file.rs +++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs @@ -1,11 +1,12 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::root_macro_call_first_node; -use rustc_ast::LitKind; +use clippy_utils::source::snippet_opt; +use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::sym; +use rustc_span::{Span, sym}; declare_clippy_lint! { /// ### What it does @@ -51,6 +52,24 @@ impl LargeIncludeFile { impl_lint_pass!(LargeIncludeFile => [LARGE_INCLUDE_FILE]); +impl LargeIncludeFile { + fn emit_lint(&self, cx: &LateContext<'_>, span: Span) { + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( + cx, + LARGE_INCLUDE_FILE, + span, + "attempted to include a large file", + |diag| { + diag.note(format!( + "the configuration allows a maximum size of {} bytes", + self.max_file_size + )); + }, + ); + } +} + impl LateLintPass<'_> for LargeIncludeFile { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { if let ExprKind::Lit(lit) = &expr.kind @@ -66,19 +85,33 @@ impl LateLintPass<'_> for LargeIncludeFile { && (cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id) || cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id)) { - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] - span_lint_and_then( - cx, - LARGE_INCLUDE_FILE, - expr.span.source_callsite(), - "attempted to include a large file", - |diag| { - diag.note(format!( - "the configuration allows a maximum size of {} bytes", - self.max_file_size - )); - }, - ); + self.emit_lint(cx, expr.span.source_callsite()); + } + } + + fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &Attribute) { + if !attr.span.from_expansion() + // Currently, rustc limits the usage of macro at the top-level of attributes, + // so we don't need to recurse into each level. + && let AttrKind::Normal(ref normal) = attr.kind + && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args + && !attr.span.contains(meta.span) + // Since the `include_str` is already expanded at this point, we can only take the + // whole attribute snippet and then modify for our suggestion. + && let Some(snippet) = snippet_opt(cx, attr.span) + // We cannot remove this because a `#[doc = include_str!("...")]` attribute can + // occupy several lines. + && let Some(start) = snippet.find('[') + && let Some(end) = snippet.rfind(']') + && let snippet = &snippet[start + 1..end] + // We check that the expansion actually comes from `include_str!` and not just from + // another macro. + && let Some(sub_snippet) = snippet.trim().strip_prefix("doc") + && let Some(sub_snippet) = sub_snippet.trim().strip_prefix("=") + && let sub_snippet = sub_snippet.trim() + && (sub_snippet.starts_with("include_str!") || sub_snippet.starts_with("include_bytes!")) + { + self.emit_lint(cx, attr.span); } } } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 47c65ee6d0b..b7887ef76a5 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -629,7 +629,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { .filter_by_name_unhygienic(is_empty) .any(|item| is_is_empty(cx, item)) }), - ty::Alias(ty::Projection, ref proj) => has_is_empty_impl(cx, proj.def_id), + ty::Alias(ty::Projection, proj) => has_is_empty_impl(cx, proj.def_id), ty::Adt(id, _) => has_is_empty_impl(cx, id.did()), ty::Array(..) | ty::Slice(..) | ty::Str => true, _ => false, diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 14110539709..c9064df25ac 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -73,6 +73,7 @@ pub mod deprecated_lints; mod absolute_paths; mod almost_complete_range; mod approx_const; +mod arbitrary_source_item_ordering; mod arc_with_non_send_sync; mod as_conversions; mod asm_syntax; @@ -400,6 +401,7 @@ use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation}; use clippy_utils::macros::FormatArgsStorage; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; +use utils::attr_collector::{AttrCollector, AttrStorage}; /// Register all pre expansion lints /// @@ -412,6 +414,8 @@ use rustc_lint::{Lint, LintId}; pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { // NOTE: Do not add any more pre-expansion passes. These should be removed eventually. store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf))); + + store.register_early_pass(move || Box::new(attrs::PostExpansionEarlyAttributes::new(conf))); } #[derive(Default)] @@ -462,6 +466,7 @@ pub(crate) enum LintCategory { #[cfg(feature = "internal")] Internal, } + #[allow(clippy::enum_glob_use)] use LintCategory::*; @@ -583,6 +588,10 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { )) }); + let attr_storage = AttrStorage::default(); + let attrs = attr_storage.clone(); + store.register_early_pass(move || Box::new(AttrCollector::new(attrs.clone()))); + // all the internal lints #[cfg(feature = "internal")] { @@ -604,6 +613,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| { Box::new(utils::internal_lints::almost_standard_lint_formulation::AlmostStandardFormulation::new()) }); + store.register_late_pass(|_| Box::new(utils::internal_lints::slow_symbol_comparisons::SlowSymbolComparisons)); } store.register_late_pass(|_| Box::new(ctfe::ClippyCtfe)); @@ -793,7 +803,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(unwrap_in_result::UnwrapInResult)); store.register_late_pass(|_| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned)); store.register_late_pass(|_| Box::new(async_yields_async::AsyncYieldsAsync)); - store.register_late_pass(move |tcx| Box::new(disallowed_macros::DisallowedMacros::new(tcx, conf))); + let attrs = attr_storage.clone(); + store.register_late_pass(move |tcx| Box::new(disallowed_macros::DisallowedMacros::new(tcx, conf, attrs.clone()))); store.register_late_pass(move |tcx| Box::new(disallowed_methods::DisallowedMethods::new(tcx, conf))); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax)); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax)); @@ -951,5 +962,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(unused_trait_names::UnusedTraitNames::new(conf))); store.register_late_pass(|_| Box::new(manual_ignore_case_cmp::ManualIgnoreCaseCmp)); store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound)); + store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf))); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index 119e410b91c..ee561ea85ed 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -29,11 +29,7 @@ pub(super) fn check( if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { return; } - } else if count - .try_to_target_usize(cx.tcx) - .map_or(true, |x| x > 32) - && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) - { + } else if count.try_to_target_usize(cx.tcx).map_or(true, |x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs index e25c03db534..9f543b79bac 100644 --- a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs @@ -1,12 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{fn_def_id, is_from_proc_macro, is_lint_allowed}; use hir::intravisit::{Visitor, walk_expr}; -use hir::{Expr, ExprKind, FnRetTy, FnSig, Node}; +use hir::{Expr, ExprKind, FnRetTy, FnSig, Node, TyKind}; use rustc_ast::Label; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; +use rustc_span::sym; use super::INFINITE_LOOP; @@ -25,13 +26,7 @@ pub(super) fn check<'tcx>( return; }; // Or, its parent function is already returning `Never` - if matches!( - parent_fn_ret, - FnRetTy::Return(hir::Ty { - kind: hir::TyKind::Never, - .. - }) - ) { + if is_never_return(parent_fn_ret) { return; } @@ -69,6 +64,16 @@ pub(super) fn check<'tcx>( fn get_parent_fn_ret_ty<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<FnRetTy<'tcx>> { for (_, parent_node) in cx.tcx.hir().parent_iter(expr.hir_id) { match parent_node { + // Skip `Coroutine` closures, these are the body of `async fn`, not async closures. + // This is because we still need to backtrack one parent node to get the `OpaqueDef` ty. + Node::Expr(Expr { + kind: + ExprKind::Closure(hir::Closure { + kind: hir::ClosureKind::Coroutine(_), + .. + }), + .. + }) => (), Node::Item(hir::Item { kind: hir::ItemKind::Fn(FnSig { decl, .. }, _, _), .. @@ -143,3 +148,41 @@ impl<'hir> Visitor<'hir> for LoopVisitor<'hir, '_> { } } } + +/// Return `true` if the given [`FnRetTy`] is never (!). +/// +/// Note: This function also take care of return type of async fn, +/// as the actual type is behind an [`OpaqueDef`](TyKind::OpaqueDef). +fn is_never_return(ret_ty: FnRetTy<'_>) -> bool { + let FnRetTy::Return(hir_ty) = ret_ty else { return false }; + + match hir_ty.kind { + TyKind::Never => true, + TyKind::OpaqueDef(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::AsyncFn { .. }, + bounds, + .. + }) => { + if let Some(trait_ref) = bounds.iter().find_map(|b| b.trait_ref()) + && let Some(segment) = trait_ref + .path + .segments + .iter() + .find(|seg| seg.ident.name == sym::future_trait) + && let Some(args) = segment.args + && let Some(cst_kind) = args + .constraints + .iter() + .find_map(|cst| (cst.ident.name == sym::Output).then_some(cst.kind)) + && let hir::AssocItemConstraintKind::Equality { + term: hir::Term::Ty(ty), + } = cst_kind + { + matches!(ty.kind, TyKind::Never) + } else { + false + } + }, + _ => false, + } +} diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index 21f9a71f2c5..094b1947324 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -80,7 +80,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) { - if bk == ty::BorrowKind::MutBorrow { + if bk == ty::BorrowKind::Mutable { if let PlaceBase::Local(id) = cmt.place.base { if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)); diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs index 1a1cde3c5bd..7da4fa76e2c 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs @@ -19,10 +19,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &' cx, ids: HirIdSet::default(), def_ids: DefIdMap::default(), - skip: false, }; - var_visitor.visit_expr(cond); - if var_visitor.skip { + if var_visitor.visit_expr(cond).is_break() { return; } let used_in_condition = &var_visitor.ids; @@ -81,7 +79,6 @@ struct VarCollectorVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, ids: HirIdSet, def_ids: DefIdMap<bool>, - skip: bool, } impl<'tcx> VarCollectorVisitor<'_, 'tcx> { @@ -104,11 +101,15 @@ impl<'tcx> VarCollectorVisitor<'_, 'tcx> { } impl<'tcx> Visitor<'tcx> for VarCollectorVisitor<'_, 'tcx> { - fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { + type Result = ControlFlow<()>; + fn visit_expr(&mut self, ex: &'tcx Expr<'_>) -> Self::Result { match ex.kind { - ExprKind::Path(_) => self.insert_def_id(ex), + ExprKind::Path(_) => { + self.insert_def_id(ex); + ControlFlow::Continue(()) + }, // If there is any function/method call… we just stop analysis - ExprKind::Call(..) | ExprKind::MethodCall(..) => self.skip = true, + ExprKind::Call(..) | ExprKind::MethodCall(..) => ControlFlow::Break(()), _ => walk_expr(self, ex), } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs index 74467522619..b7e37c1a876 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use super::WHILE_LET_ON_ITERATOR; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; @@ -204,35 +206,32 @@ fn uses_iter<'tcx>(cx: &LateContext<'tcx>, iter_expr: &IterExpr, container: &'tc struct V<'a, 'b, 'tcx> { cx: &'a LateContext<'tcx>, iter_expr: &'b IterExpr, - uses_iter: bool, } impl<'tcx> Visitor<'tcx> for V<'_, '_, 'tcx> { - fn visit_expr(&mut self, e: &'tcx Expr<'_>) { - if self.uses_iter { - // return - } else if is_expr_same_child_or_parent_field(self.cx, e, &self.iter_expr.fields, self.iter_expr.path) { - self.uses_iter = true; + type Result = ControlFlow<()>; + fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result { + if is_expr_same_child_or_parent_field(self.cx, e, &self.iter_expr.fields, self.iter_expr.path) { + ControlFlow::Break(()) } else if let (e, true) = skip_fields_and_path(e) { if let Some(e) = e { - self.visit_expr(e); + self.visit_expr(e) + } else { + ControlFlow::Continue(()) } } else if let ExprKind::Closure(&Closure { body: id, .. }) = e.kind { if is_res_used(self.cx, self.iter_expr.path, id) { - self.uses_iter = true; + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) } } else { - walk_expr(self, e); + walk_expr(self, e) } } } - let mut v = V { - cx, - iter_expr, - uses_iter: false, - }; - v.visit_expr(container); - v.uses_iter + let mut v = V { cx, iter_expr }; + v.visit_expr(container).is_break() } #[expect(clippy::too_many_lines)] @@ -242,34 +241,38 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: & iter_expr: &'b IterExpr, loop_id: HirId, after_loop: bool, - used_iter: bool, } impl<'tcx> Visitor<'tcx> for AfterLoopVisitor<'_, '_, 'tcx> { type NestedFilter = OnlyBodies; + type Result = ControlFlow<()>; fn nested_visit_map(&mut self) -> Self::Map { self.cx.tcx.hir() } - fn visit_expr(&mut self, e: &'tcx Expr<'_>) { - if self.used_iter { - return; - } + fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result { if self.after_loop { if is_expr_same_child_or_parent_field(self.cx, e, &self.iter_expr.fields, self.iter_expr.path) { - self.used_iter = true; + ControlFlow::Break(()) } else if let (e, true) = skip_fields_and_path(e) { if let Some(e) = e { - self.visit_expr(e); + self.visit_expr(e) + } else { + ControlFlow::Continue(()) } } else if let ExprKind::Closure(&Closure { body: id, .. }) = e.kind { - self.used_iter = is_res_used(self.cx, self.iter_expr.path, id); + if is_res_used(self.cx, self.iter_expr.path, id) { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } } else { - walk_expr(self, e); + walk_expr(self, e) } } else if self.loop_id == e.hir_id { self.after_loop = true; + ControlFlow::Continue(()) } else { - walk_expr(self, e); + walk_expr(self, e) } } } @@ -347,9 +350,8 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: & iter_expr, loop_id: loop_expr.hir_id, after_loop: false, - used_iter: false, }; - v.visit_expr(cx.tcx.hir().body(cx.enclosing_body.unwrap()).value); - v.used_iter + v.visit_expr(cx.tcx.hir().body(cx.enclosing_body.unwrap()).value) + .is_break() } } diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index c904137da1a..3c77db84a40 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -106,13 +106,12 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { fn future_trait_ref<'tcx>(cx: &LateContext<'tcx>, opaque: &'tcx OpaqueTy<'tcx>) -> Option<&'tcx TraitRef<'tcx>> { if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { - if let GenericBound::Trait(poly) = bound { - Some(&poly.trait_ref) - } else { - None - } - }) - && trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait() + if let GenericBound::Trait(poly) = bound { + Some(&poly.trait_ref) + } else { + None + } + }) && trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait() { return Some(trait_ref); } @@ -156,16 +155,18 @@ fn captures_all_lifetimes(cx: &LateContext<'_>, fn_def_id: LocalDefId, opaque_de .tcx .opaque_captured_lifetimes(opaque_def_id) .iter() - .filter(|&(lifetime, _)| match *lifetime { - ResolvedArg::EarlyBound(_) | ResolvedArg::LateBound(ty::INNERMOST, _, _) => true, - _ => false, + .filter(|&(lifetime, _)| { + matches!( + *lifetime, + ResolvedArg::EarlyBound(_) | ResolvedArg::LateBound(ty::INNERMOST, _, _) + ) }) .count(); num_captured_lifetimes == num_early_lifetimes + num_late_lifetimes } fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { - if let Some(Expr { + if let Some(&Expr { kind: ExprKind::Closure(&Closure { kind, body, .. }), .. }) = block.expr diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs index 1bd8813e348..fd71167f814 100644 --- a/src/tools/clippy/clippy_lints/src/manual_bits.rs +++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs @@ -7,8 +7,7 @@ use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; +use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; use rustc_span::sym; @@ -53,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Binary(bin_op, left_expr, right_expr) = expr.kind && let BinOpKind::Mul = &bin_op.node - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.from_expansion() && self.msrv.meets(msrvs::MANUAL_BITS) && let ctxt = expr.span.ctxt() && left_expr.span.ctxt() == ctxt diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs index c62bd65bea6..7a9c9963742 100644 --- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs +++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs @@ -68,7 +68,7 @@ impl LateLintPass<'_> for ManualHashOne { && let Some(init) = local.init && !init.span.from_expansion() && let ExprKind::MethodCall(seg, build_hasher, [], _) = init.kind - && seg.ident.name == sym!(build_hasher) + && seg.ident.name.as_str() == "build_hasher" && let Node::Stmt(local_stmt) = cx.tcx.parent_hir_node(local.hir_id) && let Node::Block(block) = cx.tcx.parent_hir_node(local_stmt.hir_id) @@ -96,7 +96,7 @@ impl LateLintPass<'_> for ManualHashOne { && let Node::Expr(finish_expr) = cx.tcx.parent_hir_node(path_expr.hir_id) && !finish_expr.span.from_expansion() && let ExprKind::MethodCall(seg, _, [], _) = finish_expr.kind - && seg.ident.name == sym!(finish) + && seg.ident.name.as_str() == "finish" && self.msrv.meets(msrvs::BUILD_HASHER_HASH_ONE) { diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs index 24207705743..dec8c5d85de 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs @@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { check_is_ascii(cx, macro_call.span, recv, &range, None); } } else if let ExprKind::MethodCall(path, receiver, [arg], ..) = expr.kind - && path.ident.name == sym!(contains) + && path.ident.name.as_str() == "contains" && let Some(higher::Range { start: Some(start), end: Some(end), diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs index 64cb7a06ce9..6d62b530ae7 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs @@ -148,7 +148,7 @@ fn find_bool_lit(ex: &ExprKind<'_>) -> Option<bool> { }) => Some(*b), ExprKind::Block( rustc_hir::Block { - stmts: &[], + stmts: [], expr: Some(exp), .. }, diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs index 463aa602bc8..1267fc9d0a5 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::is_type_lang_item; use rustc_ast::ast::LitKind; @@ -23,11 +25,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>, arm if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(scrutinee).kind() && let ty::Str = ty.kind() { - let mut visitor = MatchExprVisitor { cx, case_method: None }; - - visitor.visit_expr(scrutinee); - - if let Some(case_method) = visitor.case_method { + let mut visitor = MatchExprVisitor { cx }; + if let ControlFlow::Break(case_method) = visitor.visit_expr(scrutinee) { if let Some((bad_case_span, bad_case_sym)) = verify_case(&case_method, arms) { lint(cx, &case_method, bad_case_span, bad_case_sym.as_str()); } @@ -37,30 +36,33 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>, arm struct MatchExprVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - case_method: Option<CaseMethod>, } impl<'tcx> Visitor<'tcx> for MatchExprVisitor<'_, 'tcx> { - fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { - match ex.kind { - ExprKind::MethodCall(segment, receiver, [], _) if self.case_altered(segment.ident.as_str(), receiver) => {}, - _ => walk_expr(self, ex), + type Result = ControlFlow<CaseMethod>; + fn visit_expr(&mut self, ex: &'tcx Expr<'_>) -> Self::Result { + if let ExprKind::MethodCall(segment, receiver, [], _) = ex.kind { + let result = self.case_altered(segment.ident.as_str(), receiver); + if result.is_break() { + return result; + } } + + walk_expr(self, ex) } } impl MatchExprVisitor<'_, '_> { - fn case_altered(&mut self, segment_ident: &str, receiver: &Expr<'_>) -> bool { + fn case_altered(&mut self, segment_ident: &str, receiver: &Expr<'_>) -> ControlFlow<CaseMethod> { if let Some(case_method) = get_case_method(segment_ident) { let ty = self.cx.typeck_results().expr_ty(receiver).peel_refs(); if is_type_lang_item(self.cx, ty, LangItem::String) || ty.kind() == &ty::Str { - self.case_method = Some(case_method); - return true; + return ControlFlow::Break(case_method); } } - false + ControlFlow::Continue(()) } } diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs index 42d9efe4ff6..9e54475033c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs @@ -10,7 +10,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, MatchSource, Node, PatKind, UnOp}; use rustc_lint::LateContext; use rustc_span::symbol::Ident; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, sym}; use std::borrow::Cow; use std::ops::ControlFlow; @@ -95,7 +95,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: } else if let ExprKind::MethodCall(path, recv, args, ..) = guard.kind && let Some(binding) = get_pat_binding(cx, recv, outer_arm) { - check_method_calls(cx, outer_arm, path.ident.name, recv, args, guard, &binding); + check_method_calls(cx, outer_arm, path.ident.name.as_str(), recv, args, guard, &binding); } } } @@ -103,7 +103,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: fn check_method_calls<'tcx>( cx: &LateContext<'tcx>, arm: &Arm<'tcx>, - method: Symbol, + method: &str, recv: &Expr<'_>, args: &[Expr<'_>], if_expr: &Expr<'_>, @@ -112,7 +112,7 @@ fn check_method_calls<'tcx>( let ty = cx.typeck_results().expr_ty(recv).peel_refs(); let slice_like = ty.is_slice() || ty.is_array(); - let sugg = if method == sym!(is_empty) { + let sugg = if method == "is_empty" { // `s if s.is_empty()` becomes "" // `arr if arr.is_empty()` becomes [] @@ -137,9 +137,9 @@ fn check_method_calls<'tcx>( if needles.is_empty() { sugg.insert_str(1, ".."); - } else if method == sym!(starts_with) { + } else if method == "starts_with" { sugg.insert_str(sugg.len() - 1, ", .."); - } else if method == sym!(ends_with) { + } else if method == "ends_with" { sugg.insert_str(1, ".., "); } else { return; diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index 9ca75fb2615..ca45ed6ea59 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -319,10 +319,9 @@ fn found_good_method<'tcx>( node: (&PatKind<'_>, &PatKind<'_>), ) -> Option<(&'static str, Option<&'tcx Expr<'tcx>>)> { match node { - ( - PatKind::TupleStruct(ref path_left, patterns_left, _), - PatKind::TupleStruct(ref path_right, patterns_right, _), - ) if patterns_left.len() == 1 && patterns_right.len() == 1 => { + (PatKind::TupleStruct(path_left, patterns_left, _), PatKind::TupleStruct(path_right, patterns_right, _)) + if patterns_left.len() == 1 && patterns_right.len() == 1 => + { if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) { find_good_method_for_match( cx, @@ -350,8 +349,8 @@ fn found_good_method<'tcx>( None } }, - (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right)) - | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _)) + (PatKind::TupleStruct(path_left, patterns, _), PatKind::Path(path_right)) + | (PatKind::Path(path_left), PatKind::TupleStruct(path_right, patterns, _)) if patterns.len() == 1 => { if let PatKind::Wild = patterns[0].kind { @@ -381,14 +380,14 @@ fn found_good_method<'tcx>( None } }, - (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Wild) if patterns.len() == 1 => { + (PatKind::TupleStruct(path_left, patterns, _), PatKind::Wild) if patterns.len() == 1 => { if let PatKind::Wild = patterns[0].kind { get_good_method(cx, arms, path_left) } else { None } }, - (PatKind::Path(ref path_left), PatKind::Wild) => get_good_method(cx, arms, path_left), + (PatKind::Path(path_left), PatKind::Wild) => get_good_method(cx, arms, path_left), _ => None, } } diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 047d070a131..2aea25b5f12 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -247,7 +247,10 @@ impl<'a> PatState<'a> { let states = match self { Self::Wild => return None, Self::Other => { - *self = Self::StdEnum(cx.arena.alloc_from_iter((0..adt.variants().len()).map(|_| Self::Other))); + *self = Self::StdEnum( + cx.arena + .alloc_from_iter(std::iter::repeat_with(|| Self::Other).take(adt.variants().len())), + ); let Self::StdEnum(x) = self else { unreachable!(); }; diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index 06482a743dd..c1653b65e98 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -21,8 +21,8 @@ fn is_method(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol) -> bool ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name, ExprKind::Path(QPath::Resolved(_, segments)) => segments.segments.last().unwrap().ident.name == method_name, ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name, - ExprKind::Closure(&Closure { body, .. }) => { - let body = cx.tcx.hir().body(body); + ExprKind::Closure(Closure { body, .. }) => { + let body = cx.tcx.hir().body(*body); let closure_expr = peel_blocks(body.value); match closure_expr.kind { ExprKind::MethodCall(PathSegment { ident, .. }, receiver, ..) => { @@ -234,12 +234,12 @@ impl<'tcx> OffendingFilterExpr<'tcx> { // the latter only calls `effect` once let side_effect_expr_span = receiver.can_have_side_effects().then_some(receiver.span); - if cx.tcx.is_diagnostic_item(sym::Option, recv_ty.did()) && path.ident.name == sym!(is_some) { + if cx.tcx.is_diagnostic_item(sym::Option, recv_ty.did()) && path.ident.name.as_str() == "is_some" { Some(Self::IsSome { receiver, side_effect_expr_span, }) - } else if cx.tcx.is_diagnostic_item(sym::Result, recv_ty.did()) && path.ident.name == sym!(is_ok) { + } else if cx.tcx.is_diagnostic_item(sym::Result, recv_ty.did()) && path.ident.name.as_str() == "is_ok" { Some(Self::IsOk { receiver, side_effect_expr_span, diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs index cc82f6cfd63..a0c21faaa4c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs +++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs @@ -1,6 +1,7 @@ use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::diagnostics::span_lint; -use clippy_utils::{find_binding_init, path_to_local}; +use clippy_utils::macros::{is_assert_macro, root_macro_call}; +use clippy_utils::{find_binding_init, get_parent_expr, is_inside_always_const_context, path_to_local}; use rustc_hir::{Expr, HirId}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; @@ -14,6 +15,16 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ if in_external_macro(cx.sess(), expr.span) || !receiver.span.eq_ctxt(expr.span) { return; } + if let Some(parent) = get_parent_expr(cx, expr) { + if let Some(parent) = get_parent_expr(cx, parent) { + if is_inside_always_const_context(cx.tcx, expr.hir_id) + && let Some(macro_call) = root_macro_call(parent.span) + && is_assert_macro(cx, macro_call.def_id) + { + return; + } + } + } let init_expr = expr_or_init(cx, receiver); if !receiver.span.eq_ctxt(init_expr.span) { return; diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs index 9d462bd1845..9a62b719a8f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs @@ -29,10 +29,7 @@ fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) -> if cx.tcx.is_diagnostic_item(sym::ArrayIntoIter, did) { // For array::IntoIter<T, const N: usize>, the length is the second generic // parameter. - substs - .const_at(1) - .try_to_target_usize(cx.tcx) - .map(u128::from) + substs.const_at(1).try_to_target_usize(cx.tcx).map(u128::from) } else if cx.tcx.is_diagnostic_item(sym::SliceIter, did) && let ExprKind::MethodCall(_, recv, ..) = iter.kind { diff --git a/src/tools/clippy/clippy_lints/src/methods/map_all_any_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_all_any_identity.rs new file mode 100644 index 00000000000..ac11baa2d54 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/map_all_any_identity.rs @@ -0,0 +1,43 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::SpanRangeExt; +use clippy_utils::{is_expr_identity_function, is_trait_method}; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_span::{Span, sym}; + +use super::MAP_ALL_ANY_IDENTITY; + +#[allow(clippy::too_many_arguments)] +pub(super) fn check( + cx: &LateContext<'_>, + expr: &Expr<'_>, + recv: &Expr<'_>, + map_call_span: Span, + map_arg: &Expr<'_>, + any_call_span: Span, + any_arg: &Expr<'_>, + method: &str, +) { + if is_trait_method(cx, expr, sym::Iterator) + && is_trait_method(cx, recv, sym::Iterator) + && is_expr_identity_function(cx, any_arg) + && let map_any_call_span = map_call_span.with_hi(any_call_span.hi()) + && let Some(map_arg) = map_arg.span.get_source_text(cx) + { + span_lint_and_then( + cx, + MAP_ALL_ANY_IDENTITY, + map_any_call_span, + format!("usage of `.map(...).{method}(identity)`"), + |diag| { + diag.span_suggestion_verbose( + map_any_call_span, + format!("use `.{method}(...)` instead"), + format!("{method}({map_arg})"), + Applicability::MachineApplicable, + ); + }, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs new file mode 100644 index 00000000000..fc656fd78ba --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs @@ -0,0 +1,134 @@ +use crate::methods::MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES; +use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::Sugg; +use clippy_utils::{eager_or_lazy, higher, usage}; +use rustc_ast::LitKind; +use rustc_ast::ast::RangeLimits; +use rustc_data_structures::packed::Pu128; +use rustc_errors::Applicability; +use rustc_hir::{Body, Closure, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::Span; + +fn extract_count_with_applicability( + cx: &LateContext<'_>, + range: higher::Range<'_>, + applicability: &mut Applicability, +) -> Option<String> { + let start = range.start?; + let end = range.end?; + // TODO: This doens't handle if either the start or end are negative literals, or if the start is + // not a literal. In the first case, we need to be careful about how we handle computing the + // count to avoid overflows. In the second, we may need to add parenthesis to make the + // suggestion correct. + if let ExprKind::Lit(lit) = start.kind + && let LitKind::Int(Pu128(lower_bound), _) = lit.node + { + if let ExprKind::Lit(lit) = end.kind + && let LitKind::Int(Pu128(upper_bound), _) = lit.node + { + // Here we can explicitly calculate the number of iterations + let count = if upper_bound >= lower_bound { + match range.limits { + RangeLimits::HalfOpen => upper_bound - lower_bound, + RangeLimits::Closed => (upper_bound - lower_bound).checked_add(1)?, + } + } else { + 0 + }; + return Some(format!("{count}")); + } + let end_snippet = Sugg::hir_with_applicability(cx, end, "...", applicability) + .maybe_par() + .into_string(); + if lower_bound == 0 { + if range.limits == RangeLimits::Closed { + return Some(format!("{end_snippet} + 1")); + } + return Some(end_snippet); + } + if range.limits == RangeLimits::Closed { + return Some(format!("{end_snippet} - {}", lower_bound - 1)); + } + return Some(format!("{end_snippet} - {lower_bound}")); + } + None +} + +pub(super) fn check( + cx: &LateContext<'_>, + ex: &Expr<'_>, + receiver: &Expr<'_>, + arg: &Expr<'_>, + msrv: &Msrv, + method_call_span: Span, +) { + let mut applicability = Applicability::MaybeIncorrect; + if let Some(range) = higher::Range::hir(receiver) + && let ExprKind::Closure(Closure { body, .. }) = arg.kind + && let body_hir = cx.tcx.hir().body(*body) + && let Body { + params: [param], + value: body_expr, + } = body_hir + && !usage::BindingUsageFinder::are_params_used(cx, body_hir) + && let Some(count) = extract_count_with_applicability(cx, range, &mut applicability) + { + let method_to_use_name; + let new_span; + let use_take; + + if eager_or_lazy::switch_to_eager_eval(cx, body_expr) { + if msrv.meets(msrvs::REPEAT_N) { + method_to_use_name = "repeat_n"; + let body_snippet = snippet_with_applicability(cx, body_expr.span, "..", &mut applicability); + new_span = (arg.span, format!("{body_snippet}, {count}")); + use_take = false; + } else { + method_to_use_name = "repeat"; + let body_snippet = snippet_with_applicability(cx, body_expr.span, "..", &mut applicability); + new_span = (arg.span, body_snippet.to_string()); + use_take = true; + } + } else if msrv.meets(msrvs::REPEAT_WITH) { + method_to_use_name = "repeat_with"; + new_span = (param.span, String::new()); + use_take = true; + } else { + return; + } + + // We need to provide nonempty parts to diag.multipart_suggestion so we + // collate all our parts here and then remove those that are empty. + let mut parts = vec![ + ( + receiver.span.to(method_call_span), + format!("std::iter::{method_to_use_name}"), + ), + new_span, + ]; + if use_take { + parts.push((ex.span.shrink_to_hi(), format!(".take({count})"))); + } + + span_lint_and_then( + cx, + MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES, + ex.span, + "map of a closure that does not depend on its parameter over a range", + |diag| { + diag.multipart_suggestion( + if use_take { + format!("remove the explicit range and use `{method_to_use_name}` and `take`") + } else { + format!("remove the explicit range and use `{method_to_use_name}`") + }, + parts, + applicability, + ); + }, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 2a391870d70..b1809796355 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -60,13 +60,16 @@ mod manual_ok_or; mod manual_saturating_arithmetic; mod manual_str_repeat; mod manual_try_fold; +mod map_all_any_identity; mod map_clone; mod map_collect_result_unit; mod map_err_ignore; mod map_flatten; mod map_identity; mod map_unwrap_or; +mod map_with_unused_argument_over_ranges; mod mut_mutex_lock; +mod needless_as_bytes; mod needless_character_iteration; mod needless_collect; mod needless_option_as_deref; @@ -4166,6 +4169,90 @@ declare_clippy_lint! { "calling `.first().is_some()` or `.first().is_none()` instead of `.is_empty()`" } +declare_clippy_lint! { + /// ### What it does + /// It detects useless calls to `str::as_bytes()` before calling `len()` or `is_empty()`. + /// + /// ### Why is this bad? + /// The `len()` and `is_empty()` methods are also directly available on strings, and they + /// return identical results. In particular, `len()` on a string returns the number of + /// bytes. + /// + /// ### Example + /// ``` + /// let len = "some string".as_bytes().len(); + /// let b = "some string".as_bytes().is_empty(); + /// ``` + /// Use instead: + /// ``` + /// let len = "some string".len(); + /// let b = "some string".is_empty(); + /// ``` + #[clippy::version = "1.84.0"] + pub NEEDLESS_AS_BYTES, + complexity, + "detect useless calls to `as_bytes()`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `.map(…)`, followed by `.all(identity)` or `.any(identity)`. + /// + /// ### Why is this bad? + /// The `.all(…)` or `.any(…)` methods can be called directly in place of `.map(…)`. + /// + /// ### Example + /// ``` + /// # let mut v = [""]; + /// let e1 = v.iter().map(|s| s.is_empty()).all(|a| a); + /// let e2 = v.iter().map(|s| s.is_empty()).any(std::convert::identity); + /// ``` + /// Use instead: + /// ``` + /// # let mut v = [""]; + /// let e1 = v.iter().all(|s| s.is_empty()); + /// let e2 = v.iter().any(|s| s.is_empty()); + /// ``` + #[clippy::version = "1.84.0"] + pub MAP_ALL_ANY_IDENTITY, + complexity, + "combine `.map(_)` followed by `.all(identity)`/`.any(identity)` into a single call" +} + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for `Iterator::map` over ranges without using the parameter which + /// could be more clearly expressed using `std::iter::repeat(...).take(...)` + /// or `std::iter::repeat_n`. + /// + /// ### Why is this bad? + /// + /// It expresses the intent more clearly to `take` the correct number of times + /// from a generating function than to apply a closure to each number in a + /// range only to discard them. + /// + /// ### Example + /// + /// ```no_run + /// let random_numbers : Vec<_> = (0..10).map(|_| { 3 + 1 }).collect(); + /// ``` + /// Use instead: + /// ```no_run + /// let f : Vec<_> = std::iter::repeat( 3 + 1 ).take(10).collect(); + /// ``` + /// + /// ### Known Issues + /// + /// This lint may suggest replacing a `Map<Range>` with a `Take<RepeatWith>`. + /// The former implements some traits that the latter does not, such as + /// `DoubleEndedIterator`. + #[clippy::version = "1.84.0"] + pub MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES, + restriction, + "map of a trivial closure (not dependent on parameter) over a range" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -4327,6 +4414,9 @@ impl_lint_pass!(Methods => [ NEEDLESS_CHARACTER_ITERATION, MANUAL_INSPECT, UNNECESSARY_MIN_OR_MAX, + NEEDLESS_AS_BYTES, + MAP_ALL_ANY_IDENTITY, + MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -4534,15 +4624,21 @@ impl Methods { ("all", [arg]) => { unused_enumerate_index::check(cx, expr, recv, arg); needless_character_iteration::check(cx, expr, recv, arg, true); - if let Some(("cloned", recv2, [], _, _)) = method_call(recv) { - iter_overeager_cloned::check( - cx, - expr, - recv, - recv2, - iter_overeager_cloned::Op::NeedlessMove(arg), - false, - ); + match method_call(recv) { + Some(("cloned", recv2, [], _, _)) => { + iter_overeager_cloned::check( + cx, + expr, + recv, + recv2, + iter_overeager_cloned::Op::NeedlessMove(arg), + false, + ); + }, + Some(("map", _, [map_arg], _, map_call_span)) => { + map_all_any_identity::check(cx, expr, recv, map_call_span, map_arg, call_span, arg, "all"); + }, + _ => {}, } }, ("and_then", [arg]) => { @@ -4571,6 +4667,9 @@ impl Methods { { string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv); }, + Some(("map", _, [map_arg], _, map_call_span)) => { + map_all_any_identity::check(cx, expr, recv, map_call_span, map_arg, call_span, arg, "any"); + }, _ => {}, } }, @@ -4764,8 +4863,14 @@ impl Methods { unit_hash::check(cx, expr, recv, arg); }, ("is_empty", []) => { - if let Some(("as_str", recv, [], as_str_span, _)) = method_call(recv) { - redundant_as_str::check(cx, expr, recv, as_str_span, span); + match method_call(recv) { + Some(("as_bytes", prev_recv, [], _, _)) => { + needless_as_bytes::check(cx, "is_empty", recv, prev_recv, expr.span); + }, + Some(("as_str", recv, [], as_str_span, _)) => { + redundant_as_str::check(cx, expr, recv, as_str_span, span); + }, + _ => {}, } is_empty::check(cx, expr, recv); }, @@ -4795,6 +4900,11 @@ impl Methods { ); } }, + ("len", []) => { + if let Some(("as_bytes", prev_recv, [], _, _)) = method_call(recv) { + needless_as_bytes::check(cx, "len", recv, prev_recv, expr.span); + } + }, ("lock", []) => { mut_mutex_lock::check(cx, expr, recv, span); }, @@ -4802,6 +4912,7 @@ impl Methods { if name == "map" { unused_enumerate_index::check(cx, expr, recv, m_arg); map_clone::check(cx, expr, recv, m_arg, &self.msrv); + map_with_unused_argument_over_ranges::check(cx, expr, recv, m_arg, &self.msrv, span); match method_call(recv) { Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) => { iter_kv_map::check(cx, map_name, expr, recv2, m_arg, &self.msrv); @@ -5182,7 +5293,6 @@ impl ShouldImplTraitCase { } #[rustfmt::skip] -#[expect(clippy::large_const_arrays, reason = "`Span` is not sync, so this can't be static")] const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [ ShouldImplTraitCase::new("std::ops::Add", "add", 2, FN_HEADER, SelfKind::Value, OutType::Any, true), ShouldImplTraitCase::new("std::convert::AsMut", "as_mut", 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true), diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_as_bytes.rs b/src/tools/clippy/clippy_lints/src/methods/needless_as_bytes.rs new file mode 100644 index 00000000000..75e9f317230 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/needless_as_bytes.rs @@ -0,0 +1,28 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_type_lang_item; +use rustc_errors::Applicability; +use rustc_hir::{Expr, LangItem}; +use rustc_lint::LateContext; +use rustc_span::Span; + +use super::NEEDLESS_AS_BYTES; + +pub fn check(cx: &LateContext<'_>, method: &str, recv: &Expr<'_>, prev_recv: &Expr<'_>, span: Span) { + if cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice() + && let ty1 = cx.typeck_results().expr_ty_adjusted(prev_recv).peel_refs() + && (is_type_lang_item(cx, ty1, LangItem::String) || ty1.is_str()) + { + let mut app = Applicability::MachineApplicable; + let sugg = Sugg::hir_with_context(cx, prev_recv, span.ctxt(), "..", &mut app); + span_lint_and_sugg( + cx, + NEEDLESS_AS_BYTES, + span, + "needless call to `as_bytes()`", + format!("`{method}()` can be called directly on strings"), + format!("{sugg}.{method}()"), + app, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 96a31812ca4..055107068ae 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -322,7 +322,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { // Check function calls on our collection if let ExprKind::MethodCall(method_name, recv, args, _) = &expr.kind { if args.is_empty() - && method_name.ident.name == sym!(collect) + && method_name.ident.name.as_str() == "collect" && is_trait_method(self.cx, expr, sym::Iterator) { self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv)); diff --git a/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs b/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs index 65e545ed03a..db2b9d4d92f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs +++ b/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs @@ -44,7 +44,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr< if let Some(parent) = get_parent_expr(cx, expr) { let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind { if args.is_empty() - && segment.ident.name == sym!(parse) + && segment.ident.name.as_str() == "parse" && let parse_result_ty = cx.typeck_results().expr_ty(parent) && is_type_diagnostic_item(cx, parse_result_ty, sym::Result) && let ty::Adt(_, substs) = parse_result_ty.kind() @@ -58,7 +58,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr< "calling `.parse()` on a string without trimming the trailing newline character", "checking", )) - } else if segment.ident.name == sym!(ends_with) + } else if segment.ident.name.as_str() == "ends_with" && recv.span == expr.span && let [arg] = args && expr_is_string_literal_without_trailing_newline(arg) diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index ca46da81fa0..bab439015c5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -1,13 +1,15 @@ use super::utils::clone_or_copy_needed; -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::is_copy; use clippy_utils::usage::mutated_variables; use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; -use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id}; +use clippy_utils::{MaybePath, is_res_lang_ctor, is_trait_method, path_res, path_to_local_id}; use core::ops::ControlFlow; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_lint::LateContext; +use rustc_middle::query::Key; use rustc_middle::ty; use rustc_span::sym; @@ -36,9 +38,25 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a ControlFlow::Continue(Descend::Yes) } }); - let in_ty = cx.typeck_results().node_type(body.params[0].hir_id); let sugg = if !found_filtering { + // Check if the closure is .filter_map(|x| Some(x)) + if name == "filter_map" + && let hir::ExprKind::Call(expr, args) = body.value.kind + && is_res_lang_ctor(cx, path_res(cx, expr), OptionSome) + && arg_id.ty_def_id() == args[0].hir_id().ty_def_id() + && let hir::ExprKind::Path(_) = args[0].kind + { + span_lint_and_sugg( + cx, + UNNECESSARY_FILTER_MAP, + expr.span, + format!("{name} is unnecessary"), + "try removing the filter_map", + String::new(), + Applicability::MaybeIncorrect, + ); + } if name == "filter_map" { "map" } else { "map(..).next()" } } else if !found_mapping && !mutates_arg && (!clone_or_copy_needed || is_copy(cx, in_ty)) { match cx.typeck_results().expr_ty(body.value).kind() { @@ -52,7 +70,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a } else { return; }; - span_lint( + span_lint_and_sugg( cx, if name == "filter_map" { UNNECESSARY_FILTER_MAP @@ -60,7 +78,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a UNNECESSARY_FIND_MAP }, expr.span, - format!("this `.{name}` can be written more simply using `.{sugg}`"), + format!("this `.{name}` can be written more simply"), + "try instead", + sugg.to_string(), + Applicability::MaybeIncorrect, ); } } @@ -78,7 +99,7 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc (true, true) }, hir::ExprKind::MethodCall(segment, recv, [arg], _) => { - if segment.ident.name == sym!(then_some) + if segment.ident.name.as_str() == "then_some" && cx.typeck_results().expr_ty(recv).is_bool() && path_to_local_id(arg, arg_id) { diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs index e95864c6db8..ed89b3b3438 100644 --- a/src/tools/clippy/clippy_lints/src/minmax.rs +++ b/src/tools/clippy/clippy_lints/src/minmax.rs @@ -79,9 +79,9 @@ fn min_max<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a Expr<'a>) -> Option<(MinM }, ExprKind::MethodCall(path, receiver, args @ [_], _) => { if cx.typeck_results().expr_ty(receiver).is_floating_point() || is_trait_method(cx, expr, sym::Ord) { - if path.ident.name == sym!(max) { + if path.ident.name.as_str() == "max" { fetch_const(cx, Some(receiver), args, MinMax::Max) - } else if path.ident.name == sym!(min) { + } else if path.ident.name.as_str() == "min" { fetch_const(cx, Some(receiver), args, MinMax::Min) } else { None diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index ce508d85d63..1300c7d1062 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -12,11 +12,13 @@ use clippy_utils::is_from_proc_macro; use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{self, MetaItem, MetaItemKind}; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::Visibility; use rustc_session::impl_lint_pass; use rustc_span::def_id::CRATE_DEF_ID; +use rustc_span::symbol::kw; use rustc_span::{Span, sym}; declare_clippy_lint! { @@ -110,6 +112,21 @@ impl MissingDoc { return; } + if let Some(parent_def_id) = cx.tcx.opt_parent(def_id.to_def_id()) + && let DefKind::AnonConst + | DefKind::AssocConst + | DefKind::AssocFn + | DefKind::Closure + | DefKind::Const + | DefKind::Fn + | DefKind::InlineConst + | DefKind::Static { .. } + | DefKind::SyntheticCoroutineBody = cx.tcx.def_kind(parent_def_id) + { + // Nested item has no generated documentation, so it doesn't need to be documented. + return; + } + let has_doc = attrs .iter() .any(|a| a.doc_str().is_some() || Self::has_include(a.meta())) @@ -184,8 +201,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } } }, - hir::ItemKind::Const(..) - | hir::ItemKind::Enum(..) + hir::ItemKind::Const(..) => { + if it.ident.name == kw::Underscore { + note_prev_span_then_ret!(self.prev_span, it.span); + } + }, + hir::ItemKind::Enum(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) | hir::ItemKind::Static(..) diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs index fc01b6753f1..f28b431ab99 100644 --- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs +++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs @@ -116,7 +116,7 @@ fn should_lint<'tcx>( if path.ident.name == sym::debug_struct && is_type_diagnostic_item(cx, recv_ty, sym::Formatter) { has_debug_struct = true; - } else if path.ident.name == sym!(finish_non_exhaustive) + } else if path.ident.name.as_str() == "finish_non_exhaustive" && is_type_diagnostic_item(cx, recv_ty, sym::DebugStruct) { has_finish_non_exhaustive = true; diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index f95a0f63fab..e587d695c84 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::ty::AssocItemContainer; use rustc_session::declare_lint_pass; use rustc_span::{Span, sym}; @@ -138,7 +139,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { - use rustc_middle::ty::{ImplContainer, TraitContainer}; if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable_or_proc_macro(cx) { return; } @@ -156,8 +156,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { let assoc_item = cx.tcx.associated_item(impl_item.owner_id); let container_id = assoc_item.container_id(cx.tcx); let trait_def_id = match assoc_item.container { - TraitContainer => Some(container_id), - ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id), + AssocItemContainer::Trait => Some(container_id), + AssocItemContainer::Impl => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id), }; if let Some(trait_def_id) = trait_def_id { diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs index ce97370d4d9..c4836772933 100644 --- a/src/tools/clippy/clippy_lints/src/needless_continue.rs +++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs @@ -330,10 +330,11 @@ fn suggestion_snippet_for_continue_inside_else(cx: &EarlyContext<'_>, data: &Lin } fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) { - if let ast::ExprKind::Loop(loop_block, ..) = &expr.kind + if let ast::ExprKind::Loop(loop_block, loop_label, ..) = &expr.kind && let Some(last_stmt) = loop_block.stmts.last() && let ast::StmtKind::Expr(inner_expr) | ast::StmtKind::Semi(inner_expr) = &last_stmt.kind - && let ast::ExprKind::Continue(_) = inner_expr.kind + && let ast::ExprKind::Continue(continue_label) = inner_expr.kind + && compare_labels(loop_label.as_ref(), continue_label.as_ref()) { span_lint_and_help( cx, diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 46cdb82130f..a67addea948 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -347,7 +347,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessLateInit { if let LetStmt { init: None, pat: - &Pat { + Pat { kind: PatKind::Binding(BindingMode::NONE, binding_id, _, None), .. }, @@ -357,7 +357,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessLateInit { && let Some((_, Node::Stmt(local_stmt))) = parents.next() && let Some((_, Node::Block(block))) = parents.next() { - check(cx, local, local_stmt, block, binding_id); + check(cx, local, local_stmt, block, *binding_id); } } } diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs index 9a1c397b5b2..852a0ce8c6d 100644 --- a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs +++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::def_id::{DefId, DefIdMap}; -use rustc_hir::{GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, BoundPolarity, WherePredicate}; +use rustc_hir::{BoundPolarity, GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ClauseKind, PredicatePolarity}; use rustc_session::declare_lint_pass; diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index 5c631a176c4..b7dc269061c 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -183,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { .iter() .zip(fn_sig.inputs()) .zip(body.params) - .filter(|((&input, &ty), arg)| !should_skip(cx, input, ty, arg)) + .filter(|&((&input, &ty), arg)| !should_skip(cx, input, ty, arg)) .peekable(); if it.peek().is_none() { return; @@ -417,8 +417,8 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { // a closure, it'll return this variant whereas if you have just an index access, it'll // return `ImmBorrow`. So if there is "Unique" and it's a mutable reference, we add it // to the mutably used variables set. - if borrow == ty::BorrowKind::MutBorrow - || (borrow == ty::BorrowKind::UniqueImmBorrow && base_ty.ref_mutability() == Some(Mutability::Mut)) + if borrow == ty::BorrowKind::Mutable + || (borrow == ty::BorrowKind::UniqueImmutable && base_ty.ref_mutability() == Some(Mutability::Mut)) { self.add_mutably_used_var(*vid); } else if self.is_in_unsafe_block(id) { @@ -426,7 +426,7 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { // upon! self.add_mutably_used_var(*vid); } - } else if borrow == ty::ImmBorrow { + } else if borrow == ty::BorrowKind::Immutable { // If there is an `async block`, it'll contain a call to a closure which we need to // go into to ensure all "mutate" checks are found. if let Node::Expr(Expr { diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 2e5195d459f..74536028b5d 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -159,8 +159,12 @@ impl NoEffect { // Remove `impl Future<Output = T>` to get `T` if cx.tcx.ty_is_opaque_future(ret_ty) - && let Some(true_ret_ty) = - cx.tcx.infer_ctxt().build(cx.typing_mode()).err_ctxt().get_impl_future_output_ty(ret_ty) + && let Some(true_ret_ty) = cx + .tcx + .infer_ctxt() + .build(cx.typing_mode()) + .err_ctxt() + .get_impl_future_output_ty(ret_ty) { ret_ty = true_ret_ty; } diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs index 8d5a523fd8f..64587e08ddc 100644 --- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_with_applicability; +use clippy_utils::source::{snippet, snippet_with_applicability}; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -18,13 +18,13 @@ declare_clippy_lint! { /// Rust ABI can break this at any point. /// /// ### Example - /// ```no_run + /// ```rust,ignore /// #[no_mangle] /// fn example(arg_one: u32, arg_two: usize) {} /// ``` /// /// Use instead: - /// ```no_run + /// ```rust,ignore /// #[no_mangle] /// extern "C" fn example(arg_one: u32, arg_two: usize) {} /// ``` @@ -40,24 +40,25 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi { if let ItemKind::Fn(fn_sig, _, _) = &item.kind { let attrs = cx.tcx.hir().attrs(item.hir_id()); let mut app = Applicability::MaybeIncorrect; - let snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut app); + let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app); for attr in attrs { if let Some(ident) = attr.ident() && ident.name == rustc_span::sym::no_mangle && fn_sig.header.abi == Abi::Rust - && let Some((fn_attrs, _)) = snippet.split_once("fn") + && let Some((fn_attrs, _)) = fn_snippet.rsplit_once("fn") && !fn_attrs.contains("extern") { let sugg_span = fn_sig .span .with_lo(fn_sig.span.lo() + BytePos::from_usize(fn_attrs.len())) .shrink_to_lo(); + let attr_snippet = snippet(cx, attr.span, ".."); span_lint_and_then( cx, NO_MANGLE_WITH_RUST_ABI, fn_sig.span, - "`#[no_mangle]` set on a function with the default (`Rust`) ABI", + format!("`{attr_snippet}` set on a function with the default (`Rust`) ABI"), |diag| { diag.span_suggestion(sugg_span, "set an ABI", "extern \"C\" ", app) .span_suggestion(sugg_span, "or explicitly set the default", "extern \"Rust\" ", app); diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs index 3f156aa5510..0caa19cd844 100644 --- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs +++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs @@ -43,12 +43,12 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions { match &expr.kind { ExprKind::MethodCall(path, func, [param], _) => { if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def() - && ((path.ident.name == sym!(mode) + && ((path.ident.name.as_str() == "mode" && matches!( cx.tcx.get_diagnostic_name(adt.did()), Some(sym::FsOpenOptions | sym::DirBuilder) )) - || (path.ident.name == sym!(set_mode) + || (path.ident.name.as_str() == "set_mode" && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did()))) && let ExprKind::Lit(_) = param.kind && param.span.eq_ctxt(expr.span) diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs index 11c97b4ef00..0dcaec1c9a7 100644 --- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -102,7 +102,7 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet { struct S(HirIdSet); impl Delegate<'_> for S { fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) { - if matches!(kind, BorrowKind::ImmBorrow | BorrowKind::UniqueImmBorrow) { + if matches!(kind, BorrowKind::Immutable | BorrowKind::UniqueImmutable) { self.0.insert(match place.place.base { PlaceBase::Local(id) => id, PlaceBase::Upvar(id) => id.var_path.hir_id, @@ -127,7 +127,7 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet { struct S(HirIdSet); impl Delegate<'_> for S { fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) { - if matches!(kind, BorrowKind::MutBorrow) { + if matches!(kind, BorrowKind::Mutable) { self.0.insert(match place.place.base { PlaceBase::Local(id) => id, PlaceBase::Upvar(id) => id.var_path.hir_id, diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs index 8e394944c21..ab5f91c1d67 100644 --- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs +++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs @@ -107,7 +107,7 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } if let ExprKind::MethodCall(method_name, self_arg, [], _) = expr.kind - && sym!(signum) == method_name.ident.name + && method_name.ident.name.as_str() == "signum" // Check that the receiver of the signum() is a float (expressions[0] is the receiver of // the method call) { diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs index 18e6aad9c9a..794bef7b321 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs @@ -34,7 +34,7 @@ declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]); impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), + of_trait: Some(trait_ref), items: impl_items, .. }) = item.kind diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs index 56d07aeae17..808a7e005c6 100644 --- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs +++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs @@ -96,7 +96,7 @@ fn expr_as_ptr_offset_call<'tcx>( if path_segment.ident.name == sym::offset { return Some((arg_0, arg_1, Method::Offset)); } - if path_segment.ident.name == sym!(wrapping_offset) { + if path_segment.ident.name.as_str() == "wrapping_offset" { return Some((arg_0, arg_1, Method::WrappingOffset)); } } diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 9344cb41993..cb374fcf20e 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -93,7 +93,7 @@ enum IfBlockType<'hir> { fn find_let_else_ret_expression<'hir>(block: &'hir Block<'hir>) -> Option<&'hir Expr<'hir>> { if let Block { - stmts: &[], + stmts: [], expr: Some(els), .. } = block @@ -163,8 +163,8 @@ fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_ is_type_diagnostic_item(cx, caller_ty, smbl) && expr_return_none_or_err(smbl, cx, if_then, caller, None) && match smbl { - sym::Option => call_sym == sym!(is_none), - sym::Result => call_sym == sym!(is_err), + sym::Option => call_sym.as_str() == "is_none", + sym::Result => call_sym.as_str() == "is_err", _ => false, } }, diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs index 19ce08bde10..7d59bf24d93 100644 --- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs @@ -39,7 +39,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef { fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { if let TyKind::Ref(_, ref mut_ty) = ty.kind && mut_ty.mutbl == Mutability::Not - && let TyKind::Path(ref qpath) = &mut_ty.ty.kind + && let TyKind::Path(qpath) = &mut_ty.ty.kind && let last = last_path_segment(qpath) && let Some(def_id) = last.res.opt_def_id() && cx.tcx.is_diagnostic_item(sym::Option, def_id) diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 110dea8fb8e..1e0f6dff1ab 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -347,7 +347,7 @@ fn check_final_expr<'tcx>( let peeled_drop_expr = expr.peel_drop_temps(); match &peeled_drop_expr.kind { // simple return is always "bad" - ExprKind::Ret(ref inner) => { + ExprKind::Ret(inner) => { // check if expr return nothing let ret_span = if inner.is_none() && replacement == RetReplacement::Empty { extend_span_to_previous_non_ws(cx, peeled_drop_expr.span) diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs index 09f1c112352..d85f4a8fa01 100644 --- a/src/tools/clippy/clippy_lints/src/semicolon_block.rs +++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs @@ -101,17 +101,21 @@ impl SemicolonBlock { ); } - fn semicolon_outside_block( - &self, - cx: &LateContext<'_>, - block: &Block<'_>, - tail_stmt_expr: &Expr<'_>, - semi_span: Span, - ) { + fn semicolon_outside_block(&self, cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>) { let insert_span = block.span.with_lo(block.span.hi()); - // account for macro calls - let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); - let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); + + // For macro call semicolon statements (`mac!();`), the statement's span does not actually + // include the semicolon itself, so use `mac_call_stmt_semi_span`, which finds the semicolon + // based on a source snippet. + // (Does not use `stmt_span` as that requires `.from_expansion()` to return true, + // which is not the case for e.g. `line!();` and `asm!();`) + let Some(remove_span) = cx + .sess() + .source_map() + .mac_call_stmt_semi_span(tail_stmt_expr.span.source_callsite()) + else { + return; + }; if self.semicolon_outside_block_ignore_multiline && get_line(cx, remove_span) != get_line(cx, insert_span) { return; @@ -150,13 +154,12 @@ impl LateLintPass<'_> for SemicolonBlock { }; let &Stmt { kind: StmtKind::Semi(expr), - span, .. } = stmt else { return; }; - self.semicolon_outside_block(cx, block, expr, span); + self.semicolon_outside_block(cx, block, expr); }, StmtKind::Semi(Expr { kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _), diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs index fcf1c4cc5c2..6a0dfde2d9c 100644 --- a/src/tools/clippy/clippy_lints/src/serde_api.rs +++ b/src/tools/clippy/clippy_lints/src/serde_api.rs @@ -26,7 +26,7 @@ declare_lint_pass!(SerdeApi => [SERDE_API_MISUSE]); impl<'tcx> LateLintPass<'tcx> for SerdeApi { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), + of_trait: Some(trait_ref), items, .. }) = item.kind diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs index 9fdee8543a8..fa082453504 100644 --- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs +++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs @@ -174,7 +174,7 @@ impl SingleComponentPathImports { } match &item.kind { - ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => { + ItemKind::Mod(_, ModKind::Loaded(items, ..)) => { self.check_mod(items); }, ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => { diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index ec6e45256d1..8c8f11569c8 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -235,7 +235,7 @@ impl<'tcx> VectorInitializationVisitor<'_, 'tcx> { if self.initialization_found && let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind && path_to_local_id(self_arg, self.vec_alloc.local_id) - && path.ident.name == sym!(extend) + && path.ident.name.as_str() == "extend" && self.is_repeat_take(extend_arg) { self.slow_expression = Some(InitializationType::Extend(expr)); @@ -247,7 +247,7 @@ impl<'tcx> VectorInitializationVisitor<'_, 'tcx> { if self.initialization_found && let ExprKind::MethodCall(path, self_arg, [len_arg, fill_arg], _) = expr.kind && path_to_local_id(self_arg, self.vec_alloc.local_id) - && path.ident.name == sym!(resize) + && path.ident.name.as_str() == "resize" // Check that is filled with 0 && is_integer_literal(fill_arg, 0) { @@ -269,7 +269,7 @@ impl<'tcx> VectorInitializationVisitor<'_, 'tcx> { /// Returns `true` if give expression is `repeat(0).take(...)` fn is_repeat_take(&mut self, expr: &'tcx Expr<'tcx>) -> bool { if let ExprKind::MethodCall(take_path, recv, [len_arg], _) = expr.kind - && take_path.ident.name == sym!(take) + && take_path.ident.name.as_str() == "take" // Check that take is applied to `repeat(0)` && self.is_repeat_zero(recv) { diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index bf49bb60162..e09c0706006 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -286,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { if !in_external_macro(cx.sess(), e.span) && let ExprKind::MethodCall(path, receiver, ..) = &e.kind - && path.ident.name == sym!(as_bytes) + && path.ident.name.as_str() == "as_bytes" && let ExprKind::Lit(lit) = &receiver.kind && let LitKind::Str(lit_content, _) = &lit.node { @@ -332,7 +332,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { } if let ExprKind::MethodCall(path, recv, [], _) = &e.kind - && path.ident.name == sym!(into_bytes) + && path.ident.name.as_str() == "into_bytes" && let ExprKind::MethodCall(path, recv, [], _) = &recv.kind && matches!(path.ident.name.as_str(), "to_owned" | "to_string") && let ExprKind::Lit(lit) = &recv.kind @@ -493,7 +493,7 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { let tyckres = cx.typeck_results(); if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind - && path.ident.name == sym!(split_whitespace) + && path.ident.name.as_str() == "split_whitespace" && let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id) && cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id) && let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index be32dc0aab0..0d809c17989 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -334,7 +334,7 @@ fn strip_non_ident_wrappers(expr: &Expr) -> &Expr { let mut output = expr; loop { output = match &output.kind { - ExprKind::Paren(ref inner) | ExprKind::Unary(_, ref inner) => inner, + ExprKind::Paren(inner) | ExprKind::Unary(_, inner) => inner, _ => { return output; }, @@ -348,13 +348,13 @@ fn extract_related_binops(kind: &ExprKind) -> Option<Vec<BinaryOp<'_>>> { fn if_statement_binops(kind: &ExprKind) -> Option<Vec<BinaryOp<'_>>> { match kind { - ExprKind::If(ref condition, _, _) => chained_binops(&condition.kind), - ExprKind::Paren(ref e) => if_statement_binops(&e.kind), - ExprKind::Block(ref block, _) => { + ExprKind::If(condition, _, _) => chained_binops(&condition.kind), + ExprKind::Paren(e) => if_statement_binops(&e.kind), + ExprKind::Block(block, _) => { let mut output = None; for stmt in &block.stmts { - match stmt.kind { - StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => { + match &stmt.kind { + StmtKind::Expr(e) | StmtKind::Semi(e) => { output = append_opt_vecs(output, if_statement_binops(&e.kind)); }, _ => {}, @@ -383,7 +383,7 @@ fn append_opt_vecs<A>(target_opt: Option<Vec<A>>, source_opt: Option<Vec<A>>) -> fn chained_binops(kind: &ExprKind) -> Option<Vec<BinaryOp<'_>>> { match kind { ExprKind::Binary(_, left_outer, right_outer) => chained_binops_helper(left_outer, right_outer), - ExprKind::Paren(ref e) | ExprKind::Unary(_, ref e) => chained_binops(&e.kind), + ExprKind::Paren(e) | ExprKind::Unary(_, e) => chained_binops(&e.kind), _ => None, } } @@ -391,16 +391,14 @@ fn chained_binops(kind: &ExprKind) -> Option<Vec<BinaryOp<'_>>> { fn chained_binops_helper<'expr>(left_outer: &'expr Expr, right_outer: &'expr Expr) -> Option<Vec<BinaryOp<'expr>>> { match (&left_outer.kind, &right_outer.kind) { ( - ExprKind::Paren(ref left_e) | ExprKind::Unary(_, ref left_e), - ExprKind::Paren(ref right_e) | ExprKind::Unary(_, ref right_e), + ExprKind::Paren(left_e) | ExprKind::Unary(_, left_e), + ExprKind::Paren(right_e) | ExprKind::Unary(_, right_e), ) => chained_binops_helper(left_e, right_e), - (ExprKind::Paren(ref left_e) | ExprKind::Unary(_, ref left_e), _) => chained_binops_helper(left_e, right_outer), - (_, ExprKind::Paren(ref right_e) | ExprKind::Unary(_, ref right_e)) => { - chained_binops_helper(left_outer, right_e) - }, + (ExprKind::Paren(left_e) | ExprKind::Unary(_, left_e), _) => chained_binops_helper(left_e, right_outer), + (_, ExprKind::Paren(right_e) | ExprKind::Unary(_, right_e)) => chained_binops_helper(left_outer, right_e), ( - ExprKind::Binary(Spanned { node: left_op, .. }, ref left_left, ref left_right), - ExprKind::Binary(Spanned { node: right_op, .. }, ref right_left, ref right_right), + ExprKind::Binary(Spanned { node: left_op, .. }, left_left, left_right), + ExprKind::Binary(Spanned { node: right_op, .. }, right_left, right_right), ) => match ( chained_binops_helper(left_left, left_right), chained_binops_helper(right_left, right_right), diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index 6cba560393d..23362506cca 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -392,7 +392,7 @@ impl<'tcx> IndexBinding<'_, 'tcx> { for stmt in self.block.stmts { match stmt.kind { StmtKind::Expr(expr) | StmtKind::Semi(expr) => v.visit_expr(expr), - StmtKind::Let(LetStmt { ref init, .. }) => { + StmtKind::Let(LetStmt { init, .. }) => { if let Some(init) = init.as_ref() { v.visit_expr(init); } diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 3da4bf67558..07bf4319ff0 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -10,8 +10,8 @@ use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{ - GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath, - TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicate, BoundPolarity, + BoundPolarity, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath, + TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { let mut self_bounds_map = FxHashMap::default(); for predicate in item.generics.predicates { - if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate + if let WherePredicate::BoundPredicate(bound_predicate) = predicate && bound_predicate.origin != PredicateOrigin::ImplTrait && !bound_predicate.span.from_expansion() && let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind @@ -268,7 +268,7 @@ impl TraitBounds { let mut map: UnhashMap<SpanlessTy<'_, '_>, Vec<&GenericBound<'_>>> = UnhashMap::default(); let mut applicability = Applicability::MaybeIncorrect; for bound in generics.predicates { - if let WherePredicate::BoundPredicate(ref p) = bound + if let WherePredicate::BoundPredicate(p) = bound && p.origin != PredicateOrigin::ImplTrait && p.bounds.len() as u64 <= self.max_trait_bounds && !p.span.from_expansion() @@ -379,7 +379,7 @@ struct ComparableTraitRef<'a, 'tcx> { impl PartialEq for ComparableTraitRef<'_, '_> { fn eq(&self, other: &Self) -> bool { - SpanlessEq::new(self.cx).eq_modifiers(self.modifiers, other.modifiers) + SpanlessEq::eq_modifiers(self.modifiers, other.modifiers) && SpanlessEq::new(self.cx) .paths_by_resolution() .eq_path(self.trait_ref.path, other.trait_ref.path) diff --git a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs index 1dfc9f7091e..ca9daf2d2a0 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs @@ -43,7 +43,7 @@ fn binops_with_local(cx: &LateContext<'_>, local_expr: &Expr<'_>, expr: &Expr<'_ binops_with_local(cx, local_expr, lhs) || binops_with_local(cx, local_expr, rhs) }, ExprKind::MethodCall(path, receiver, [arg], _) - if path.ident.name == sym!(contains) + if path.ident.name.as_str() == "contains" // ... `contains` called on some kind of range && let Some(receiver_adt) = cx.typeck_results().expr_ty(receiver).peel_refs().ty_adt_def() && let lang_items = cx.tcx.lang_items() @@ -81,7 +81,7 @@ pub(super) fn check<'tcx>( if let Some(then_some_call) = peel_parent_unsafe_blocks(cx, expr) && let ExprKind::MethodCall(path, receiver, [arg], _) = then_some_call.kind && cx.typeck_results().expr_ty(receiver).is_bool() - && path.ident.name == sym!(then_some) + && path.ident.name.as_str() == "then_some" && is_local_with_projections(transmutable) && binops_with_local(cx, transmutable, receiver) && is_normalizable(cx, cx.param_env, from_ty) diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 44eb0a6c593..0bba611116b 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -295,7 +295,7 @@ fn expr_has_unnecessary_safety_comment<'tcx>( if cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, ref node)| { matches!( node, - Node::Block(&Block { + Node::Block(Block { rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), .. }), diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs index bf2d75ea1a9..1a1284ce9c4 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs @@ -194,7 +194,7 @@ fn needs_inferred_result_ty( let (id, receiver, args) = match e.kind { ExprKind::Call( Expr { - kind: ExprKind::Path(ref path), + kind: ExprKind::Path(path), hir_id, .. }, diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs index e7d26fa238e..0f4bd286145 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -149,7 +149,7 @@ fn is_empty_block(expr: &Expr<'_>) -> bool { expr.kind, ExprKind::Block( Block { - stmts: &[], + stmts: [], expr: None, .. }, diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index cf406b817da..7c9455bf8ab 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; -use clippy_utils::{is_res_lang_ctor, is_trait_method, match_trait_method, paths, peel_blocks}; +use clippy_utils::{is_res_lang_ctor, is_trait_method, match_def_path, match_trait_method, paths, peel_blocks}; use hir::{ExprKind, HirId, PatKind}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -83,6 +83,28 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { /// to consider the arms, and we want to avoid breaking the logic for situations where things /// get desugared to match. fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'tcx>) { + let fn_def_id = block.hir_id.owner.to_def_id(); + if let Some(impl_id) = cx.tcx.impl_of_method(fn_def_id) + && let Some(trait_id) = cx.tcx.trait_id_of_impl(impl_id) + { + // We don't want to lint inside io::Read or io::Write implementations, as the author has more + // information about their trait implementation than our lint, see https://github.com/rust-lang/rust-clippy/issues/4836 + if cx.tcx.is_diagnostic_item(sym::IoRead, trait_id) || cx.tcx.is_diagnostic_item(sym::IoWrite, trait_id) { + return; + } + + let async_paths: [&[&str]; 4] = [ + &paths::TOKIO_IO_ASYNCREADEXT, + &paths::TOKIO_IO_ASYNCWRITEEXT, + &paths::FUTURES_IO_ASYNCREADEXT, + &paths::FUTURES_IO_ASYNCWRITEEXT, + ]; + + if async_paths.into_iter().any(|path| match_def_path(cx, trait_id, path)) { + return; + } + } + for stmt in block.stmts { if let hir::StmtKind::Semi(exp) = stmt.kind { check_expr(cx, exp); @@ -222,7 +244,7 @@ fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { } fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { - while let ExprKind::Call(func, [ref arg_0]) = expr.kind + while let ExprKind::Call(func, [arg_0]) = expr.kind && matches!( func.kind, ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..)) @@ -244,7 +266,7 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { /// waited on. Otherwise return None. fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind { - if let ExprKind::Call(func, [ref arg_0]) = expr.kind { + if let ExprKind::Call(func, [arg_0]) = expr.kind { if matches!( func.kind, ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..)) diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index 096b3ff9a2e..89bb429e265 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -217,7 +217,7 @@ fn is_option_as_mut_use(tcx: TyCtxt<'_>, expr_id: HirId) -> bool { impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> { fn borrow(&mut self, cat: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) { - if let ty::BorrowKind::MutBorrow = bk + if let ty::BorrowKind::Mutable = bk && is_potentially_local_place(self.local_id, &cat.place) && !is_option_as_mut_use(self.tcx, diag_expr_id) { diff --git a/src/tools/clippy/clippy_lints/src/utils/attr_collector.rs b/src/tools/clippy/clippy_lints/src/utils/attr_collector.rs new file mode 100644 index 00000000000..1522553bbf5 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/utils/attr_collector.rs @@ -0,0 +1,40 @@ +use std::mem; +use std::sync::OnceLock; + +use rustc_ast::{Attribute, Crate}; +use rustc_data_structures::sync::Lrc; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::impl_lint_pass; +use rustc_span::Span; + +#[derive(Clone, Default)] +pub struct AttrStorage(pub Lrc<OnceLock<Vec<Span>>>); + +pub struct AttrCollector { + storage: AttrStorage, + attrs: Vec<Span>, +} + +impl AttrCollector { + pub fn new(storage: AttrStorage) -> Self { + Self { + storage, + attrs: Vec::new(), + } + } +} + +impl_lint_pass!(AttrCollector => []); + +impl EarlyLintPass for AttrCollector { + fn check_attribute(&mut self, _cx: &EarlyContext<'_>, attr: &Attribute) { + self.attrs.push(attr.span); + } + + fn check_crate_post(&mut self, _: &EarlyContext<'_>, _: &Crate) { + self.storage + .0 + .set(mem::take(&mut self.attrs)) + .expect("should only be called once"); + } +} diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 31f9d84f5e4..1bf24083665 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -396,7 +396,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.pat(field!(let_expr.pat)); // Does what ExprKind::Cast does, only adds a clause for the type // if it's a path - if let Some(TyKind::Path(ref qpath)) = let_expr.value.ty.as_ref().map(|ty| &ty.kind) { + if let Some(TyKind::Path(qpath)) = let_expr.value.ty.as_ref().map(|ty| &ty.kind) { bind!(self, qpath); chain!(self, "let TyKind::Path(ref {qpath}) = {let_expr}.ty.kind"); self.qpath(qpath); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index f662c7651f6..deb983b6971 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -6,5 +6,6 @@ pub mod lint_without_lint_pass; pub mod msrv_attr_impl; pub mod outer_expn_data_pass; pub mod produce_ice; +pub mod slow_symbol_comparisons; pub mod unnecessary_def_path; pub mod unsorted_clippy_utils_paths; diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs index a3f9abe4f96..eaeb754a23f 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs @@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { if let ExprKind::Call(func, [call_cx, call_lint, call_sp, call_msg, call_f]) = expr.kind && is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"]) - && let ExprKind::Closure(&Closure { body, .. }) = &call_f.kind + && let ExprKind::Closure(&Closure { body, .. }) = call_f.kind && let body = cx.tcx.hir().body(body) && let only_expr = peel_blocks_with_stmt(body.value) && let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 51235de9f29..af38e066559 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -21,7 +21,7 @@ declare_clippy_lint! { /// /// ### Why is this bad? /// The compiler only knows lints via a `LintPass`. Without - /// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not + /// putting a lint to a `LintPass::lint_vec()`'s return, the compiler will not /// know the name of the lint. /// /// ### Known problems @@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { .expect("lints must have a description field"); if let ExprKind::Lit(Spanned { - node: LitKind::Str(ref sym, _), + node: LitKind::Str(sym, _), .. }) = field.expr.kind { @@ -159,8 +159,8 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { let body = cx.tcx.hir().body_owned_by( impl_item_refs .iter() - .find(|iiref| iiref.ident.as_str() == "get_lints") - .expect("LintPass needs to implement get_lints") + .find(|iiref| iiref.ident.as_str() == "lint_vec") + .expect("LintPass needs to implement lint_vec") .id .owner_id .def_id, @@ -218,9 +218,7 @@ pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'_>) { if let Some(value) = extract_clippy_version_value(cx, item) { - // The `sym!` macro doesn't work as it only expects a single token. - // It's better to keep it this way and have a direct `Symbol::intern` call here. - if value == Symbol::intern("pre 1.29.0") { + if value.as_str() == "pre 1.29.0" { return; } @@ -251,7 +249,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<' pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> { let attrs = cx.tcx.hir().attrs(item.hir_id()); attrs.iter().find_map(|attr| { - if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind + if let ast::AttrKind::Normal(attr_kind) = &attr.kind // Identify attribute && let [tool_name, attr_name] = &attr_kind.item.path.segments[..] && tool_name.ident.name == sym::clippy diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs index 63fcbd61528..68692246153 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs @@ -42,7 +42,7 @@ impl LateLintPass<'_> for MsrvAttrImpl { .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_))) .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV)) }) - && !items.iter().any(|item| item.ident.name == sym!(check_attributes)) + && !items.iter().any(|item| item.ident.name.as_str() == "check_attributes") { let context = if is_late_pass { "LateContext" } else { "EarlyContext" }; let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" }; diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs new file mode 100644 index 00000000000..3742be0e103 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs @@ -0,0 +1,69 @@ +use clippy_utils::consts::{ConstEvalCtxt, Constant}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::match_type; +use clippy_utils::{match_function_call, paths}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// + /// Detects symbol comparision using `Symbol::intern`. + /// + /// ### Why is this bad? + /// + /// Comparision via `Symbol::as_str()` is faster if the interned symbols are not reused. + /// + /// ### Example + /// + /// None, see suggestion. + pub SLOW_SYMBOL_COMPARISONS, + internal, + "detects slow comparisions of symbol" +} + +declare_lint_pass!(SlowSymbolComparisons => [SLOW_SYMBOL_COMPARISONS]); + +fn check_slow_comparison<'tcx>( + cx: &LateContext<'tcx>, + op1: &'tcx Expr<'tcx>, + op2: &'tcx Expr<'tcx>, +) -> Option<(Span, String)> { + if match_type(cx, cx.typeck_results().expr_ty(op1), &paths::SYMBOL) + && let Some([symbol_name_expr]) = match_function_call(cx, op2, &paths::SYMBOL_INTERN) + && let Some(Constant::Str(symbol_name)) = ConstEvalCtxt::new(cx).eval_simple(symbol_name_expr) + { + Some((op1.span, symbol_name)) + } else { + None + } +} + +impl<'tcx> LateLintPass<'tcx> for SlowSymbolComparisons { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if let ExprKind::Binary(op, left, right) = expr.kind + && (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) + && let Some((symbol_span, symbol_name)) = + check_slow_comparison(cx, left, right).or_else(|| check_slow_comparison(cx, right, left)) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + SLOW_SYMBOL_COMPARISONS, + expr.span, + "comparing `Symbol` via `Symbol::intern`", + "use `Symbol::as_str` and check the string instead", + format!( + "{}.as_str() {} \"{symbol_name}\"", + snippet_with_applicability(cx, symbol_span, "symbol", &mut applicability), + op.node.as_str() + ), + applicability, + ); + }; + } +} diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index 13e9ead9a57..4476cd1005e 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -1,5 +1,7 @@ +pub mod attr_collector; pub mod author; pub mod dump_hir; pub mod format_args_collector; + #[cfg(feature = "internal")] pub mod internal_lints; diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index bfb3a76ad25..75169e05734 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -21,7 +21,7 @@ use rustc_hir::{ ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety, TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource, }; -use rustc_lint::{LateContext, LintContext}; +use rustc_lint::{EarlyContext, LateContext, LintContext}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::symbol::{Ident, kw}; @@ -63,8 +63,8 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit), } && match end_pat { Pat::Str(text) => end_str.ends_with(text), - Pat::MultiStr(texts) => texts.iter().any(|s| start_str.ends_with(s)), - Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), + Pat::MultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)), + Pat::OwnedMultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)), Pat::Sym(sym) => end_str.ends_with(sym.as_str()), Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit), }) @@ -333,26 +333,32 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { match attr.kind { AttrKind::Normal(..) => { if let Some(ident) = attr.ident() { - // TODO: I feel like it's likely we can use `Cow` instead but this will require quite a bit of - // refactoring // NOTE: This will likely have false positives, like `allow = 1` - ( - Pat::OwnedMultiStr(vec![ident.to_string(), "#".to_owned()]), - Pat::Str(""), - ) + let ident_string = ident.to_string(); + if attr.style == AttrStyle::Outer { + ( + Pat::OwnedMultiStr(vec!["#[".to_owned() + &ident_string, ident_string]), + Pat::Str(""), + ) + } else { + ( + Pat::OwnedMultiStr(vec!["#![".to_owned() + &ident_string, ident_string]), + Pat::Str(""), + ) + } } else { (Pat::Str("#"), Pat::Str("]")) } }, AttrKind::DocComment(_kind @ CommentKind::Line, ..) => { - if matches!(attr.style, AttrStyle::Outer) { + if attr.style == AttrStyle::Outer { (Pat::Str("///"), Pat::Str("")) } else { (Pat::Str("//!"), Pat::Str("")) } }, AttrKind::DocComment(_kind @ CommentKind::Block, ..) => { - if matches!(attr.style, AttrStyle::Outer) { + if attr.style == AttrStyle::Outer { (Pat::Str("/**"), Pat::Str("*/")) } else { (Pat::Str("/*!"), Pat::Str("*/")) @@ -429,11 +435,12 @@ impl_with_search_pat!((_cx: LateContext<'tcx>, self: ImplItem<'_>) => impl_item_ impl_with_search_pat!((_cx: LateContext<'tcx>, self: FieldDef<'_>) => field_def_search_pat(self)); impl_with_search_pat!((_cx: LateContext<'tcx>, self: Variant<'_>) => variant_search_pat(self)); impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ty<'_>) => ty_search_pat(self)); -impl_with_search_pat!((_cx: LateContext<'tcx>, self: Attribute) => attr_search_pat(self)); impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self)); impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node)); impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self)); +impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self)); + impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { type Context = LateContext<'cx>; diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 67c31abbdda..24a02c7ef87 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -1,3 +1,7 @@ +//! A simple const eval API, for use on arbitrary HIR expressions. +//! +//! This cannot use rustc's const eval, aka miri, as arbitrary HIR expressions cannot be lowered to +//! executable MIR bodies, so we have to do this instead. #![allow(clippy::float_cmp)] use crate::macros::HirNode; @@ -379,6 +383,8 @@ impl Ord for FullInt { /// The context required to evaluate a constant expression. /// /// This is currently limited to constant folding and reading the value of named constants. +/// +/// See the module level documentation for some context. pub struct ConstEvalCtxt<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 4877fb65d37..ddb7a6635e0 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -9,6 +9,8 @@ //! ~The `INTERNAL_METADATA_COLLECTOR` lint use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan, SubdiagMessage}; +#[cfg(debug_assertions)] +use rustc_errors::{EmissionGuarantee, SubstitutionPart, Suggestions}; use rustc_hir::HirId; use rustc_lint::{LateContext, Lint, LintContext}; use rustc_span::Span; @@ -28,6 +30,43 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { } } +/// Makes sure that a diagnostic is well formed. +/// +/// rustc debug asserts a few properties about spans, +/// but the clippy repo uses a distributed rustc build with debug assertions disabled, +/// so this has historically led to problems during subtree syncs where those debug assertions +/// only started triggered there. +/// +/// This function makes sure we also validate them in debug clippy builds. +#[cfg(debug_assertions)] +fn validate_diag(diag: &Diag<'_, impl EmissionGuarantee>) { + let suggestions = match &diag.suggestions { + Suggestions::Enabled(suggs) => &**suggs, + Suggestions::Sealed(suggs) => &**suggs, + Suggestions::Disabled => return, + }; + + for substitution in suggestions.iter().flat_map(|s| &s.substitutions) { + assert_eq!( + substitution + .parts + .iter() + .find(|SubstitutionPart { snippet, span }| snippet.is_empty() && span.is_empty()), + None, + "span must not be empty and have no suggestion" + ); + + assert_eq!( + substitution + .parts + .array_windows() + .find(|[a, b]| a.span.overlaps(b.span)), + None, + "suggestion must not have overlapping parts" + ); + } +} + /// Emit a basic lint message with a `msg` and a `span`. /// /// This is the most primitive of our lint emission methods and can @@ -64,6 +103,9 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult cx.span_lint(lint, sp, |diag| { diag.primary_message(msg); docs_link(diag, lint); + + #[cfg(debug_assertions)] + validate_diag(diag); }); } @@ -118,6 +160,9 @@ pub fn span_lint_and_help<T: LintContext>( diag.help(help.into()); } docs_link(diag, lint); + + #[cfg(debug_assertions)] + validate_diag(diag); }); } @@ -175,6 +220,9 @@ pub fn span_lint_and_note<T: LintContext>( diag.note(note.into()); } docs_link(diag, lint); + + #[cfg(debug_assertions)] + validate_diag(diag); }); } @@ -208,6 +256,9 @@ where diag.primary_message(msg); f(diag); docs_link(diag, lint); + + #[cfg(debug_assertions)] + validate_diag(diag); }); } @@ -240,6 +291,9 @@ pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, s cx.tcx.node_span_lint(lint, hir_id, sp, |diag| { diag.primary_message(msg); docs_link(diag, lint); + + #[cfg(debug_assertions)] + validate_diag(diag); }); } @@ -280,6 +334,9 @@ pub fn span_lint_hir_and_then( diag.primary_message(msg); f(diag); docs_link(diag, lint); + + #[cfg(debug_assertions)] + validate_diag(diag); }); } @@ -316,7 +373,7 @@ pub fn span_lint_hir_and_then( /// | /// = note: `-D fold-any` implied by `-D warnings` /// ``` -#[expect(clippy::collapsible_span_lint_calls)] +#[cfg_attr(not(debug_assertions), expect(clippy::collapsible_span_lint_calls))] pub fn span_lint_and_sugg<T: LintContext>( cx: &T, lint: &'static Lint, @@ -328,5 +385,8 @@ pub fn span_lint_and_sugg<T: LintContext>( ) { span_lint_and_then(cx, lint, sp, msg.into(), |diag| { diag.span_suggestion(sp, help.into(), sugg, applicability); + + #[cfg(debug_assertions)] + validate_diag(diag); }); } diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 3175a9a1dd3..11bbe734844 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -103,7 +103,7 @@ impl<'hir> IfLet<'hir> { /// Parses an `if let` expression pub fn hir(cx: &LateContext<'_>, expr: &Expr<'hir>) -> Option<Self> { if let ExprKind::If( - Expr { + &Expr { kind: ExprKind::Let(&hir::LetExpr { pat: let_pat, @@ -381,12 +381,12 @@ impl<'hir> WhileLet<'hir> { /// Parses a desugared `while let` loop pub const fn hir(expr: &Expr<'hir>) -> Option<Self> { if let ExprKind::Loop( - Block { + &Block { expr: - Some(Expr { + Some(&Expr { kind: ExprKind::If( - Expr { + &Expr { kind: ExprKind::Let(&hir::LetExpr { pat: let_pat, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 8004bc68b2e..cb69f8e5a0e 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -128,7 +128,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { self.inter_expr().eq_path_segments(left, right) } - pub fn eq_modifiers(&mut self, left: TraitBoundModifiers, right: TraitBoundModifiers) -> bool { + pub fn eq_modifiers(left: TraitBoundModifiers, right: TraitBoundModifiers) -> bool { std::mem::discriminant(&left.constness) == std::mem::discriminant(&right.constness) && std::mem::discriminant(&left.polarity) == std::mem::discriminant(&right.polarity) } @@ -1201,11 +1201,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(ty); self.hash_pat(pat); }, - TyKind::Ptr(ref mut_ty) => { + TyKind::Ptr(mut_ty) => { self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, - TyKind::Ref(lifetime, ref mut_ty) => { + TyKind::Ref(lifetime, mut_ty) => { self.hash_lifetime(lifetime); self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); @@ -1230,14 +1230,19 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(ty); } }, - TyKind::Path(ref qpath) => self.hash_qpath(qpath), + TyKind::Path(qpath) => self.hash_qpath(qpath), TyKind::TraitObject(_, lifetime, _) => { self.hash_lifetime(lifetime); }, TyKind::Typeof(anon_const) => { self.hash_body(anon_const.body); }, - TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::OpaqueDef(_) | TyKind::AnonAdt(_) => {}, + TyKind::Err(_) + | TyKind::Infer + | TyKind::Never + | TyKind::InferDelegation(..) + | TyKind::OpaqueDef(_) + | TyKind::AnonAdt(_) => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index ad85dfa2d1e..50d334acf18 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -9,6 +9,7 @@ #![feature(rustc_private)] #![feature(assert_matches)] #![feature(unwrap_infallible)] +#![feature(array_windows)] #![recursion_limit = "512"] #![allow( clippy::missing_errors_doc, @@ -688,11 +689,11 @@ pub fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> Vec<Res> { /// /// This function is expensive and should be used sparingly. pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> { - let (base, path) = match *path { + let (base, path) = match path { [primitive] => { return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)]; }, - [base, ref path @ ..] => (base, path), + [base, path @ ..] => (base, path), _ => return Vec::new(), }; @@ -744,7 +745,7 @@ pub fn def_path_res_with_base(tcx: TyCtxt<'_>, mut base: Vec<Res>, mut path: &[& } /// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`]. -pub fn def_path_def_ids(tcx: TyCtxt<'_>, path: &[&str]) -> impl Iterator<Item = DefId> { +pub fn def_path_def_ids(tcx: TyCtxt<'_>, path: &[&str]) -> impl Iterator<Item = DefId> + use<> { def_path_res(tcx, path).into_iter().filter_map(|res| res.opt_def_id()) } @@ -934,7 +935,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { } }, ExprKind::Call(repl_func, []) => is_default_equivalent_call(cx, repl_func), - ExprKind::Call(from_func, [ref arg]) => is_default_equivalent_from(cx, from_func, arg), + ExprKind::Call(from_func, [arg]) => is_default_equivalent_from(cx, from_func, arg), ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone), ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])), _ => false, @@ -947,7 +948,7 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: & { match arg.kind { ExprKind::Lit(hir::Lit { - node: LitKind::Str(ref sym, _), + node: LitKind::Str(sym, _), .. }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String), ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec), @@ -1209,8 +1210,8 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<' let capture = match capture.info.capture_kind { UpvarCapture::ByValue => CaptureKind::Value, UpvarCapture::ByRef(kind) => match kind { - BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not), - BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => { + BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not), + BorrowKind::UniqueImmutable | BorrowKind::Mutable => { CaptureKind::Ref(Mutability::Mut) }, }, @@ -1337,15 +1338,17 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> { pub struct ContainsName<'a, 'tcx> { pub cx: &'a LateContext<'tcx>, pub name: Symbol, - pub result: bool, } impl<'tcx> Visitor<'tcx> for ContainsName<'_, 'tcx> { + type Result = ControlFlow<()>; type NestedFilter = nested_filter::OnlyBodies; - fn visit_name(&mut self, name: Symbol) { + fn visit_name(&mut self, name: Symbol) -> Self::Result { if self.name == name { - self.result = true; + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) } } @@ -1356,13 +1359,8 @@ impl<'tcx> Visitor<'tcx> for ContainsName<'_, 'tcx> { /// Checks if an `Expr` contains a certain name. pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool { - let mut cn = ContainsName { - name, - result: false, - cx, - }; - cn.visit_expr(expr); - cn.result + let mut cn = ContainsName { cx, name }; + cn.visit_expr(expr).is_break() } /// Returns `true` if `expr` contains a return expression @@ -3340,8 +3338,8 @@ pub fn get_path_from_caller_to_method_type<'tcx>( let assoc_item = tcx.associated_item(method); let def_id = assoc_item.container_id(tcx); match assoc_item.container { - rustc_ty::TraitContainer => get_path_to_callee(tcx, from, def_id), - rustc_ty::ImplContainer => { + rustc_ty::AssocItemContainer::Trait => get_path_to_callee(tcx, from, def_id), + rustc_ty::AssocItemContainer::Impl => { let ty = tcx.type_of(def_id).instantiate_identity(); get_path_to_ty(tcx, from, ty, args) }, @@ -3459,7 +3457,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St pub fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool { matches!( cx.tcx.parent_hir_node(id), - Node::Stmt(..) | Node::Block(Block { stmts: &[], .. }) + Node::Stmt(..) | Node::Block(Block { stmts: [], .. }) ) } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 8f9f75d6824..666ec8df930 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -404,7 +404,7 @@ fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { } fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool { - // FIXME(effects, fee1-dead) revert to const destruct once it works again + // FIXME(const_trait_impl, fee1-dead) revert to const destruct once it works again #[expect(unused)] fn is_ty_const_destruct_unused<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool { // Avoid selecting for simple cases, such as builtin types. @@ -412,7 +412,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> return true; } - // FIXME(effects) constness + // FIXME(const_trait_impl) constness let obligation = Obligation::new( tcx, ObligationCause::dummy_with_span(body.span), diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 41785e161d0..ce1a20e0066 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, TypingMode, + TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, UintTy, Upcast, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; @@ -274,11 +274,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())) .collect::<Vec<_>>(); - let trait_ref = TraitRef::new( - tcx, - trait_id, - [GenericArg::from(ty)].into_iter().chain(args), - ); + let trait_ref = TraitRef::new(tcx, trait_id, [GenericArg::from(ty)].into_iter().chain(args)); debug_assert_matches!( tcx.def_kind(trait_id), @@ -975,9 +971,7 @@ pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 { match (cx.layout_of(ty).map(|layout| layout.size.bytes()), ty.kind()) { (Ok(size), _) => size, (Err(_), ty::Tuple(list)) => list.iter().map(|t| approx_ty_size(cx, t)).sum(), - (Err(_), ty::Array(t, n)) => { - n.try_to_target_usize(cx.tcx).unwrap_or_default() * approx_ty_size(cx, *t) - }, + (Err(_), ty::Array(t, n)) => n.try_to_target_usize(cx.tcx).unwrap_or_default() * approx_ty_size(cx, *t), (Err(_), ty::Adt(def, subst)) if def.is_struct() => def .variants() .iter() @@ -1284,7 +1278,12 @@ pub fn make_normalized_projection_with_regions<'tcx>( pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { let cause = ObligationCause::dummy(); - match tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)).at(&cause, param_env).query_normalize(ty) { + match tcx + .infer_ctxt() + .build(TypingMode::from_param_env(param_env)) + .at(&cause, param_env) + .query_normalize(ty) + { Ok(ty) => ty.value, Err(_) => ty, } diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs index 3021f21df12..d7640ebfb00 100644 --- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs @@ -302,9 +302,9 @@ fn type_is_inferable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> bo // Check that all type parameters appear in the functions input types. (0..(generics.parent_count + generics.own_params.len()) as u32).all(|index| { fn_sig - .inputs() - .iter() - .any(|input_ty| contains_param(*input_ty.skip_binder(), index)) + .inputs() + .iter() + .any(|input_ty| contains_param(*input_ty.skip_binder(), index)) }) } diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index 8af3bdccaa1..c8c25456f69 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -67,7 +67,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) { - if bk == ty::BorrowKind::MutBorrow { + if bk == ty::BorrowKind::Mutable { self.update(cmt); } } @@ -109,34 +109,28 @@ impl<'tcx> Visitor<'tcx> for ParamBindingIdCollector { pub struct BindingUsageFinder<'a, 'tcx> { cx: &'a LateContext<'tcx>, binding_ids: Vec<HirId>, - usage_found: bool, } impl<'a, 'tcx> BindingUsageFinder<'a, 'tcx> { pub fn are_params_used(cx: &'a LateContext<'tcx>, body: &'tcx hir::Body<'tcx>) -> bool { let mut finder = BindingUsageFinder { cx, binding_ids: ParamBindingIdCollector::collect_binding_hir_ids(body), - usage_found: false, }; - finder.visit_body(body); - finder.usage_found + finder.visit_body(body).is_break() } } impl<'tcx> Visitor<'tcx> for BindingUsageFinder<'_, 'tcx> { + type Result = ControlFlow<()>; type NestedFilter = nested_filter::OnlyBodies; - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - if !self.usage_found { - intravisit::walk_expr(self, expr); - } - } - - fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) -> Self::Result { if let Res::Local(id) = path.res { if self.binding_ids.contains(&id) { - self.usage_found = true; + return ControlFlow::Break(()); } } + + ControlFlow::Continue(()) } fn nested_visit_map(&mut self) -> Self::Map { diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index 8db6502dbfb..8f5ec185bf1 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -324,17 +324,15 @@ pub fn is_local_used<'tcx>(cx: &LateContext<'tcx>, visitable: impl Visitable<'tc pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { struct V<'a, 'tcx> { cx: &'a LateContext<'tcx>, - is_const: bool, } + impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> { + type Result = ControlFlow<()>; type NestedFilter = intravisit::nested_filter::None; - fn visit_expr(&mut self, e: &'tcx Expr<'_>) { - if !self.is_const { - return; - } + fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result { match e.kind { - ExprKind::ConstBlock(_) => return, + ExprKind::ConstBlock(_) => return ControlFlow::Continue(()), ExprKind::Call( &Expr { kind: ExprKind::Path(ref p), @@ -394,37 +392,34 @@ pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> | ExprKind::Type(..) => (), _ => { - self.is_const = false; - return; + return ControlFlow::Break(()); }, } - walk_expr(self, e); + + walk_expr(self, e) } } - let mut v = V { cx, is_const: true }; - v.visit_expr(e); - v.is_const + let mut v = V { cx }; + v.visit_expr(e).is_continue() } /// Checks if the given expression performs an unsafe operation outside of an unsafe block. pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { struct V<'a, 'tcx> { cx: &'a LateContext<'tcx>, - is_unsafe: bool, } impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; + type Result = ControlFlow<()>; + fn nested_visit_map(&mut self) -> Self::Map { self.cx.tcx.hir() } - fn visit_expr(&mut self, e: &'tcx Expr<'_>) { - if self.is_unsafe { - return; - } + fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result { match e.kind { ExprKind::Unary(UnOp::Deref, e) if self.cx.typeck_results().expr_ty(e).is_unsafe_ptr() => { - self.is_unsafe = true; + ControlFlow::Break(()) }, ExprKind::MethodCall(..) if self @@ -435,13 +430,13 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe }) => { - self.is_unsafe = true; + ControlFlow::Break(()) }, ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() { ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe => { - self.is_unsafe = true; + ControlFlow::Break(()) }, - ty::FnPtr(_, hdr) if hdr.safety == Safety::Unsafe => self.is_unsafe = true, + ty::FnPtr(_, hdr) if hdr.safety == Safety::Unsafe => ControlFlow::Break(()), _ => walk_expr(self, e), }, ExprKind::Path(ref p) @@ -451,56 +446,54 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { .opt_def_id() .map_or(false, |id| self.cx.tcx.is_mutable_static(id)) => { - self.is_unsafe = true; + ControlFlow::Break(()) }, _ => walk_expr(self, e), } } - fn visit_block(&mut self, b: &'tcx Block<'_>) { - if !matches!(b.rules, BlockCheckMode::UnsafeBlock(_)) { - walk_block(self, b); + fn visit_block(&mut self, b: &'tcx Block<'_>) -> Self::Result { + if matches!(b.rules, BlockCheckMode::UnsafeBlock(_)) { + ControlFlow::Continue(()) + } else { + walk_block(self, b) } } - fn visit_nested_item(&mut self, id: ItemId) { - if let ItemKind::Impl(i) = &self.cx.tcx.hir().item(id).kind { - self.is_unsafe = i.safety == Safety::Unsafe; + fn visit_nested_item(&mut self, id: ItemId) -> Self::Result { + if let ItemKind::Impl(i) = &self.cx.tcx.hir().item(id).kind + && i.safety == Safety::Unsafe + { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) } } } - let mut v = V { cx, is_unsafe: false }; - v.visit_expr(e); - v.is_unsafe + let mut v = V { cx }; + v.visit_expr(e).is_break() } /// Checks if the given expression contains an unsafe block pub fn contains_unsafe_block<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { struct V<'cx, 'tcx> { cx: &'cx LateContext<'tcx>, - found_unsafe: bool, } impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> { + type Result = ControlFlow<()>; type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { self.cx.tcx.hir() } - fn visit_block(&mut self, b: &'tcx Block<'_>) { - if self.found_unsafe { - return; - } + fn visit_block(&mut self, b: &'tcx Block<'_>) -> Self::Result { if b.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) { - self.found_unsafe = true; - return; + ControlFlow::Break(()) + } else { + walk_block(self, b) } - walk_block(self, b); } } - let mut v = V { - cx, - found_unsafe: false, - }; - v.visit_expr(e); - v.found_unsafe + let mut v = V { cx }; + v.visit_expr(e).is_break() } /// Runs the given function for each sub-expression producing the final value consumed by the parent diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index e11ab40b9de..37d9cce2465 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-10-18" +channel = "nightly-2024-11-07" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 5774e20e0be..b8e0413e97b 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -396,7 +396,8 @@ struct Renderer<'a> { impl Renderer<'_> { fn markdown(input: &str) -> Safe<String> { - let parser = Parser::new_ext(input, Options::all()); + let input = clippy_config::sanitize_explanation(input); + let parser = Parser::new_ext(&input, Options::all()); let mut html_output = String::new(); html::push_html(&mut html_output, parser); // Oh deer, what a hack :O diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs index 1fd03cfe36d..d59e9cbbb61 100644 --- a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs +++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs @@ -7,7 +7,7 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_session; extern crate rustc_lint; -use rustc_lint::LintPass; +use rustc_lint::{LintPass, LintVec}; declare_tool_lint! { pub clippy::TEST_LINT, @@ -35,6 +35,9 @@ impl LintPass for Pass { fn name(&self) -> &'static str { "TEST_LINT" } + fn get_lints(&self) -> LintVec { + vec![TEST_LINT] + } } declare_lint_pass!(Pass2 => [TEST_LINT_REGISTERED]); diff --git a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.fixed b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.fixed new file mode 100644 index 00000000000..2cbd646a0fd --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.fixed @@ -0,0 +1,24 @@ +#![feature(rustc_private)] +#![warn(clippy::slow_symbol_comparisons)] + +extern crate rustc_span; + +use clippy_utils::sym; +use rustc_span::Symbol; + +fn main() { + let symbol = sym!(example); + let other_symbol = sym!(other_example); + + // Should lint + let slow_comparison = symbol.as_str() == "example"; + //~^ error: comparing `Symbol` via `Symbol::intern` + let slow_comparison_macro = symbol.as_str() == "example"; + //~^ error: comparing `Symbol` via `Symbol::intern` + let slow_comparison_backwards = symbol.as_str() == "example"; + //~^ error: comparing `Symbol` via `Symbol::intern` + + // Should not lint + let faster_comparison = symbol.as_str() == "other_example"; + let preinterned_comparison = symbol == other_symbol; +} diff --git a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.rs b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.rs new file mode 100644 index 00000000000..0cea3c3fcff --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.rs @@ -0,0 +1,24 @@ +#![feature(rustc_private)] +#![warn(clippy::slow_symbol_comparisons)] + +extern crate rustc_span; + +use clippy_utils::sym; +use rustc_span::Symbol; + +fn main() { + let symbol = sym!(example); + let other_symbol = sym!(other_example); + + // Should lint + let slow_comparison = symbol == Symbol::intern("example"); + //~^ error: comparing `Symbol` via `Symbol::intern` + let slow_comparison_macro = symbol == sym!(example); + //~^ error: comparing `Symbol` via `Symbol::intern` + let slow_comparison_backwards = sym!(example) == symbol; + //~^ error: comparing `Symbol` via `Symbol::intern` + + // Should not lint + let faster_comparison = symbol.as_str() == "other_example"; + let preinterned_comparison = symbol == other_symbol; +} diff --git a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.stderr b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.stderr new file mode 100644 index 00000000000..72cb20a7fed --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.stderr @@ -0,0 +1,23 @@ +error: comparing `Symbol` via `Symbol::intern` + --> tests/ui-internal/slow_symbol_comparisons.rs:14:27 + | +LL | let slow_comparison = symbol == Symbol::intern("example"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `Symbol::as_str` and check the string instead: `symbol.as_str() == "example"` + | + = note: `-D clippy::slow-symbol-comparisons` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::slow_symbol_comparisons)]` + +error: comparing `Symbol` via `Symbol::intern` + --> tests/ui-internal/slow_symbol_comparisons.rs:16:33 + | +LL | let slow_comparison_macro = symbol == sym!(example); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `Symbol::as_str` and check the string instead: `symbol.as_str() == "example"` + +error: comparing `Symbol` via `Symbol::intern` + --> tests/ui-internal/slow_symbol_comparisons.rs:18:37 + | +LL | let slow_comparison_backwards = sym!(example) == symbol; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `Symbol::as_str` and check the string instead: `symbol.as_str() == "example"` + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed index eb79fdbc4b4..8e7f020c1f6 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed @@ -1,6 +1,7 @@ #![feature(rustc_private)] #![deny(clippy::internal)] #![allow( + clippy::slow_symbol_comparisons, clippy::borrow_deref_ref, clippy::unnecessary_operation, unused_must_use, diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs index bbea13af92a..9aeeb9aaf3a 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs @@ -1,6 +1,7 @@ #![feature(rustc_private)] #![deny(clippy::internal)] #![allow( + clippy::slow_symbol_comparisons, clippy::borrow_deref_ref, clippy::unnecessary_operation, unused_must_use, diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr index 551167a9ff5..668c11722f9 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr @@ -1,5 +1,5 @@ error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:15:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:16:5 | LL | Symbol::intern("foo").as_str() == "clippy"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::sym::clippy` @@ -12,25 +12,25 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::unnecessary_symbol_str)]` implied by `#[deny(clippy::internal)]` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:16:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:17:5 | LL | Symbol::intern("foo").to_string() == "self"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::symbol::kw::SelfLower` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:17:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:18:5 | LL | Symbol::intern("foo").to_ident_string() != "Self"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") != rustc_span::symbol::kw::SelfUpper` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:18:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:19:5 | LL | &*Ident::empty().as_str() == "clippy"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ident::empty().name == rustc_span::sym::clippy` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:19:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:20:5 | LL | "clippy" == Ident::empty().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::clippy == Ident::empty().name` diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml new file mode 100644 index 00000000000..fbdb0c9c37d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml @@ -0,0 +1 @@ +trait-assoc-item-kinds-order = ["fn", "type", "const", "type"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml new file mode 100644 index 00000000000..720655e5cce --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml @@ -0,0 +1 @@ +trait-assoc-item-kinds-order = ["const", "type"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml new file mode 100644 index 00000000000..0dd5407be10 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml @@ -0,0 +1 @@ +source-item-ordering = ["enum", "impl", "module", "struct", "trait", "struct"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default/clippy.toml new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default/clippy.toml diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml new file mode 100644 index 00000000000..ddca5cfa577 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml @@ -0,0 +1,12 @@ +trait-assoc-item-kinds-order = ["const", "type", "fn"] +source-item-ordering = ["enum", "impl", "module", "struct", "trait"] +module-item-order-groupings = [ + ["modules", ["extern_crate", "mod", "foreign_mod"]], + ["use", ["use"]], + ["macros", ["macro"]], + ["global_asm", ["global_asm"]], + ["UPPER_SNAKE_CASE", ["static", "const"]], + ["PascalCase", ["ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl"]], + ["lower_snake_case", ["fn"]] +] + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_enum/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_enum/clippy.toml new file mode 100644 index 00000000000..2144bdc9a0c --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_enum/clippy.toml @@ -0,0 +1 @@ +source-item-ordering = ["enum"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_impl/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_impl/clippy.toml new file mode 100644 index 00000000000..54b6727fabf --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_impl/clippy.toml @@ -0,0 +1 @@ +source-item-ordering = ["impl"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_trait/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_trait/clippy.toml new file mode 100644 index 00000000000..b551611c35e --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/only_trait/clippy.toml @@ -0,0 +1 @@ +source-item-ordering = ["trait"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_1.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_1.stderr new file mode 100644 index 00000000000..e441c7c1241 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_1.stderr @@ -0,0 +1,8 @@ +error: error reading Clippy's configuration file: Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. The trait associated item kinds are: [Const, Fn, Type] + --> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml:1:32 + | +LL | trait-assoc-item-kinds-order = ["fn", "type", "const", "type"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_2.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_2.stderr new file mode 100644 index 00000000000..183f0b03319 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_2.stderr @@ -0,0 +1,8 @@ +error: error reading Clippy's configuration file: Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. The trait associated item kinds are: [Const, Fn, Type] + --> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml:1:32 + | +LL | trait-assoc-item-kinds-order = ["const", "type"] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_3.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_3.stderr new file mode 100644 index 00000000000..abf58dbd110 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_3.stderr @@ -0,0 +1,8 @@ +error: error reading Clippy's configuration file: The category "Struct" was enabled more than once in the source ordering configuration. + --> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml:1:24 + | +LL | source-item-ordering = ["enum", "impl", "module", "struct", "trait", "struct"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs new file mode 100644 index 00000000000..e9bcc30c15e --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs @@ -0,0 +1,186 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: default default_exp bad_conf_1 bad_conf_2 bad_conf_3 +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default +//@[default_exp] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default_exp +//@[bad_conf_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1 +//@[bad_conf_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2 +//@[bad_conf_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3 + +#![allow(dead_code)] +#![warn(clippy::arbitrary_source_item_ordering)] + +/// This module gets linted before clippy gives up. +mod i_am_just_right { + const AFTER: i8 = 0; + + const BEFORE: i8 = 0; +} + +/// Since the upper module passes linting, the lint now recurses into this module. +mod this_is_in_the_wrong_position { + const A: i8 = 1; + const C: i8 = 0; +} + +// Use statements should not be linted internally - this is normally auto-sorted using rustfmt. +use std::rc::{Rc, Weak}; +use std::sync::{Arc, Barrier, RwLock}; + +const SNAKE_CASE: &str = "zzzzzzzz"; + +const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + +const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + +trait BasicEmptyTrait {} + +trait CloneSelf { + fn clone_self(&self) -> Self; +} + +enum EnumOrdered { + A, + B, + C, +} + +enum EnumUnordered { + A, + B, + C, +} + +#[allow(clippy::arbitrary_source_item_ordering)] +enum EnumUnorderedAllowed { + A, + B, + C, +} + +struct StructOrdered { + a: bool, + b: bool, + c: bool, +} + +impl BasicEmptyTrait for StructOrdered {} + +impl CloneSelf for StructOrdered { + fn clone_self(&self) -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +impl Default for StructOrdered { + fn default() -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +impl std::clone::Clone for StructOrdered { + fn clone(&self) -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +#[derive(Clone, Default)] +struct StructUnordered { + a: bool, + b: bool, + c: bool, + d: bool, +} + +impl TraitUnordered for StructUnordered { + const A: bool = false; + const B: bool = false; + const C: bool = false; + + type SomeType = (); + + fn a() {} + fn b() {} + fn c() {} +} + +impl TraitUnorderedItemKinds for StructUnordered { + const A: bool = false; + const B: bool = false; + const C: bool = false; + + type SomeType = (); + + fn a() {} + fn b() {} + fn c() {} +} + +struct StructUnorderedGeneric<T> { + _1: std::marker::PhantomData<T>, + a: bool, + b: bool, + c: bool, + d: bool, +} + +trait TraitOrdered { + const A: bool; + const B: bool; + const C: bool; + + type SomeType; + + fn a(); + fn b(); + fn c(); +} + +trait TraitUnordered { + const A: bool; + const B: bool; + const C: bool; + + type SomeType; + + fn a(); + fn b(); + fn c(); +} + +trait TraitUnorderedItemKinds { + const A: bool; + const B: bool; + const C: bool; + + type SomeType; + + fn a(); + fn b(); + fn c(); +} + +#[derive(std::clone::Clone, Default)] +struct ZisShouldBeBeforeZeMainFn; + +fn main() { + // test code goes here +} + +#[cfg(test)] +mod test { + const B: i8 = 1; + + const A: i8 = 0; +} diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs new file mode 100644 index 00000000000..0fccbd4790b --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs @@ -0,0 +1,174 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: var_1 +//@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1 + +#![allow(dead_code)] +#![warn(clippy::arbitrary_source_item_ordering)] + +/// This module gets linted before clippy gives up. +mod i_am_just_right { + const AFTER: i8 = 0; + + const BEFORE: i8 = 0; +} + +/// Since the upper module passes linting, the lint now recurses into this module. +mod this_is_in_the_wrong_position { + const A: i8 = 1; + const C: i8 = 0; +} + +// Use statements should not be linted internally - this is normally auto-sorted using rustfmt. +use std::rc::{Rc, Weak}; +use std::sync::{Arc, Barrier, RwLock}; + +const SNAKE_CASE: &str = "zzzzzzzz"; + +const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + +const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + +trait BasicEmptyTrait {} + +trait CloneSelf { + fn clone_self(&self) -> Self; +} + +enum EnumOrdered { + A, + B, + C, +} + +enum EnumUnordered { + A, + B, + C, +} + +#[allow(clippy::arbitrary_source_item_ordering)] +enum EnumUnorderedAllowed { + A, + B, + C, +} + +struct StructOrdered { + a: bool, + b: bool, + c: bool, +} + +impl BasicEmptyTrait for StructOrdered {} + +impl CloneSelf for StructOrdered { + fn clone_self(&self) -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +impl Default for StructOrdered { + fn default() -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +impl std::clone::Clone for StructOrdered { + fn clone(&self) -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +#[derive(Clone, Default)] +struct StructUnordered { + a: bool, + b: bool, + c: bool, + d: bool, +} + +impl TraitUnordered for StructUnordered { + fn a() {} + fn b() {} + fn c() {} + + type SomeType = (); + + const A: bool = false; + const B: bool = false; + const C: bool = false; +} + +impl TraitUnorderedItemKinds for StructUnordered { + fn a() {} + + type SomeType = (); + + const A: bool = false; +} + +struct StructUnorderedGeneric<T> { + _1: std::marker::PhantomData<T>, + a: bool, + b: bool, + c: bool, + d: bool, +} + +trait TraitOrdered { + fn a(); + fn b(); + fn c(); + + type SomeType; + + const A: bool; + const B: bool; + const C: bool; +} + +trait TraitUnordered { + fn a(); + fn b(); + fn c(); + + type SomeType; + + const A: bool; + const B: bool; + const C: bool; +} + +trait TraitUnorderedItemKinds { + fn a(); + + type SomeType; + + const A: bool; +} + +#[derive(std::clone::Clone, Default)] +struct ZisShouldBeBeforeZeMainFn; + +fn main() { + // test code goes here +} + +#[cfg(test)] +mod test { + const B: i8 = 1; + + const A: i8 = 0; +} diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr new file mode 100644 index 00000000000..062bf25ea62 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr @@ -0,0 +1,226 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:21:14 + | +LL | use std::rc::Weak; + | ^^^^ + | +note: should be placed before `SNAKE_CASE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:19:7 + | +LL | const SNAKE_CASE: &str = "zzzzzzzz"; + | ^^^^^^^^^^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:64:1 + | +LL | / impl CloneSelf for StructOrdered { +LL | | fn clone_self(&self) -> Self { +LL | | Self { +LL | | a: true, +... | +LL | | } +LL | | } + | |_^ + | +note: should be placed before the following item + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:54:1 + | +LL | / impl Default for StructOrdered { +LL | | fn default() -> Self { +LL | | Self { +LL | | a: true, +... | +LL | | } +LL | | } + | |_^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7 + | +LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `TraitUnorderedItemKinds` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:7 + | +LL | trait TraitUnorderedItemKinds { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:1 + | +LL | impl BasicEmptyTrait for StructOrdered {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before the following item + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:138:1 + | +LL | / impl TraitUnordered for StructUnordered { +LL | | const A: bool = false; +LL | | const C: bool = false; +LL | | const B: bool = false; +... | +LL | | fn b() {} +LL | | } + | |_^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:5 + | +LL | mod this_is_in_the_wrong_position { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `main` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:165:4 + | +LL | fn main() { + | ^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:178:7 + | +LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `ZisShouldBeBeforeZeMainFn` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:176:8 + | +LL | struct ZisShouldBeBeforeZeMainFn; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:12:11 + | +LL | const AFTER: i8 = 0; + | ^^^^^ + | +note: should be placed before `BEFORE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:10:11 + | +LL | const BEFORE: i8 = 0; + | ^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:38:5 + | +LL | B, + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:37:5 + | +LL | C, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:88:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:87:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:115:11 + | +LL | const B: bool; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:114:11 + | +LL | const C: bool; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:8 + | +LL | fn b(); + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:8 + | +LL | fn c(); + | ^ + +error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:127:5 + | +LL | const A: bool; + | ^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:5 + | +LL | type SomeType; + | ^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:141:11 + | +LL | const B: bool = false; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11 + | +LL | const C: bool = false; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8 + | +LL | fn b() {} + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:146:8 + | +LL | fn c() {} + | ^ + +error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:156:5 + | +LL | const A: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:5 + | +LL | type SomeType = (); + | ^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:172:11 + | +LL | const A: i8 = 1; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11 + | +LL | const C: i8 = 0; + | ^ + +error: aborting due to 17 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs new file mode 100644 index 00000000000..2765bf935b7 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs @@ -0,0 +1,185 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: default +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default + +#![allow(dead_code)] +#![warn(clippy::arbitrary_source_item_ordering)] + +/// This module gets linted before clippy gives up. +mod i_am_just_right { + const BEFORE: i8 = 0; + + const AFTER: i8 = 0; +} + +// Use statements should not be linted internally - this is normally auto-sorted using rustfmt. +use std::rc::Rc; +use std::sync::{Arc, Barrier, RwLock}; + +const SNAKE_CASE: &str = "zzzzzzzz"; + +use std::rc::Weak; + +trait BasicEmptyTrait {} + +trait CloneSelf { + fn clone_self(&self) -> Self; +} + +enum EnumOrdered { + A, + B, + C, +} + +enum EnumUnordered { + A, + C, + B, +} + +#[allow(clippy::arbitrary_source_item_ordering)] +enum EnumUnorderedAllowed { + A, + C, + B, +} + +struct StructOrdered { + a: bool, + b: bool, + c: bool, +} + +impl Default for StructOrdered { + fn default() -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +impl CloneSelf for StructOrdered { + fn clone_self(&self) -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +impl std::clone::Clone for StructOrdered { + fn clone(&self) -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +#[derive(Default, Clone)] +struct StructUnordered { + a: bool, + c: bool, + b: bool, + d: bool, +} + +struct StructUnorderedGeneric<T> { + _1: std::marker::PhantomData<T>, + a: bool, + c: bool, + b: bool, + d: bool, +} + +trait TraitOrdered { + const A: bool; + const B: bool; + const C: bool; + + type SomeType; + + fn a(); + fn b(); + fn c(); +} + +trait TraitUnordered { + const A: bool; + const C: bool; + const B: bool; + + type SomeType; + + fn a(); + fn c(); + fn b(); +} + +trait TraitUnorderedItemKinds { + type SomeType; + + const A: bool; + const B: bool; + const C: bool; + + fn a(); + fn b(); + fn c(); +} + +const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + +impl TraitUnordered for StructUnordered { + const A: bool = false; + const C: bool = false; + const B: bool = false; + + type SomeType = (); + + fn a() {} + fn c() {} + fn b() {} +} + +// Trait impls should be located just after the type they implement it for. +impl BasicEmptyTrait for StructOrdered {} + +impl TraitUnorderedItemKinds for StructUnordered { + type SomeType = (); + + const A: bool = false; + const B: bool = false; + const C: bool = false; + + fn a() {} + fn b() {} + fn c() {} +} + +fn main() { + // test code goes here +} + +/// Note that the linting pass is stopped before recursing into this module. +mod this_is_in_the_wrong_position { + const C: i8 = 0; + const A: i8 = 1; +} + +#[derive(Default, std::clone::Clone)] +struct ZisShouldBeBeforeZeMainFn; + +const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + +#[cfg(test)] +mod test { + const B: i8 = 1; + + const A: i8 = 0; +} diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs new file mode 100644 index 00000000000..44902336573 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs @@ -0,0 +1,174 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: var_1 +//@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1 + +#![allow(dead_code)] +#![warn(clippy::arbitrary_source_item_ordering)] + +/// This module gets linted before clippy gives up. +mod i_am_just_right { + const AFTER: i8 = 0; + + const BEFORE: i8 = 0; +} + +/// Since the upper module passes linting, the lint now recurses into this module. +mod this_is_in_the_wrong_position { + const A: i8 = 1; + const C: i8 = 0; +} + +// Use statements should not be linted internally - this is normally auto-sorted using rustfmt. +use std::rc::{Rc, Weak}; +use std::sync::{Arc, Barrier, RwLock}; + +const SNAKE_CASE: &str = "zzzzzzzz"; + +const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + +const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + +trait BasicEmptyTrait {} + +trait CloneSelf { + fn clone_self(&self) -> Self; +} + +enum EnumOrdered { + A, + B, + C, +} + +enum EnumUnordered { + A, + B, + C, +} + +#[allow(clippy::arbitrary_source_item_ordering)] +enum EnumUnorderedAllowed { + A, + B, + C, +} + +struct StructOrdered { + a: bool, + b: bool, + c: bool, +} + +impl BasicEmptyTrait for StructOrdered {} + +impl CloneSelf for StructOrdered { + fn clone_self(&self) -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +impl Default for StructOrdered { + fn default() -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +impl std::clone::Clone for StructOrdered { + fn clone(&self) -> Self { + Self { + a: true, + b: true, + c: true, + } + } +} + +#[derive(Clone, Default)] +struct StructUnordered { + a: bool, + b: bool, + c: bool, + d: bool, +} + +impl TraitUnordered for StructUnordered { + fn a() {} + fn c() {} + fn b() {} + + type SomeType = (); + + const A: bool = false; + const C: bool = false; + const B: bool = false; +} + +impl TraitUnorderedItemKinds for StructUnordered { + const A: bool = false; + + type SomeType = (); + + fn a() {} +} + +struct StructUnorderedGeneric<T> { + _1: std::marker::PhantomData<T>, + a: bool, + b: bool, + c: bool, + d: bool, +} + +trait TraitOrdered { + fn a(); + fn b(); + fn c(); + + type SomeType; + + const A: bool; + const B: bool; + const C: bool; +} + +trait TraitUnordered { + fn a(); + fn c(); + fn b(); + + type SomeType; + + const A: bool; + const C: bool; + const B: bool; +} + +trait TraitUnorderedItemKinds { + const A: bool; + + type SomeType; + + fn a(); +} + +#[derive(std::clone::Clone, Default)] +struct ZisShouldBeBeforeZeMainFn; + +fn main() { + // test code goes here +} + +#[cfg(test)] +mod test { + const B: i8 = 1; + + const A: i8 = 0; +} diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr new file mode 100644 index 00000000000..f31f7f68c17 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr @@ -0,0 +1,100 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:105:8 + | +LL | fn b() {} + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:104:8 + | +LL | fn c() {} + | ^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:111:11 + | +LL | const B: bool = false; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:110:11 + | +LL | const C: bool = false; + | ^ + +error: incorrect ordering of impl items (defined order: [Fn, Type, Const]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5 + | +LL | type SomeType = (); + | ^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `A` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:115:5 + | +LL | const A: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of impl items (defined order: [Fn, Type, Const]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5 + | +LL | fn a() {} + | ^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5 + | +LL | type SomeType = (); + | ^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:145:8 + | +LL | fn b(); + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:144:8 + | +LL | fn c(); + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:151:11 + | +LL | const B: bool; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:150:11 + | +LL | const C: bool; + | ^ + +error: incorrect ordering of trait items (defined order: [Fn, Type, Const]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:157:5 + | +LL | type SomeType; + | ^^^^^^^^^^^^^^ + | +note: should be placed before `A` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:155:5 + | +LL | const A: bool; + | ^^^^^^^^^^^^^^ + +error: incorrect ordering of trait items (defined order: [Fn, Type, Const]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:159:5 + | +LL | fn a(); + | ^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:157:5 + | +LL | type SomeType; + | ^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr new file mode 100644 index 00000000000..57069fd8fee --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr @@ -0,0 +1,16 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:22:5 + | +LL | A, + | ^ + | +note: should be placed before `B` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:21:5 + | +LL | B, + | ^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs new file mode 100644 index 00000000000..e8002c4a163 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs @@ -0,0 +1,43 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: only_enum +//@[only_enum] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_enum + +#![allow(dead_code)] +#![warn(clippy::arbitrary_source_item_ordering)] + +fn main() {} + +struct StructUnordered { + b: bool, + a: bool, +} + +enum EnumOrdered { + A, + B, +} + +enum EnumUnordered { + B, + A, +} + +trait TraitUnordered { + const B: bool; + const A: bool; + + type SomeType; + + fn b(); + fn a(); +} + +trait TraitUnorderedItemKinds { + type SomeType; + + const A: bool; + + fn a(); +} + +const ZIS_SHOULD_BE_AT_THE_TOP: () = (); diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr new file mode 100644 index 00000000000..40348ecbdae --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr @@ -0,0 +1,40 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:8 + | +LL | fn a() {} + | ^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:42:8 + | +LL | fn b() {} + | ^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5 + | +LL | type SomeType = i8; + | ^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `a` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:5 + | +LL | fn a() {} + | ^^^^^^^^^ + +error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:47:5 + | +LL | const A: bool = true; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5 + | +LL | type SomeType = i8; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs new file mode 100644 index 00000000000..bd969c865b5 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs @@ -0,0 +1,67 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: only_impl +//@[only_impl] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_impl + +#![allow(dead_code)] +#![warn(clippy::arbitrary_source_item_ordering)] + +fn main() {} + +struct StructUnordered { + b: bool, + a: bool, +} + +struct BasicStruct {} + +trait BasicTrait { + const A: bool; + + type SomeType; + + fn b(); + fn a(); +} + +enum EnumUnordered { + B, + A, +} + +trait TraitUnordered { + const B: bool; + const A: bool; + + type SomeType; + + fn b(); + fn a(); +} + +impl BasicTrait for StructUnordered { + fn b() {} + fn a() {} + + type SomeType = i8; + + const A: bool = true; +} + +trait TraitUnorderedItemKinds { + type SomeType; + + const A: bool; + + fn a(); +} + +const ZIS_SHOULD_BE_AT_THE_TOP: () = (); + +impl BasicTrait for BasicStruct { + const A: bool = true; + + type SomeType = i8; + + fn a() {} + fn b() {} +} diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr new file mode 100644 index 00000000000..9b86ebd48e3 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr @@ -0,0 +1,40 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:32:11 + | +LL | const A: bool; + | ^ + | +note: should be placed before `B` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:31:11 + | +LL | const B: bool; + | ^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:37:8 + | +LL | fn a(); + | ^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:36:8 + | +LL | fn b(); + | ^ + +error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:43:5 + | +LL | const A: bool; + | ^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:41:5 + | +LL | type SomeType; + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs new file mode 100644 index 00000000000..979a52ecb10 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs @@ -0,0 +1,48 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: only_trait +//@[only_trait] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_trait + +#![allow(dead_code)] +#![warn(clippy::arbitrary_source_item_ordering)] + +fn main() {} + +struct StructUnordered { + b: bool, + a: bool, +} + +trait TraitOrdered { + const A: bool; + const B: bool; + + type SomeType; + + fn a(); + fn b(); +} + +enum EnumUnordered { + B, + A, +} + +trait TraitUnordered { + const B: bool; + const A: bool; + + type SomeType; + + fn b(); + fn a(); +} + +trait TraitUnorderedItemKinds { + type SomeType; + + const A: bool; + + fn a(); +} + +const ZIS_SHOULD_BE_AT_THE_TOP: () = (); diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/var_1/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/var_1/clippy.toml new file mode 100644 index 00000000000..bede035e388 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/var_1/clippy.toml @@ -0,0 +1 @@ +trait-assoc-item-kinds-order = ["fn", "type", "const"] diff --git a/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr index ddeb2f8cc70..2e3386628b4 100644 --- a/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr +++ b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr @@ -1,11 +1,39 @@ +error: use of a disallowed macro `std::vec` + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:16:5 + | +LL | vec![1, 2, 3]; + | ^^^^^^^^^^^^^ + | + = note: `-D clippy::disallowed-macros` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::disallowed_macros)]` + +error: use of a disallowed macro `serde::Serialize` + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:18:14 + | +LL | #[derive(Serialize)] + | ^^^^^^^^^ + | + = note: no serializing + +error: use of a disallowed macro `macros::attr` + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:31:1 + | +LL | / macros::attr! { +LL | | struct S; +LL | | } + | |_^ + +error: use of a disallowed macro `proc_macros::Derive` + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:47:10 + | +LL | #[derive(Derive)] + | ^^^^^^ + error: use of a disallowed macro `std::println` --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:13:5 | LL | println!("one"); | ^^^^^^^^^^^^^^^ - | - = note: `-D clippy::disallowed-macros` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::disallowed_macros)]` error: use of a disallowed macro `std::println` --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:14:5 @@ -19,20 +47,6 @@ error: use of a disallowed macro `std::cfg` LL | cfg!(unix); | ^^^^^^^^^^ -error: use of a disallowed macro `std::vec` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:16:5 - | -LL | vec![1, 2, 3]; - | ^^^^^^^^^^^^^ - -error: use of a disallowed macro `serde::Serialize` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:18:14 - | -LL | #[derive(Serialize)] - | ^^^^^^^^^ - | - = note: no serializing - error: use of a disallowed macro `macros::expr` --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:21:13 | @@ -69,14 +83,6 @@ error: use of a disallowed macro `macros::binop` LL | let _ = macros::binop!(1); | ^^^^^^^^^^^^^^^^^ -error: use of a disallowed macro `macros::attr` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:31:1 - | -LL | / macros::attr! { -LL | | struct S; -LL | | } - | |_^ - error: use of a disallowed macro `macros::item` --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:36:5 | @@ -95,11 +101,5 @@ error: use of a disallowed macro `macros::item` LL | macros::item!(); | ^^^^^^^^^^^^^^^ -error: use of a disallowed macro `proc_macros::Derive` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:47:10 - | -LL | #[derive(Derive)] - | ^^^^^^ - error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs index f3dbb6ad1cf..dc9349f75a0 100644 --- a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs +++ b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs @@ -1,8 +1,8 @@ #![warn(clippy::large_include_file)] // Good -const GOOD_INCLUDE_BYTES: &[u8; 581] = include_bytes!("large_include_file.rs"); -const GOOD_INCLUDE_STR: &str = include_str!("large_include_file.rs"); +const GOOD_INCLUDE_BYTES: &[u8; 68] = include_bytes!("../../ui/author.rs"); +const GOOD_INCLUDE_STR: &str = include_str!("../../ui/author.rs"); #[allow(clippy::large_include_file)] const ALLOWED_TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt"); @@ -11,6 +11,9 @@ const ALLOWED_TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt"); // Bad const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt"); +//~^ large_include_file const TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt"); +//~^ large_include_file +#[doc = include_str!("too_big.txt")] //~ large_include_file fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr index 34224065f07..9e1494a47bb 100644 --- a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr +++ b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr @@ -9,12 +9,20 @@ LL | const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt"); = help: to override `-D warnings` add `#[allow(clippy::large_include_file)]` error: attempted to include a large file - --> tests/ui-toml/large_include_file/large_include_file.rs:14:35 + --> tests/ui-toml/large_include_file/large_include_file.rs:15:35 | LL | const TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the configuration allows a maximum size of 600 bytes -error: aborting due to 2 previous errors +error: attempted to include a large file + --> tests/ui-toml/large_include_file/large_include_file.rs:18:1 + | +LL | #[doc = include_str!("too_big.txt")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the configuration allows a maximum size of 600 bytes + +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs index 79c8751468d..c5d00c91b05 100644 --- a/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs +++ b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs @@ -51,4 +51,10 @@ pub mod __macro { } } +#[warn(clippy::missing_errors_doc)] +#[test] +fn test() -> Result<(), ()> { + Ok(()) +} + fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 5cf9c0fb271..6fa583fc041 100644 --- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -54,12 +54,14 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect max-trait-bounds min-ident-chars-threshold missing-docs-in-crate-items + module-item-order-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior semicolon-inside-block-ignore-singleline semicolon-outside-block-ignore-multiline single-char-binding-names-threshold + source-item-ordering stack-size-threshold standard-macro-braces struct-field-name-threshold @@ -68,6 +70,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect too-large-for-stack too-many-arguments-threshold too-many-lines-threshold + trait-assoc-item-kinds-order trivial-copy-size-limit type-complexity-threshold unnecessary-box-size @@ -138,12 +141,14 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect max-trait-bounds min-ident-chars-threshold missing-docs-in-crate-items + module-item-order-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior semicolon-inside-block-ignore-singleline semicolon-outside-block-ignore-multiline single-char-binding-names-threshold + source-item-ordering stack-size-threshold standard-macro-braces struct-field-name-threshold @@ -152,6 +157,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect too-large-for-stack too-many-arguments-threshold too-many-lines-threshold + trait-assoc-item-kinds-order trivial-copy-size-limit type-complexity-threshold unnecessary-box-size @@ -222,12 +228,14 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni max-trait-bounds min-ident-chars-threshold missing-docs-in-crate-items + module-item-order-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior semicolon-inside-block-ignore-singleline semicolon-outside-block-ignore-multiline single-char-binding-names-threshold + source-item-ordering stack-size-threshold standard-macro-braces struct-field-name-threshold @@ -236,6 +244,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni too-large-for-stack too-many-arguments-threshold too-many-lines-threshold + trait-assoc-item-kinds-order trivial-copy-size-limit type-complexity-threshold unnecessary-box-size diff --git a/src/tools/clippy/tests/ui/allow_attributes.fixed b/src/tools/clippy/tests/ui/allow_attributes.fixed index 058dbb77a32..8f6c962e2f5 100644 --- a/src/tools/clippy/tests/ui/allow_attributes.fixed +++ b/src/tools/clippy/tests/ui/allow_attributes.fixed @@ -1,4 +1,5 @@ //@aux-build:proc_macros.rs +//@aux-build:proc_macro_derive.rs #![allow(unused)] #![warn(clippy::allow_attributes)] #![no_main] @@ -65,3 +66,9 @@ fn deny_allow_attributes() -> Option<u8> { allow?; Some(42) } + +// Edge case where the generated tokens spans match on #[repr(transparent)] which tricks the proc +// macro check +#[repr(transparent)] +#[derive(proc_macro_derive::AllowLintSameSpan)] // This macro generates tokens with the same span as the whole struct and repr +struct IgnoreDerived; diff --git a/src/tools/clippy/tests/ui/allow_attributes.rs b/src/tools/clippy/tests/ui/allow_attributes.rs index 6d94ce50e4c..cb6c4dcf715 100644 --- a/src/tools/clippy/tests/ui/allow_attributes.rs +++ b/src/tools/clippy/tests/ui/allow_attributes.rs @@ -1,4 +1,5 @@ //@aux-build:proc_macros.rs +//@aux-build:proc_macro_derive.rs #![allow(unused)] #![warn(clippy::allow_attributes)] #![no_main] @@ -65,3 +66,9 @@ fn deny_allow_attributes() -> Option<u8> { allow?; Some(42) } + +// Edge case where the generated tokens spans match on #[repr(transparent)] which tricks the proc +// macro check +#[repr(transparent)] +#[derive(proc_macro_derive::AllowLintSameSpan)] // This macro generates tokens with the same span as the whole struct and repr +struct IgnoreDerived; diff --git a/src/tools/clippy/tests/ui/allow_attributes.stderr b/src/tools/clippy/tests/ui/allow_attributes.stderr index 10dac0bc808..5a4ff287acd 100644 --- a/src/tools/clippy/tests/ui/allow_attributes.stderr +++ b/src/tools/clippy/tests/ui/allow_attributes.stderr @@ -1,5 +1,5 @@ error: #[allow] attribute found - --> tests/ui/allow_attributes.rs:12:3 + --> tests/ui/allow_attributes.rs:13:3 | LL | #[allow(dead_code)] | ^^^^^ help: replace it with: `expect` @@ -8,24 +8,16 @@ LL | #[allow(dead_code)] = help: to override `-D warnings` add `#[allow(clippy::allow_attributes)]` error: #[allow] attribute found - --> tests/ui/allow_attributes.rs:21:30 + --> tests/ui/allow_attributes.rs:22:30 | LL | #[cfg_attr(panic = "unwind", allow(dead_code))] | ^^^^^ help: replace it with: `expect` error: #[allow] attribute found - --> tests/ui/allow_attributes.rs:52:7 + --> tests/ui/allow_attributes.rs:53:7 | LL | #[allow(unused)] | ^^^^^ help: replace it with: `expect` -error: #[allow] attribute found - --> tests/ui/allow_attributes.rs:52:7 - | -LL | #[allow(unused)] - | ^^^^^ help: replace it with: `expect` - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr index 86d7845df04..9c1ac5af91b 100644 --- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr +++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr @@ -43,14 +43,5 @@ LL | #[allow(unused)] | = help: try adding a reason at the end with `, reason = ".."` -error: `allow` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:46:5 - | -LL | #[allow(unused)] - | ^^^^^^^^^^^^^^^^ - | - = help: try adding a reason at the end with `, reason = ".."` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/attrs.stderr b/src/tools/clippy/tests/ui/attrs.stderr index cd409fc8701..a7fdceaba6f 100644 --- a/src/tools/clippy/tests/ui/attrs.stderr +++ b/src/tools/clippy/tests/ui/attrs.stderr @@ -1,12 +1,3 @@ -error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea - --> tests/ui/attrs.rs:5:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::inline-always` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::inline_always)]` - error: the since field must contain a semver-compliant version --> tests/ui/attrs.rs:27:14 | @@ -22,5 +13,14 @@ error: the since field must contain a semver-compliant version LL | #[deprecated(since = "1")] | ^^^^^^^^^^^ +error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea + --> tests/ui/attrs.rs:5:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::inline-always` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::inline_always)]` + error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui-internal/author.rs b/src/tools/clippy/tests/ui/author.rs index eb1f3e3f870..0a1be356896 100644 --- a/src/tools/clippy/tests/ui-internal/author.rs +++ b/src/tools/clippy/tests/ui/author.rs @@ -1,5 +1,3 @@ -#![warn(clippy::author)] - fn main() { #[clippy::author] let x: char = 0x45 as char; diff --git a/src/tools/clippy/tests/ui-internal/author.stdout b/src/tools/clippy/tests/ui/author.stdout index eed704e82fe..eed704e82fe 100644 --- a/src/tools/clippy/tests/ui-internal/author.stdout +++ b/src/tools/clippy/tests/ui/author.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/blocks.rs b/src/tools/clippy/tests/ui/author/blocks.rs index 164f7d0d9d6..164f7d0d9d6 100644 --- a/src/tools/clippy/tests/ui-internal/author/blocks.rs +++ b/src/tools/clippy/tests/ui/author/blocks.rs diff --git a/src/tools/clippy/tests/ui-internal/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout index 6bf48d5ba4e..6bf48d5ba4e 100644 --- a/src/tools/clippy/tests/ui-internal/author/blocks.stdout +++ b/src/tools/clippy/tests/ui/author/blocks.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/call.rs b/src/tools/clippy/tests/ui/author/call.rs index e99c3c41dc4..e99c3c41dc4 100644 --- a/src/tools/clippy/tests/ui-internal/author/call.rs +++ b/src/tools/clippy/tests/ui/author/call.rs diff --git a/src/tools/clippy/tests/ui-internal/author/call.stdout b/src/tools/clippy/tests/ui/author/call.stdout index 59d4da490fe..59d4da490fe 100644 --- a/src/tools/clippy/tests/ui-internal/author/call.stdout +++ b/src/tools/clippy/tests/ui/author/call.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/if.rs b/src/tools/clippy/tests/ui/author/if.rs index 946088ab346..946088ab346 100644 --- a/src/tools/clippy/tests/ui-internal/author/if.rs +++ b/src/tools/clippy/tests/ui/author/if.rs diff --git a/src/tools/clippy/tests/ui-internal/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout index a85dcddd331..a85dcddd331 100644 --- a/src/tools/clippy/tests/ui-internal/author/if.stdout +++ b/src/tools/clippy/tests/ui/author/if.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/issue_3849.rs b/src/tools/clippy/tests/ui/author/issue_3849.rs index 5f65746d71f..5f65746d71f 100644 --- a/src/tools/clippy/tests/ui-internal/author/issue_3849.rs +++ b/src/tools/clippy/tests/ui/author/issue_3849.rs diff --git a/src/tools/clippy/tests/ui-internal/author/issue_3849.stdout b/src/tools/clippy/tests/ui/author/issue_3849.stdout index a5a8c0304ee..a5a8c0304ee 100644 --- a/src/tools/clippy/tests/ui-internal/author/issue_3849.stdout +++ b/src/tools/clippy/tests/ui/author/issue_3849.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/loop.rs b/src/tools/clippy/tests/ui/author/loop.rs index ff5b6100117..ff5b6100117 100644 --- a/src/tools/clippy/tests/ui-internal/author/loop.rs +++ b/src/tools/clippy/tests/ui/author/loop.rs diff --git a/src/tools/clippy/tests/ui-internal/author/loop.stdout b/src/tools/clippy/tests/ui/author/loop.stdout index 609d2491061..609d2491061 100644 --- a/src/tools/clippy/tests/ui-internal/author/loop.stdout +++ b/src/tools/clippy/tests/ui/author/loop.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/macro_in_closure.rs b/src/tools/clippy/tests/ui/author/macro_in_closure.rs index 444e6a12165..444e6a12165 100644 --- a/src/tools/clippy/tests/ui-internal/author/macro_in_closure.rs +++ b/src/tools/clippy/tests/ui/author/macro_in_closure.rs diff --git a/src/tools/clippy/tests/ui-internal/author/macro_in_closure.stdout b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout index 66caf382d89..66caf382d89 100644 --- a/src/tools/clippy/tests/ui-internal/author/macro_in_closure.stdout +++ b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/macro_in_loop.rs b/src/tools/clippy/tests/ui/author/macro_in_loop.rs index 8a520501f8d..8a520501f8d 100644 --- a/src/tools/clippy/tests/ui-internal/author/macro_in_loop.rs +++ b/src/tools/clippy/tests/ui/author/macro_in_loop.rs diff --git a/src/tools/clippy/tests/ui-internal/author/macro_in_loop.stdout b/src/tools/clippy/tests/ui/author/macro_in_loop.stdout index 3f9be297c33..3f9be297c33 100644 --- a/src/tools/clippy/tests/ui-internal/author/macro_in_loop.stdout +++ b/src/tools/clippy/tests/ui/author/macro_in_loop.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/matches.rs b/src/tools/clippy/tests/ui/author/matches.rs index 674e07ec2d3..674e07ec2d3 100644 --- a/src/tools/clippy/tests/ui-internal/author/matches.rs +++ b/src/tools/clippy/tests/ui/author/matches.rs diff --git a/src/tools/clippy/tests/ui-internal/author/matches.stdout b/src/tools/clippy/tests/ui/author/matches.stdout index 91b3b6f6877..91b3b6f6877 100644 --- a/src/tools/clippy/tests/ui-internal/author/matches.stdout +++ b/src/tools/clippy/tests/ui/author/matches.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/repeat.rs b/src/tools/clippy/tests/ui/author/repeat.rs index d8e9d589e68..d8e9d589e68 100644 --- a/src/tools/clippy/tests/ui-internal/author/repeat.rs +++ b/src/tools/clippy/tests/ui/author/repeat.rs diff --git a/src/tools/clippy/tests/ui-internal/author/repeat.stdout b/src/tools/clippy/tests/ui/author/repeat.stdout index d9e3f864f12..d9e3f864f12 100644 --- a/src/tools/clippy/tests/ui-internal/author/repeat.stdout +++ b/src/tools/clippy/tests/ui/author/repeat.stdout diff --git a/src/tools/clippy/tests/ui-internal/author/struct.rs b/src/tools/clippy/tests/ui/author/struct.rs index a99bdfc1313..a99bdfc1313 100644 --- a/src/tools/clippy/tests/ui-internal/author/struct.rs +++ b/src/tools/clippy/tests/ui/author/struct.rs diff --git a/src/tools/clippy/tests/ui-internal/author/struct.stdout b/src/tools/clippy/tests/ui/author/struct.stdout index 0b332d5e7d0..0b332d5e7d0 100644 --- a/src/tools/clippy/tests/ui-internal/author/struct.stdout +++ b/src/tools/clippy/tests/ui/author/struct.stdout diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs index bd90042c1da..fbf84337382 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs @@ -1,4 +1,4 @@ -#![feature(repr128, proc_macro_quote)] +#![feature(repr128, proc_macro_quote, proc_macro_span)] #![allow(incomplete_features)] #![allow(clippy::field_reassign_with_default)] #![allow(clippy::eq_op)] @@ -182,3 +182,51 @@ pub fn non_canonical_clone_derive(_: TokenStream) -> TokenStream { impl Copy for NonCanonicalClone {} } } + +// Derive macro that generates the following but where all generated spans are set to the entire +// input span. +// +// ``` +// #[allow(clippy::missing_const_for_fn)] +// fn check() {} +// ``` +#[proc_macro_derive(AllowLintSameSpan)] +pub fn allow_lint_same_span_derive(input: TokenStream) -> TokenStream { + let mut iter = input.into_iter(); + let first = iter.next().unwrap(); + let last = iter.last().unwrap(); + let span = first.span().join(last.span()).unwrap(); + let span_help = |mut t: TokenTree| -> TokenTree { + t.set_span(span); + t + }; + // Generate the TokenStream but setting all the spans to the entire input span + <TokenStream as FromIterator<TokenTree>>::from_iter([ + span_help(Punct::new('#', Spacing::Alone).into()), + span_help( + Group::new( + Delimiter::Bracket, + <TokenStream as FromIterator<TokenTree>>::from_iter([ + Ident::new("allow", span).into(), + span_help( + Group::new( + Delimiter::Parenthesis, + <TokenStream as FromIterator<TokenTree>>::from_iter([ + Ident::new("clippy", span).into(), + span_help(Punct::new(':', Spacing::Joint).into()), + span_help(Punct::new(':', Spacing::Alone).into()), + Ident::new("missing_const_for_fn", span).into(), + ]), + ) + .into(), + ), + ]), + ) + .into(), + ), + Ident::new("fn", span).into(), + Ident::new("check", span).into(), + span_help(Group::new(Delimiter::Parenthesis, TokenStream::new()).into()), + span_help(Group::new(Delimiter::Brace, TokenStream::new()).into()), + ]) +} diff --git a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr index d410f25b2c2..1bad259b09a 100644 --- a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr +++ b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr @@ -1,12 +1,17 @@ error: `clippy::restriction` is not meant to be enabled as a group + | + = note: because of the command line `--warn clippy::restriction` + = help: enable the restriction lints you need individually + = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]` + +error: `clippy::restriction` is not meant to be enabled as a group --> tests/ui/blanket_clippy_restriction_lints.rs:6:9 | LL | #![warn(clippy::restriction)] | ^^^^^^^^^^^^^^^^^^^ | = help: enable the restriction lints you need individually - = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]` error: `clippy::restriction` is not meant to be enabled as a group --> tests/ui/blanket_clippy_restriction_lints.rs:8:9 @@ -24,10 +29,5 @@ LL | #![forbid(clippy::restriction)] | = help: enable the restriction lints you need individually -error: `clippy::restriction` is not meant to be enabled as a group - | - = note: because of the command line `--warn clippy::restriction` - = help: enable the restriction lints you need individually - error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed index ea5e983de3b..22e984c46d2 100644 --- a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed +++ b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed @@ -71,3 +71,9 @@ mod false_negative { assert_ne!(addr_x, addr_y); } } + +fn issue_13584() { + let s = "Hello, world!\n"; + let p = &raw const *s; + let _ = p as *const i8; +} diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.rs b/src/tools/clippy/tests/ui/borrow_deref_ref.rs index 8c8905b150e..61d89193f42 100644 --- a/src/tools/clippy/tests/ui/borrow_deref_ref.rs +++ b/src/tools/clippy/tests/ui/borrow_deref_ref.rs @@ -71,3 +71,9 @@ mod false_negative { assert_ne!(addr_x, addr_y); } } + +fn issue_13584() { + let s = "Hello, world!\n"; + let p = &raw const *s; + let _ = p as *const i8; +} diff --git a/src/tools/clippy/tests/ui/const_is_empty.rs b/src/tools/clippy/tests/ui/const_is_empty.rs index 04e0de91ecf..b5e27b61548 100644 --- a/src/tools/clippy/tests/ui/const_is_empty.rs +++ b/src/tools/clippy/tests/ui/const_is_empty.rs @@ -171,3 +171,17 @@ fn constant_from_external_crate() { let _ = std::env::consts::EXE_EXTENSION.is_empty(); // Do not lint, `exe_ext` comes from the `std` crate } + +fn issue_13106() { + const { + assert!(!NON_EMPTY_STR.is_empty()); + } + + const { + assert!(EMPTY_STR.is_empty()); + } + + const { + EMPTY_STR.is_empty(); + } +} diff --git a/src/tools/clippy/tests/ui/const_is_empty.stderr b/src/tools/clippy/tests/ui/const_is_empty.stderr index 7f80b520b1a..0afba940d8b 100644 --- a/src/tools/clippy/tests/ui/const_is_empty.stderr +++ b/src/tools/clippy/tests/ui/const_is_empty.stderr @@ -157,5 +157,11 @@ error: this expression always evaluates to true LL | let _ = val.is_empty(); | ^^^^^^^^^^^^^^ -error: aborting due to 26 previous errors +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:185:9 + | +LL | EMPTY_STR.is_empty(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 27 previous errors diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed index 355f2bc7736..5cf5c608a85 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed @@ -54,8 +54,9 @@ fn test_units() { /// This tests allowed identifiers. /// KiB MiB GiB TiB PiB EiB +/// MHz GHz THz /// AccessKit -/// CoreFoundation CoreGraphics CoreText +/// CoAP CoreFoundation CoreGraphics CoreText /// Direct2D Direct3D DirectWrite DirectX /// ECMAScript /// GPLv2 GPLv3 diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs index 9ced2677622..420211c6539 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs @@ -54,8 +54,9 @@ fn test_units() { /// This tests allowed identifiers. /// KiB MiB GiB TiB PiB EiB +/// MHz GHz THz /// AccessKit -/// CoreFoundation CoreGraphics CoreText +/// CoAP CoreFoundation CoreGraphics CoreText /// Direct2D Direct3D DirectWrite DirectX /// ECMAScript /// GPLv2 GPLv3 diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr index 67c0464149c..27a04e4b558 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr @@ -133,7 +133,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:78:5 + --> tests/ui/doc/doc-fixable.rs:79:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:95:5 + --> tests/ui/doc/doc-fixable.rs:96:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -155,7 +155,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:103:8 + --> tests/ui/doc/doc-fixable.rs:104:8 | LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL | /// ## `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:106:7 + --> tests/ui/doc/doc-fixable.rs:107:7 | LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | /// # `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:108:22 + --> tests/ui/doc/doc-fixable.rs:109:22 | LL | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ @@ -188,7 +188,7 @@ LL | /// Not a title #897 `CamelCaseThing` | ~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:109:5 + --> tests/ui/doc/doc-fixable.rs:110:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -199,7 +199,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:116:5 + --> tests/ui/doc/doc-fixable.rs:117:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:129:5 + --> tests/ui/doc/doc-fixable.rs:130:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -221,7 +221,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:140:43 + --> tests/ui/doc/doc-fixable.rs:141:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -232,7 +232,7 @@ LL | /** E.g., serialization of an empty list: `FooBar` | ~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:145:5 + --> tests/ui/doc/doc-fixable.rs:146:5 | LL | And BarQuz too. | ^^^^^^ @@ -243,7 +243,7 @@ LL | And `BarQuz` too. | ~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:146:1 + --> tests/ui/doc/doc-fixable.rs:147:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -254,7 +254,7 @@ LL | `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:151:43 + --> tests/ui/doc/doc-fixable.rs:152:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -265,7 +265,7 @@ LL | /** E.g., serialization of an empty list: `FooBar` | ~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:156:5 + --> tests/ui/doc/doc-fixable.rs:157:5 | LL | And BarQuz too. | ^^^^^^ @@ -276,7 +276,7 @@ LL | And `BarQuz` too. | ~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:157:1 + --> tests/ui/doc/doc-fixable.rs:158:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -287,7 +287,7 @@ LL | `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:168:5 + --> tests/ui/doc/doc-fixable.rs:169:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -298,7 +298,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it` | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:187:22 + --> tests/ui/doc/doc-fixable.rs:188:22 | LL | /// An iterator over mycrate::Collection's values. | ^^^^^^^^^^^^^^^^^^^ @@ -309,7 +309,7 @@ LL | /// An iterator over `mycrate::Collection`'s values. | ~~~~~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:211:34 + --> tests/ui/doc/doc-fixable.rs:212:34 | LL | /// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint | ^^^^^^^^^^^^^^^ @@ -320,7 +320,7 @@ LL | /// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint` | ~~~~~~~~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:234:22 + --> tests/ui/doc/doc-fixable.rs:235:22 | LL | /// There is no try (do() or do_not()). | ^^^^ @@ -331,7 +331,7 @@ LL | /// There is no try (`do()` or do_not()). | ~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:234:30 + --> tests/ui/doc/doc-fixable.rs:235:30 | LL | /// There is no try (do() or do_not()). | ^^^^^^^^ @@ -342,7 +342,7 @@ LL | /// There is no try (do() or `do_not()`). | ~~~~~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:237:5 + --> tests/ui/doc/doc-fixable.rs:238:5 | LL | /// ABes | ^^^^ @@ -353,7 +353,7 @@ LL | /// `ABes` | ~~~~~~ error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:243:9 + --> tests/ui/doc/doc-fixable.rs:244:9 | LL | /// foo() | ^^^^^ @@ -364,7 +364,7 @@ LL | /// `foo()` | ~~~~~~~ error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> tests/ui/doc/doc-fixable.rs:247:5 + --> tests/ui/doc/doc-fixable.rs:248:5 | LL | /// https://github.com/rust-lang/rust-clippy/pull/12836 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<https://github.com/rust-lang/rust-clippy/pull/12836>` diff --git a/src/tools/clippy/tests/ui/infinite_loops.rs b/src/tools/clippy/tests/ui/infinite_loops.rs index b6cb7ff49b0..0613eddce26 100644 --- a/src/tools/clippy/tests/ui/infinite_loops.rs +++ b/src/tools/clippy/tests/ui/infinite_loops.rs @@ -3,6 +3,7 @@ #![allow(clippy::never_loop)] #![warn(clippy::infinite_loop)] +#![feature(async_closure)] extern crate proc_macros; use proc_macros::{external, with_span}; @@ -428,4 +429,23 @@ fn continue_outer() { } } +// don't suggest adding `-> !` to async fn/closure that already returning `-> !` +mod issue_12338 { + use super::do_something; + + async fn foo() -> ! { + loop { + do_something(); + } + } + + fn bar() { + let _ = async || -> ! { + loop { + do_something(); + } + }; + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/infinite_loops.stderr b/src/tools/clippy/tests/ui/infinite_loops.stderr index 7635a7442f4..3a3ed7d0fe8 100644 --- a/src/tools/clippy/tests/ui/infinite_loops.stderr +++ b/src/tools/clippy/tests/ui/infinite_loops.stderr @@ -1,5 +1,5 @@ error: infinite loop detected - --> tests/ui/infinite_loops.rs:13:5 + --> tests/ui/infinite_loops.rs:14:5 | LL | / loop { LL | | @@ -15,7 +15,7 @@ LL | fn no_break() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:20:5 + --> tests/ui/infinite_loops.rs:21:5 | LL | / loop { LL | | @@ -32,7 +32,7 @@ LL | fn all_inf() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:22:9 + --> tests/ui/infinite_loops.rs:23:9 | LL | / loop { LL | | @@ -49,7 +49,7 @@ LL | fn all_inf() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:24:13 + --> tests/ui/infinite_loops.rs:25:13 | LL | / loop { LL | | @@ -63,7 +63,7 @@ LL | fn all_inf() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:38:5 + --> tests/ui/infinite_loops.rs:39:5 | LL | / loop { LL | | @@ -74,7 +74,7 @@ LL | | } = help: if this is not intended, try adding a `break` or `return` condition in the loop error: infinite loop detected - --> tests/ui/infinite_loops.rs:51:5 + --> tests/ui/infinite_loops.rs:52:5 | LL | / loop { LL | | fn inner_fn() -> ! { @@ -90,7 +90,7 @@ LL | fn no_break_never_ret_noise() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:94:5 + --> tests/ui/infinite_loops.rs:95:5 | LL | / loop { LL | | @@ -107,7 +107,7 @@ LL | fn break_inner_but_not_outer_1(cond: bool) -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:105:5 + --> tests/ui/infinite_loops.rs:106:5 | LL | / loop { LL | | @@ -124,7 +124,7 @@ LL | fn break_inner_but_not_outer_2(cond: bool) -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:119:9 + --> tests/ui/infinite_loops.rs:120:9 | LL | / loop { LL | | @@ -138,7 +138,7 @@ LL | fn break_outer_but_not_inner() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:142:9 + --> tests/ui/infinite_loops.rs:143:9 | LL | / loop { LL | | @@ -155,7 +155,7 @@ LL | fn break_wrong_loop(cond: bool) -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:182:5 + --> tests/ui/infinite_loops.rs:183:5 | LL | / loop { LL | | @@ -172,7 +172,7 @@ LL | fn match_like() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:223:5 + --> tests/ui/infinite_loops.rs:224:5 | LL | / loop { LL | | @@ -186,7 +186,7 @@ LL | fn match_like() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:228:5 + --> tests/ui/infinite_loops.rs:229:5 | LL | / loop { LL | | @@ -203,7 +203,7 @@ LL | fn match_like() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:333:9 + --> tests/ui/infinite_loops.rs:334:9 | LL | / loop { LL | | @@ -217,7 +217,7 @@ LL | fn problematic_trait_method() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:343:9 + --> tests/ui/infinite_loops.rs:344:9 | LL | / loop { LL | | @@ -231,7 +231,7 @@ LL | fn could_be_problematic() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:352:9 + --> tests/ui/infinite_loops.rs:353:9 | LL | / loop { LL | | @@ -245,7 +245,7 @@ LL | let _loop_forever = || -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:366:8 + --> tests/ui/infinite_loops.rs:367:8 | LL | Ok(loop { | ________^ @@ -256,7 +256,7 @@ LL | | }) = help: if this is not intended, try adding a `break` or `return` condition in the loop error: infinite loop detected - --> tests/ui/infinite_loops.rs:408:5 + --> tests/ui/infinite_loops.rs:409:5 | LL | / 'infinite: loop { LL | | @@ -272,7 +272,7 @@ LL | fn continue_outer() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:415:5 + --> tests/ui/infinite_loops.rs:416:5 | LL | / loop { LL | | @@ -289,7 +289,7 @@ LL | fn continue_outer() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:417:9 + --> tests/ui/infinite_loops.rs:418:9 | LL | / 'inner: loop { LL | | loop { @@ -304,7 +304,7 @@ LL | fn continue_outer() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:425:5 + --> tests/ui/infinite_loops.rs:426:5 | LL | / loop { LL | | diff --git a/src/tools/clippy/tests/ui/iter_without_into_iter.stderr b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr index 7c42fa1dd89..d748c85003b 100644 --- a/src/tools/clippy/tests/ui/iter_without_into_iter.stderr +++ b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr @@ -13,8 +13,8 @@ help: consider implementing `IntoIterator` for `&S1` | LL + LL + impl IntoIterator for &S1 { -LL + type IntoIter = std::slice::Iter<'_, u8>; LL + type Item = &u8; +LL + type IntoIter = std::slice::Iter<'_, u8>; LL + fn into_iter(self) -> Self::IntoIter { LL + self.iter() LL + } @@ -34,8 +34,8 @@ help: consider implementing `IntoIterator` for `&mut S1` | LL + LL + impl IntoIterator for &mut S1 { -LL + type IntoIter = std::slice::IterMut<'_, u8>; LL + type Item = &mut u8; +LL + type IntoIter = std::slice::IterMut<'_, u8>; LL + fn into_iter(self) -> Self::IntoIter { LL + self.iter() LL + } @@ -55,8 +55,8 @@ help: consider implementing `IntoIterator` for `&S3<'a>` | LL + LL + impl IntoIterator for &S3<'a> { -LL + type IntoIter = std::slice::Iter<'_, u8>; LL + type Item = &u8; +LL + type IntoIter = std::slice::Iter<'_, u8>; LL + fn into_iter(self) -> Self::IntoIter { LL + self.iter() LL + } @@ -76,8 +76,8 @@ help: consider implementing `IntoIterator` for `&mut S3<'a>` | LL + LL + impl IntoIterator for &mut S3<'a> { -LL + type IntoIter = std::slice::IterMut<'_, u8>; LL + type Item = &mut u8; +LL + type IntoIter = std::slice::IterMut<'_, u8>; LL + fn into_iter(self) -> Self::IntoIter { LL + self.iter() LL + } @@ -96,8 +96,8 @@ help: consider implementing `IntoIterator` for `&S8<T>` | LL + LL + impl IntoIterator for &S8<T> { -LL + type IntoIter = std::slice::Iter<'static, T>; LL + type Item = &T; +LL + type IntoIter = std::slice::Iter<'static, T>; LL + fn into_iter(self) -> Self::IntoIter { LL + self.iter() LL + } @@ -117,8 +117,8 @@ help: consider implementing `IntoIterator` for `&S9<T>` | LL + LL + impl IntoIterator for &S9<T> { -LL + type IntoIter = std::slice::Iter<'_, T>; LL + type Item = &T; +LL + type IntoIter = std::slice::Iter<'_, T>; LL + fn into_iter(self) -> Self::IntoIter { LL + self.iter() LL + } @@ -138,8 +138,8 @@ help: consider implementing `IntoIterator` for `&mut S9<T>` | LL + LL + impl IntoIterator for &mut S9<T> { -LL + type IntoIter = std::slice::IterMut<'_, T>; LL + type Item = &mut T; +LL + type IntoIter = std::slice::IterMut<'_, T>; LL + fn into_iter(self) -> Self::IntoIter { LL + self.iter() LL + } @@ -162,8 +162,8 @@ help: consider implementing `IntoIterator` for `&Issue12037` | LL ~ LL + impl IntoIterator for &Issue12037 { -LL + type IntoIter = std::slice::Iter<'_, u8>; LL + type Item = &u8; +LL + type IntoIter = std::slice::Iter<'_, u8>; LL + fn into_iter(self) -> Self::IntoIter { LL + self.iter() LL + } diff --git a/src/tools/clippy/tests/ui/large_const_arrays.fixed b/src/tools/clippy/tests/ui/large_const_arrays.fixed index 543ce460e7b..e5b28cb6a9d 100644 --- a/src/tools/clippy/tests/ui/large_const_arrays.fixed +++ b/src/tools/clippy/tests/ui/large_const_arrays.fixed @@ -9,11 +9,13 @@ pub struct S { // Should lint pub(crate) static FOO_PUB_CRATE: [u32; 1_000_000] = [0u32; 1_000_000]; pub static FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; +static FOO_COMPUTED: [u32; 1_000 * 100] = [0u32; 1_000 * 100]; static FOO: [u32; 1_000_000] = [0u32; 1_000_000]; // Good pub(crate) const G_FOO_PUB_CRATE: [u32; 250] = [0u32; 250]; pub const G_FOO_PUB: [u32; 250] = [0u32; 250]; +const G_FOO_COMPUTED: [u32; 25 * 10] = [0u32; 25 * 10]; const G_FOO: [u32; 250] = [0u32; 250]; fn main() { diff --git a/src/tools/clippy/tests/ui/large_const_arrays.rs b/src/tools/clippy/tests/ui/large_const_arrays.rs index e23a8081171..b9593225da2 100644 --- a/src/tools/clippy/tests/ui/large_const_arrays.rs +++ b/src/tools/clippy/tests/ui/large_const_arrays.rs @@ -9,11 +9,13 @@ pub struct S { // Should lint pub(crate) const FOO_PUB_CRATE: [u32; 1_000_000] = [0u32; 1_000_000]; pub const FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; +const FOO_COMPUTED: [u32; 1_000 * 100] = [0u32; 1_000 * 100]; const FOO: [u32; 1_000_000] = [0u32; 1_000_000]; // Good pub(crate) const G_FOO_PUB_CRATE: [u32; 250] = [0u32; 250]; pub const G_FOO_PUB: [u32; 250] = [0u32; 250]; +const G_FOO_COMPUTED: [u32; 25 * 10] = [0u32; 25 * 10]; const G_FOO: [u32; 250] = [0u32; 250]; fn main() { diff --git a/src/tools/clippy/tests/ui/large_const_arrays.stderr b/src/tools/clippy/tests/ui/large_const_arrays.stderr index 88f921b81f7..27112205390 100644 --- a/src/tools/clippy/tests/ui/large_const_arrays.stderr +++ b/src/tools/clippy/tests/ui/large_const_arrays.stderr @@ -20,13 +20,21 @@ LL | pub const FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; error: large array defined as const --> tests/ui/large_const_arrays.rs:12:1 | +LL | const FOO_COMPUTED: [u32; 1_000 * 100] = [0u32; 1_000 * 100]; + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: make this a static item: `static` + +error: large array defined as const + --> tests/ui/large_const_arrays.rs:13:1 + | LL | const FOO: [u32; 1_000_000] = [0u32; 1_000_000]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:21:5 + --> tests/ui/large_const_arrays.rs:23:5 | LL | pub const BAR_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | ^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +42,7 @@ LL | pub const BAR_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:22:5 + --> tests/ui/large_const_arrays.rs:24:5 | LL | const BAR: [u32; 1_000_000] = [0u32; 1_000_000]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +50,7 @@ LL | const BAR: [u32; 1_000_000] = [0u32; 1_000_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:23:5 + --> tests/ui/large_const_arrays.rs:25:5 | LL | pub const BAR_STRUCT_PUB: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | ^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +58,7 @@ LL | pub const BAR_STRUCT_PUB: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:24:5 + --> tests/ui/large_const_arrays.rs:26:5 | LL | const BAR_STRUCT: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +66,7 @@ LL | const BAR_STRUCT: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:25:5 + --> tests/ui/large_const_arrays.rs:27:5 | LL | pub const BAR_S_PUB: [Option<&str>; 200_000] = [Some("str"); 200_000]; | ^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,12 +74,12 @@ LL | pub const BAR_S_PUB: [Option<&str>; 200_000] = [Some("str"); 200_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:26:5 + --> tests/ui/large_const_arrays.rs:28:5 | LL | const BAR_S: [Option<&str>; 200_000] = [Some("str"); 200_000]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: make this a static item: `static` -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors diff --git a/src/tools/clippy/tests/ui/manual_bits.fixed b/src/tools/clippy/tests/ui/manual_bits.fixed index 4de01905e8a..8e5cb7d38b9 100644 --- a/src/tools/clippy/tests/ui/manual_bits.fixed +++ b/src/tools/clippy/tests/ui/manual_bits.fixed @@ -56,3 +56,14 @@ fn main() { let _ = (u128::BITS as usize).pow(5); let _ = &(u128::BITS as usize); } + +fn should_not_lint() { + macro_rules! bits_via_macro { + ($T: ty) => { + size_of::<$T>() * 8; + }; + } + + bits_via_macro!(u8); + bits_via_macro!(String); +} diff --git a/src/tools/clippy/tests/ui/manual_bits.rs b/src/tools/clippy/tests/ui/manual_bits.rs index d4f369fcf87..5e492ed15d2 100644 --- a/src/tools/clippy/tests/ui/manual_bits.rs +++ b/src/tools/clippy/tests/ui/manual_bits.rs @@ -56,3 +56,14 @@ fn main() { let _ = (size_of::<u128>() * 8).pow(5); let _ = &(size_of::<u128>() * 8); } + +fn should_not_lint() { + macro_rules! bits_via_macro { + ($T: ty) => { + size_of::<$T>() * 8; + }; + } + + bits_via_macro!(u8); + bits_via_macro!(String); +} diff --git a/src/tools/clippy/tests/ui/map_all_any_identity.fixed b/src/tools/clippy/tests/ui/map_all_any_identity.fixed new file mode 100644 index 00000000000..c92462ab9c2 --- /dev/null +++ b/src/tools/clippy/tests/ui/map_all_any_identity.fixed @@ -0,0 +1,21 @@ +#![warn(clippy::map_all_any_identity)] + +fn main() { + let _ = ["foo"].into_iter().any(|s| s == "foo"); + //~^ map_all_any_identity + let _ = ["foo"].into_iter().all(|s| s == "foo"); + //~^ map_all_any_identity + + // + // Do not lint + // + // Not identity + let _ = ["foo"].into_iter().map(|s| s.len()).any(|n| n > 0); + // Macro + macro_rules! map { + ($x:expr) => { + $x.into_iter().map(|s| s == "foo") + }; + } + map!(["foo"]).any(|a| a); +} diff --git a/src/tools/clippy/tests/ui/map_all_any_identity.rs b/src/tools/clippy/tests/ui/map_all_any_identity.rs new file mode 100644 index 00000000000..0e4a564ca04 --- /dev/null +++ b/src/tools/clippy/tests/ui/map_all_any_identity.rs @@ -0,0 +1,21 @@ +#![warn(clippy::map_all_any_identity)] + +fn main() { + let _ = ["foo"].into_iter().map(|s| s == "foo").any(|a| a); + //~^ map_all_any_identity + let _ = ["foo"].into_iter().map(|s| s == "foo").all(std::convert::identity); + //~^ map_all_any_identity + + // + // Do not lint + // + // Not identity + let _ = ["foo"].into_iter().map(|s| s.len()).any(|n| n > 0); + // Macro + macro_rules! map { + ($x:expr) => { + $x.into_iter().map(|s| s == "foo") + }; + } + map!(["foo"]).any(|a| a); +} diff --git a/src/tools/clippy/tests/ui/map_all_any_identity.stderr b/src/tools/clippy/tests/ui/map_all_any_identity.stderr new file mode 100644 index 00000000000..98fdcc2a939 --- /dev/null +++ b/src/tools/clippy/tests/ui/map_all_any_identity.stderr @@ -0,0 +1,26 @@ +error: usage of `.map(...).any(identity)` + --> tests/ui/map_all_any_identity.rs:4:33 + | +LL | let _ = ["foo"].into_iter().map(|s| s == "foo").any(|a| a); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::map-all-any-identity` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::map_all_any_identity)]` +help: use `.any(...)` instead + | +LL | let _ = ["foo"].into_iter().any(|s| s == "foo"); + | ~~~~~~~~~~~~~~~~~~~ + +error: usage of `.map(...).all(identity)` + --> tests/ui/map_all_any_identity.rs:6:33 + | +LL | let _ = ["foo"].into_iter().map(|s| s == "foo").all(std::convert::identity); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `.all(...)` instead + | +LL | let _ = ["foo"].into_iter().all(|s| s == "foo"); + | ~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.fixed b/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.fixed new file mode 100644 index 00000000000..cf520e71a64 --- /dev/null +++ b/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.fixed @@ -0,0 +1,73 @@ +#![allow( + unused, + clippy::redundant_closure, + clippy::reversed_empty_ranges, + clippy::identity_op +)] +#![warn(clippy::map_with_unused_argument_over_ranges)] + +fn do_something() -> usize { + todo!() +} + +fn do_something_interesting(x: usize, y: usize) -> usize { + todo!() +} + +macro_rules! gen { + () => { + (0..10).map(|_| do_something()); + }; +} + +fn main() { + // These should be raised + std::iter::repeat_with(|| do_something()).take(10); + std::iter::repeat_with(|| do_something()).take(10); + std::iter::repeat_with(|| do_something()).take(11); + std::iter::repeat_with(|| do_something()).take(7); + std::iter::repeat_with(|| do_something()).take(8); + std::iter::repeat_n(3, 10); + std::iter::repeat_with(|| { + let x = 3; + x + 2 + }).take(10); + std::iter::repeat_with(|| do_something()).take(10).collect::<Vec<_>>(); + let upper = 4; + std::iter::repeat_with(|| do_something()).take(upper); + let upper_fn = || 4; + std::iter::repeat_with(|| do_something()).take(upper_fn()); + std::iter::repeat_with(|| do_something()).take(upper_fn() + 1); + std::iter::repeat_with(|| do_something()).take(upper_fn() - 2); + std::iter::repeat_with(|| do_something()).take(upper_fn() - 1); + (-3..9).map(|_| do_something()); + std::iter::repeat_with(|| do_something()).take(0); + std::iter::repeat_with(|| do_something()).take(1); + std::iter::repeat_with(|| do_something()).take((1 << 4) - 0); + // These should not be raised + gen!(); + let lower = 2; + let lower_fn = || 2; + (lower..upper_fn()).map(|_| do_something()); // Ranges not starting at zero not yet handled + (lower_fn()..upper_fn()).map(|_| do_something()); // Ranges not starting at zero not yet handled + (lower_fn()..=upper_fn()).map(|_| do_something()); // Ranges not starting at zero not yet handled + (0..10).map(|x| do_something_interesting(x, 4)); // Actual map over range + "Foobar".chars().map(|_| do_something()); // Not a map over range + // i128::MAX == 340282366920938463463374607431768211455 + (0..=340282366920938463463374607431768211455).map(|_: u128| do_something()); // Can't be replaced due to overflow +} + +#[clippy::msrv = "1.27"] +fn msrv_1_27() { + (0..10).map(|_| do_something()); +} + +#[clippy::msrv = "1.28"] +fn msrv_1_28() { + std::iter::repeat_with(|| do_something()).take(10); +} + +#[clippy::msrv = "1.81"] +fn msrv_1_82() { + std::iter::repeat(3).take(10); +} diff --git a/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.rs b/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.rs new file mode 100644 index 00000000000..298eee9ca3f --- /dev/null +++ b/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.rs @@ -0,0 +1,73 @@ +#![allow( + unused, + clippy::redundant_closure, + clippy::reversed_empty_ranges, + clippy::identity_op +)] +#![warn(clippy::map_with_unused_argument_over_ranges)] + +fn do_something() -> usize { + todo!() +} + +fn do_something_interesting(x: usize, y: usize) -> usize { + todo!() +} + +macro_rules! gen { + () => { + (0..10).map(|_| do_something()); + }; +} + +fn main() { + // These should be raised + (0..10).map(|_| do_something()); + (0..10).map(|_foo| do_something()); + (0..=10).map(|_| do_something()); + (3..10).map(|_| do_something()); + (3..=10).map(|_| do_something()); + (0..10).map(|_| 3); + (0..10).map(|_| { + let x = 3; + x + 2 + }); + (0..10).map(|_| do_something()).collect::<Vec<_>>(); + let upper = 4; + (0..upper).map(|_| do_something()); + let upper_fn = || 4; + (0..upper_fn()).map(|_| do_something()); + (0..=upper_fn()).map(|_| do_something()); + (2..upper_fn()).map(|_| do_something()); + (2..=upper_fn()).map(|_| do_something()); + (-3..9).map(|_| do_something()); + (9..3).map(|_| do_something()); + (9..=9).map(|_| do_something()); + (1..=1 << 4).map(|_| do_something()); + // These should not be raised + gen!(); + let lower = 2; + let lower_fn = || 2; + (lower..upper_fn()).map(|_| do_something()); // Ranges not starting at zero not yet handled + (lower_fn()..upper_fn()).map(|_| do_something()); // Ranges not starting at zero not yet handled + (lower_fn()..=upper_fn()).map(|_| do_something()); // Ranges not starting at zero not yet handled + (0..10).map(|x| do_something_interesting(x, 4)); // Actual map over range + "Foobar".chars().map(|_| do_something()); // Not a map over range + // i128::MAX == 340282366920938463463374607431768211455 + (0..=340282366920938463463374607431768211455).map(|_: u128| do_something()); // Can't be replaced due to overflow +} + +#[clippy::msrv = "1.27"] +fn msrv_1_27() { + (0..10).map(|_| do_something()); +} + +#[clippy::msrv = "1.28"] +fn msrv_1_28() { + (0..10).map(|_| do_something()); +} + +#[clippy::msrv = "1.81"] +fn msrv_1_82() { + (0..10).map(|_| 3); +} diff --git a/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.stderr b/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.stderr new file mode 100644 index 00000000000..0b56c6d9521 --- /dev/null +++ b/src/tools/clippy/tests/ui/map_with_unused_argument_over_ranges.stderr @@ -0,0 +1,223 @@ +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:25:5 + | +LL | (0..10).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::map-with-unused-argument-over-ranges` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::map_with_unused_argument_over_ranges)]` +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (0..10).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(10); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:26:5 + | +LL | (0..10).map(|_foo| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (0..10).map(|_foo| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(10); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:27:5 + | +LL | (0..=10).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (0..=10).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(11); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:28:5 + | +LL | (3..10).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (3..10).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(7); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:29:5 + | +LL | (3..=10).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (3..=10).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(8); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:30:5 + | +LL | (0..10).map(|_| 3); + | ^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_n` + | +LL | std::iter::repeat_n(3, 10); + | ~~~~~~~~~~~~~~~~~~~ ~~~~~ + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:31:5 + | +LL | / (0..10).map(|_| { +LL | | let x = 3; +LL | | x + 2 +LL | | }); + | |______^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL ~ std::iter::repeat_with(|| { +LL | let x = 3; +LL | x + 2 +LL ~ }).take(10); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:35:5 + | +LL | (0..10).map(|_| do_something()).collect::<Vec<_>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (0..10).map(|_| do_something()).collect::<Vec<_>>(); +LL + std::iter::repeat_with(|| do_something()).take(10).collect::<Vec<_>>(); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:37:5 + | +LL | (0..upper).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (0..upper).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(upper); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:39:5 + | +LL | (0..upper_fn()).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (0..upper_fn()).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(upper_fn()); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:40:5 + | +LL | (0..=upper_fn()).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (0..=upper_fn()).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(upper_fn() + 1); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:41:5 + | +LL | (2..upper_fn()).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (2..upper_fn()).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(upper_fn() - 2); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:42:5 + | +LL | (2..=upper_fn()).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (2..=upper_fn()).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(upper_fn() - 1); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:44:5 + | +LL | (9..3).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (9..3).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(0); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:45:5 + | +LL | (9..=9).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (9..=9).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(1); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:46:5 + | +LL | (1..=1 << 4).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (1..=1 << 4).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take((1 << 4) - 0); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:67:5 + | +LL | (0..10).map(|_| do_something()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat_with` and `take` + | +LL - (0..10).map(|_| do_something()); +LL + std::iter::repeat_with(|| do_something()).take(10); + | + +error: map of a closure that does not depend on its parameter over a range + --> tests/ui/map_with_unused_argument_over_ranges.rs:72:5 + | +LL | (0..10).map(|_| 3); + | ^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit range and use `repeat` and `take` + | +LL | std::iter::repeat(3).take(10); + | ~~~~~~~~~~~~~~~~~ ~ +++++++++ + +error: aborting due to 18 previous errors + diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed index f7b6e1a186b..754fe061c4a 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed @@ -2,7 +2,6 @@ #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] #![feature(const_trait_impl, abi_vectorcall)] - use std::mem::transmute; struct Game { @@ -104,7 +103,7 @@ fn main() {} struct D; -/* FIXME(effects) +/* FIXME(const_trait_impl) impl const Drop for D { fn drop(&mut self) { todo!(); @@ -113,7 +112,7 @@ impl const Drop for D { */ // Lint this, since it can be dropped in const contexts -// FIXME(effects) +// FIXME(const_trait_impl) const fn d(this: D) {} //~^ ERROR: this could be a `const fn` diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs index 4866e321024..460be0733e0 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs @@ -2,7 +2,6 @@ #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] #![feature(const_trait_impl, abi_vectorcall)] - use std::mem::transmute; struct Game { @@ -104,7 +103,7 @@ fn main() {} struct D; -/* FIXME(effects) +/* FIXME(const_trait_impl) impl const Drop for D { fn drop(&mut self) { todo!(); @@ -113,7 +112,7 @@ impl const Drop for D { */ // Lint this, since it can be dropped in const contexts -// FIXME(effects) +// FIXME(const_trait_impl) fn d(this: D) {} //~^ ERROR: this could be a `const fn` diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr index f28dec5c7f1..d553c522556 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:14:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:13:5 | LL | / pub fn new() -> Self { LL | | @@ -16,7 +16,7 @@ LL | pub const fn new() -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:20:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:19:5 | LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { LL | | @@ -30,7 +30,7 @@ LL | const fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:27:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:26:1 | LL | / fn one() -> i32 { LL | | @@ -44,7 +44,7 @@ LL | const fn one() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:33:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:32:1 | LL | / fn two() -> i32 { LL | | @@ -59,7 +59,7 @@ LL | const fn two() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:40:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:39:1 | LL | / fn string() -> String { LL | | @@ -73,7 +73,7 @@ LL | const fn string() -> String { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:46:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:45:1 | LL | / unsafe fn four() -> i32 { LL | | @@ -87,7 +87,7 @@ LL | const unsafe fn four() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:52:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:51:1 | LL | / fn generic<T>(t: T) -> T { LL | | @@ -101,7 +101,7 @@ LL | const fn generic<T>(t: T) -> T { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:61:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:60:1 | LL | / fn generic_arr<T: Copy>(t: [T; 1]) -> T { LL | | @@ -115,7 +115,7 @@ LL | const fn generic_arr<T: Copy>(t: [T; 1]) -> T { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:75:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:74:9 | LL | / pub fn b(self, a: &A) -> B { LL | | @@ -129,7 +129,7 @@ LL | pub const fn b(self, a: &A) -> B { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:85:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:84:5 | LL | / fn const_fn_stabilized_before_msrv(byte: u8) { LL | | @@ -143,7 +143,7 @@ LL | const fn const_fn_stabilized_before_msrv(byte: u8) { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:97:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:96:1 | LL | / fn msrv_1_46() -> i32 { LL | | @@ -157,7 +157,7 @@ LL | const fn msrv_1_46() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:117:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:116:1 | LL | fn d(this: D) {} | ^^^^^^^^^^^^^^^^ @@ -168,7 +168,7 @@ LL | const fn d(this: D) {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:125:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:124:9 | LL | / fn deref_ptr_can_be_const(self) -> usize { LL | | @@ -182,7 +182,7 @@ LL | const fn deref_ptr_can_be_const(self) -> usize { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:130:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:129:9 | LL | / fn deref_copied_val(self) -> usize { LL | | @@ -196,7 +196,7 @@ LL | const fn deref_copied_val(self) -> usize { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:141:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:140:5 | LL | / fn union_access_can_be_const() { LL | | @@ -211,7 +211,7 @@ LL | const fn union_access_can_be_const() { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:149:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:148:9 | LL | extern "C" fn c() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -222,7 +222,7 @@ LL | const extern "C" fn c() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:153:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:152:9 | LL | extern fn implicit_c() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | const extern fn implicit_c() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:170:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:169:9 | LL | / pub fn new(strings: Vec<String>) -> Self { LL | | Self { strings } @@ -246,7 +246,7 @@ LL | pub const fn new(strings: Vec<String>) -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:175:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:174:9 | LL | / pub fn empty() -> Self { LL | | Self { strings: Vec::new() } @@ -259,7 +259,7 @@ LL | pub const fn empty() -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:186:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:185:9 | LL | / pub fn new(text: String) -> Self { LL | | let vec = Vec::new(); @@ -273,7 +273,7 @@ LL | pub const fn new(text: String) -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:205:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:204:5 | LL | fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -284,7 +284,7 @@ LL | const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:209:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:208:5 | LL | extern "C-unwind" fn c_unwind() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -295,7 +295,7 @@ LL | const extern "C-unwind" fn c_unwind() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:211:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:210:5 | LL | extern "system" fn system() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -306,7 +306,7 @@ LL | const extern "system" fn system() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:213:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:212:5 | LL | extern "system-unwind" fn system_unwind() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -317,7 +317,7 @@ LL | const extern "system-unwind" fn system_unwind() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:215:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:214:5 | LL | pub extern "vectorcall" fn std_call() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -328,7 +328,7 @@ LL | pub const extern "vectorcall" fn std_call() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:217:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:216:5 | LL | pub extern "vectorcall-unwind" fn std_call_unwind() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/missing_doc.rs b/src/tools/clippy/tests/ui/missing_doc.rs index 9c936d7fa23..31bc4309582 100644 --- a/src/tools/clippy/tests/ui/missing_doc.rs +++ b/src/tools/clippy/tests/ui/missing_doc.rs @@ -116,6 +116,14 @@ with_span!(span pub fn foo_pm() {}); with_span!(span pub static FOO_PM: u32 = 0;); with_span!(span pub const FOO2_PM: u32 = 0;); +// Don't lint unnamed constants +const _: () = (); + +fn issue13298() { + // Rustdoc doesn't generate documentation for items within other items like fns or consts + const MSG: &str = "Hello, world!"; +} + // issue #12197 // Undocumented field originated inside of spanned proc-macro attribute /// Some dox for struct. diff --git a/src/tools/clippy/tests/ui/missing_doc.stderr b/src/tools/clippy/tests/ui/missing_doc.stderr index ef0f96a5b71..133c76ac9d4 100644 --- a/src/tools/clippy/tests/ui/missing_doc.stderr +++ b/src/tools/clippy/tests/ui/missing_doc.stderr @@ -88,5 +88,14 @@ error: missing documentation for a function LL | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: missing documentation for a function + --> tests/ui/missing_doc.rs:122:1 + | +LL | / fn issue13298() { +LL | | // Rustdoc doesn't generate documentation for items within other items like fns or consts +LL | | const MSG: &str = "Hello, world!"; +LL | | } + | |_^ + +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/needless_as_bytes.fixed b/src/tools/clippy/tests/ui/needless_as_bytes.fixed new file mode 100644 index 00000000000..042342311fd --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_as_bytes.fixed @@ -0,0 +1,50 @@ +#![warn(clippy::needless_as_bytes)] +#![allow(clippy::const_is_empty)] + +struct S; + +impl S { + fn as_bytes(&self) -> &[u8] { + &[] + } +} + +fn main() { + if "some string".is_empty() { + //~^ needless_as_bytes + println!("len = {}", "some string".len()); + //~^ needless_as_bytes + } + + let s = String::from("yet another string"); + if s.is_empty() { + //~^ needless_as_bytes + println!("len = {}", s.len()); + //~^ needless_as_bytes + } + + // Do not lint + let _ = S.as_bytes().is_empty(); + let _ = S.as_bytes().len(); + let _ = (&String::new() as &dyn AsBytes).as_bytes().len(); + macro_rules! m { + (1) => { + "" + }; + (2) => { + "".as_bytes() + }; + } + m!(1).as_bytes().len(); + m!(2).len(); +} + +pub trait AsBytes { + fn as_bytes(&self) -> &[u8]; +} + +impl AsBytes for String { + fn as_bytes(&self) -> &[u8] { + &[] + } +} diff --git a/src/tools/clippy/tests/ui/needless_as_bytes.rs b/src/tools/clippy/tests/ui/needless_as_bytes.rs new file mode 100644 index 00000000000..c481e041e0a --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_as_bytes.rs @@ -0,0 +1,50 @@ +#![warn(clippy::needless_as_bytes)] +#![allow(clippy::const_is_empty)] + +struct S; + +impl S { + fn as_bytes(&self) -> &[u8] { + &[] + } +} + +fn main() { + if "some string".as_bytes().is_empty() { + //~^ needless_as_bytes + println!("len = {}", "some string".as_bytes().len()); + //~^ needless_as_bytes + } + + let s = String::from("yet another string"); + if s.as_bytes().is_empty() { + //~^ needless_as_bytes + println!("len = {}", s.as_bytes().len()); + //~^ needless_as_bytes + } + + // Do not lint + let _ = S.as_bytes().is_empty(); + let _ = S.as_bytes().len(); + let _ = (&String::new() as &dyn AsBytes).as_bytes().len(); + macro_rules! m { + (1) => { + "" + }; + (2) => { + "".as_bytes() + }; + } + m!(1).as_bytes().len(); + m!(2).len(); +} + +pub trait AsBytes { + fn as_bytes(&self) -> &[u8]; +} + +impl AsBytes for String { + fn as_bytes(&self) -> &[u8] { + &[] + } +} diff --git a/src/tools/clippy/tests/ui/needless_as_bytes.stderr b/src/tools/clippy/tests/ui/needless_as_bytes.stderr new file mode 100644 index 00000000000..3391238a142 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_as_bytes.stderr @@ -0,0 +1,29 @@ +error: needless call to `as_bytes()` + --> tests/ui/needless_as_bytes.rs:13:8 + | +LL | if "some string".as_bytes().is_empty() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `is_empty()` can be called directly on strings: `"some string".is_empty()` + | + = note: `-D clippy::needless-as-bytes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_as_bytes)]` + +error: needless call to `as_bytes()` + --> tests/ui/needless_as_bytes.rs:15:30 + | +LL | println!("len = {}", "some string".as_bytes().len()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `len()` can be called directly on strings: `"some string".len()` + +error: needless call to `as_bytes()` + --> tests/ui/needless_as_bytes.rs:20:8 + | +LL | if s.as_bytes().is_empty() { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: `is_empty()` can be called directly on strings: `s.is_empty()` + +error: needless call to `as_bytes()` + --> tests/ui/needless_as_bytes.rs:22:30 + | +LL | println!("len = {}", s.as_bytes().len()); + | ^^^^^^^^^^^^^^^^^^ help: `len()` can be called directly on strings: `s.len()` + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/needless_continue.rs b/src/tools/clippy/tests/ui/needless_continue.rs index c26a292c8cb..b6d8a8f61ae 100644 --- a/src/tools/clippy/tests/ui/needless_continue.rs +++ b/src/tools/clippy/tests/ui/needless_continue.rs @@ -151,3 +151,20 @@ mod issue_2329 { } } } + +fn issue_13641() { + 'a: while std::hint::black_box(true) { + #[allow(clippy::never_loop)] + loop { + continue 'a; + } + } + + #[allow(clippy::never_loop)] + while std::hint::black_box(true) { + 'b: loop { + continue 'b; + //~^ ERROR: this `continue` expression is redundant + } + } +} diff --git a/src/tools/clippy/tests/ui/needless_continue.stderr b/src/tools/clippy/tests/ui/needless_continue.stderr index ec7c9ba39a7..0741ba69248 100644 --- a/src/tools/clippy/tests/ui/needless_continue.stderr +++ b/src/tools/clippy/tests/ui/needless_continue.stderr @@ -136,5 +136,13 @@ LL | | } println!("bar-5"); } -error: aborting due to 8 previous errors +error: this `continue` expression is redundant + --> tests/ui/needless_continue.rs:166:13 + | +LL | continue 'b; + | ^^^^^^^^^^^^ + | + = help: consider dropping the `continue` expression + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/no_lints.rs b/src/tools/clippy/tests/ui/no_lints.rs deleted file mode 100644 index a8467bb6ef7..00000000000 --- a/src/tools/clippy/tests/ui/no_lints.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![deny(clippy::all)] - -fn main() {} \ No newline at end of file diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs index 8c1ea81d2ac..8be149d1863 100644 --- a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs +++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs @@ -2,30 +2,30 @@ #![allow(unused)] #![warn(clippy::no_mangle_with_rust_abi)] -#[no_mangle] +#[unsafe(no_mangle)] fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI +//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI //~| NOTE: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings` -#[no_mangle] +#[unsafe(no_mangle)] pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI +//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI /// # Safety /// This function shouldn't be called unless the horsemen are ready -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI +//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI /// # Safety /// This function shouldn't be called unless the horsemen are ready -#[no_mangle] +#[unsafe(no_mangle)] unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI +//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI -#[no_mangle] +#[unsafe(no_mangle)] fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( - //~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI + //~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI arg_one: u32, arg_two: usize, ) -> u32 { @@ -33,13 +33,13 @@ fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lin } // Must not run on functions that explicitly opt in to using the Rust ABI with `extern "Rust"` -#[no_mangle] +#[unsafe(no_mangle)] #[rustfmt::skip] extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {} fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {} -#[no_mangle] +#[unsafe(no_mangle)] extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {} extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {} @@ -48,6 +48,11 @@ extern "C" { fn c_abi_in_block(arg_one: u32, arg_two: usize); } +mod r#fn { + #[unsafe(no_mangle)] + pub(in super::r#fn) fn with_some_fn_around() {} +} + fn main() { // test code goes here } diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr index 27b8b39a21a..a00ebe5e1ac 100644 --- a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr +++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr @@ -1,4 +1,4 @@ -error: `#[no_mangle]` set on a function with the default (`Rust`) ABI +error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI --> tests/ui/no_mangle_with_rust_abi.rs:6:1 | LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} @@ -15,7 +15,7 @@ help: or explicitly set the default LL | extern "Rust" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} | +++++++++++++ -error: `#[no_mangle]` set on a function with the default (`Rust`) ABI +error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI --> tests/ui/no_mangle_with_rust_abi.rs:11:1 | LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} @@ -30,7 +30,7 @@ help: or explicitly set the default LL | pub extern "Rust" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} | +++++++++++++ -error: `#[no_mangle]` set on a function with the default (`Rust`) ABI +error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI --> tests/ui/no_mangle_with_rust_abi.rs:17:1 | LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} @@ -45,7 +45,7 @@ help: or explicitly set the default LL | pub unsafe extern "Rust" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} | +++++++++++++ -error: `#[no_mangle]` set on a function with the default (`Rust`) ABI +error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI --> tests/ui/no_mangle_with_rust_abi.rs:23:1 | LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} @@ -60,7 +60,7 @@ help: or explicitly set the default LL | unsafe extern "Rust" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} | +++++++++++++ -error: `#[no_mangle]` set on a function with the default (`Rust`) ABI +error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI --> tests/ui/no_mangle_with_rust_abi.rs:27:1 | LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( @@ -79,5 +79,20 @@ help: or explicitly set the default LL | extern "Rust" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( | +++++++++++++ -error: aborting due to 5 previous errors +error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI + --> tests/ui/no_mangle_with_rust_abi.rs:53:5 + | +LL | pub(in super::r#fn) fn with_some_fn_around() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: set an ABI + | +LL | pub(in super::r#fn) extern "C" fn with_some_fn_around() {} + | ++++++++++ +help: or explicitly set the default + | +LL | pub(in super::r#fn) extern "Rust" fn with_some_fn_around() {} + | +++++++++++++ + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi_2021.rs b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi_2021.rs new file mode 100644 index 00000000000..c7c97335348 --- /dev/null +++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi_2021.rs @@ -0,0 +1,57 @@ +//@edition:2021 +// +// Edition 2024 requires the use of #[unsafe(no_mangle)] + +//@no-rustfix: overlapping suggestions +#![allow(unused)] +#![warn(clippy::no_mangle_with_rust_abi)] + +#[no_mangle] +fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} +//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI +//~| NOTE: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings` + +#[no_mangle] +pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} +//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI + +/// # Safety +/// This function shouldn't be called unless the horsemen are ready +#[no_mangle] +pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} +//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI + +/// # Safety +/// This function shouldn't be called unless the horsemen are ready +#[no_mangle] +unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} +//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI + +#[no_mangle] +fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( + //~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI + arg_one: u32, + arg_two: usize, +) -> u32 { + 0 +} + +// Must not run on functions that explicitly opt in to using the Rust ABI with `extern "Rust"` +#[no_mangle] +#[rustfmt::skip] +extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {} + +fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {} + +#[no_mangle] +extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {} + +extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {} + +extern "C" { + fn c_abi_in_block(arg_one: u32, arg_two: usize); +} + +fn main() { + // test code goes here +} diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi_2021.stderr b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi_2021.stderr new file mode 100644 index 00000000000..15075be72d0 --- /dev/null +++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi_2021.stderr @@ -0,0 +1,83 @@ +error: `#[no_mangle]` set on a function with the default (`Rust`) ABI + --> tests/ui/no_mangle_with_rust_abi_2021.rs:10:1 + | +LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::no_mangle_with_rust_abi)]` +help: set an ABI + | +LL | extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} + | ++++++++++ +help: or explicitly set the default + | +LL | extern "Rust" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} + | +++++++++++++ + +error: `#[no_mangle]` set on a function with the default (`Rust`) ABI + --> tests/ui/no_mangle_with_rust_abi_2021.rs:15:1 + | +LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: set an ABI + | +LL | pub extern "C" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} + | ++++++++++ +help: or explicitly set the default + | +LL | pub extern "Rust" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} + | +++++++++++++ + +error: `#[no_mangle]` set on a function with the default (`Rust`) ABI + --> tests/ui/no_mangle_with_rust_abi_2021.rs:21:1 + | +LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: set an ABI + | +LL | pub unsafe extern "C" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} + | ++++++++++ +help: or explicitly set the default + | +LL | pub unsafe extern "Rust" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} + | +++++++++++++ + +error: `#[no_mangle]` set on a function with the default (`Rust`) ABI + --> tests/ui/no_mangle_with_rust_abi_2021.rs:27:1 + | +LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: set an ABI + | +LL | unsafe extern "C" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} + | ++++++++++ +help: or explicitly set the default + | +LL | unsafe extern "Rust" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} + | +++++++++++++ + +error: `#[no_mangle]` set on a function with the default (`Rust`) ABI + --> tests/ui/no_mangle_with_rust_abi_2021.rs:31:1 + | +LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( +LL | | +LL | | arg_one: u32, +LL | | arg_two: usize, +LL | | ) -> u32 { + | |________^ + | +help: set an ABI + | +LL | extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( + | ++++++++++ +help: or explicitly set the default + | +LL | extern "Rust" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( + | +++++++++++++ + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr index eafffdaf8a6..578f918f013 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr @@ -118,25 +118,25 @@ error: this boolean expression can be simplified --> tests/ui/nonminimal_bool.rs:161:8 | LL | if !(12 == a) {} - | ^^^^^^^^^^ help: try: `12 != a` + | ^^^^^^^^^^ help: try: `(12 != a)` error: this boolean expression can be simplified --> tests/ui/nonminimal_bool.rs:162:8 | LL | if !(a == 12) {} - | ^^^^^^^^^^ help: try: `a != 12` + | ^^^^^^^^^^ help: try: `(a != 12)` error: this boolean expression can be simplified --> tests/ui/nonminimal_bool.rs:163:8 | LL | if !(12 != a) {} - | ^^^^^^^^^^ help: try: `12 == a` + | ^^^^^^^^^^ help: try: `(12 == a)` error: this boolean expression can be simplified --> tests/ui/nonminimal_bool.rs:164:8 | LL | if !(a != 12) {} - | ^^^^^^^^^^ help: try: `a == 12` + | ^^^^^^^^^^ help: try: `(a == 12)` error: this boolean expression can be simplified --> tests/ui/nonminimal_bool.rs:168:8 diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed index a23310c1ad9..65ccaaca891 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed +++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed @@ -110,9 +110,33 @@ fn dont_warn_for_negated_partial_ord_comparison() { fn issue_12625() { let a = 0; let b = 0; - if (a as u64) < b {} //~ ERROR: this boolean expression can be simplified - if (a as u64) < b {} //~ ERROR: this boolean expression can be simplified - if a as u64 > b {} //~ ERROR: this boolean expression can be simplified + if ((a as u64) < b) {} //~ ERROR: this boolean expression can be simplified + if ((a as u64) < b) {} //~ ERROR: this boolean expression can be simplified + if (a as u64 > b) {} //~ ERROR: this boolean expression can be simplified +} + +fn issue_12761() { + let a = 0; + let b = 0; + let c = 0; + if (a < b) as i32 == c {} //~ ERROR: this boolean expression can be simplified + if (a < b) | (a > c) {} //~ ERROR: this boolean expression can be simplified + let opt: Option<usize> = Some(1); + let res: Result<usize, usize> = Ok(1); + if res.is_err() as i32 == c {} //~ ERROR: this boolean expression can be simplified + if res.is_err() | opt.is_some() {} //~ ERROR: this boolean expression can be simplified + + fn a(a: bool) -> bool { + (4 <= 3).b() //~ ERROR: this boolean expression can be simplified + } + + trait B { + fn b(&self) -> bool { + true + } + } + + impl B for bool {} } fn issue_13436() { diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs index 6c844373af7..06db3a1d4a5 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs +++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs @@ -115,6 +115,30 @@ fn issue_12625() { if !(a as u64 <= b) {} //~ ERROR: this boolean expression can be simplified } +fn issue_12761() { + let a = 0; + let b = 0; + let c = 0; + if !(a >= b) as i32 == c {} //~ ERROR: this boolean expression can be simplified + if !(a >= b) | !(a <= c) {} //~ ERROR: this boolean expression can be simplified + let opt: Option<usize> = Some(1); + let res: Result<usize, usize> = Ok(1); + if !res.is_ok() as i32 == c {} //~ ERROR: this boolean expression can be simplified + if !res.is_ok() | !opt.is_none() {} //~ ERROR: this boolean expression can be simplified + + fn a(a: bool) -> bool { + (!(4 > 3)).b() //~ ERROR: this boolean expression can be simplified + } + + trait B { + fn b(&self) -> bool { + true + } + } + + impl B for bool {} +} + fn issue_13436() { fn not_zero(x: i32) -> bool { x != 0 diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr b/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr index 52803e828ae..66c50f9ff1e 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr @@ -83,127 +83,169 @@ error: this boolean expression can be simplified --> tests/ui/nonminimal_bool_methods.rs:113:8 | LL | if !(a as u64 >= b) {} - | ^^^^^^^^^^^^^^^^ help: try: `(a as u64) < b` + | ^^^^^^^^^^^^^^^^ help: try: `((a as u64) < b)` error: this boolean expression can be simplified --> tests/ui/nonminimal_bool_methods.rs:114:8 | LL | if !((a as u64) >= b) {} - | ^^^^^^^^^^^^^^^^^^ help: try: `(a as u64) < b` + | ^^^^^^^^^^^^^^^^^^ help: try: `((a as u64) < b)` error: this boolean expression can be simplified --> tests/ui/nonminimal_bool_methods.rs:115:8 | LL | if !(a as u64 <= b) {} - | ^^^^^^^^^^^^^^^^ help: try: `a as u64 > b` + | ^^^^^^^^^^^^^^^^ help: try: `(a as u64 > b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:131:9 + --> tests/ui/nonminimal_bool_methods.rs:122:8 + | +LL | if !(a >= b) as i32 == c {} + | ^^^^^^^^^ help: try: `(a < b)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:123:8 + | +LL | if !(a >= b) | !(a <= c) {} + | ^^^^^^^^^ help: try: `(a < b)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:123:20 + | +LL | if !(a >= b) | !(a <= c) {} + | ^^^^^^^^^ help: try: `(a > c)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:126:8 + | +LL | if !res.is_ok() as i32 == c {} + | ^^^^^^^^^^^^ help: try: `res.is_err()` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:127:8 + | +LL | if !res.is_ok() | !opt.is_none() {} + | ^^^^^^^^^^^^ help: try: `res.is_err()` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:127:23 + | +LL | if !res.is_ok() | !opt.is_none() {} + | ^^^^^^^^^^^^^^ help: try: `opt.is_some()` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:130:9 + | +LL | (!(4 > 3)).b() + | ^^^^^^^^^^ help: try: `(4 <= 3)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:155:9 | LL | _ = !opt.is_some_and(|x| x < 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x >= 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:132:9 + --> tests/ui/nonminimal_bool_methods.rs:156:9 | LL | _ = !opt.is_some_and(|x| x <= 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x > 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:133:9 + --> tests/ui/nonminimal_bool_methods.rs:157:9 | LL | _ = !opt.is_some_and(|x| x > 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x <= 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:134:9 + --> tests/ui/nonminimal_bool_methods.rs:158:9 | LL | _ = !opt.is_some_and(|x| x >= 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x < 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:135:9 + --> tests/ui/nonminimal_bool_methods.rs:159:9 | LL | _ = !opt.is_some_and(|x| x == 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x != 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:136:9 + --> tests/ui/nonminimal_bool_methods.rs:160:9 | LL | _ = !opt.is_some_and(|x| x != 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x == 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:145:9 + --> tests/ui/nonminimal_bool_methods.rs:169:9 | LL | _ = !opt.is_none_or(|x| x < 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x >= 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:146:9 + --> tests/ui/nonminimal_bool_methods.rs:170:9 | LL | _ = !opt.is_none_or(|x| x <= 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x > 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:147:9 + --> tests/ui/nonminimal_bool_methods.rs:171:9 | LL | _ = !opt.is_none_or(|x| x > 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x <= 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:148:9 + --> tests/ui/nonminimal_bool_methods.rs:172:9 | LL | _ = !opt.is_none_or(|x| x >= 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x < 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:149:9 + --> tests/ui/nonminimal_bool_methods.rs:173:9 | LL | _ = !opt.is_none_or(|x| x == 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x != 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:150:9 + --> tests/ui/nonminimal_bool_methods.rs:174:9 | LL | _ = !opt.is_none_or(|x| x != 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x == 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:157:9 + --> tests/ui/nonminimal_bool_methods.rs:181:9 | LL | _ = !opt.is_some_and(|x| !x); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:161:9 + --> tests/ui/nonminimal_bool_methods.rs:185:9 | LL | _ = !opt.is_none_or(|x| !x); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:168:9 + --> tests/ui/nonminimal_bool_methods.rs:192:9 | LL | _ = !opt.is_some_and(|x| x.is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x.is_err())` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:169:9 + --> tests/ui/nonminimal_bool_methods.rs:193:9 | LL | _ = !opt.is_some_and(|x| x.is_err()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x.is_ok())` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:170:9 + --> tests/ui/nonminimal_bool_methods.rs:194:9 | LL | _ = !opt.is_none_or(|x| x.is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x.is_err())` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:171:9 + --> tests/ui/nonminimal_bool_methods.rs:195:9 | LL | _ = !opt.is_none_or(|x| x.is_err()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x.is_ok())` -error: aborting due to 34 previous errors +error: aborting due to 41 previous errors diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index e03df1658ee..2ac59718786 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -54,7 +54,7 @@ #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] #![allow(named_arguments_used_positionally)] -#![allow(temporary_cstring_as_ptr)] +#![allow(dangling_pointers_from_temporaries)] #![allow(undropped_manually_drops)] #![allow(unknown_lints)] #![allow(unused_labels)] diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index b906079d7df..a5ae727b7ee 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -1,17 +1,11 @@ -error: lint `temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries` - --> tests/ui/rename.rs:57:10 - | -LL | #![allow(temporary_cstring_as_ptr)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries` - | - = note: `-D renamed-and-removed-lints` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]` - error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` --> tests/ui/rename.rs:63:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` + | + = note: `-D renamed-and-removed-lints` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` --> tests/ui/rename.rs:64:9 @@ -403,5 +397,5 @@ error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_e LL | #![warn(clippy::reverse_range_loop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges` -error: aborting due to 67 previous errors +error: aborting due to 66 previous errors diff --git a/src/tools/clippy/tests/ui/repeat_vec_with_capacity.fixed b/src/tools/clippy/tests/ui/repeat_vec_with_capacity.fixed index 2afe2f43325..f72b61b5f6c 100644 --- a/src/tools/clippy/tests/ui/repeat_vec_with_capacity.fixed +++ b/src/tools/clippy/tests/ui/repeat_vec_with_capacity.fixed @@ -1,3 +1,4 @@ +#![allow(clippy::map_with_unused_argument_over_ranges)] #![warn(clippy::repeat_vec_with_capacity)] fn main() { diff --git a/src/tools/clippy/tests/ui/repeat_vec_with_capacity.rs b/src/tools/clippy/tests/ui/repeat_vec_with_capacity.rs index 659f2a3953d..c0cc81f7843 100644 --- a/src/tools/clippy/tests/ui/repeat_vec_with_capacity.rs +++ b/src/tools/clippy/tests/ui/repeat_vec_with_capacity.rs @@ -1,3 +1,4 @@ +#![allow(clippy::map_with_unused_argument_over_ranges)] #![warn(clippy::repeat_vec_with_capacity)] fn main() { diff --git a/src/tools/clippy/tests/ui/repeat_vec_with_capacity.stderr b/src/tools/clippy/tests/ui/repeat_vec_with_capacity.stderr index cec9c6ea84a..43027c9cb89 100644 --- a/src/tools/clippy/tests/ui/repeat_vec_with_capacity.stderr +++ b/src/tools/clippy/tests/ui/repeat_vec_with_capacity.stderr @@ -1,5 +1,5 @@ error: repeating `Vec::with_capacity` using `vec![x; n]`, which does not retain capacity - --> tests/ui/repeat_vec_with_capacity.rs:5:9 + --> tests/ui/repeat_vec_with_capacity.rs:6:9 | LL | vec![Vec::<()>::with_capacity(42); 123]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | (0..123).map(|_| Vec::<()>::with_capacity(42)).collect::<Vec<_>>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: repeating `Vec::with_capacity` using `vec![x; n]`, which does not retain capacity - --> tests/ui/repeat_vec_with_capacity.rs:11:9 + --> tests/ui/repeat_vec_with_capacity.rs:12:9 | LL | vec![Vec::<()>::with_capacity(42); n]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | (0..n).map(|_| Vec::<()>::with_capacity(42)).collect::<Vec<_>>(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: repeating `Vec::with_capacity` using `iter::repeat`, which does not retain capacity - --> tests/ui/repeat_vec_with_capacity.rs:26:9 + --> tests/ui/repeat_vec_with_capacity.rs:27:9 | LL | std::iter::repeat(Vec::<()>::with_capacity(42)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.fixed b/src/tools/clippy/tests/ui/semicolon_outside_block.fixed index 148e112e0bc..ac7e86631ca 100644 --- a/src/tools/clippy/tests/ui/semicolon_outside_block.fixed +++ b/src/tools/clippy/tests/ui/semicolon_outside_block.fixed @@ -80,5 +80,13 @@ fn main() { { unit_fn_block(); }; + unsafe { + std::arch::asm!("") + }; + + { + line!() + }; + unit_fn_block() } diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.rs b/src/tools/clippy/tests/ui/semicolon_outside_block.rs index c767201469a..68f25339e32 100644 --- a/src/tools/clippy/tests/ui/semicolon_outside_block.rs +++ b/src/tools/clippy/tests/ui/semicolon_outside_block.rs @@ -80,5 +80,13 @@ fn main() { { unit_fn_block(); }; + unsafe { + std::arch::asm!(""); + } + + { + line!(); + } + unit_fn_block() } diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.stderr b/src/tools/clippy/tests/ui/semicolon_outside_block.stderr index 68b44c8f980..ff8c00048f6 100644 --- a/src/tools/clippy/tests/ui/semicolon_outside_block.stderr +++ b/src/tools/clippy/tests/ui/semicolon_outside_block.stderr @@ -51,5 +51,33 @@ LL - { m!(()); } LL + { m!(()) }; | -error: aborting due to 4 previous errors +error: consider moving the `;` outside the block for consistent formatting + --> tests/ui/semicolon_outside_block.rs:83:5 + | +LL | / unsafe { +LL | | std::arch::asm!(""); +LL | | } + | |_____^ + | +help: put the `;` here + | +LL ~ std::arch::asm!("") +LL ~ }; + | + +error: consider moving the `;` outside the block for consistent formatting + --> tests/ui/semicolon_outside_block.rs:87:5 + | +LL | / { +LL | | line!(); +LL | | } + | |_____^ + | +help: put the `;` here + | +LL ~ line!() +LL ~ }; + | + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/suspicious_map.rs b/src/tools/clippy/tests/ui/suspicious_map.rs index d4247fcd926..d4a52cb110f 100644 --- a/src/tools/clippy/tests/ui/suspicious_map.rs +++ b/src/tools/clippy/tests/ui/suspicious_map.rs @@ -1,3 +1,4 @@ +#![allow(clippy::map_with_unused_argument_over_ranges)] #![warn(clippy::suspicious_map)] fn main() { diff --git a/src/tools/clippy/tests/ui/suspicious_map.stderr b/src/tools/clippy/tests/ui/suspicious_map.stderr index 2a5e2bf2a34..769adebaede 100644 --- a/src/tools/clippy/tests/ui/suspicious_map.stderr +++ b/src/tools/clippy/tests/ui/suspicious_map.stderr @@ -1,5 +1,5 @@ error: this call to `map()` won't have an effect on the call to `count()` - --> tests/ui/suspicious_map.rs:4:13 + --> tests/ui/suspicious_map.rs:5:13 | LL | let _ = (0..3).map(|x| x + 2).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | let _ = (0..3).map(|x| x + 2).count(); = help: to override `-D warnings` add `#[allow(clippy::suspicious_map)]` error: this call to `map()` won't have an effect on the call to `count()` - --> tests/ui/suspicious_map.rs:8:13 + --> tests/ui/suspicious_map.rs:9:13 | LL | let _ = (0..3).map(f).count(); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unnecessary_filter_map.rs b/src/tools/clippy/tests/ui/unnecessary_filter_map.rs index 1e0d7d12965..8cf102ab0a5 100644 --- a/src/tools/clippy/tests/ui/unnecessary_filter_map.rs +++ b/src/tools/clippy/tests/ui/unnecessary_filter_map.rs @@ -1,26 +1,31 @@ +//@no-rustfix #![allow(dead_code)] fn main() { let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); - //~^ ERROR: this `.filter_map` can be written more simply using `.filter` + //~^ ERROR: this `.filter_map` can be written more simply //~| NOTE: `-D clippy::unnecessary-filter-map` implied by `-D warnings` let _ = (0..4).filter_map(|x| { - //~^ ERROR: this `.filter_map` can be written more simply using `.filter` + //~^ ERROR: this `.filter_map` can be written more simply if x > 1 { return Some(x); }; None }); let _ = (0..4).filter_map(|x| match x { - //~^ ERROR: this `.filter_map` can be written more simply using `.filter` + //~^ ERROR: this `.filter_map` can be written more simply 0 | 1 => None, _ => Some(x), }); let _ = (0..4).filter_map(|x| Some(x + 1)); - //~^ ERROR: this `.filter_map` can be written more simply using `.map` + //~^ ERROR: this `.filter_map` can be written more simply let _ = (0..4).filter_map(i32::checked_abs); + + let _ = (0..4).filter_map(Some); + + let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); } fn filter_map_none_changes_item_type() -> impl Iterator<Item = bool> { diff --git a/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr b/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr index f32d444ba9e..b21589c5f84 100644 --- a/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr @@ -1,14 +1,14 @@ -error: this `.filter_map` can be written more simply using `.filter` - --> tests/ui/unnecessary_filter_map.rs:4:13 +error: this `.filter_map` can be written more simply + --> tests/ui/unnecessary_filter_map.rs:5:13 | LL | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter` | = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_filter_map)]` -error: this `.filter_map` can be written more simply using `.filter` - --> tests/ui/unnecessary_filter_map.rs:7:13 +error: this `.filter_map` can be written more simply + --> tests/ui/unnecessary_filter_map.rs:8:13 | LL | let _ = (0..4).filter_map(|x| { | _____________^ @@ -18,10 +18,10 @@ LL | | return Some(x); LL | | }; LL | | None LL | | }); - | |______^ + | |______^ help: try instead: `filter` -error: this `.filter_map` can be written more simply using `.filter` - --> tests/ui/unnecessary_filter_map.rs:14:13 +error: this `.filter_map` can be written more simply + --> tests/ui/unnecessary_filter_map.rs:15:13 | LL | let _ = (0..4).filter_map(|x| match x { | _____________^ @@ -29,19 +29,40 @@ LL | | LL | | 0 | 1 => None, LL | | _ => Some(x), LL | | }); - | |______^ + | |______^ help: try instead: `filter` -error: this `.filter_map` can be written more simply using `.map` - --> tests/ui/unnecessary_filter_map.rs:20:13 +error: this `.filter_map` can be written more simply + --> tests/ui/unnecessary_filter_map.rs:21:13 | LL | let _ = (0..4).filter_map(|x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map` -error: this `.filter_map` can be written more simply using `.filter` - --> tests/ui/unnecessary_filter_map.rs:160:14 +error: redundant closure + --> tests/ui/unnecessary_filter_map.rs:28:57 + | +LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); + | ^^^^^^^^^^^ help: replace the closure with the function itself: `Some` + | + = note: `-D clippy::redundant-closure` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]` + +error: filter_map is unnecessary + --> tests/ui/unnecessary_filter_map.rs:28:61 + | +LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); + | ^^^^ help: try removing the filter_map + +error: this `.filter_map` can be written more simply + --> tests/ui/unnecessary_filter_map.rs:28:13 + | +LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map` + +error: this `.filter_map` can be written more simply + --> tests/ui/unnecessary_filter_map.rs:165:14 | LL | let _x = std::iter::once(1).filter_map(|n| (n > 1).then_some(n)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter` -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_find_map.rs b/src/tools/clippy/tests/ui/unnecessary_find_map.rs index 9972b68092a..c357d853248 100644 --- a/src/tools/clippy/tests/ui/unnecessary_find_map.rs +++ b/src/tools/clippy/tests/ui/unnecessary_find_map.rs @@ -1,24 +1,25 @@ +//@no-rustfix #![allow(dead_code)] fn main() { let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None }); - //~^ ERROR: this `.find_map` can be written more simply using `.find` + //~^ ERROR: this `.find_map` can be written more simply //~| NOTE: `-D clippy::unnecessary-find-map` implied by `-D warnings` let _ = (0..4).find_map(|x| { - //~^ ERROR: this `.find_map` can be written more simply using `.find` + //~^ ERROR: this `.find_map` can be written more simply if x > 1 { return Some(x); }; None }); let _ = (0..4).find_map(|x| match x { - //~^ ERROR: this `.find_map` can be written more simply using `.find` + //~^ ERROR: this `.find_map` can be written more simply 0 | 1 => None, _ => Some(x), }); let _ = (0..4).find_map(|x| Some(x + 1)); - //~^ ERROR: this `.find_map` can be written more simply using `.map(..).next()` + //~^ ERROR: this `.find_map` can be written more simply let _ = (0..4).find_map(i32::checked_abs); } diff --git a/src/tools/clippy/tests/ui/unnecessary_find_map.stderr b/src/tools/clippy/tests/ui/unnecessary_find_map.stderr index bb939a99214..98a6c3d164a 100644 --- a/src/tools/clippy/tests/ui/unnecessary_find_map.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_find_map.stderr @@ -1,14 +1,14 @@ -error: this `.find_map` can be written more simply using `.find` - --> tests/ui/unnecessary_find_map.rs:4:13 +error: this `.find_map` can be written more simply + --> tests/ui/unnecessary_find_map.rs:5:13 | LL | let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find` | = note: `-D clippy::unnecessary-find-map` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_find_map)]` -error: this `.find_map` can be written more simply using `.find` - --> tests/ui/unnecessary_find_map.rs:7:13 +error: this `.find_map` can be written more simply + --> tests/ui/unnecessary_find_map.rs:8:13 | LL | let _ = (0..4).find_map(|x| { | _____________^ @@ -18,10 +18,10 @@ LL | | return Some(x); LL | | }; LL | | None LL | | }); - | |______^ + | |______^ help: try instead: `find` -error: this `.find_map` can be written more simply using `.find` - --> tests/ui/unnecessary_find_map.rs:14:13 +error: this `.find_map` can be written more simply + --> tests/ui/unnecessary_find_map.rs:15:13 | LL | let _ = (0..4).find_map(|x| match x { | _____________^ @@ -29,19 +29,19 @@ LL | | LL | | 0 | 1 => None, LL | | _ => Some(x), LL | | }); - | |______^ + | |______^ help: try instead: `find` -error: this `.find_map` can be written more simply using `.map(..).next()` - --> tests/ui/unnecessary_find_map.rs:20:13 +error: this `.find_map` can be written more simply + --> tests/ui/unnecessary_find_map.rs:21:13 | LL | let _ = (0..4).find_map(|x| Some(x + 1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map(..).next()` -error: this `.find_map` can be written more simply using `.find` - --> tests/ui/unnecessary_find_map.rs:32:14 +error: this `.find_map` can be written more simply + --> tests/ui/unnecessary_find_map.rs:33:14 | LL | let _x = std::iter::once(1).find_map(|n| (n > 1).then_some(n)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find` error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/unused_io_amount.rs b/src/tools/clippy/tests/ui/unused_io_amount.rs index f5b200d5ffe..175c4ca7689 100644 --- a/src/tools/clippy/tests/ui/unused_io_amount.rs +++ b/src/tools/clippy/tests/ui/unused_io_amount.rs @@ -277,4 +277,18 @@ fn allow_works<F: std::io::Read>(mut f: F) { f.read(&mut data).unwrap(); } +struct Reader {} + +impl Read for Reader { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + todo!() + } + + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + // We shouldn't recommend using Read::read_exact inside Read::read_exact! + self.read(buf).unwrap(); + Ok(()) + } +} + fn main() {} diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml index cd9641eedd8..eadfd7107c7 100644 --- a/src/tools/clippy/triagebot.toml +++ b/src/tools/clippy/triagebot.toml @@ -21,13 +21,11 @@ new_pr = true contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" users_on_vacation = [ "matthiaskrgr", - "giraffate", ] [assign.owners] "/.github" = ["@flip1995"] "/book" = ["@flip1995"] -"/util/gh-pages" = ["@xFrednet"] "*" = [ "@Manishearth", "@llogiq", diff --git a/src/tools/clippy/util/gh-pages/index_template.html b/src/tools/clippy/util/gh-pages/index_template.html index 2412f0fd181..deb0ef0b499 100644 --- a/src/tools/clippy/util/gh-pages/index_template.html +++ b/src/tools/clippy/util/gh-pages/index_template.html @@ -52,12 +52,12 @@ Otherwise, have a great day =^.^= <noscript> {# #} <div class="alert alert-danger" role="alert"> {# #} - Sorry, this site only works with JavaScript! :( {# #} + Lints search and filtering only works with JS enabled. :( {# #} </div> {# #} </noscript> {# #} <div> {# #} - <div class="panel panel-default"> {# #} + <div class="panel panel-default" id="menu-filters"> {# #} <div class="panel-body row"> {# #} <div id="upper-filters" class="col-12 col-md-5"> {# #} <div class="btn-group" id="lint-levels" tabindex="-1"> {# #} @@ -104,7 +104,7 @@ Otherwise, have a great day =^.^= <li role="separator" class="divider"></li> {# #} </ul> {# #} </div> {# #} - <div class="btn-group", id="lint-applicabilities" tabindex="-1"> {# #} + <div class="btn-group" id="lint-applicabilities" tabindex="-1"> {# #} <button type="button" class="btn btn-default dropdown-toggle"> {# #} Applicability {#+ #} <span class="badge">4</span> {#+ #} @@ -143,26 +143,29 @@ Otherwise, have a great day =^.^= </div> {# #} </div> {% for lint in lints %} - <article class="panel panel-default collapsed" id="{{lint.id}}"> {# #} - <header class="panel-heading" onclick="expandLint('{{lint.id}}')"> {# #} - <h2 class="panel-title"> {# #} - <div class="panel-title-name" id="lint-{{lint.id}}"> {# #} - <span>{{lint.id}}</span> {#+ #} - <a href="#{{lint.id}}" class="anchor label label-default" onclick="openLint(event)">¶</a> {#+ #} - <a href="" class="anchor label label-default" onclick="copyToClipboard(event)"> {# #} - 📋 {# #} - </a> {# #} - </div> {# #} + <article class="panel panel-default" id="{{lint.id}}"> {# #} + <input id="label-{{lint.id}}" type="checkbox"> {# #} + <label for="label-{{lint.id}}" onclick="highlightIfNeeded('{{lint.id}}')"> {# #} + <header class="panel-heading"> {# #} + <h2 class="panel-title"> {# #} + <div class="panel-title-name" id="lint-{{lint.id}}"> {# #} + <span>{{lint.id}}</span> {#+ #} + <a href="#{{lint.id}}" onclick="lintAnchor(event)" class="anchor label label-default">¶</a> {#+ #} + <a href="" class="anchor label label-default" onclick="copyToClipboard(event)"> {# #} + 📋 {# #} + </a> {# #} + </div> {# #} - <div class="panel-title-addons"> {# #} - <span class="label label-lint-group label-default label-group-{{lint.group}}">{{lint.group}}</span> {#+ #} + <div class="panel-title-addons"> {# #} + <span class="label label-lint-group label-default label-group-{{lint.group}}">{{lint.group}}</span> {#+ #} - <span class="label label-lint-level label-lint-level-{{lint.level}}">{{lint.level}}</span> {#+ #} + <span class="label label-lint-level label-lint-level-{{lint.level}}">{{lint.level}}</span> {#+ #} - <span class="label label-doc-folding">+</span> {# #} - </div> {# #} - </h2> {# #} - </header> {# #} + <span class="label label-doc-folding"></span> {# #} + </div> {# #} + </h2> {# #} + </header> {# #} + </label> {# #} <div class="list-group lint-docs"> {# #} <div class="list-group-item lint-doc-md">{{Self::markdown(lint.docs)}}</div> {# #} diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js index cc22a39b3d1..9a5365b2158 100644 --- a/src/tools/clippy/util/gh-pages/script.js +++ b/src/tools/clippy/util/gh-pages/script.js @@ -138,25 +138,27 @@ function onEachLazy(lazyArray, func) { } } -function highlightIfNeeded(elem) { - onEachLazy(elem.querySelectorAll("pre > code.language-rust:not(.highlighted)"), el => { +function highlightIfNeeded(lintId) { + onEachLazy(document.querySelectorAll(`#${lintId} pre > code:not(.hljs)`), el => { hljs.highlightElement(el.parentElement) el.classList.add("highlighted"); }); } function expandLint(lintId) { - const lintElem = document.getElementById(lintId); - const isCollapsed = lintElem.classList.toggle("collapsed"); - lintElem.querySelector(".label-doc-folding").innerText = isCollapsed ? "+" : "−"; - highlightIfNeeded(lintElem); + const elem = document.querySelector(`#${lintId} > input[type="checkbox"]`); + elem.checked = true; + highlightIfNeeded(lintId); } -// Show details for one lint -function openLint(event) { +function lintAnchor(event) { event.preventDefault(); event.stopPropagation(); - expandLint(event.target.getAttribute("href").slice(1)); + + const id = event.target.getAttribute("href").replace("#", ""); + window.location.hash = id; + + expandLint(id); } function copyToClipboard(event) { @@ -520,7 +522,7 @@ function scrollToLint(lintId) { // If the page we arrive on has link to a given lint, we scroll to it. function scrollToLintByURL() { - const lintId = window.location.hash.substring(2); + const lintId = window.location.hash.substring(1); if (lintId.length > 0) { scrollToLint(lintId); } diff --git a/src/tools/clippy/util/gh-pages/style.css b/src/tools/clippy/util/gh-pages/style.css index a68a10b1401..896f2fdac76 100644 --- a/src/tools/clippy/util/gh-pages/style.css +++ b/src/tools/clippy/util/gh-pages/style.css @@ -204,7 +204,7 @@ details[open] { } /* Expanding the mdBook theme*/ -.light { +.light, body:not([class]) { --inline-code-bg: #f6f7f6; } .rust { @@ -220,6 +220,21 @@ details[open] { --inline-code-bg: #191f26; } +@media (prefers-color-scheme: dark) { + body:not([class]) { + /* + In case JS is disabled and the user's system is in dark mode, we take "coal" as default + dark theme. + */ + --inline-code-bg: #1d1f21; + } +} + +html:not(.js) #settings-dropdown, +html:not(.js)#menu-filters { + display: none; +} + #settings-dropdown { position: absolute; margin: 0.7em; @@ -309,12 +324,12 @@ L4.75,12h2.5l0.5393066-2.1572876 c0.2276001-0.1062012,0.4459839-0.2269287,0.649 .page-header { border-color: var(--theme-popup-border); } -.panel-default > .panel-heading { +.panel-default .panel-heading { background: var(--theme-hover); color: var(--fg); border: 1px solid var(--theme-popup-border); } -.panel-default > .panel-heading:hover { +.panel-default .panel-heading:hover { filter: brightness(90%); } .list-group-item { @@ -410,9 +425,25 @@ body { color: var(--fg); } -article.collapsed .lint-docs { +article > label { + width: 100%; + margin: 0; +} +article > input[type="checkbox"] { display: none; } +article > input[type="checkbox"] + label .label-doc-folding::before { + content: "+"; +} +article > input[type="checkbox"]:checked + label .label-doc-folding::before { + content: "−"; +} +.lint-docs { + display: none; +} +article > input[type="checkbox"]:checked ~ .lint-docs { + display: block; +} .github-corner svg { fill: var(--fg); diff --git a/src/tools/clippy/util/gh-pages/theme.js b/src/tools/clippy/util/gh-pages/theme.js index bc296955ddf..90f57d4469d 100644 --- a/src/tools/clippy/util/gh-pages/theme.js +++ b/src/tools/clippy/util/gh-pages/theme.js @@ -45,6 +45,10 @@ function setTheme(theme, store) { } (function() { + // This file is loaded first. If so, we add the `js` class on the `<html>` + // element. + document.documentElement.classList.add("js"); + // loading the theme after the initial load const prefersDark = window.matchMedia("(prefers-color-scheme: dark)"); const theme = loadValue("theme"); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index ecb8343fba3..e6fbba943a4 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -236,8 +236,11 @@ pub struct Config { /// Run ignored tests pub run_ignored: bool, - /// Whether to run tests with `ignore-debug` header - pub with_debug_assertions: bool, + /// Whether rustc was built with debug assertions. + pub with_rustc_debug_assertions: bool, + + /// Whether std was built with debug assertions. + pub with_std_debug_assertions: bool, /// Only run tests that match these filters pub filters: Vec<String>, diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 980b3f6829a..8570a8ce115 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -46,7 +46,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-coverage-map", "ignore-coverage-run", "ignore-cross-compile", - "ignore-debug", "ignore-eabi", "ignore-emscripten", "ignore-endian-big", @@ -82,6 +81,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-powerpc", "ignore-remote", "ignore-riscv64", + "ignore-rustc-debug-assertions", "ignore-s390x", "ignore-sgx", "ignore-sparc64", @@ -89,6 +89,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-stable", "ignore-stage1", "ignore-stage2", + "ignore-std-debug-assertions", "ignore-test", "ignore-thumb", "ignore-thumbv8m.base-none-eabi", @@ -135,6 +136,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-relocation-model-pic", "needs-run-enabled", "needs-rust-lld", + "needs-rustc-debug-assertions", "needs-sanitizer-address", "needs-sanitizer-cfi", "needs-sanitizer-dataflow", @@ -147,6 +149,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-shadow-call-stack", "needs-sanitizer-support", "needs-sanitizer-thread", + "needs-std-debug-assertions", "needs-symlink", "needs-threads", "needs-unwind", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index b9314f0abbb..3ab552903dc 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -202,9 +202,14 @@ pub(super) fn parse_cfg_name_directive<'a>( message: "when running tests remotely", } condition! { - name: "debug", - condition: config.with_debug_assertions, - message: "when running tests with `ignore-debug` header", + name: "rustc-debug-assertions", + condition: config.with_rustc_debug_assertions, + message: "when rustc is built with debug assertions", + } + condition! { + name: "std-debug-assertions", + condition: config.with_std_debug_assertions, + message: "when std is built with debug assertions", } condition! { name: config.debugger.as_ref().map(|d| d.to_str()), diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index a744fb61b9c..77570c58db5 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -159,6 +159,16 @@ pub(super) fn handle_needs( condition: cache.llvm_zstd, ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression", }, + Need { + name: "needs-rustc-debug-assertions", + condition: config.with_rustc_debug_assertions, + ignore_reason: "ignored if rustc wasn't built with debug assertions", + }, + Need { + name: "needs-std-debug-assertions", + condition: config.with_std_debug_assertions, + ignore_reason: "ignored if std wasn't built with debug assertions", + }, ]; let (name, comment) = match ln.split_once([':', ' ']) { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 0e735dc77c4..c3fb8d4ab80 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -74,6 +74,8 @@ struct ConfigBuilder { git_hash: bool, system_llvm: bool, profiler_runtime: bool, + rustc_debug_assertions: bool, + std_debug_assertions: bool, } impl ConfigBuilder { @@ -122,6 +124,16 @@ impl ConfigBuilder { self } + fn rustc_debug_assertions(&mut self, is_enabled: bool) -> &mut Self { + self.rustc_debug_assertions = is_enabled; + self + } + + fn std_debug_assertions(&mut self, is_enabled: bool) -> &mut Self { + self.std_debug_assertions = is_enabled; + self + } + fn build(&mut self) -> Config { let args = &[ "compiletest", @@ -170,6 +182,12 @@ impl ConfigBuilder { if self.profiler_runtime { args.push("--profiler-runtime".to_owned()); } + if self.rustc_debug_assertions { + args.push("--with-rustc-debug-assertions".to_owned()); + } + if self.std_debug_assertions { + args.push("--with-std-debug-assertions".to_owned()); + } args.push("--rustc-path".to_string()); // This is a subtle/fragile thing. On rust-lang CI, there is no global @@ -315,6 +333,32 @@ fn only_target() { } #[test] +fn rustc_debug_assertions() { + let config: Config = cfg().rustc_debug_assertions(false).build(); + + assert!(check_ignore(&config, "//@ needs-rustc-debug-assertions")); + assert!(!check_ignore(&config, "//@ ignore-rustc-debug-assertions")); + + let config: Config = cfg().rustc_debug_assertions(true).build(); + + assert!(!check_ignore(&config, "//@ needs-rustc-debug-assertions")); + assert!(check_ignore(&config, "//@ ignore-rustc-debug-assertions")); +} + +#[test] +fn std_debug_assertions() { + let config: Config = cfg().std_debug_assertions(false).build(); + + assert!(check_ignore(&config, "//@ needs-std-debug-assertions")); + assert!(!check_ignore(&config, "//@ ignore-std-debug-assertions")); + + let config: Config = cfg().std_debug_assertions(true).build(); + + assert!(!check_ignore(&config, "//@ needs-std-debug-assertions")); + assert!(check_ignore(&config, "//@ ignore-std-debug-assertions")); +} + +#[test] fn stage() { let config: Config = cfg().stage_id("stage1-x86_64-unknown-linux-gnu").build(); @@ -583,10 +627,6 @@ fn wasm_special() { ("wasm32-unknown-emscripten", "emscripten", true), ("wasm32-unknown-emscripten", "wasm32", true), ("wasm32-unknown-emscripten", "wasm32-bare", false), - ("wasm32-wasi", "emscripten", false), - ("wasm32-wasi", "wasm32", true), - ("wasm32-wasi", "wasm32-bare", false), - ("wasm32-wasi", "wasi", true), ("wasm32-wasip1", "emscripten", false), ("wasm32-wasip1", "wasm32", true), ("wasm32-wasip1", "wasm32-bare", false), diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 5c06a39c477..bf4a3124075 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -88,7 +88,8 @@ pub fn parse_config(args: Vec<String>) -> Config { .optopt("", "run", "whether to execute run-* tests", "auto | always | never") .optflag("", "ignored", "run tests marked as ignored") .optflag("", "has-enzyme", "run tests that require enzyme") - .optflag("", "with-debug-assertions", "whether to run tests with `ignore-debug` header") + .optflag("", "with-rustc-debug-assertions", "whether rustc was built with debug assertions") + .optflag("", "with-std-debug-assertions", "whether std was built with debug assertions") .optmulti( "", "skip", @@ -235,7 +236,8 @@ pub fn parse_config(args: Vec<String>) -> Config { let src_base = opt_path(matches, "src-base"); let run_ignored = matches.opt_present("ignored"); - let with_debug_assertions = matches.opt_present("with-debug-assertions"); + let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions"); + let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions"); let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode"); let has_html_tidy = if mode == Mode::Rustdoc { Command::new("tidy") @@ -293,7 +295,8 @@ pub fn parse_config(args: Vec<String>) -> Config { suite: matches.opt_str("suite").unwrap(), debugger: None, run_ignored, - with_debug_assertions, + with_rustc_debug_assertions, + with_std_debug_assertions, filters, skip: matches.opt_strs("skip"), filter_exact: matches.opt_present("exact"), diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs index fa7c0bf5c0c..e95ef4d9062 100644 --- a/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs +++ b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs)] +#![feature(intrinsics, rustc_attrs)] #[rustc_intrinsic] #[rustc_nounwind] diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs index b5feac8c677..cd48bd2accb 100644 --- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs +++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs @@ -1,3 +1,5 @@ +#![feature(never_type)] + use std::rc::Rc; use std::{mem, num, ptr}; @@ -12,6 +14,18 @@ fn id<T>(x: T) -> T { x } +#[derive(Copy, Clone)] +enum Either<T, U> { + Left(T), + Right(U), +} +#[derive(Copy, Clone)] +enum Either2<T, U> { + Left(T), + #[allow(unused)] + Right(U, ()), +} + fn test_abi_compat<T: Clone, U: Clone>(t: T, u: U) { fn id<T>(x: T) -> T { x @@ -81,6 +95,8 @@ fn main() { test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32); // - 1-ZST test_abi_compat((), [0u8; 0]); + + // Guaranteed null-pointer-layout optimizations: // - Guaranteed Option<X> null-pointer-optimizations (RFC 3391). test_abi_compat(&0u32 as *const u32, Some(&0u32)); test_abi_compat(main as fn(), Some(main as fn())); @@ -89,6 +105,7 @@ fn main() { test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1u32).unwrap()))); // - Guaranteed Result<X, ZST1> does the same as Option<X> (RFC 3391) test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(&0u32)); + test_abi_compat(&0u32 as *const u32, Result::<_, !>::Ok(&0u32)); test_abi_compat(main as fn(), Result::<_, ()>::Ok(main as fn())); test_abi_compat(0u32, Result::<_, ()>::Ok(num::NonZeroU32::new(1).unwrap())); test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(Wrapper(&0u32))); @@ -99,6 +116,13 @@ fn main() { test_abi_compat(0u32, Result::<(), _>::Err(num::NonZeroU32::new(1).unwrap())); test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(Wrapper(&0u32))); test_abi_compat(0u32, Result::<(), _>::Err(Wrapper(num::NonZeroU32::new(1).unwrap()))); + // - Guaranteed null-pointer-optimizations for custom option-like types + test_abi_compat(&0u32 as *const u32, Either::<_, ()>::Left(&0u32)); + test_abi_compat(&0u32 as *const u32, Either::<_, !>::Left(&0u32)); + test_abi_compat(&0u32 as *const u32, Either::<(), _>::Right(&0u32)); + test_abi_compat(&0u32 as *const u32, Either::<!, _>::Right(&0u32)); + test_abi_compat(&0u32 as *const u32, Either2::<_, ()>::Left(&0u32)); + test_abi_compat(&0u32 as *const u32, Either2::<_, [u8; 0]>::Left(&0u32)); // These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible // with the wrapped field. diff --git a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml index 4b97637088c..e0135a0269a 100644 --- a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml +++ b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml @@ -51,6 +51,7 @@ jobs: cargo workspaces rename --from proc-macro-api proc_macro_api cargo workspaces rename --from proc-macro-srv proc_macro_srv cargo workspaces rename --from project-model project_model + cargo workspaces rename --from test-fixture test_fixture cargo workspaces rename --from test-utils test_utils cargo workspaces rename --from text-edit text_edit # Remove library crates from the workspaces so we don't auto-publish them as well diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 424357e8473..55705de9b2c 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1492,9 +1492,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.75.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5bc2cfc7264d84215a08875ef90a1d35f76b5c9ad1993515d2da7e4e40b2b4b" +checksum = "709fde78db053c78c87776ec738677649f791645883f82ff145f68caf9f18e1a" dependencies = [ "bitflags 2.6.0", "ra-ap-rustc_index", @@ -1503,9 +1503,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index" -version = "0.75.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8929140697812e5dd09e19cf446d85146332363f0dbc125d4214834c34ead96" +checksum = "da115d496e5abd65e2dceb6883d7597593badfe23fea3439202b8da5a11ea250" dependencies = [ "arrayvec", "ra-ap-rustc_index_macros", @@ -1514,9 +1514,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.75.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514a3f5d04c8b4a2750f29746cc9abb1f78deb7e72e4ad1dc95bbc608f3db157" +checksum = "be86d06a75a8125c1ace197d5030e6e02721348d32e572baea35c891669ad1e2" dependencies = [ "proc-macro2", "quote", @@ -1525,9 +1525,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.75.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276fcb1205da071a0cd64416f3f0e198043c11f176c5b501a45dbf0cb33979f2" +checksum = "b64b46ae0d8f59acc32e64e0085532b831f0d6182d870a7cd86c046c2c46e722" dependencies = [ "unicode-properties", "unicode-xid", @@ -1535,9 +1535,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.75.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "961b30b22cfac296b14b72e9f95e79c16cebc8c926872755fb1568a6c4243a62" +checksum = "dbdaad19ddbd0ff46e947ca8dbb6ae678a112d3938669fb3ad6bfd244917e24b" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", @@ -1545,9 +1545,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.75.0" +version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614232513814a4b714fea7f11345d31c0c277bca3089bb6ca1ec20870bfc022a" +checksum = "dc5761e37c78d98ede9f20f6b66526093d0be66aa256d5cbdf214495843ba74d" dependencies = [ "ra-ap-rustc_index", "rustc-hash 2.0.0", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 1099d2cb918..94e7de553bf 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.75", default-features = false } -ra-ap-rustc_parse_format = { version = "0.75", default-features = false } -ra-ap-rustc_index = { version = "0.75", default-features = false } -ra-ap-rustc_abi = { version = "0.75", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.75", default-features = false } +ra-ap-rustc_lexer = { version = "0.76", default-features = false } +ra-ap-rustc_parse_format = { version = "0.76", default-features = false } +ra-ap-rustc_index = { version = "0.76", default-features = false } +ra-ap-rustc_abi = { version = "0.76", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.76", default-features = false } # local crates that aren't published to crates.io. These should not have versions. test-fixture = { path = "./crates/test-fixture" } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index 0b108b54e67..1ab49e91569 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -407,7 +407,7 @@ impl ExprCollector<'_> { let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); let generic_args = e .generic_arg_list() - .and_then(|it| GenericArgs::from_ast(&self.ctx(), it)) + .and_then(|it| GenericArgs::from_ast(&mut self.ctx(), it)) .map(Box::new); self.alloc_expr( Expr::MethodCall { receiver, method_name, args, generic_args }, @@ -533,7 +533,7 @@ impl ExprCollector<'_> { ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e), ast::Expr::CastExpr(e) => { let expr = self.collect_expr_opt(e.expr()); - let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); + let type_ref = TypeRef::from_ast_opt(&mut self.ctx(), e.ty()); self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) } ast::Expr::RefExpr(e) => { @@ -572,13 +572,15 @@ impl ExprCollector<'_> { arg_types.reserve_exact(num_params); for param in pl.params() { let pat = this.collect_pat_top(param.pat()); - let type_ref = param.ty().map(|it| TypeRef::from_ast(&this.ctx(), it)); + let type_ref = param.ty().map(|it| TypeRef::from_ast(&mut this.ctx(), it)); args.push(pat); arg_types.push(type_ref); } } - let ret_type = - e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&this.ctx(), it)); + let ret_type = e + .ret_type() + .and_then(|r| r.ty()) + .map(|it| TypeRef::from_ast(&mut this.ctx(), it)); let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine); let prev_try_block_label = this.current_try_block_label.take(); @@ -705,7 +707,7 @@ impl ExprCollector<'_> { ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr), ast::Expr::OffsetOfExpr(e) => { - let container = TypeRef::from_ast_opt(&self.ctx(), e.ty()); + let container = TypeRef::from_ast_opt(&mut self.ctx(), e.ty()); let fields = e.fields().map(|it| it.as_name()).collect(); self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr) } @@ -1317,7 +1319,7 @@ impl ExprCollector<'_> { return; } let pat = self.collect_pat_top(stmt.pat()); - let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); + let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&mut self.ctx(), it)); let initializer = stmt.initializer().map(|e| self.collect_expr(e)); let else_branch = stmt .let_else() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index f49018eaf38..6d07dc8f9be 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -37,6 +37,7 @@ pub struct FunctionData { pub name: Name, pub params: Box<[TypeRefId]>, pub ret_type: TypeRefId, + // FIXME: why are these stored here? They should be accessed via the query pub attrs: Attrs, pub visibility: RawVisibility, pub abi: Option<Symbol>, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs index a59bbf7e221..22005695af6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs @@ -21,7 +21,79 @@ //! //! This is a work of fiction. Any similarities to Kotlin's `BindingContext` are //! a coincidence. -pub mod keys; + +pub mod keys { + use std::marker::PhantomData; + + use hir_expand::{attrs::AttrId, MacroCallId}; + use rustc_hash::FxHashMap; + use syntax::{ast, AstNode, AstPtr}; + + use crate::{ + dyn_map::{DynMap, Policy}, + BlockId, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId, + LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, + TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId, + }; + + pub type Key<K, V> = crate::dyn_map::Key<AstPtr<K>, V, AstPtrPolicy<K, V>>; + + pub const BLOCK: Key<ast::BlockExpr, BlockId> = Key::new(); + pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new(); + pub const CONST: Key<ast::Const, ConstId> = Key::new(); + pub const STATIC: Key<ast::Static, StaticId> = Key::new(); + pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new(); + pub const IMPL: Key<ast::Impl, ImplId> = Key::new(); + pub const TRAIT: Key<ast::Trait, TraitId> = Key::new(); + pub const TRAIT_ALIAS: Key<ast::TraitAlias, TraitAliasId> = Key::new(); + pub const STRUCT: Key<ast::Struct, StructId> = Key::new(); + pub const UNION: Key<ast::Union, UnionId> = Key::new(); + pub const ENUM: Key<ast::Enum, EnumId> = Key::new(); + pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new(); + pub const USE: Key<ast::Use, UseId> = Key::new(); + + pub const ENUM_VARIANT: Key<ast::Variant, EnumVariantId> = Key::new(); + pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); + pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); + pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new(); + pub const CONST_PARAM: Key<ast::ConstParam, TypeOrConstParamId> = Key::new(); + pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); + + pub const MACRO_RULES: Key<ast::MacroRules, MacroRulesId> = Key::new(); + pub const MACRO2: Key<ast::MacroDef, Macro2Id> = Key::new(); + pub const PROC_MACRO: Key<ast::Fn, ProcMacroId> = Key::new(); + pub const MACRO_CALL: Key<ast::MacroCall, MacroCallId> = Key::new(); + pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new(); + pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, MacroCallId, Box<[Option<MacroCallId>]>)> = + Key::new(); + + /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are + /// equal if they point to exactly the same object. + /// + /// In general, we do not guarantee that we have exactly one instance of a + /// syntax tree for each file. We probably should add such guarantee, but, for + /// the time being, we will use identity-less AstPtr comparison. + pub struct AstPtrPolicy<AST, ID> { + _phantom: PhantomData<(AST, ID)>, + } + + impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> { + type K = AstPtr<AST>; + type V = ID; + fn insert(map: &mut DynMap, key: AstPtr<AST>, value: ID) { + map.map + .entry::<FxHashMap<AstPtr<AST>, ID>>() + .or_insert_with(Default::default) + .insert(key, value); + } + fn get<'a>(map: &'a DynMap, key: &AstPtr<AST>) -> Option<&'a ID> { + map.map.get::<FxHashMap<AstPtr<AST>, ID>>()?.get(key) + } + fn is_empty(map: &DynMap) -> bool { + map.map.get::<FxHashMap<AstPtr<AST>, ID>>().map_or(true, |it| it.is_empty()) + } + } +} use std::{ hash::Hash, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs deleted file mode 100644 index 9d330a7bf1c..00000000000 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs +++ /dev/null @@ -1,72 +0,0 @@ -//! keys to be used with `DynMap` - -use std::marker::PhantomData; - -use hir_expand::{attrs::AttrId, MacroCallId}; -use rustc_hash::FxHashMap; -use syntax::{ast, AstNode, AstPtr}; - -use crate::{ - dyn_map::{DynMap, Policy}, - BlockId, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId, - LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, - TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId, -}; - -pub type Key<K, V> = crate::dyn_map::Key<AstPtr<K>, V, AstPtrPolicy<K, V>>; - -pub const BLOCK: Key<ast::BlockExpr, BlockId> = Key::new(); -pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new(); -pub const CONST: Key<ast::Const, ConstId> = Key::new(); -pub const STATIC: Key<ast::Static, StaticId> = Key::new(); -pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new(); -pub const IMPL: Key<ast::Impl, ImplId> = Key::new(); -pub const TRAIT: Key<ast::Trait, TraitId> = Key::new(); -pub const TRAIT_ALIAS: Key<ast::TraitAlias, TraitAliasId> = Key::new(); -pub const STRUCT: Key<ast::Struct, StructId> = Key::new(); -pub const UNION: Key<ast::Union, UnionId> = Key::new(); -pub const ENUM: Key<ast::Enum, EnumId> = Key::new(); -pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new(); -pub const USE: Key<ast::Use, UseId> = Key::new(); - -pub const ENUM_VARIANT: Key<ast::Variant, EnumVariantId> = Key::new(); -pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); -pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); -pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new(); -pub const CONST_PARAM: Key<ast::ConstParam, TypeOrConstParamId> = Key::new(); -pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); - -pub const MACRO_RULES: Key<ast::MacroRules, MacroRulesId> = Key::new(); -pub const MACRO2: Key<ast::MacroDef, Macro2Id> = Key::new(); -pub const PROC_MACRO: Key<ast::Fn, ProcMacroId> = Key::new(); -pub const MACRO_CALL: Key<ast::MacroCall, MacroCallId> = Key::new(); -pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new(); -pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, MacroCallId, Box<[Option<MacroCallId>]>)> = - Key::new(); - -/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are -/// equal if they point to exactly the same object. -/// -/// In general, we do not guarantee that we have exactly one instance of a -/// syntax tree for each file. We probably should add such guarantee, but, for -/// the time being, we will use identity-less AstPtr comparison. -pub struct AstPtrPolicy<AST, ID> { - _phantom: PhantomData<(AST, ID)>, -} - -impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> { - type K = AstPtr<AST>; - type V = ID; - fn insert(map: &mut DynMap, key: AstPtr<AST>, value: ID) { - map.map - .entry::<FxHashMap<AstPtr<AST>, ID>>() - .or_insert_with(Default::default) - .insert(key, value); - } - fn get<'a>(map: &'a DynMap, key: &AstPtr<AST>) -> Option<&'a ID> { - map.map.get::<FxHashMap<AstPtr<AST>, ID>>()?.get(key) - } - fn is_empty(map: &DynMap) -> bool { - map.map.get::<FxHashMap<AstPtr<AST>, ID>>().map_or(true, |it| it.is_empty()) - } -} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs index d430733fcad..5315c1c6fbd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs @@ -161,14 +161,14 @@ impl Expander { types_map: &mut TypesMap, types_source_map: &mut TypesSourceMap, ) -> Option<Path> { - let ctx = LowerCtx::with_span_map_cell( + let mut ctx = LowerCtx::with_span_map_cell( db, self.current_file_id, self.span_map.clone(), types_map, types_source_map, ); - Path::from_src(&ctx, path) + Path::from_src(&mut ctx, path) } fn within_limit<F, T: ast::AstNode>( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index 6b79850e9c4..11e9bb0d886 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -451,7 +451,7 @@ pub(crate) struct GenericParamsCollector { impl GenericParamsCollector { pub(crate) fn fill( &mut self, - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, node: &dyn HasGenericParams, add_param_attrs: impl FnMut( Either<LocalTypeOrConstParamId, LocalLifetimeParamId>, @@ -468,7 +468,7 @@ impl GenericParamsCollector { pub(crate) fn fill_bounds( &mut self, - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, type_bounds: Option<ast::TypeBoundList>, target: Either<TypeRefId, LifetimeRef>, ) { @@ -479,7 +479,7 @@ impl GenericParamsCollector { fn fill_params( &mut self, - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, params: ast::GenericParamList, mut add_param_attrs: impl FnMut( Either<LocalTypeOrConstParamId, LocalLifetimeParamId>, @@ -535,7 +535,11 @@ impl GenericParamsCollector { } } - fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx<'_>, where_clause: ast::WhereClause) { + fn fill_where_predicates( + &mut self, + lower_ctx: &mut LowerCtx<'_>, + where_clause: ast::WhereClause, + ) { for pred in where_clause.predicates() { let target = if let Some(type_ref) = pred.ty() { Either::Left(TypeRef::from_ast(lower_ctx, type_ref)) @@ -569,7 +573,7 @@ impl GenericParamsCollector { fn add_where_predicate_from_bound( &mut self, - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, bound: ast::TypeBound, hrtb_lifetimes: Option<&[Name]>, target: Either<TypeRefId, LifetimeRef>, @@ -670,8 +674,9 @@ impl GenericParamsCollector { { let (mut macro_types_map, mut macro_types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = expander.ctx(db, &mut macro_types_map, &mut macro_types_source_map); - let type_ref = TypeRef::from_ast(&ctx, expanded.tree()); + let mut ctx = + expander.ctx(db, &mut macro_types_map, &mut macro_types_source_map); + let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree()); self.fill_implicit_impl_trait_args( db, generics_types_map, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs index 2582340c0f8..4d83ef99c84 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs @@ -98,7 +98,7 @@ pub struct TraitRef { impl TraitRef { /// Converts an `ast::PathType` to a `hir::TraitRef`. - pub(crate) fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> Option<Self> { + pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> { // FIXME: Use `Path::from_src` match node { ast::Type::PathType(path) => { @@ -240,7 +240,7 @@ pub enum TraitBoundModifier { impl TypeRef { /// Converts an `ast::TypeRef` to a `hir::TypeRef`. - pub fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> TypeRefId { + pub fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> TypeRefId { let ty = match &node { ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()), ast::Type::TupleType(inner) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter( @@ -321,8 +321,9 @@ impl TypeRef { // Disallow nested impl traits TypeRef::Error } else { - let _guard = ctx.outer_impl_trait_scope(true); - TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) + ctx.with_outer_impl_trait_scope(true, |ctx| { + TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) + }) } } ast::Type::DynTraitType(inner) => { @@ -336,7 +337,7 @@ impl TypeRef { ctx.alloc_type_ref(ty, AstPtr::new(&node)) } - pub(crate) fn from_ast_opt(ctx: &LowerCtx<'_>, node: Option<ast::Type>) -> TypeRefId { + pub(crate) fn from_ast_opt(ctx: &mut LowerCtx<'_>, node: Option<ast::Type>) -> TypeRefId { match node { Some(node) => TypeRef::from_ast(ctx, node), None => ctx.alloc_error_type(), @@ -410,7 +411,7 @@ impl TypeRef { } pub(crate) fn type_bounds_from_ast( - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, type_bounds_opt: Option<ast::TypeBoundList>, ) -> ThinVec<TypeBound> { if let Some(type_bounds) = type_bounds_opt { @@ -423,8 +424,8 @@ pub(crate) fn type_bounds_from_ast( } impl TypeBound { - pub(crate) fn from_ast(ctx: &LowerCtx<'_>, node: ast::TypeBound) -> Self { - let lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?); + pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self { + let mut lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?); match node.kind() { ast::TypeBoundKind::PathType(path_type) => { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index a04f12cab76..e96e38eceeb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -361,9 +361,7 @@ impl ItemScope { self.macro_invocations.get(&call).copied() } - pub(crate) fn iter_macro_invoc( - &self, - ) -> impl Iterator<Item = (&AstId<ast::MacroCall>, &MacroCallId)> { + pub fn iter_macro_invoc(&self) -> impl Iterator<Item = (&AstId<ast::MacroCall>, &MacroCallId)> { self.macro_invocations.iter() } } @@ -401,9 +399,7 @@ impl ItemScope { self.macro_invocations.insert(call, call_id); } - pub(crate) fn attr_macro_invocs( - &self, - ) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { + pub fn attr_macro_invocs(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { self.attr_macros.iter().map(|(k, v)| (*k, *v)) } @@ -440,7 +436,7 @@ impl ItemScope { }); } - pub(crate) fn derive_macro_invocs( + pub fn derive_macro_invocs( &self, ) -> impl Iterator< Item = ( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index bd17fce37b7..d519c1708b3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -234,11 +234,11 @@ impl<'a> Ctx<'a> { fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let visibility = self.lower_visibility(strukt); let name = strukt.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(strukt); - let (fields, kind, attrs) = self.lower_fields(&strukt.kind(), &body_ctx); + let (fields, kind, attrs) = self.lower_fields(&strukt.kind(), &mut body_ctx); let (generic_params, generics_source_map) = self.lower_generic_params(HasImplicitSelf::No, strukt); types_map.shrink_to_fit(); @@ -273,7 +273,7 @@ impl<'a> Ctx<'a> { fn lower_fields( &mut self, strukt_kind: &ast::StructKind, - body_ctx: &LowerCtx<'_>, + body_ctx: &mut LowerCtx<'_>, ) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) { match strukt_kind { ast::StructKind::Record(it) => { @@ -308,7 +308,11 @@ impl<'a> Ctx<'a> { } } - fn lower_record_field(&mut self, field: &ast::RecordField, body_ctx: &LowerCtx<'_>) -> Field { + fn lower_record_field( + &mut self, + field: &ast::RecordField, + body_ctx: &mut LowerCtx<'_>, + ) -> Field { let name = match field.name() { Some(name) => name.as_name(), None => Name::missing(), @@ -323,7 +327,7 @@ impl<'a> Ctx<'a> { &mut self, idx: usize, field: &ast::TupleField, - body_ctx: &LowerCtx<'_>, + body_ctx: &mut LowerCtx<'_>, ) -> Field { let name = Name::new_tuple_field(idx); let visibility = self.lower_visibility(field); @@ -334,13 +338,13 @@ impl<'a> Ctx<'a> { fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let visibility = self.lower_visibility(union); let name = union.name()?.as_name(); let ast_id = self.source_ast_id_map.ast_id(union); let (fields, _, attrs) = match union.record_field_list() { Some(record_field_list) => { - self.lower_fields(&StructKind::Record(record_field_list), &body_ctx) + self.lower_fields(&StructKind::Record(record_field_list), &mut body_ctx) } None => (Box::default(), FieldsShape::Record, Vec::default()), }; @@ -409,12 +413,12 @@ impl<'a> Ctx<'a> { fn lower_variant(&mut self, variant: &ast::Variant) -> Idx<Variant> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let name = match variant.name() { Some(name) => name.as_name(), None => Name::missing(), }; - let (fields, kind, attrs) = self.lower_fields(&variant.kind(), &body_ctx); + let (fields, kind, attrs) = self.lower_fields(&variant.kind(), &mut body_ctx); let ast_id = self.source_ast_id_map.ast_id(variant); types_map.shrink_to_fit(); types_source_map.shrink_to_fit(); @@ -436,7 +440,7 @@ impl<'a> Ctx<'a> { fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let visibility = self.lower_visibility(func); let name = func.name()?.as_name(); @@ -457,7 +461,7 @@ impl<'a> Ctx<'a> { RawAttrs::new(self.db.upcast(), &self_param, self.span_map()), ); let self_type = match self_param.ty() { - Some(type_ref) => TypeRef::from_ast(&body_ctx, type_ref), + Some(type_ref) => TypeRef::from_ast(&mut body_ctx, type_ref), None => { let self_type = body_ctx.alloc_type_ref_desugared(TypeRef::Path( Name::new_symbol_root(sym::Self_.clone()).into(), @@ -492,7 +496,7 @@ impl<'a> Ctx<'a> { Param { type_ref: None } } None => { - let type_ref = TypeRef::from_ast_opt(&body_ctx, param.ty()); + let type_ref = TypeRef::from_ast_opt(&mut body_ctx, param.ty()); Param { type_ref: Some(type_ref) } } }; @@ -502,7 +506,7 @@ impl<'a> Ctx<'a> { let ret_type = match func.ret_type() { Some(rt) => match rt.ty() { - Some(type_ref) => TypeRef::from_ast(&body_ctx, type_ref), + Some(type_ref) => TypeRef::from_ast(&mut body_ctx, type_ref), None if rt.thin_arrow_token().is_some() => body_ctx.alloc_error_type(), None => body_ctx.alloc_type_ref_desugared(TypeRef::unit()), }, @@ -581,11 +585,11 @@ impl<'a> Ctx<'a> { ) -> Option<FileItemTreeId<TypeAlias>> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let name = type_alias.name()?.as_name(); - let type_ref = type_alias.ty().map(|it| TypeRef::from_ast(&body_ctx, it)); + let type_ref = type_alias.ty().map(|it| TypeRef::from_ast(&mut body_ctx, it)); let visibility = self.lower_visibility(type_alias); - let bounds = self.lower_type_bounds(type_alias, &body_ctx); + let bounds = self.lower_type_bounds(type_alias, &mut body_ctx); let ast_id = self.source_ast_id_map.ast_id(type_alias); let (generic_params, generics_source_map) = self.lower_generic_params(HasImplicitSelf::No, type_alias); @@ -612,9 +616,9 @@ impl<'a> Ctx<'a> { fn lower_static(&mut self, static_: &ast::Static) -> Option<FileItemTreeId<Static>> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let name = static_.name()?.as_name(); - let type_ref = TypeRef::from_ast_opt(&body_ctx, static_.ty()); + let type_ref = TypeRef::from_ast_opt(&mut body_ctx, static_.ty()); let visibility = self.lower_visibility(static_); let mutable = static_.mut_token().is_some(); let has_safe_kw = static_.safe_token().is_some(); @@ -639,9 +643,9 @@ impl<'a> Ctx<'a> { fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let name = konst.name().map(|it| it.as_name()); - let type_ref = TypeRef::from_ast_opt(&body_ctx, konst.ty()); + let type_ref = TypeRef::from_ast_opt(&mut body_ctx, konst.ty()); let visibility = self.lower_visibility(konst); let ast_id = self.source_ast_id_map.ast_id(konst); types_map.shrink_to_fit(); @@ -724,14 +728,14 @@ impl<'a> Ctx<'a> { fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId<Impl> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); let ast_id = self.source_ast_id_map.ast_id(impl_def); // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only // equals itself. - let self_ty = TypeRef::from_ast_opt(&body_ctx, impl_def.self_ty()); - let target_trait = impl_def.trait_().and_then(|tr| TraitRef::from_ast(&body_ctx, tr)); + let self_ty = TypeRef::from_ast_opt(&mut body_ctx, impl_def.self_ty()); + let target_trait = impl_def.trait_().and_then(|tr| TraitRef::from_ast(&mut body_ctx, tr)); let is_negative = impl_def.excl_token().is_some(); let is_unsafe = impl_def.unsafe_token().is_some(); @@ -870,13 +874,8 @@ impl<'a> Ctx<'a> { ) -> (Arc<GenericParams>, TypesSourceMap) { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); + let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map); debug_assert!(self.generic_param_attr_buffer.is_empty(),); - let add_param_attrs = |item: Either<LocalTypeOrConstParamId, LocalLifetimeParamId>, - param| { - let attrs = RawAttrs::new(self.db.upcast(), ¶m, body_ctx.span_map()); - debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none()); - }; body_ctx.take_impl_traits_bounds(); let mut generics = GenericParamsCollector::default(); @@ -892,16 +891,19 @@ impl<'a> Ctx<'a> { ); // add super traits as bounds on Self // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar` - generics.fill_bounds( - &body_ctx, - bounds, - Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path( - Name::new_symbol_root(sym::Self_.clone()).into(), - ))), - ); + let bound_target = Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path( + Name::new_symbol_root(sym::Self_.clone()).into(), + ))); + generics.fill_bounds(&mut body_ctx, bounds, bound_target); } - generics.fill(&body_ctx, node, add_param_attrs); + let span_map = body_ctx.span_map().clone(); + let add_param_attrs = |item: Either<LocalTypeOrConstParamId, LocalLifetimeParamId>, + param| { + let attrs = RawAttrs::new(self.db.upcast(), ¶m, span_map.as_ref()); + debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none()); + }; + generics.fill(&mut body_ctx, node, add_param_attrs); let generics = generics.finish(types_map, &mut types_source_map); (generics, types_source_map) @@ -910,7 +912,7 @@ impl<'a> Ctx<'a> { fn lower_type_bounds( &mut self, node: &dyn ast::HasTypeBounds, - body_ctx: &LowerCtx<'_>, + body_ctx: &mut LowerCtx<'_>, ) -> Box<[TypeBound]> { match node.type_bound_list() { Some(bound_list) => { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index f6ed826f04c..eb55ba1d53d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -47,7 +47,6 @@ pub mod resolver; pub mod nameres; -pub mod child_by_source; pub mod src; pub mod find_path; @@ -354,9 +353,9 @@ impl_loc!(ProcMacroLoc, id: Function, container: CrateRootModuleId); pub struct BlockId(ra_salsa::InternId); #[derive(Debug, Hash, PartialEq, Eq, Clone)] pub struct BlockLoc { - ast_id: AstId<ast::BlockExpr>, + pub ast_id: AstId<ast::BlockExpr>, /// The containing module. - module: ModuleId, + pub module: ModuleId, } impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); @@ -838,16 +837,18 @@ impl InTypeConstId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum GeneralConstId { ConstId(ConstId), + StaticId(StaticId), ConstBlockId(ConstBlockId), InTypeConstId(InTypeConstId), } -impl_from!(ConstId, ConstBlockId, InTypeConstId for GeneralConstId); +impl_from!(ConstId, StaticId, ConstBlockId, InTypeConstId for GeneralConstId); impl GeneralConstId { pub fn generic_def(self, db: &dyn DefDatabase) -> Option<GenericDefId> { match self { GeneralConstId::ConstId(it) => Some(it.into()), + GeneralConstId::StaticId(_) => None, GeneralConstId::ConstBlockId(it) => it.lookup(db).parent.as_generic_def_id(db), GeneralConstId::InTypeConstId(it) => it.lookup(db).owner.as_generic_def_id(db), } @@ -855,6 +856,9 @@ impl GeneralConstId { pub fn name(self, db: &dyn DefDatabase) -> String { match self { + GeneralConstId::StaticId(it) => { + db.static_data(it).name.display(db.upcast(), Edition::CURRENT).to_string() + } GeneralConstId::ConstId(const_id) => db .const_data(const_id) .name @@ -935,7 +939,7 @@ impl_from!( ); impl GenericDefId { - fn file_id_and_params_of( + pub fn file_id_and_params_of( self, db: &dyn DefDatabase, ) -> (HirFileId, Option<ast::GenericParamList>) { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs index df5847929c5..6d1a3d17447 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs @@ -1,10 +1,7 @@ //! Context for lowering paths. -use std::cell::{OnceCell, RefCell}; +use std::{cell::OnceCell, mem}; -use hir_expand::{ - span_map::{SpanMap, SpanMapRef}, - AstId, HirFileId, InFile, -}; +use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile}; use span::{AstIdMap, AstIdNode}; use stdx::thin_vec::ThinVec; use syntax::ast; @@ -21,28 +18,11 @@ pub struct LowerCtx<'a> { file_id: HirFileId, span_map: OnceCell<SpanMap>, ast_id_map: OnceCell<Arc<AstIdMap>>, - impl_trait_bounds: RefCell<Vec<ThinVec<TypeBound>>>, + impl_trait_bounds: Vec<ThinVec<TypeBound>>, // Prevent nested impl traits like `impl Foo<impl Bar>`. - outer_impl_trait: RefCell<bool>, - types_map: RefCell<(&'a mut TypesMap, &'a mut TypesSourceMap)>, -} - -pub(crate) struct OuterImplTraitGuard<'a, 'b> { - ctx: &'a LowerCtx<'b>, - old: bool, -} - -impl<'a, 'b> OuterImplTraitGuard<'a, 'b> { - fn new(ctx: &'a LowerCtx<'b>, impl_trait: bool) -> Self { - let old = ctx.outer_impl_trait.replace(impl_trait); - Self { ctx, old } - } -} - -impl Drop for OuterImplTraitGuard<'_, '_> { - fn drop(&mut self) { - self.ctx.outer_impl_trait.replace(self.old); - } + outer_impl_trait: bool, + types_map: &'a mut TypesMap, + types_source_map: &'a mut TypesSourceMap, } impl<'a> LowerCtx<'a> { @@ -57,9 +37,10 @@ impl<'a> LowerCtx<'a> { file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new(), - impl_trait_bounds: RefCell::new(Vec::new()), - outer_impl_trait: RefCell::default(), - types_map: RefCell::new((types_map, types_source_map)), + impl_trait_bounds: Vec::new(), + outer_impl_trait: false, + types_map, + types_source_map, } } @@ -75,17 +56,18 @@ impl<'a> LowerCtx<'a> { file_id, span_map, ast_id_map: OnceCell::new(), - impl_trait_bounds: RefCell::new(Vec::new()), - outer_impl_trait: RefCell::default(), - types_map: RefCell::new((types_map, types_source_map)), + impl_trait_bounds: Vec::new(), + outer_impl_trait: false, + types_map, + types_source_map, } } - pub(crate) fn span_map(&self) -> SpanMapRef<'_> { - self.span_map.get_or_init(|| self.db.span_map(self.file_id)).as_ref() + pub(crate) fn span_map(&self) -> &SpanMap { + self.span_map.get_or_init(|| self.db.span_map(self.file_id)) } - pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> { + pub(crate) fn lower_path(&mut self, ast: ast::Path) -> Option<Path> { Path::from_src(self, ast) } @@ -96,44 +78,44 @@ impl<'a> LowerCtx<'a> { ) } - pub fn update_impl_traits_bounds(&self, bounds: ThinVec<TypeBound>) { - self.impl_trait_bounds.borrow_mut().push(bounds); + pub fn update_impl_traits_bounds_from_type_ref(&mut self, type_ref: TypeRefId) { + TypeRef::walk(type_ref, self.types_map, &mut |tr| { + if let TypeRef::ImplTrait(bounds) = tr { + self.impl_trait_bounds.push(bounds.clone()); + } + }); } - pub fn take_impl_traits_bounds(&self) -> Vec<ThinVec<TypeBound>> { - self.impl_trait_bounds.take() + pub fn take_impl_traits_bounds(&mut self) -> Vec<ThinVec<TypeBound>> { + mem::take(&mut self.impl_trait_bounds) } pub(crate) fn outer_impl_trait(&self) -> bool { - *self.outer_impl_trait.borrow() + self.outer_impl_trait } - pub(crate) fn outer_impl_trait_scope<'b>( - &'b self, + pub(crate) fn with_outer_impl_trait_scope<R>( + &mut self, impl_trait: bool, - ) -> OuterImplTraitGuard<'b, 'a> { - OuterImplTraitGuard::new(self, impl_trait) + f: impl FnOnce(&mut Self) -> R, + ) -> R { + let old = mem::replace(&mut self.outer_impl_trait, impl_trait); + let result = f(self); + self.outer_impl_trait = old; + result } - pub(crate) fn alloc_type_ref(&self, type_ref: TypeRef, node: TypePtr) -> TypeRefId { - let mut types_map = self.types_map.borrow_mut(); - let (types_map, types_source_map) = &mut *types_map; - let id = types_map.types.alloc(type_ref); - types_source_map.types_map_back.insert(id, InFile::new(self.file_id, node)); + pub(crate) fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId { + let id = self.types_map.types.alloc(type_ref); + self.types_source_map.types_map_back.insert(id, InFile::new(self.file_id, node)); id } - pub(crate) fn alloc_type_ref_desugared(&self, type_ref: TypeRef) -> TypeRefId { - self.types_map.borrow_mut().0.types.alloc(type_ref) - } - - pub(crate) fn alloc_error_type(&self) -> TypeRefId { - self.types_map.borrow_mut().0.types.alloc(TypeRef::Error) + pub(crate) fn alloc_type_ref_desugared(&mut self, type_ref: TypeRef) -> TypeRefId { + self.types_map.types.alloc(type_ref) } - // FIXME: If we alloc while holding this, well... Bad Things will happen. Need to change this - // to use proper mutability instead of interior mutability. - pub(crate) fn types_map(&self) -> std::cell::Ref<'_, TypesMap> { - std::cell::Ref::map(self.types_map.borrow(), |it| &*it.0) + pub(crate) fn alloc_error_type(&mut self) -> TypeRefId { + self.types_map.types.alloc(TypeRef::Error) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs index dc6947c5b56..aa2c4a6f1bc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs @@ -121,7 +121,7 @@ pub enum GenericArg { impl Path { /// Converts an `ast::Path` to `Path`. Works with use trees. /// It correctly handles `$crate` based path from macro call. - pub fn from_src(ctx: &LowerCtx<'_>, path: ast::Path) -> Option<Path> { + pub fn from_src(ctx: &mut LowerCtx<'_>, path: ast::Path) -> Option<Path> { lower::lower_path(ctx, path) } @@ -284,7 +284,7 @@ impl<'a> PathSegments<'a> { impl GenericArgs { pub(crate) fn from_ast( - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, node: ast::GenericArgList, ) -> Option<GenericArgs> { lower::lower_generic_args(lower_ctx, node) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs index c328b9c6ce2..553e615b94f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs @@ -19,12 +19,11 @@ use crate::{ /// Converts an `ast::Path` to `Path`. Works with use trees. /// It correctly handles `$crate` based path from macro call. -pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path> { +pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<Path> { let mut kind = PathKind::Plain; let mut type_anchor = None; let mut segments = Vec::new(); let mut generic_args = Vec::new(); - let span_map = ctx.span_map(); loop { let segment = path.segment()?; @@ -37,7 +36,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path if name_ref.text() == "$crate" { break kind = resolve_crate_root( ctx.db.upcast(), - span_map.span_for_range(name_ref.syntax().text_range()).ctx, + ctx.span_map().span_for_range(name_ref.syntax().text_range()).ctx, ) .map(PathKind::DollarCrate) .unwrap_or(PathKind::Crate); @@ -151,7 +150,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path // We follow what it did anyway :) if segments.len() == 1 && kind == PathKind::Plain { if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { - let syn_ctxt = span_map.span_for_range(path.segment()?.syntax().text_range()).ctx; + let syn_ctxt = ctx.span_map().span_for_range(path.segment()?.syntax().text_range()).ctx; if let Some(macro_call_id) = ctx.db.lookup_intern_syntax_context(syn_ctxt).outer_expn { if ctx.db.lookup_intern_macro_call(macro_call_id).def.local_inner { kind = match resolve_crate_root(ctx.db.upcast(), syn_ctxt) { @@ -183,7 +182,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path } pub(super) fn lower_generic_args( - lower_ctx: &LowerCtx<'_>, + lower_ctx: &mut LowerCtx<'_>, node: ast::GenericArgList, ) -> Option<GenericArgs> { let mut args = Vec::new(); @@ -192,13 +191,7 @@ pub(super) fn lower_generic_args( match generic_arg { ast::GenericArg::TypeArg(type_arg) => { let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty()); - let types_map = lower_ctx.types_map(); - TypeRef::walk(type_ref, &types_map, &mut |tr| { - if let TypeRef::ImplTrait(bounds) = tr { - lower_ctx.update_impl_traits_bounds(bounds.clone()); - } - }); - drop(types_map); + lower_ctx.update_impl_traits_bounds_from_type_ref(type_ref); args.push(GenericArg::Type(type_ref)); } ast::GenericArg::AssocTypeArg(assoc_type_arg) => { @@ -208,27 +201,22 @@ pub(super) fn lower_generic_args( } if let Some(name_ref) = assoc_type_arg.name_ref() { // Nested impl traits like `impl Foo<Assoc = impl Bar>` are allowed - let _guard = lower_ctx.outer_impl_trait_scope(false); - let name = name_ref.as_name(); - let args = assoc_type_arg - .generic_arg_list() - .and_then(|args| lower_generic_args(lower_ctx, args)); - let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); - let type_ref = type_ref.inspect(|&tr| { - let types_map = lower_ctx.types_map(); - TypeRef::walk(tr, &types_map, &mut |tr| { - if let TypeRef::ImplTrait(bounds) = tr { - lower_ctx.update_impl_traits_bounds(bounds.clone()); - } - }); - drop(types_map); + lower_ctx.with_outer_impl_trait_scope(false, |lower_ctx| { + let name = name_ref.as_name(); + let args = assoc_type_arg + .generic_arg_list() + .and_then(|args| lower_generic_args(lower_ctx, args)); + let type_ref = + assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); + let type_ref = type_ref + .inspect(|&tr| lower_ctx.update_impl_traits_bounds_from_type_ref(tr)); + let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { + l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() + } else { + Box::default() + }; + bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds }); }); - let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { - l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() - } else { - Box::default() - }; - bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds }); } } ast::GenericArg::LifetimeArg(lifetime_arg) => { @@ -258,7 +246,7 @@ pub(super) fn lower_generic_args( /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). fn lower_generic_args_from_fn_path( - ctx: &LowerCtx<'_>, + ctx: &mut LowerCtx<'_>, params: Option<ast::ParamList>, ret_type: Option<ast::RetType>, ) -> Option<GenericArgs> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 4bc78afacc0..05cd7bd37b4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -615,7 +615,7 @@ pub(crate) fn associated_ty_data_query( let type_alias_data = db.type_alias_data(type_alias); let generic_params = generics(db.upcast(), type_alias.into()); let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); - let ctx = + let mut ctx = crate::TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, type_alias.into()) .with_type_param_mode(crate::lower::ParamLoweringMode::Variable); @@ -627,14 +627,16 @@ pub(crate) fn associated_ty_data_query( .build(); let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner); - let mut bounds: Vec<_> = type_alias_data - .bounds - .iter() - .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) - .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) - .collect(); + let mut bounds = Vec::new(); + for bound in &type_alias_data.bounds { + ctx.lower_type_bound(bound, self_ty.clone(), false).for_each(|pred| { + if let Some(pred) = generic_predicate_to_inline_bound(db, &pred, &self_ty) { + bounds.push(pred); + } + }); + } - if !ctx.unsized_types.borrow().contains(&self_ty) { + if !ctx.unsized_types.contains(&self_ty) { let sized_trait = db .lang_item(resolver.krate(), LangItem::Sized) .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id)); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index 091cfcd4654..142766c039b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -8,7 +8,7 @@ use hir_def::{ path::Path, resolver::{Resolver, ValueNs}, type_ref::LiteralConstRef, - ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId, + ConstBlockLoc, EnumVariantId, GeneralConstId, HasModule as _, StaticId, }; use hir_expand::Lookup; use stdx::never; @@ -56,6 +56,21 @@ pub enum ConstEvalError { MirEvalError(MirEvalError), } +impl ConstEvalError { + pub fn pretty_print( + &self, + f: &mut String, + db: &dyn HirDatabase, + span_formatter: impl Fn(span::FileId, span::TextRange) -> String, + edition: span::Edition, + ) -> std::result::Result<(), std::fmt::Error> { + match self { + ConstEvalError::MirLowerError(e) => e.pretty_print(f, db, span_formatter, edition), + ConstEvalError::MirEvalError(e) => e.pretty_print(f, db, span_formatter, edition), + } + } +} + impl From<MirLowerError> for ConstEvalError { fn from(value: MirLowerError) -> Self { match value { @@ -236,6 +251,10 @@ pub(crate) fn const_eval_query( GeneralConstId::ConstId(c) => { db.monomorphized_mir_body(c.into(), subst, db.trait_environment(c.into()))? } + GeneralConstId::StaticId(s) => { + let krate = s.module(db.upcast()).krate(); + db.monomorphized_mir_body(s.into(), subst, TraitEnvironment::empty(krate))? + } GeneralConstId::ConstBlockId(c) => { let ConstBlockLoc { parent, root } = db.lookup_intern_anonymous_const(c); let body = db.body(parent); @@ -249,7 +268,7 @@ pub(crate) fn const_eval_query( } GeneralConstId::InTypeConstId(c) => db.mir_body(c.into())?, }; - let c = interpret_mir(db, body, false, trait_env).0?; + let c = interpret_mir(db, body, false, trait_env)?.0?; Ok(c) } @@ -262,7 +281,7 @@ pub(crate) fn const_eval_static_query( Substitution::empty(Interner), db.trait_environment_for_body(def.into()), )?; - let c = interpret_mir(db, body, false, None).0?; + let c = interpret_mir(db, body, false, None)?.0?; Ok(c) } @@ -294,7 +313,7 @@ pub(crate) fn const_eval_discriminant_variant( Substitution::empty(Interner), db.trait_environment_for_body(def), )?; - let c = interpret_mir(db, mir_body, false, None).0?; + let c = interpret_mir(db, mir_body, false, None)?.0?; let c = if is_signed { try_const_isize(db, &c).unwrap() } else { @@ -335,7 +354,7 @@ pub(crate) fn eval_to_const( } } if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr) { - if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 { + if let Ok((Ok(result), _)) = interpret_mir(db, Arc::new(mir_body), true, None) { return result; } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 277dabe9aa3..4e95bdf219f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -2033,7 +2033,7 @@ impl HirDisplayWithTypesMap for TypeRefId { TypeRef::Macro(macro_call) => { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = hir_def::lower::LowerCtx::new( + let mut ctx = hir_def::lower::LowerCtx::new( f.db.upcast(), macro_call.file_id, &mut types_map, @@ -2041,7 +2041,7 @@ impl HirDisplayWithTypesMap for TypeRefId { ); let macro_call = macro_call.to_node(f.db.upcast()); match macro_call.path() { - Some(path) => match Path::from_src(&ctx, path) { + Some(path) => match Path::from_src(&mut ctx, path) { Some(path) => path.hir_fmt(f, &types_map)?, None => write!(f, "{{macro}}")?, }, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 3685ed56964..01e0b635b22 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1420,7 +1420,7 @@ impl<'a> InferenceContext<'a> { Some(path) => path, None => return (self.err_ty(), None), }; - let ctx = crate::lower::TyLoweringContext::new( + let mut ctx = crate::lower::TyLoweringContext::new( self.db, &self.resolver, &self.body.types, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 442daa9f9ee..7550d197a3b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -151,7 +151,7 @@ impl InferenceContext<'_> { let last = path.segments().last()?; // Don't use `self.make_ty()` here as we need `orig_ns`. - let ctx = crate::lower::TyLoweringContext::new( + let mut ctx = crate::lower::TyLoweringContext::new( self.db, &self.resolver, &self.body.types, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index c5fa20bc8ac..0c1f63880cd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -6,8 +6,9 @@ use base_db::ra_salsa::Cycle; use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy}; use hir_def::{ layout::{ - BackendRepr, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData, - Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout, WrappingRange, + BackendRepr, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError, + LayoutData, Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout, + WrappingRange, }, LocalFieldId, StructId, }; @@ -294,11 +295,12 @@ pub fn layout_of_ty_query( .checked_mul(count, dl) .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?; - let backend_repr = if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let backend_repr = + if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) { + BackendRepr::Uninhabited + } else { + BackendRepr::Memory { sized: true } + }; let largest_niche = if count != 0 { element.largest_niche } else { None }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index e3a92e52f61..b868ea95f85 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -6,8 +6,8 @@ //! //! This usually involves resolving names, collecting generic arguments etc. use std::{ - cell::{Cell, OnceCell, RefCell, RefMut}, - iter, + cell::OnceCell, + iter, mem, ops::{self, Not as _}, }; @@ -72,47 +72,32 @@ use crate::{ TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, }; -#[derive(Debug)] -enum ImplTraitLoweringState { +#[derive(Debug, Default)] +struct ImplTraitLoweringState { /// When turning `impl Trait` into opaque types, we have to collect the /// bounds at the same time to get the IDs correct (without becoming too - /// complicated). I don't like using interior mutability (as for the - /// counter), but I've tried and failed to make the lifetimes work for - /// passing around a `&mut TyLoweringContext`. The core problem is that - /// we're grouping the mutable data (the counter and this field) together - /// with the immutable context (the references to the DB and resolver). - /// Splitting this up would be a possible fix. - Opaque(RefCell<Arena<ImplTrait>>), - Param(Cell<u16>), - Variable(Cell<u16>), - Disallowed, + /// complicated). + mode: ImplTraitLoweringMode, + // This is structured as a struct with fields and not as an enum because it helps with the borrow checker. + opaque_type_data: Arena<ImplTrait>, + param_and_variable_counter: u16, } impl ImplTraitLoweringState { - fn new(impl_trait_mode: ImplTraitLoweringMode) -> ImplTraitLoweringState { - match impl_trait_mode { - ImplTraitLoweringMode::Opaque => Self::Opaque(RefCell::new(Arena::new())), - ImplTraitLoweringMode::Param => Self::Param(Cell::new(0)), - ImplTraitLoweringMode::Variable => Self::Variable(Cell::new(0)), - ImplTraitLoweringMode::Disallowed => Self::Disallowed, - } + fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState { + Self { mode, opaque_type_data: Arena::new(), param_and_variable_counter: 0 } } - - fn take(&self) -> Self { - match self { - Self::Opaque(x) => Self::Opaque(RefCell::new(x.take())), - Self::Param(x) => Self::Param(Cell::new(x.get())), - Self::Variable(x) => Self::Variable(Cell::new(x.get())), - Self::Disallowed => Self::Disallowed, + fn param(counter: u16) -> Self { + Self { + mode: ImplTraitLoweringMode::Param, + opaque_type_data: Arena::new(), + param_and_variable_counter: counter, } } - - fn swap(&self, impl_trait_mode: &Self) { - match (self, impl_trait_mode) { - (Self::Opaque(x), Self::Opaque(y)) => x.swap(y), - (Self::Param(x), Self::Param(y)) => x.swap(y), - (Self::Variable(x), Self::Variable(y)) => x.swap(y), - (Self::Disallowed, Self::Disallowed) => (), - _ => panic!("mismatched lowering mode"), + fn variable(counter: u16) -> Self { + Self { + mode: ImplTraitLoweringMode::Variable, + opaque_type_data: Arena::new(), + param_and_variable_counter: counter, } } } @@ -137,9 +122,9 @@ pub struct TyLoweringContext<'a> { /// possible currently, so this should be fine for now. pub type_param_mode: ParamLoweringMode, impl_trait_mode: ImplTraitLoweringState, - expander: RefCell<Option<Expander>>, + expander: Option<Expander>, /// Tracks types with explicit `?Sized` bounds. - pub(crate) unsized_types: RefCell<FxHashSet<Ty>>, + pub(crate) unsized_types: FxHashSet<Ty>, } impl<'a> TyLoweringContext<'a> { @@ -159,7 +144,7 @@ impl<'a> TyLoweringContext<'a> { types_source_map: Option<&'a TypesSourceMap>, owner: Option<TypeOwnerId>, ) -> Self { - let impl_trait_mode = ImplTraitLoweringState::Disallowed; + let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed); let type_param_mode = ParamLoweringMode::Placeholder; let in_binders = DebruijnIndex::INNERMOST; Self { @@ -172,38 +157,26 @@ impl<'a> TyLoweringContext<'a> { in_binders, impl_trait_mode, type_param_mode, - expander: RefCell::new(None), - unsized_types: RefCell::default(), + expander: None, + unsized_types: FxHashSet::default(), } } pub fn with_debruijn<T>( - &self, + &mut self, debruijn: DebruijnIndex, - f: impl FnOnce(&TyLoweringContext<'_>) -> T, + f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, ) -> T { - let impl_trait_mode = self.impl_trait_mode.take(); - let expander = self.expander.take(); - let unsized_types = self.unsized_types.take(); - let new_ctx = Self { - in_binders: debruijn, - impl_trait_mode, - expander: RefCell::new(expander), - unsized_types: RefCell::new(unsized_types), - generics: self.generics.clone(), - ..*self - }; - let result = f(&new_ctx); - self.impl_trait_mode.swap(&new_ctx.impl_trait_mode); - self.expander.replace(new_ctx.expander.into_inner()); - self.unsized_types.replace(new_ctx.unsized_types.into_inner()); + let old_debruijn = mem::replace(&mut self.in_binders, debruijn); + let result = f(self); + self.in_binders = old_debruijn; result } pub fn with_shifted_in<T>( - &self, + &mut self, debruijn: DebruijnIndex, - f: impl FnOnce(&TyLoweringContext<'_>) -> T, + f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, ) -> T { self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f) } @@ -227,7 +200,7 @@ impl<'a> TyLoweringContext<'a> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] pub enum ImplTraitLoweringMode { /// `impl Trait` gets lowered into an opaque type that doesn't unify with /// anything except itself. This is used in places where values flow 'out', @@ -244,6 +217,7 @@ pub enum ImplTraitLoweringMode { /// currently checking. Variable, /// `impl Trait` is disallowed and will be an error. + #[default] Disallowed, } @@ -254,12 +228,13 @@ pub enum ParamLoweringMode { } impl<'a> TyLoweringContext<'a> { - pub fn lower_ty(&self, type_ref: TypeRefId) -> Ty { + pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty { self.lower_ty_ext(type_ref).0 } - pub fn lower_const(&self, const_ref: &ConstRef, const_type: Ty) -> Const { + pub fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const { let Some(owner) = self.owner else { return unknown_const(const_type) }; + let debruijn = self.in_binders; const_or_path_to_chalk( self.db, self.resolver, @@ -268,7 +243,7 @@ impl<'a> TyLoweringContext<'a> { const_ref, self.type_param_mode, || self.generics(), - self.in_binders, + debruijn, ) } @@ -278,7 +253,7 @@ impl<'a> TyLoweringContext<'a> { .as_ref() } - pub fn lower_ty_ext(&self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) { + pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) { let mut res = None; let type_ref = &self.types_map[type_ref_id]; let ty = match type_ref { @@ -337,8 +312,8 @@ impl<'a> TyLoweringContext<'a> { } TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds), TypeRef::ImplTrait(bounds) => { - match &self.impl_trait_mode { - ImplTraitLoweringState::Opaque(opaque_type_data) => { + match self.impl_trait_mode.mode { + ImplTraitLoweringMode::Opaque => { let origin = match self.resolver.generic_def() { Some(GenericDefId::FunctionId(it)) => Either::Left(it), Some(GenericDefId::TypeAliasId(it)) => Either::Right(it), @@ -350,7 +325,7 @@ impl<'a> TyLoweringContext<'a> { // this dance is to make sure the data is in the right // place even if we encounter more opaque types while // lowering the bounds - let idx = opaque_type_data.borrow_mut().alloc(ImplTrait { + let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait { bounds: crate::make_single_type_binders(Vec::default()), }); // We don't want to lower the bounds inside the binders @@ -366,7 +341,7 @@ impl<'a> TyLoweringContext<'a> { .with_debruijn(DebruijnIndex::INNERMOST, |ctx| { ctx.lower_impl_trait(bounds, self.resolver.krate()) }); - opaque_type_data.borrow_mut()[idx] = actual_opaque_type_data; + self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data; let impl_trait_id = origin.either( |f| ImplTraitId::ReturnTypeImplTrait(f, idx), @@ -378,11 +353,13 @@ impl<'a> TyLoweringContext<'a> { let parameters = generics.bound_vars_subst(self.db, self.in_binders); TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner) } - ImplTraitLoweringState::Param(counter) => { - let idx = counter.get(); + ImplTraitLoweringMode::Param => { + let idx = self.impl_trait_mode.param_and_variable_counter; // Count the number of `impl Trait` things that appear within our bounds. // Since those have been emitted as implicit type args already. - counter.set(idx + self.count_impl_traits(type_ref_id) as u16); + self.impl_trait_mode.param_and_variable_counter = + idx + self.count_impl_traits(type_ref_id) as u16; + let db = self.db; let kind = self .generics() .expect("param impl trait lowering must be in a generic def") @@ -398,15 +375,17 @@ impl<'a> TyLoweringContext<'a> { }) .nth(idx as usize) .map_or(TyKind::Error, |id| { - TyKind::Placeholder(to_placeholder_idx(self.db, id.into())) + TyKind::Placeholder(to_placeholder_idx(db, id.into())) }); kind.intern(Interner) } - ImplTraitLoweringState::Variable(counter) => { - let idx = counter.get(); + ImplTraitLoweringMode::Variable => { + let idx = self.impl_trait_mode.param_and_variable_counter; // Count the number of `impl Trait` things that appear within our bounds. // Since t hose have been emitted as implicit type args already. - counter.set(idx + self.count_impl_traits(type_ref_id) as u16); + self.impl_trait_mode.param_and_variable_counter = + idx + self.count_impl_traits(type_ref_id) as u16; + let debruijn = self.in_binders; let kind = self .generics() .expect("variable impl trait lowering must be in a generic def") @@ -423,33 +402,31 @@ impl<'a> TyLoweringContext<'a> { }) .nth(idx as usize) .map_or(TyKind::Error, |id| { - TyKind::BoundVar(BoundVar { debruijn: self.in_binders, index: id }) + TyKind::BoundVar(BoundVar { debruijn, index: id }) }); kind.intern(Interner) } - ImplTraitLoweringState::Disallowed => { + ImplTraitLoweringMode::Disallowed => { // FIXME: report error TyKind::Error.intern(Interner) } } } TypeRef::Macro(macro_call) => { - let (mut expander, recursion_start) = { - match RefMut::filter_map(self.expander.borrow_mut(), Option::as_mut) { + let (expander, recursion_start) = { + match &mut self.expander { // There already is an expander here, this means we are already recursing - Ok(expander) => (expander, false), + Some(expander) => (expander, false), // No expander was created yet, so we are at the start of the expansion recursion // and therefore have to create an expander. - Err(expander) => ( - RefMut::map(expander, |it| { - it.insert(Expander::new( - self.db.upcast(), - macro_call.file_id, - self.resolver.module(), - )) - }), - true, - ), + None => { + let expander = self.expander.insert(Expander::new( + self.db.upcast(), + macro_call.file_id, + self.resolver.module(), + )); + (expander, true) + } } }; let ty = { @@ -465,19 +442,16 @@ impl<'a> TyLoweringContext<'a> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = expander.ctx( + let mut ctx = expander.ctx( self.db.upcast(), &mut types_map, &mut types_source_map, ); // FIXME: Report syntax errors in expansion here - let type_ref = TypeRef::from_ast(&ctx, expanded.tree()); + let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree()); - drop(expander); - - // FIXME: That may be better served by mutating `self` then restoring, but this requires - // making it `&mut self`. - let inner_ctx = TyLoweringContext { + // Can't mutate `self`, must create a new instance, because of the lifetimes. + let mut inner_ctx = TyLoweringContext { db: self.db, resolver: self.resolver, generics: self.generics.clone(), @@ -486,30 +460,27 @@ impl<'a> TyLoweringContext<'a> { in_binders: self.in_binders, owner: self.owner, type_param_mode: self.type_param_mode, - impl_trait_mode: self.impl_trait_mode.take(), - expander: RefCell::new(self.expander.take()), - unsized_types: RefCell::new(self.unsized_types.take()), + impl_trait_mode: mem::take(&mut self.impl_trait_mode), + expander: self.expander.take(), + unsized_types: mem::take(&mut self.unsized_types), }; let ty = inner_ctx.lower_ty(type_ref); - self.impl_trait_mode.swap(&inner_ctx.impl_trait_mode); - *self.expander.borrow_mut() = inner_ctx.expander.into_inner(); - *self.unsized_types.borrow_mut() = inner_ctx.unsized_types.into_inner(); + self.impl_trait_mode = inner_ctx.impl_trait_mode; + self.expander = inner_ctx.expander; + self.unsized_types = inner_ctx.unsized_types; - self.expander.borrow_mut().as_mut().unwrap().exit(mark); + self.expander.as_mut().unwrap().exit(mark); Some(ty) } - _ => { - drop(expander); - None - } + _ => None, } }; // drop the expander, resetting it to pre-recursion state if recursion_start { - *self.expander.borrow_mut() = None; + self.expander = None; } ty.unwrap_or_else(|| TyKind::Error.intern(Interner)) } @@ -544,7 +515,7 @@ impl<'a> TyLoweringContext<'a> { } pub(crate) fn lower_ty_relative_path( - &self, + &mut self, ty: Ty, // We need the original resolution to lower `Self::AssocTy` correctly res: Option<TypeNs>, @@ -565,7 +536,7 @@ impl<'a> TyLoweringContext<'a> { } pub(crate) fn lower_partly_resolved_path( - &self, + &mut self, resolution: TypeNs, resolved_segment: PathSegment<'_>, remaining_segments: PathSegments<'_>, @@ -706,7 +677,7 @@ impl<'a> TyLoweringContext<'a> { self.lower_ty_relative_path(ty, Some(resolution), remaining_segments) } - pub(crate) fn lower_path(&self, path: &Path) -> (Ty, Option<TypeNs>) { + pub(crate) fn lower_path(&mut self, path: &Path) -> (Ty, Option<TypeNs>) { // Resolve the path (in type namespace) if let Some(type_ref) = path.type_anchor() { let (ty, res) = self.lower_ty_ext(type_ref); @@ -736,7 +707,7 @@ impl<'a> TyLoweringContext<'a> { self.lower_partly_resolved_path(resolution, resolved_segment, remaining_segments, false) } - fn select_associated_type(&self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty { + fn select_associated_type(&mut self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty { let Some((generics, res)) = self.generics().zip(res) else { return TyKind::Error.intern(Interner); }; @@ -746,6 +717,8 @@ impl<'a> TyLoweringContext<'a> { res, Some(segment.name.clone()), move |name, t, associated_ty| { + let generics = self.generics().unwrap(); + if name != segment.name { return None; } @@ -797,7 +770,7 @@ impl<'a> TyLoweringContext<'a> { } fn lower_path_inner( - &self, + &mut self, segment: PathSegment<'_>, typeable: TyDefId, infer_args: bool, @@ -814,7 +787,7 @@ impl<'a> TyLoweringContext<'a> { /// Collect generic arguments from a path into a `Substs`. See also /// `create_substs_for_ast_path` and `def_to_ty` in rustc. pub(super) fn substs_from_path( - &self, + &mut self, path: &Path, // Note that we don't call `db.value_type(resolved)` here, // `ValueTyDefId` is just a convenient way to pass generics and @@ -855,7 +828,7 @@ impl<'a> TyLoweringContext<'a> { } pub(super) fn substs_from_path_segment( - &self, + &mut self, segment: PathSegment<'_>, def: Option<GenericDefId>, infer_args: bool, @@ -870,7 +843,7 @@ impl<'a> TyLoweringContext<'a> { } fn substs_from_args_and_bindings( - &self, + &mut self, args_and_bindings: Option<&GenericArgs>, def: Option<GenericDefId>, infer_args: bool, @@ -959,11 +932,11 @@ impl<'a> TyLoweringContext<'a> { self.db, id, arg, - &mut (), + self, self.types_map, - |_, type_ref| self.lower_ty(type_ref), - |_, const_ref, ty| self.lower_const(const_ref, ty), - |_, lifetime_ref| self.lower_lifetime(lifetime_ref), + |this, type_ref| this.lower_ty(type_ref), + |this, const_ref, ty| this.lower_const(const_ref, ty), + |this, lifetime_ref| this.lower_lifetime(lifetime_ref), ); substs.push(arg); } @@ -1016,7 +989,7 @@ impl<'a> TyLoweringContext<'a> { } pub(crate) fn lower_trait_ref_from_resolved_path( - &self, + &mut self, resolved: TraitId, segment: PathSegment<'_>, explicit_self_ty: Ty, @@ -1025,7 +998,7 @@ impl<'a> TyLoweringContext<'a> { TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } } - fn lower_trait_ref_from_path(&self, path: &Path, explicit_self_ty: Ty) -> Option<TraitRef> { + fn lower_trait_ref_from_path(&mut self, path: &Path, explicit_self_ty: Ty) -> Option<TraitRef> { let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? { // FIXME(trait_alias): We need to handle trait alias here. TypeNs::TraitId(tr) => tr, @@ -1035,12 +1008,16 @@ impl<'a> TyLoweringContext<'a> { Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty)) } - fn lower_trait_ref(&self, trait_ref: &HirTraitRef, explicit_self_ty: Ty) -> Option<TraitRef> { + fn lower_trait_ref( + &mut self, + trait_ref: &HirTraitRef, + explicit_self_ty: Ty, + ) -> Option<TraitRef> { self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty) } fn trait_ref_substs_from_path( - &self, + &mut self, segment: PathSegment<'_>, resolved: TraitId, explicit_self_ty: Ty, @@ -1049,11 +1026,11 @@ impl<'a> TyLoweringContext<'a> { } pub(crate) fn lower_where_predicate<'b>( - &'b self, + &'b mut self, where_predicate: &'b WherePredicate, &def: &GenericDefId, ignore_bindings: bool, - ) -> impl Iterator<Item = QuantifiedWhereClause> + 'b { + ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> { match where_predicate { WherePredicate::ForLifetime { target, bound, .. } | WherePredicate::TypeBound { target, bound } => { @@ -1087,12 +1064,12 @@ impl<'a> TyLoweringContext<'a> { .into_iter() } - pub(crate) fn lower_type_bound( - &'a self, - bound: &'a TypeBound, + pub(crate) fn lower_type_bound<'b>( + &'b mut self, + bound: &'b TypeBound, self_ty: Ty, ignore_bindings: bool, - ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { + ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> { let mut trait_ref = None; let clause = match bound { TypeBound::Path(path, TraitBoundModifier::None) => { @@ -1111,7 +1088,7 @@ impl<'a> TyLoweringContext<'a> { .lower_trait_ref_from_path(path, self_ty.clone()) .map(|trait_ref| trait_ref.hir_trait_id()); if trait_id == sized_trait { - self.unsized_types.borrow_mut().insert(self_ty); + self.unsized_types.insert(self_ty); } None } @@ -1131,17 +1108,18 @@ impl<'a> TyLoweringContext<'a> { }; clause.into_iter().chain( trait_ref - .into_iter() .filter(move |_| !ignore_bindings) - .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), + .map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)) + .into_iter() + .flatten(), ) } - fn assoc_type_bindings_from_type_bound( - &'a self, - bound: &'a TypeBound, + fn assoc_type_bindings_from_type_bound<'b>( + &'b mut self, + bound: &'b TypeBound, trait_ref: TraitRef, - ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { + ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> { let last_segment = match bound { TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => { path.segments().last() @@ -1192,22 +1170,16 @@ impl<'a> TyLoweringContext<'a> { binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), ); if let Some(type_ref) = binding.type_ref { - match (&self.types_map[type_ref], &self.impl_trait_mode) { - (TypeRef::ImplTrait(_), ImplTraitLoweringState::Disallowed) => (), - ( - _, - ImplTraitLoweringState::Disallowed | ImplTraitLoweringState::Opaque(_), - ) => { + match (&self.types_map[type_ref], self.impl_trait_mode.mode) { + (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (), + (_, ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque) => { let ty = self.lower_ty(type_ref); let alias_eq = AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; predicates .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); } - ( - _, - ImplTraitLoweringState::Param(_) | ImplTraitLoweringState::Variable(_), - ) => { + (_, ImplTraitLoweringMode::Param | ImplTraitLoweringMode::Variable) => { // Find the generic index for the target of our `bound` let target_param_idx = self .resolver @@ -1244,14 +1216,14 @@ impl<'a> TyLoweringContext<'a> { self.owner, ) .with_type_param_mode(self.type_param_mode); - match &self.impl_trait_mode { - ImplTraitLoweringState::Param(_) => { + match self.impl_trait_mode.mode { + ImplTraitLoweringMode::Param => { ext.impl_trait_mode = - ImplTraitLoweringState::Param(Cell::new(counter)); + ImplTraitLoweringState::param(counter); } - ImplTraitLoweringState::Variable(_) => { + ImplTraitLoweringMode::Variable => { ext.impl_trait_mode = - ImplTraitLoweringState::Variable(Cell::new(counter)); + ImplTraitLoweringState::variable(counter); } _ => unreachable!(), } @@ -1278,7 +1250,7 @@ impl<'a> TyLoweringContext<'a> { }) } - fn lower_dyn_trait(&self, bounds: &[TypeBound]) -> Ty { + fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty { let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); // INVARIANT: The principal trait bound, if present, must come first. Others may be in any // order but should be in the same order for the same set but possibly different order of @@ -1287,22 +1259,26 @@ impl<'a> TyLoweringContext<'a> { // These invariants are utilized by `TyExt::dyn_trait()` and chalk. let mut lifetime = None; let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { - let mut bounds: Vec<_> = bounds - .iter() - .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)) - .filter(|b| match b.skip_binders() { - WhereClause::Implemented(_) | WhereClause::AliasEq(_) => true, - WhereClause::LifetimeOutlives(_) => false, - WhereClause::TypeOutlives(t) => { - lifetime = Some(t.lifetime.clone()); - false + let mut lowered_bounds = Vec::new(); + for b in bounds { + ctx.lower_type_bound(b, self_ty.clone(), false).for_each(|b| { + let filter = match b.skip_binders() { + WhereClause::Implemented(_) | WhereClause::AliasEq(_) => true, + WhereClause::LifetimeOutlives(_) => false, + WhereClause::TypeOutlives(t) => { + lifetime = Some(t.lifetime.clone()); + false + } + }; + if filter { + lowered_bounds.push(b); } - }) - .collect(); + }); + } let mut multiple_regular_traits = false; let mut multiple_same_projection = false; - bounds.sort_unstable_by(|lhs, rhs| { + lowered_bounds.sort_unstable_by(|lhs, rhs| { use std::cmp::Ordering; match (lhs.skip_binders(), rhs.skip_binders()) { (WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => { @@ -1344,13 +1320,13 @@ impl<'a> TyLoweringContext<'a> { return None; } - bounds.first().and_then(|b| b.trait_id())?; + lowered_bounds.first().and_then(|b| b.trait_id())?; // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the // bounds. We shouldn't have repeated elements besides auto traits at this point. - bounds.dedup(); + lowered_bounds.dedup(); - Some(QuantifiedWhereClauses::from_iter(Interner, bounds)) + Some(QuantifiedWhereClauses::from_iter(Interner, lowered_bounds)) }); if let Some(bounds) = bounds { @@ -1376,16 +1352,16 @@ impl<'a> TyLoweringContext<'a> { } } - fn lower_impl_trait(&self, bounds: &[TypeBound], krate: CrateId) -> ImplTrait { + fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: CrateId) -> ImplTrait { cov_mark::hit!(lower_rpit); let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { - let mut predicates: Vec<_> = bounds - .iter() - .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)) - .collect(); + let mut predicates = Vec::new(); + for b in bounds { + predicates.extend(ctx.lower_type_bound(b, self_ty.clone(), false)); + } - if !ctx.unsized_types.borrow().contains(&self_ty) { + if !ctx.unsized_types.contains(&self_ty) { let sized_trait = ctx .db .lang_item(krate, LangItem::Sized) @@ -1562,7 +1538,7 @@ pub(crate) fn field_types_query( }; let generics = generics(db.upcast(), def); let mut res = ArenaMap::default(); - let ctx = TyLoweringContext::new(db, &resolver, var_data.types_map(), def.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, var_data.types_map(), def.into()) .with_type_param_mode(ParamLoweringMode::Variable); for (field_id, field_data) in var_data.fields().iter() { res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref))); @@ -1596,7 +1572,7 @@ pub(crate) fn generic_predicates_for_param_query( let generics = generics(db.upcast(), def); // we have to filter out all other predicates *first*, before attempting to lower them - let predicate = |pred: &_, def: &_, ctx: &TyLoweringContext<'_>| match pred { + let predicate = |pred: &_, def: &_, ctx: &mut TyLoweringContext<'_>| match pred { WherePredicate::ForLifetime { target, bound, .. } | WherePredicate::TypeBound { target, bound, .. } => { let invalid_target = match target { @@ -1642,16 +1618,19 @@ pub(crate) fn generic_predicates_for_param_query( let mut predicates = Vec::new(); for (params, def) in resolver.all_generic_params() { ctx.types_map = ¶ms.types_map; - predicates.extend( - params.where_predicates().filter(|pred| predicate(pred, def, &ctx)).flat_map(|pred| { - ctx.lower_where_predicate(pred, def, true).map(|p| make_binders(db, &generics, p)) - }), - ); + for pred in params.where_predicates() { + if predicate(pred, def, &mut ctx) { + predicates.extend( + ctx.lower_where_predicate(pred, def, true) + .map(|p| make_binders(db, &generics, p)), + ); + } + } } let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); if !subst.is_empty(Interner) { - let explicitly_unsized_tys = ctx.unsized_types.into_inner(); + let explicitly_unsized_tys = ctx.unsized_types; if let Some(implicitly_sized_predicates) = implicitly_sized_clauses( db, param_id.parent, @@ -1731,7 +1710,7 @@ pub(crate) fn trait_environment_query( let subst = generics(db.upcast(), def).placeholder_subst(db); if !subst.is_empty(Interner) { - let explicitly_unsized_tys = ctx.unsized_types.into_inner(); + let explicitly_unsized_tys = ctx.unsized_types; if let Some(implicitly_sized_clauses) = implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver) { @@ -1801,16 +1780,19 @@ where let mut predicates = Vec::new(); for (params, def) in resolver.all_generic_params() { ctx.types_map = ¶ms.types_map; - predicates.extend(params.where_predicates().filter(|pred| filter(pred, def)).flat_map( - |pred| { - ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p)) - }, - )); + for pred in params.where_predicates() { + if filter(pred, def) { + predicates.extend( + ctx.lower_where_predicate(pred, def, false) + .map(|p| make_binders(db, &generics, p)), + ); + } + } } if generics.len() > 0 { let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); - let explicitly_unsized_tys = ctx.unsized_types.into_inner(); + let explicitly_unsized_tys = ctx.unsized_types; if let Some(implicitly_sized_predicates) = implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver) { @@ -1906,7 +1888,8 @@ pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> let mut val = p.default.as_ref().map_or_else( || unknown_const_as_generic(db.const_param_ty(id)), |c| { - let c = ctx.lower_const(c, ctx.lower_ty(p.ty)); + let param_ty = ctx.lower_ty(p.ty); + let c = ctx.lower_const(c, param_ty); c.cast(Interner) }, ); @@ -1946,11 +1929,11 @@ pub(crate) fn generic_defaults_recover( fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { let data = db.function_data(def); let resolver = def.resolver(db.upcast()); - let ctx_params = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) + let mut ctx_params = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Variable) .with_type_param_mode(ParamLoweringMode::Variable); let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr)); - let ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) + let mut ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); let ret = ctx_ret.lower_ty(data.ret_type); @@ -1982,7 +1965,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> { let data = db.const_data(def); let generics = generics(db.upcast(), def.into()); let resolver = def.resolver(db.upcast()); - let ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) .with_type_param_mode(ParamLoweringMode::Variable); make_binders(db, &generics, ctx.lower_ty(data.type_ref)) @@ -1992,7 +1975,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> { fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders<Ty> { let data = db.static_data(def); let resolver = def.resolver(db.upcast()); - let ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()); + let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()); Binders::empty(Interner, ctx.lower_ty(data.type_ref)) } @@ -2001,7 +1984,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS let struct_data = db.struct_data(def); let fields = struct_data.variant_data.fields(); let resolver = def.resolver(db.upcast()); - let ctx = TyLoweringContext::new( + let mut ctx = TyLoweringContext::new( db, &resolver, struct_data.variant_data.types_map(), @@ -2038,7 +2021,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) let var_data = db.enum_variant_data(def); let fields = var_data.variant_data.fields(); let resolver = def.resolver(db.upcast()); - let ctx = TyLoweringContext::new( + let mut ctx = TyLoweringContext::new( db, &resolver, var_data.variant_data.types_map(), @@ -2087,7 +2070,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { let generics = generics(db.upcast(), t.into()); let resolver = t.resolver(db.upcast()); let type_alias_data = db.type_alias_data(t); - let ctx = TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, t.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, t.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); let inner = if type_alias_data.is_extern { @@ -2169,7 +2152,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db.upcast()); let generics = generics(db.upcast(), impl_id.into()); - let ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into()) .with_type_param_mode(ParamLoweringMode::Variable); make_binders(db, &generics, ctx.lower_ty(impl_data.self_ty)) } @@ -2179,7 +2162,8 @@ pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> T let parent_data = db.generic_params(def.parent()); let data = &parent_data[def.local_id()]; let resolver = def.parent().resolver(db.upcast()); - let ctx = TyLoweringContext::new(db, &resolver, &parent_data.types_map, def.parent().into()); + let mut ctx = + TyLoweringContext::new(db, &resolver, &parent_data.types_map, def.parent().into()); match data { TypeOrConstParamData::TypeParamData(_) => { never!(); @@ -2201,7 +2185,7 @@ pub(crate) fn impl_self_ty_recover( pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db.upcast()); - let ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into()) .with_type_param_mode(ParamLoweringMode::Variable); let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders(); let target_trait = impl_data.target_trait.as_ref()?; @@ -2215,17 +2199,13 @@ pub(crate) fn return_type_impl_traits( // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe let data = db.function_data(def); let resolver = def.resolver(db.upcast()); - let ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) + let mut ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); let _ret = ctx_ret.lower_ty(data.ret_type); let generics = generics(db.upcast(), def.into()); - let return_type_impl_traits = ImplTraits { - impl_traits: match ctx_ret.impl_trait_mode { - ImplTraitLoweringState::Opaque(x) => x.into_inner(), - _ => unreachable!(), - }, - }; + let return_type_impl_traits = + ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data }; if return_type_impl_traits.impl_traits.is_empty() { None } else { @@ -2239,18 +2219,13 @@ pub(crate) fn type_alias_impl_traits( ) -> Option<Arc<Binders<ImplTraits>>> { let data = db.type_alias_data(def); let resolver = def.resolver(db.upcast()); - let ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); if let Some(type_ref) = data.type_ref { let _ty = ctx.lower_ty(type_ref); } - let type_alias_impl_traits = ImplTraits { - impl_traits: match ctx.impl_trait_mode { - ImplTraitLoweringState::Opaque(x) => x.into_inner(), - _ => unreachable!(), - }, - }; + let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data }; if type_alias_impl_traits.impl_traits.is_empty() { None } else { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index e73b9dc27d1..d7029651fc1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -12,8 +12,8 @@ use hir_def::{ lang_item::LangItem, layout::{TagEncoding, Variants}, resolver::{HasResolver, TypeNs, ValueNs}, - AdtId, ConstId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, - StaticId, VariantId, + AdtId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, StaticId, + VariantId, }; use hir_expand::{mod_path::path, name::Name, HirFileIdExt, InFile}; use intern::sym; @@ -40,8 +40,8 @@ use crate::{ static_lifetime, traits::FnTrait, utils::{detect_variant_from_bytes, ClosureSubst}, - CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstScalar, FnDefId, Interner, MemoryMap, - Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, + CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, FnDefId, Interner, + MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, }; use super::{ @@ -585,13 +585,9 @@ pub fn interpret_mir( // (and probably should) do better here, for example by excluding bindings outside of the target expression. assert_placeholder_ty_is_unused: bool, trait_env: Option<Arc<TraitEnvironment>>, -) -> (Result<Const>, MirOutput) { +) -> Result<(Result<Const>, MirOutput)> { let ty = body.locals[return_slot()].ty.clone(); - let mut evaluator = - match Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env) { - Ok(it) => it, - Err(e) => return (Err(e), MirOutput { stdout: vec![], stderr: vec![] }), - }; + let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?; let it: Result<Const> = (|| { if evaluator.ptr_size() != std::mem::size_of::<usize>() { not_supported!("targets with different pointer size from host"); @@ -613,7 +609,7 @@ pub fn interpret_mir( }; Ok(intern_const_scalar(ConstScalar::Bytes(bytes, memory_map), ty)) })(); - (it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr }) + Ok((it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr })) } #[cfg(test)] @@ -1899,8 +1895,8 @@ impl Evaluator<'_> { #[allow(clippy::double_parens)] fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<Interval> { - let ty = &konst.data(Interner).ty; - let chalk_ir::ConstValue::Concrete(c) = &konst.data(Interner).value else { + let ConstData { ty, value: chalk_ir::ConstValue::Concrete(c) } = &konst.data(Interner) + else { not_supported!("evaluating non concrete constant"); }; let result_owner; @@ -2908,14 +2904,14 @@ impl Evaluator<'_> { pub fn render_const_using_debug_impl( db: &dyn HirDatabase, - owner: ConstId, + owner: DefWithBodyId, c: &Const, ) -> Result<String> { - let mut evaluator = Evaluator::new(db, owner.into(), false, None)?; + let mut evaluator = Evaluator::new(db, owner, false, None)?; let locals = &Locals { ptr: ArenaMap::new(), body: db - .mir_body(owner.into()) + .mir_body(owner) .map_err(|_| MirEvalError::NotSupported("unreachable".to_owned()))?, drop_flags: DropFlags::default(), }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index 595a78da10f..30d11373732 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -32,7 +32,7 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), ) .map_err(|e| MirEvalError::MirLowerError(func_id, e))?; - let (result, output) = interpret_mir(db, body, false, None); + let (result, output) = interpret_mir(db, body, false, None)?; result?; Ok((output.stdout().into_owned(), output.stderr().into_owned())) } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 88eb3b127e0..ebd84fd2be2 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -34,7 +34,10 @@ pub mod term_search; mod display; -use std::{mem::discriminant, ops::ControlFlow}; +use std::{ + mem::discriminant, + ops::{ControlFlow, Not}, +}; use arrayvec::ArrayVec; use base_db::{CrateDisplayName, CrateId, CrateOrigin}; @@ -2303,22 +2306,15 @@ impl Function { self, db: &dyn HirDatabase, span_formatter: impl Fn(FileId, TextRange) -> String, - ) -> String { + ) -> Result<String, ConstEvalError> { let krate = HasModule::krate(&self.id, db.upcast()); let edition = db.crate_graph()[krate].edition; - let body = match db.monomorphized_mir_body( + let body = db.monomorphized_mir_body( self.id.into(), Substitution::empty(Interner), db.trait_environment(self.id.into()), - ) { - Ok(body) => body, - Err(e) => { - let mut r = String::new(); - _ = e.pretty_print(&mut r, db, &span_formatter, edition); - return r; - } - }; - let (result, output) = interpret_mir(db, body, false, None); + )?; + let (result, output) = interpret_mir(db, body, false, None)?; let mut text = match result { Ok(_) => "pass".to_owned(), Err(e) => { @@ -2337,7 +2333,7 @@ impl Function { text += "\n--------- stderr ---------\n"; text += &stderr; } - text + Ok(text) } } @@ -2560,9 +2556,9 @@ impl Const { /// Evaluate the constant and return the result as a string. /// /// This function is intended for IDE assistance, different from [`Const::render_eval`]. - pub fn eval(self, db: &dyn HirDatabase, edition: Edition) -> Result<String, ConstEvalError> { + pub fn eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> { let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?; - Ok(format!("{}", c.display(db, edition))) + Ok(format!("{}", c.display(db, self.krate(db).edition(db)))) } /// Evaluate the constant and return the result as a string, with more detailed information. @@ -2597,7 +2593,7 @@ impl Const { } } } - if let Ok(s) = mir::render_const_using_debug_impl(db, self.id, &c) { + if let Ok(s) = mir::render_const_using_debug_impl(db, self.id.into(), &c) { Ok(s) } else { Ok(format!("{}", c.display(db, edition))) @@ -2636,6 +2632,53 @@ impl Static { pub fn ty(self, db: &dyn HirDatabase) -> Type { Type::from_value_def(db, self.id) } + + /// Evaluate the static and return the result as a string. + /// + /// This function is intended for IDE assistance, different from [`Static::render_eval`]. + pub fn eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> { + let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?; + Ok(format!("{}", c.display(db, self.krate(db).edition(db)))) + } + + /// Evaluate the static and return the result as a string, with more detailed information. + /// + /// This function is intended for user-facing display. + pub fn render_eval( + self, + db: &dyn HirDatabase, + edition: Edition, + ) -> Result<String, ConstEvalError> { + let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?; + let data = &c.data(Interner); + if let TyKind::Scalar(s) = data.ty.kind(Interner) { + if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) { + if let hir_ty::ConstValue::Concrete(c) = &data.value { + if let hir_ty::ConstScalar::Bytes(b, _) = &c.interned { + let value = u128::from_le_bytes(mir::pad16(b, false)); + let value_signed = + i128::from_le_bytes(mir::pad16(b, matches!(s, Scalar::Int(_)))); + let mut result = if let Scalar::Int(_) = s { + value_signed.to_string() + } else { + value.to_string() + }; + if value >= 10 { + format_to!(result, " ({value:#X})"); + return Ok(result); + } else { + return Ok(result); + } + } + } + } + } + if let Ok(s) = mir::render_const_using_debug_impl(db, self.id.into(), &c) { + Ok(s) + } else { + Ok(format!("{}", c.display(db, edition))) + } + } } impl HasVisibility for Static { @@ -2697,6 +2740,18 @@ impl Trait { hir_ty::dyn_compatibility::dyn_compatibility(db, self.id) } + pub fn dyn_compatibility_all_violations( + &self, + db: &dyn HirDatabase, + ) -> Option<Vec<DynCompatibilityViolation>> { + let mut violations = vec![]; + hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| { + violations.push(violation); + ControlFlow::Continue(()) + }); + violations.is_empty().not().then_some(violations) + } + fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> { db.trait_data(self.id) .macro_calls diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index feb9a344d8a..9d3f8e5fba4 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -1,5 +1,6 @@ //! See `Semantics`. +mod child_by_source; mod source_to_def; use std::{ @@ -1271,9 +1272,9 @@ impl<'db> SemanticsImpl<'db> { let analyze = self.analyze(ty.syntax())?; let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = + let mut ctx = LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map); - let type_ref = crate::TypeRef::from_ast(&ctx, ty.clone()); + let type_ref = crate::TypeRef::from_ast(&mut ctx, ty.clone()); let ty = hir_ty::TyLoweringContext::new_maybe_unowned( self.db, &analyze.resolver, @@ -1289,9 +1290,9 @@ impl<'db> SemanticsImpl<'db> { let analyze = self.analyze(path.syntax())?; let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = + let mut ctx = LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map); - let hir_path = Path::from_src(&ctx, path.clone())?; + let hir_path = Path::from_src(&mut ctx, path.clone())?; match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? { TypeNs::TraitId(id) => Some(Trait { id }), _ => None, @@ -1974,9 +1975,9 @@ impl SemanticsScope<'_> { pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option<PathResolution> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = + let mut ctx = LowerCtx::new(self.db.upcast(), self.file_id, &mut types_map, &mut types_source_map); - let path = Path::from_src(&ctx, ast_path.clone())?; + let path = Path::from_src(&mut ctx, ast_path.clone())?; resolve_hir_path( self.db, &self.resolver, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index 0438278ca27..ec65ea9a9a8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -8,7 +8,7 @@ use either::Either; use hir_expand::{attrs::collect_attrs, HirFileId}; use syntax::{ast, AstPtr}; -use crate::{ +use hir_def::{ db::DefDatabase, dyn_map::{ keys::{self, Key}, @@ -23,7 +23,7 @@ use crate::{ VariantId, }; -pub trait ChildBySource { +pub(crate) trait ChildBySource { fn child_by_source(&self, db: &dyn DefDatabase, file_id: HirFileId) -> DynMap { let mut res = DynMap::default(); self.child_by_source_to(db, &mut res, file_id); diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 5357e824d09..08333c2d76c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -87,7 +87,6 @@ use either::Either; use hir_def::{ - child_by_source::ChildBySource, dyn_map::{ keys::{self, Key}, DynMap, @@ -111,7 +110,10 @@ use syntax::{ AstNode, AstPtr, SyntaxNode, }; -use crate::{db::HirDatabase, InFile, InlineAsmOperand, SemanticsImpl}; +use crate::{ + db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand, + SemanticsImpl, +}; #[derive(Default)] pub(super) struct SourceToDefCache { diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 8d6e228e14c..c16454cff68 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -616,9 +616,9 @@ impl SourceAnalyzer { ) -> Option<Macro> { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = + let mut ctx = LowerCtx::new(db.upcast(), macro_call.file_id, &mut types_map, &mut types_source_map); - let path = macro_call.value.path().and_then(|ast| Path::from_src(&ctx, ast))?; + let path = macro_call.value.path().and_then(|ast| Path::from_src(&mut ctx, ast))?; self.resolver .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang)) .map(|(it, _)| it.into()) @@ -731,8 +731,9 @@ impl SourceAnalyzer { let (mut types_map, mut types_source_map) = (TypesMap::default(), TypesSourceMap::default()); - let ctx = LowerCtx::new(db.upcast(), self.file_id, &mut types_map, &mut types_source_map); - let hir_path = Path::from_src(&ctx, path.clone())?; + let mut ctx = + LowerCtx::new(db.upcast(), self.file_id, &mut types_map, &mut types_source_map); + let hir_path = Path::from_src(&mut ctx, path.clone())?; // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are // trying to resolve foo::bar. diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs index f01b4ea0fd4..83f4a6b123c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs @@ -104,7 +104,7 @@ fn edit_struct_def( ast::make::tokens::single_newline().text(), ); edit.insert(tuple_fields_text_range.start(), w.syntax().text()); - if !w.syntax().last_token().is_some_and(|t| t.kind() == SyntaxKind::COMMA) { + if w.syntax().last_token().is_none_or(|t| t.kind() != SyntaxKind::COMMA) { edit.insert(tuple_fields_text_range.start(), ","); } edit.insert( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs new file mode 100644 index 00000000000..f4b4c22d98d --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs @@ -0,0 +1,430 @@ +use either::Either; +use ide_db::assists::{AssistId, AssistKind, GroupLabel}; +use syntax::{ + ast::{self, edit::IndentLevel, make, HasGenericParams, HasName}, + syntax_editor, AstNode, +}; + +use crate::{AssistContext, Assists}; + +// Assist: generate_fn_type_alias_named +// +// Generate a type alias for the function with named parameters. +// +// ``` +// unsafe fn fo$0o(n: i32) -> i32 { 42i32 } +// ``` +// -> +// ``` +// type ${0:FooFn} = unsafe fn(n: i32) -> i32; +// +// unsafe fn foo(n: i32) -> i32 { 42i32 } +// ``` + +// Assist: generate_fn_type_alias_unnamed +// +// Generate a type alias for the function with unnamed parameters. +// +// ``` +// unsafe fn fo$0o(n: i32) -> i32 { 42i32 } +// ``` +// -> +// ``` +// type ${0:FooFn} = unsafe fn(i32) -> i32; +// +// unsafe fn foo(n: i32) -> i32 { 42i32 } +// ``` + +pub(crate) fn generate_fn_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let name = ctx.find_node_at_offset::<ast::Name>()?; + let func = &name.syntax().parent()?; + let func_node = ast::Fn::cast(func.clone())?; + let param_list = func_node.param_list()?; + + let assoc_owner = func.ancestors().nth(2).and_then(Either::<ast::Trait, ast::Impl>::cast); + // This is where we'll insert the type alias, since type aliases in `impl`s or `trait`s are not supported + let insertion_node = assoc_owner + .as_ref() + .map_or_else(|| func, |impl_| impl_.as_ref().either(AstNode::syntax, AstNode::syntax)); + + for style in ParamStyle::ALL { + acc.add_group( + &GroupLabel("Generate a type alias for function...".into()), + style.assist_id(), + style.label(), + func_node.syntax().text_range(), + |builder| { + let mut edit = builder.make_editor(func); + + let alias_name = format!("{}Fn", stdx::to_camel_case(&name.to_string())); + + let mut fn_params_vec = Vec::new(); + + if let Some(self_ty) = + param_list.self_param().and_then(|p| ctx.sema.type_of_self(&p)) + { + let is_ref = self_ty.is_reference(); + let is_mut = self_ty.is_mutable_reference(); + + if let Some(adt) = self_ty.strip_references().as_adt() { + let inner_type = make::ty(adt.name(ctx.db()).as_str()); + + let ast_self_ty = + if is_ref { make::ty_ref(inner_type, is_mut) } else { inner_type }; + + fn_params_vec.push(make::unnamed_param(ast_self_ty)); + } + } + + fn_params_vec.extend(param_list.params().filter_map(|p| match style { + ParamStyle::Named => Some(p), + ParamStyle::Unnamed => p.ty().map(make::unnamed_param), + })); + + let generic_params = func_node.generic_param_list(); + + let is_unsafe = func_node.unsafe_token().is_some(); + let ty = make::ty_fn_ptr( + None, + is_unsafe, + func_node.abi(), + fn_params_vec.into_iter(), + func_node.ret_type(), + ); + + // Insert new alias + let ty_alias = make::ty_alias( + &alias_name, + generic_params, + None, + None, + Some((ast::Type::FnPtrType(ty), None)), + ) + .clone_for_update(); + + let indent = IndentLevel::from_node(insertion_node); + edit.insert_all( + syntax_editor::Position::before(insertion_node), + vec![ + ty_alias.syntax().clone().into(), + make::tokens::whitespace(&format!("\n\n{indent}")).into(), + ], + ); + + if let Some(cap) = ctx.config.snippet_cap { + if let Some(name) = ty_alias.name() { + edit.add_annotation(name.syntax(), builder.make_placeholder_snippet(cap)); + } + } + + builder.add_file_edits(ctx.file_id(), edit); + }, + ); + } + + Some(()) +} + +enum ParamStyle { + Named, + Unnamed, +} + +impl ParamStyle { + const ALL: &'static [ParamStyle] = &[ParamStyle::Named, ParamStyle::Unnamed]; + + fn assist_id(&self) -> AssistId { + let s = match self { + ParamStyle::Named => "generate_fn_type_alias_named", + ParamStyle::Unnamed => "generate_fn_type_alias_unnamed", + }; + + AssistId(s, AssistKind::Generate) + } + + fn label(&self) -> &'static str { + match self { + ParamStyle::Named => "Generate a type alias for function with named params", + ParamStyle::Unnamed => "Generate a type alias for function with unnamed params", + } + } +} + +#[cfg(test)] +mod tests { + use crate::tests::check_assist_by_label; + + use super::*; + + #[test] + fn generate_fn_alias_unnamed_simple() { + check_assist_by_label( + generate_fn_type_alias, + r#" +fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = fn(u32) -> i32; + +fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Unnamed.label(), + ); + } + + #[test] + fn generate_fn_alias_unnamed_unsafe() { + check_assist_by_label( + generate_fn_type_alias, + r#" +unsafe fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = unsafe fn(u32) -> i32; + +unsafe fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Unnamed.label(), + ); + } + + #[test] + fn generate_fn_alias_unnamed_extern() { + check_assist_by_label( + generate_fn_type_alias, + r#" +extern fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = extern fn(u32) -> i32; + +extern fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Unnamed.label(), + ); + } + + #[test] + fn generate_fn_type_unnamed_extern_abi() { + check_assist_by_label( + generate_fn_type_alias, + r#" +extern "FooABI" fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = extern "FooABI" fn(u32) -> i32; + +extern "FooABI" fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Unnamed.label(), + ); + } + + #[test] + fn generate_fn_alias_unnamed_unsafe_extern_abi() { + check_assist_by_label( + generate_fn_type_alias, + r#" +unsafe extern "FooABI" fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = unsafe extern "FooABI" fn(u32) -> i32; + +unsafe extern "FooABI" fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Unnamed.label(), + ); + } + + #[test] + fn generate_fn_alias_unnamed_generics() { + check_assist_by_label( + generate_fn_type_alias, + r#" +fn fo$0o<A, B>(a: A, b: B) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn}<A, B> = fn(A, B) -> i32; + +fn foo<A, B>(a: A, b: B) -> i32 { return 42; } +"#, + ParamStyle::Unnamed.label(), + ); + } + + #[test] + fn generate_fn_alias_unnamed_generics_bounds() { + check_assist_by_label( + generate_fn_type_alias, + r#" +fn fo$0o<A: Trait, B: Trait>(a: A, b: B) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn}<A: Trait, B: Trait> = fn(A, B) -> i32; + +fn foo<A: Trait, B: Trait>(a: A, b: B) -> i32 { return 42; } +"#, + ParamStyle::Unnamed.label(), + ); + } + + #[test] + fn generate_fn_alias_unnamed_self() { + check_assist_by_label( + generate_fn_type_alias, + r#" +struct S; + +impl S { + fn fo$0o(&mut self, param: u32) -> i32 { return 42; } +} +"#, + r#" +struct S; + +type ${0:FooFn} = fn(&mut S, u32) -> i32; + +impl S { + fn foo(&mut self, param: u32) -> i32 { return 42; } +} +"#, + ParamStyle::Unnamed.label(), + ); + } + + #[test] + fn generate_fn_alias_named_simple() { + check_assist_by_label( + generate_fn_type_alias, + r#" +fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = fn(param: u32) -> i32; + +fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Named.label(), + ); + } + + #[test] + fn generate_fn_alias_named_unsafe() { + check_assist_by_label( + generate_fn_type_alias, + r#" +unsafe fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = unsafe fn(param: u32) -> i32; + +unsafe fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Named.label(), + ); + } + + #[test] + fn generate_fn_alias_named_extern() { + check_assist_by_label( + generate_fn_type_alias, + r#" +extern fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = extern fn(param: u32) -> i32; + +extern fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Named.label(), + ); + } + + #[test] + fn generate_fn_type_named_extern_abi() { + check_assist_by_label( + generate_fn_type_alias, + r#" +extern "FooABI" fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = extern "FooABI" fn(param: u32) -> i32; + +extern "FooABI" fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Named.label(), + ); + } + + #[test] + fn generate_fn_alias_named_unsafe_extern_abi() { + check_assist_by_label( + generate_fn_type_alias, + r#" +unsafe extern "FooABI" fn fo$0o(param: u32) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn} = unsafe extern "FooABI" fn(param: u32) -> i32; + +unsafe extern "FooABI" fn foo(param: u32) -> i32 { return 42; } +"#, + ParamStyle::Named.label(), + ); + } + + #[test] + fn generate_fn_alias_named_generics() { + check_assist_by_label( + generate_fn_type_alias, + r#" +fn fo$0o<A, B>(a: A, b: B) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn}<A, B> = fn(a: A, b: B) -> i32; + +fn foo<A, B>(a: A, b: B) -> i32 { return 42; } +"#, + ParamStyle::Named.label(), + ); + } + + #[test] + fn generate_fn_alias_named_generics_bounds() { + check_assist_by_label( + generate_fn_type_alias, + r#" +fn fo$0o<A: Trait, B: Trait>(a: A, b: B) -> i32 { return 42; } +"#, + r#" +type ${0:FooFn}<A: Trait, B: Trait> = fn(a: A, b: B) -> i32; + +fn foo<A: Trait, B: Trait>(a: A, b: B) -> i32 { return 42; } +"#, + ParamStyle::Named.label(), + ); + } + + #[test] + fn generate_fn_alias_named_self() { + check_assist_by_label( + generate_fn_type_alias, + r#" +struct S; + +impl S { + fn fo$0o(&mut self, param: u32) -> i32 { return 42; } +} +"#, + r#" +struct S; + +type ${0:FooFn} = fn(&mut S, param: u32) -> i32; + +impl S { + fn foo(&mut self, param: u32) -> i32 { return 42; } +} +"#, + ParamStyle::Named.label(), + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs index 6b504a918b4..2bd4c4da1e2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs @@ -51,10 +51,7 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_> | ast::Expr::MatchExpr(_) | ast::Expr::MacroExpr(_) | ast::Expr::BinExpr(_) - | ast::Expr::CallExpr(_) => { - let edition = ctx.sema.scope(variable.syntax())?.krate().edition(ctx.db()); - konst.eval(ctx.sema.db, edition).ok()? - } + | ast::Expr::CallExpr(_) => konst.eval(ctx.sema.db).ok()?, _ => return None, }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 8aaf5d6fff2..5c95b25f28d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -161,6 +161,7 @@ mod handlers { mod generate_enum_is_method; mod generate_enum_projection_method; mod generate_enum_variant; + mod generate_fn_type_alias; mod generate_from_impl_for_enum; mod generate_function; mod generate_getter_or_setter; @@ -289,6 +290,7 @@ mod handlers { generate_enum_projection_method::generate_enum_as_method, generate_enum_projection_method::generate_enum_try_into_method, generate_enum_variant::generate_enum_variant, + generate_fn_type_alias::generate_fn_type_alias, generate_from_impl_for_enum::generate_from_impl_for_enum, generate_function::generate_function, generate_impl::generate_impl, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 933d45d7508..64b7ab1a123 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -1549,6 +1549,36 @@ fn main() { } #[test] +fn doctest_generate_fn_type_alias_named() { + check_doc_test( + "generate_fn_type_alias_named", + r#####" +unsafe fn fo$0o(n: i32) -> i32 { 42i32 } +"#####, + r#####" +type ${0:FooFn} = unsafe fn(n: i32) -> i32; + +unsafe fn foo(n: i32) -> i32 { 42i32 } +"#####, + ) +} + +#[test] +fn doctest_generate_fn_type_alias_unnamed() { + check_doc_test( + "generate_fn_type_alias_unnamed", + r#####" +unsafe fn fo$0o(n: i32) -> i32 { 42i32 } +"#####, + r#####" +type ${0:FooFn} = unsafe fn(i32) -> i32; + +unsafe fn foo(n: i32) -> i32 { 42i32 } +"#####, + ) +} + +#[test] fn doctest_generate_from_impl_for_enum() { check_doc_test( "generate_from_impl_for_enum", diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index ec3c2fe3556..0f00ad45f98 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -281,8 +281,8 @@ pub(crate) fn render_resolution_with_import( import_edit: LocatedImport, ) -> Option<Builder> { let resolution = ScopeDef::from(import_edit.original_item); - let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?; - //this now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead + let local_name = get_import_name(resolution, &ctx, &import_edit)?; + // This now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead. let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution); let ctx = ctx.doc_aliases(doc_aliases); Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution)) @@ -294,7 +294,7 @@ pub(crate) fn render_resolution_with_import_pat( import_edit: LocatedImport, ) -> Option<Builder> { let resolution = ScopeDef::from(import_edit.original_item); - let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?; + let local_name = get_import_name(resolution, &ctx, &import_edit)?; Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution)) } @@ -357,6 +357,24 @@ pub(crate) fn render_expr( Some(item) } +fn get_import_name( + resolution: ScopeDef, + ctx: &RenderContext<'_>, + import_edit: &LocatedImport, +) -> Option<hir::Name> { + // FIXME: Temporary workaround for handling aliased import. + // This should be removed after we have proper support for importing alias. + // <https://github.com/rust-lang/rust-analyzer/issues/14079> + + // If `item_to_import` matches `original_item`, we are importing the item itself (not its parent module). + // In this case, we can use the last segment of `import_path`, as it accounts for the aliased name. + if import_edit.item_to_import == import_edit.original_item { + import_edit.import_path.segments().last().cloned() + } else { + scope_def_to_name(resolution, ctx, import_edit) + } +} + fn scope_def_to_name( resolution: ScopeDef, ctx: &RenderContext<'_>, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 0b532064fb2..4b949e0d657 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -1669,3 +1669,54 @@ mod module { "#]], ); } + +#[test] +fn re_export_aliased() { + check( + r#" +mod outer { + mod inner { + pub struct BarStruct; + pub fn bar_fun() {} + pub mod bar {} + } + pub use inner::bar as foo; + pub use inner::bar_fun as foo_fun; + pub use inner::BarStruct as FooStruct; +} +fn function() { + foo$0 +} +"#, + expect![[r#" + st FooStruct (use outer::FooStruct) BarStruct + md foo (use outer::foo) + fn foo_fun() (use outer::foo_fun) fn() + "#]], + ); +} + +#[test] +fn re_export_aliased_pattern() { + check( + r#" +mod outer { + mod inner { + pub struct BarStruct; + pub fn bar_fun() {} + pub mod bar {} + } + pub use inner::bar as foo; + pub use inner::bar_fun as foo_fun; + pub use inner::BarStruct as FooStruct; +} +fn function() { + let foo$0 +} +"#, + expect![[r#" + st FooStruct (use outer::FooStruct) + md foo (use outer::foo) + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 45c723d09d4..1f1b6478d36 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -382,7 +382,7 @@ pub fn semantic_diagnostics( // A bunch of parse errors in a file indicate some bigger structural parse changes in the // file, so we skip semantic diagnostics so we can show these faster. Some(m) => { - if !db.parse_errors(file_id).as_deref().is_some_and(|es| es.len() >= 16) { + if db.parse_errors(file_id).as_deref().is_none_or(|es| es.len() < 16) { m.diagnostics(db, &mut diags, config.style_lints); } } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 6cac4f1ee48..332dfacbb43 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -158,7 +158,7 @@ fn hover_offset( if let Some(doc_comment) = token_as_doc_comment(&original_token) { cov_mark::hit!(no_highlight_on_comment_hover); return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| { - let res = hover_for_definition(sema, file_id, def, &node, None, config, edition); + let res = hover_for_definition(sema, file_id, def, &node, None, false, config, edition); Some(RangeInfo::new(range, res)) }); } @@ -172,6 +172,7 @@ fn hover_offset( Definition::from(resolution?), &original_token.parent()?, None, + false, config, edition, ); @@ -218,6 +219,7 @@ fn hover_offset( break 'a vec![( Definition::Macro(macro_), sema.resolve_macro_call_arm(¯o_call), + false, node, )]; } @@ -234,19 +236,34 @@ fn hover_offset( decl, .. }) => { - vec![(Definition::ExternCrateDecl(decl), None, node)] + vec![(Definition::ExternCrateDecl(decl), None, false, node)] } class => { - multizip((class.definitions(), iter::repeat(None), iter::repeat(node))) - .collect::<Vec<_>>() + let is_def = matches!(class, IdentClass::NameClass(_)); + multizip(( + class.definitions(), + iter::repeat(None), + iter::repeat(is_def), + iter::repeat(node), + )) + .collect::<Vec<_>>() } } } .into_iter() - .unique_by(|&(def, _, _)| def) - .map(|(def, macro_arm, node)| { - hover_for_definition(sema, file_id, def, &node, macro_arm, config, edition) + .unique_by(|&(def, _, _, _)| def) + .map(|(def, macro_arm, hovered_definition, node)| { + hover_for_definition( + sema, + file_id, + def, + &node, + macro_arm, + hovered_definition, + config, + edition, + ) }) .collect::<Vec<_>>(), ) @@ -366,6 +383,7 @@ pub(crate) fn hover_for_definition( def: Definition, scope_node: &SyntaxNode, macro_arm: Option<u32>, + hovered_definition: bool, config: &HoverConfig, edition: Edition, ) -> HoverResult { @@ -397,6 +415,7 @@ pub(crate) fn hover_for_definition( famous_defs.as_ref(), ¬able_traits, macro_arm, + hovered_definition, config, edition, ); diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index a31b14dbd3e..d9ddc2d015b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -273,7 +273,7 @@ pub(super) fn keyword( let markup = process_markup( sema.db, Definition::Module(doc_owner), - &markup(Some(docs.into()), description, None), + &markup(Some(docs.into()), description, None, None), config, ); Some(HoverResult { markup, actions }) @@ -419,6 +419,7 @@ pub(super) fn definition( famous_defs: Option<&FamousDefs<'_, '_>>, notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)], macro_arm: Option<u32>, + hovered_definition: bool, config: &HoverConfig, edition: Edition, ) -> Markup { @@ -456,7 +457,7 @@ pub(super) fn definition( _ => def.label(db, edition), }; let docs = def.docs(db, famous_defs, edition); - let value = (|| match def { + let value = || match def { Definition::Variant(it) => { if !it.parent_enum(db).is_data_carrying(db) { match it.eval(db) { @@ -485,18 +486,24 @@ pub(super) fn definition( } } Definition::Static(it) => { - let source = it.source(db)?; - let mut body = source.value.body()?.syntax().clone(); - if let Some(macro_file) = source.file_id.macro_file() { - let span_map = db.expansion_span_map(macro_file); - body = prettify_macro_expansion(db, body, &span_map, it.krate(db).into()); + let body = it.render_eval(db, edition); + match body { + Ok(it) => Some(it), + Err(_) => { + let source = it.source(db)?; + let mut body = source.value.body()?.syntax().clone(); + if let Some(macro_file) = source.file_id.macro_file() { + let span_map = db.expansion_span_map(macro_file); + body = prettify_macro_expansion(db, body, &span_map, it.krate(db).into()); + } + Some(body.to_string()) + } } - Some(body.to_string()) } _ => None, - })(); + }; - let layout_info = match def { + let layout_info = || match def { Definition::Field(it) => render_memory_layout( config.memory_layout, || it.layout(db), @@ -529,34 +536,38 @@ pub(super) fn definition( _ => None, }; - let dyn_compatibility_info = if let Definition::Trait(it) = def { - let mut dyn_compatibility_info = String::new(); - render_dyn_compatibility(db, &mut dyn_compatibility_info, it.dyn_compatibility(db)); - Some(dyn_compatibility_info) - } else { - None + let dyn_compatibility_info = || match def { + Definition::Trait(it) => { + let mut dyn_compatibility_info = String::new(); + render_dyn_compatibility(db, &mut dyn_compatibility_info, it.dyn_compatibility(db)); + Some(dyn_compatibility_info) + } + _ => None, }; - let mut desc = String::new(); - if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits, edition) { - desc.push_str(¬able_traits); - desc.push('\n'); - } - if let Some(layout_info) = layout_info { - desc.push_str(&layout_info); - desc.push('\n'); - } - if let Some(dyn_compatibility_info) = dyn_compatibility_info { - desc.push_str(&dyn_compatibility_info); - desc.push('\n'); + let mut extra = String::new(); + if hovered_definition { + if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition) { + extra.push_str("\n___\n"); + extra.push_str(¬able_traits); + } + if let Some(layout_info) = layout_info() { + extra.push_str("\n___\n"); + extra.push_str(&layout_info); + } + if let Some(dyn_compatibility_info) = dyn_compatibility_info() { + extra.push_str("\n___\n"); + extra.push_str(&dyn_compatibility_info); + } } + let mut desc = String::new(); desc.push_str(&label); - if let Some(value) = value { + if let Some(value) = value() { desc.push_str(" = "); desc.push_str(&value); } - markup(docs.map(Into::into), desc, mod_path) + markup(docs.map(Into::into), desc, extra.is_empty().not().then_some(extra), mod_path) } pub(super) fn literal( @@ -626,7 +637,7 @@ pub(super) fn literal( Some(s.into()) } -fn render_notable_trait_comment( +fn render_notable_trait( db: &RootDatabase, notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)], edition: Edition, @@ -635,7 +646,7 @@ fn render_notable_trait_comment( let mut needs_impl_header = true; for (trait_, assoc_types) in notable_traits { desc.push_str(if mem::take(&mut needs_impl_header) { - "// Implements notable traits: " + "Implements notable traits: " } else { ", " }); @@ -728,13 +739,12 @@ fn type_info( ) .into() } else { - let mut desc = - match render_notable_trait_comment(db, ¬able_traits(db, &original), edition) { - Some(desc) => desc + "\n", - None => String::new(), - }; - format_to!(desc, "{}", original.display(db, edition)); - Markup::fenced_block(&desc) + let mut desc = format!("```rust\n{}\n```", original.display(db, edition)); + if let Some(extra) = render_notable_trait(db, ¬able_traits(db, &original), edition) { + desc.push_str("\n___\n"); + desc.push_str(&extra); + }; + desc.into() }; if let Some(actions) = HoverAction::goto_type_from_targets(db, targets, edition) { res.actions.push(actions); @@ -786,20 +796,16 @@ fn closure_ty( }; let mut markup = format!("```rust\n{}", c.display_with_id(sema.db, edition)); + if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) { + push_new_def(hir::Trait::from(trait_).into()) + } + format_to!(markup, "\n{}\n```", c.display_with_impl(sema.db, edition),); if let Some(layout) = render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None) { - format_to!(markup, " {layout}"); + format_to!(markup, "\n___\n{layout}"); } - if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) { - push_new_def(hir::Trait::from(trait_).into()) - } - format_to!( - markup, - "\n{}\n```{adjusted}\n\n## Captures\n{}", - c.display_with_impl(sema.db, edition), - captures_rendered, - ); + format_to!(markup, "{adjusted}\n\n## Captures\n{}", captures_rendered,); let mut res = HoverResult::default(); if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) { @@ -824,7 +830,12 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) -> .map(|module| path(db, module, definition_owner_name(db, def, edition), edition)) } -fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Markup { +fn markup( + docs: Option<String>, + rust: String, + extra: Option<String>, + mod_path: Option<String>, +) -> Markup { let mut buf = String::new(); if let Some(mod_path) = mod_path { @@ -832,7 +843,11 @@ fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Marku format_to!(buf, "```rust\n{}\n```\n\n", mod_path); } } - format_to!(buf, "```rust\n{}\n```", desc); + format_to!(buf, "```rust\n{}\n```", rust); + + if let Some(extra) = extra { + buf.push_str(&extra); + } if let Some(doc) = docs { format_to!(buf, "\n___\n\n{}", doc); @@ -862,7 +877,7 @@ fn render_memory_layout( let config = config?; let layout = layout().ok()?; - let mut label = String::from("// "); + let mut label = String::new(); if let Some(render) = config.size { let size = match tag(&layout) { @@ -994,55 +1009,53 @@ fn render_dyn_compatibility( safety: Option<DynCompatibilityViolation>, ) { let Some(osv) = safety else { - buf.push_str("// Dyn Compatible: Yes"); + buf.push_str("Is Dyn compatible"); return; }; - buf.push_str("// Dyn Compatible: No\n// - Reason: "); + buf.push_str("Is not Dyn compatible due to "); match osv { DynCompatibilityViolation::SizedSelf => { - buf.push_str("has a `Self: Sized` bound"); + buf.push_str("having a `Self: Sized` bound"); } DynCompatibilityViolation::SelfReferential => { - buf.push_str("has a bound that references `Self`"); + buf.push_str("having a bound that references `Self`"); } DynCompatibilityViolation::Method(func, mvc) => { let name = hir::Function::from(func).name(db); - format_to!( - buf, - "has a method `{}` that is non dispatchable because of:\n// - ", - name.as_str() - ); + format_to!(buf, "having a method `{}` that is not dispatchable due to ", name.as_str()); let desc = match mvc { MethodViolationCode::StaticMethod => "missing a receiver", - MethodViolationCode::ReferencesSelfInput => "a parameter references `Self`", - MethodViolationCode::ReferencesSelfOutput => "the return type references `Self`", + MethodViolationCode::ReferencesSelfInput => "having a parameter referencing `Self`", + MethodViolationCode::ReferencesSelfOutput => "the return type referencing `Self`", MethodViolationCode::ReferencesImplTraitInTrait => { - "the return type contains `impl Trait`" + "the return type containing `impl Trait`" } MethodViolationCode::AsyncFn => "being async", MethodViolationCode::WhereClauseReferencesSelf => { - "a where clause references `Self`" + "a where clause referencing `Self`" + } + MethodViolationCode::Generic => "having a const or type generic parameter", + MethodViolationCode::UndispatchableReceiver => { + "having a non-dispatchable receiver type" } - MethodViolationCode::Generic => "a non-lifetime generic parameter", - MethodViolationCode::UndispatchableReceiver => "a non-dispatchable receiver type", }; buf.push_str(desc); } DynCompatibilityViolation::AssocConst(const_) => { let name = hir::Const::from(const_).name(db); if let Some(name) = name { - format_to!(buf, "has an associated constant `{}`", name.as_str()); + format_to!(buf, "having an associated constant `{}`", name.as_str()); } else { - buf.push_str("has an associated constant"); + buf.push_str("having an associated constant"); } } DynCompatibilityViolation::GAT(alias) => { let name = hir::TypeAlias::from(alias).name(db); - format_to!(buf, "has a generic associated type `{}`", name.as_str()); + format_to!(buf, "having a generic associated type `{}`", name.as_str()); } DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait) => { let name = hir::Trait::from(super_trait).name(db); - format_to!(buf, "has a dyn incompatible supertrait `{}`", name.as_str()); + format_to!(buf, "having a dyn incompatible supertrait `{}`", name.as_str()); } } } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 3e402630419..0ffbf988c35 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -260,7 +260,6 @@ fn foo() { *local* ```rust - // size = 4, align = 4 let local: i32 ``` "#]], @@ -348,9 +347,11 @@ fn main() { expect![[r#" *|* ```rust - {closure#0} // size = 8, align = 8, niches = 1 + {closure#0} impl Fn(i32) -> i32 ``` + ___ + size = 8, align = 8, niches = 1 ## Captures * `x` by immutable borrow @@ -370,9 +371,11 @@ fn main() { expect![[r#" *|* ```rust - {closure#0} // size = 0, align = 1 + {closure#0} impl Fn(i32) -> i32 ``` + ___ + size = 0, align = 1 ## Captures This closure captures nothing @@ -403,9 +406,11 @@ fn main() { expect![[r#" *|* ```rust - {closure#0} // size = 16 (0x10), align = 8, niches = 1 + {closure#0} impl FnOnce() ``` + ___ + size = 16 (0x10), align = 8, niches = 1 ## Captures * `x.f1` by move @@ -431,9 +436,11 @@ fn main() { expect![[r#" *|* ```rust - {closure#0} // size = 8, align = 8, niches = 1 + {closure#0} impl FnMut() ``` + ___ + size = 8, align = 8, niches = 1 ## Captures * `x` by mutable borrow @@ -455,9 +462,11 @@ fn main() { "#, expect![[r#" ```rust - {closure#0} // size = 8, align = 8, niches = 1 + {closure#0} impl FnOnce() -> S2 ``` + ___ + size = 8, align = 8, niches = 1 Coerced to: &impl FnOnce() -> S2 ## Captures @@ -551,9 +560,12 @@ fn main() { *iter* ```rust - // size = 8, align = 4 let mut iter: Iter<Scan<OtherStruct<OtherStruct<i32>>, impl Fn(&mut u32, &u32, &mut u32) -> Option<u32>, u32>> ``` + + --- + + size = 8, align = 4 "#]], ); } @@ -793,9 +805,12 @@ struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 } ``` ```rust - // size = 1, align = 1, offset = 6 field_a: u8 ``` + + --- + + size = 1, align = 1, offset = 6 "#]], ); } @@ -819,7 +834,6 @@ fn main() { ``` ```rust - // size = 4, align = 4, offset = 0 pub field_a: u32 ``` "#]], @@ -842,9 +856,12 @@ fn main() { ``` ```rust - // size = 4, align = 4, offset = 0 pub field_a: u32 ``` + + --- + + size = 4, align = 4, offset = 0 "#]], ); } @@ -867,7 +884,6 @@ fn main() { ``` ```rust - // size = 4, align = 4, offset = 0 pub 0: u32 ``` "#]], @@ -888,7 +904,6 @@ fn foo(foo: Foo) { ``` ```rust - // size = 4, align = 4, offset = 0 pub 0: u32 ``` "#]], @@ -909,11 +924,14 @@ struct Foo$0(pub u32) where u32: Copy; ``` ```rust - // size = 4, align = 4 struct Foo(pub u32) where u32: Copy, ``` + + --- + + size = 4, align = 4 "#]], ); } @@ -932,11 +950,14 @@ struct Foo$0 { field: u32 } ``` ```rust - // size = 4, align = 4 struct Foo { field: u32, } ``` + + --- + + size = 4, align = 4 "#]], ); check( @@ -951,7 +972,6 @@ struct Foo$0 where u32: Copy { field: u32 } ``` ```rust - // size = 4, align = 4 struct Foo where u32: Copy, @@ -959,6 +979,10 @@ struct Foo$0 where u32: Copy { field: u32 } field: u32, } ``` + + --- + + size = 4, align = 4 "#]], ); } @@ -978,13 +1002,16 @@ fn hover_record_struct_limit() { ``` ```rust - // size = 12 (0xC), align = 4 struct Foo { a: u32, b: i32, c: i32, } ``` + + --- + + size = 12 (0xC), align = 4 "#]], ); check_hover_fields_limit( @@ -1000,11 +1027,14 @@ fn hover_record_struct_limit() { ``` ```rust - // size = 4, align = 4 struct Foo { a: u32, } ``` + + --- + + size = 4, align = 4 "#]], ); check_hover_fields_limit( @@ -1020,7 +1050,6 @@ fn hover_record_struct_limit() { ``` ```rust - // size = 16 (0x10), align = 4 struct Foo { a: u32, b: i32, @@ -1028,6 +1057,10 @@ fn hover_record_struct_limit() { /* … */ } ``` + + --- + + size = 16 (0x10), align = 4 "#]], ); check_hover_fields_limit( @@ -1043,9 +1076,12 @@ fn hover_record_struct_limit() { ``` ```rust - // size = 12 (0xC), align = 4 struct Foo ``` + + --- + + size = 12 (0xC), align = 4 "#]], ); check_hover_fields_limit( @@ -1061,9 +1097,12 @@ fn hover_record_struct_limit() { ``` ```rust - // size = 12 (0xC), align = 4 struct Foo { /* … */ } ``` + + --- + + size = 12 (0xC), align = 4 "#]], ); @@ -1081,9 +1120,12 @@ fn hover_record_struct_limit() { ``` ```rust - // size = 0, align = 1 struct Foo {} ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -1103,9 +1145,12 @@ fn hover_record_variant_limit() { ``` ```rust - // size = 12 (0xC), align = 4 A { a: u32, b: i32, c: i32, } ``` + + --- + + size = 12 (0xC), align = 4 "#]], ); check_hover_fields_limit( @@ -1121,9 +1166,12 @@ fn hover_record_variant_limit() { ``` ```rust - // size = 4, align = 4 A { a: u32, } ``` + + --- + + size = 4, align = 4 "#]], ); check_hover_fields_limit( @@ -1139,9 +1187,12 @@ fn hover_record_variant_limit() { ``` ```rust - // size = 16 (0x10), align = 4 A { a: u32, b: i32, c: i32, /* … */ } ``` + + --- + + size = 16 (0x10), align = 4 "#]], ); check_hover_fields_limit( @@ -1157,9 +1208,12 @@ fn hover_record_variant_limit() { ``` ```rust - // size = 12 (0xC), align = 4 A ``` + + --- + + size = 12 (0xC), align = 4 "#]], ); check_hover_fields_limit( @@ -1175,9 +1229,12 @@ fn hover_record_variant_limit() { ``` ```rust - // size = 12 (0xC), align = 4 A { /* … */ } ``` + + --- + + size = 12 (0xC), align = 4 "#]], ); } @@ -1195,12 +1252,15 @@ fn hover_enum_limit() { ``` ```rust - // size = 1, align = 1, niches = 254 enum Foo { A, B, } ``` + + --- + + size = 1, align = 1, niches = 254 "#]], ); check_hover_enum_variants_limit( @@ -1214,12 +1274,15 @@ fn hover_enum_limit() { ``` ```rust - // size = 1, align = 1, niches = 254 enum Foo { A, /* … */ } ``` + + --- + + size = 1, align = 1, niches = 254 "#]], ); check_hover_enum_variants_limit( @@ -1233,9 +1296,12 @@ fn hover_enum_limit() { ``` ```rust - // size = 1, align = 1, niches = 254 enum Foo { /* … */ } ``` + + --- + + size = 1, align = 1, niches = 254 "#]], ); check_hover_enum_variants_limit( @@ -1249,9 +1315,12 @@ fn hover_enum_limit() { ``` ```rust - // size = 1, align = 1, niches = 254 enum Foo ``` + + --- + + size = 1, align = 1, niches = 254 "#]], ); check_hover_enum_variants_limit( @@ -1274,7 +1343,6 @@ fn hover_enum_limit() { ``` ```rust - // size = 12 (0xC), align = 4, niches = 4294967288 enum Enum { Variant {}, Variant2 { /* … */ }, @@ -1286,6 +1354,10 @@ fn hover_enum_limit() { /* … */ } ``` + + --- + + size = 12 (0xC), align = 4, niches = 4294967288 "#]], ); } @@ -1303,12 +1375,15 @@ fn hover_union_limit() { ``` ```rust - // size = 4, align = 4 union Foo { a: u32, b: i32, } ``` + + --- + + size = 4, align = 4 "#]], ); check_hover_fields_limit( @@ -1322,12 +1397,15 @@ fn hover_union_limit() { ``` ```rust - // size = 4, align = 4 union Foo { a: u32, /* … */ } ``` + + --- + + size = 4, align = 4 "#]], ); check_hover_fields_limit( @@ -1341,9 +1419,12 @@ fn hover_union_limit() { ``` ```rust - // size = 4, align = 4 union Foo { /* … */ } ``` + + --- + + size = 4, align = 4 "#]], ); check_hover_fields_limit( @@ -1357,9 +1438,12 @@ fn hover_union_limit() { ``` ```rust - // size = 4, align = 4 union Foo ``` + + --- + + size = 4, align = 4 "#]], ); } @@ -1378,11 +1462,14 @@ struct Foo$0 where u32: Copy; ``` ```rust - // size = 0, align = 1 struct Foo where u32: Copy, ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -1457,7 +1544,7 @@ const foo$0: u32 = { ``` ```rust - static foo: u32 = 456 + static foo: u32 = 456 (0x1C8) ``` "#]], ); @@ -1548,9 +1635,12 @@ fn main() { *zz* ```rust - // size = 8, align = 4 let zz: Test<i32> ``` + + --- + + size = 8, align = 4 "#]], ); check_hover_range( @@ -1600,9 +1690,12 @@ fn main() { let b$0ar = Some(12); } *bar* ```rust - // size = 4, align = 4 let bar: Option<i32> ``` + + --- + + size = 4, align = 4 "#]], ); } @@ -1670,7 +1763,6 @@ fn hover_for_local_variable() { *foo* ```rust - // size = 4, align = 4 foo: i32 ``` "#]], @@ -1685,9 +1777,12 @@ fn hover_for_local_variable_pat() { *foo* ```rust - // size = 4, align = 4 foo: i32 ``` + + --- + + size = 4, align = 4 "#]], ) } @@ -1700,7 +1795,6 @@ fn hover_local_var_edge() { *foo* ```rust - // size = 4, align = 4 foo: i32 ``` "#]], @@ -1715,9 +1809,12 @@ fn hover_for_param_edge() { *foo* ```rust - // size = 4, align = 4 foo: i32 ``` + + --- + + size = 4, align = 4 "#]], ) } @@ -1760,9 +1857,12 @@ fn main() { let foo_$0test = Thing::new(); } *foo_test* ```rust - // size = 4, align = 4 let foo_test: Thing ``` + + --- + + size = 4, align = 4 "#]], ) } @@ -1985,7 +2085,6 @@ fn y() { *x* ```rust - // size = 4, align = 4 let x: i32 ``` "#]], @@ -2116,7 +2215,6 @@ fn foo(bar:u32) { let a = id!(ba$0r); } *bar* ```rust - // size = 4, align = 4 bar: u32 ``` "#]], @@ -2135,7 +2233,6 @@ fn foo(bar:u32) { let a = id!(ba$0r); } *bar* ```rust - // size = 4, align = 4 bar: u32 ``` "#]], @@ -2371,9 +2468,12 @@ fn test_hover_function_pointer_show_identifiers() { ``` ```rust - // size = 8, align = 8, niches = 1 type foo = fn(a: i32, b: i32) -> i32 ``` + + --- + + size = 8, align = 8, niches = 1 "#]], ); } @@ -2390,9 +2490,12 @@ fn test_hover_function_pointer_no_identifier() { ``` ```rust - // size = 8, align = 8, niches = 1 type foo = fn(i32, i32) -> i32 ``` + + --- + + size = 8, align = 8, niches = 1 "#]], ); } @@ -2537,7 +2640,6 @@ fn foo() { let bar = Ba$0r; } ``` ```rust - // size = 0, align = 1 struct Bar ``` @@ -2574,7 +2676,6 @@ fn foo() { let bar = Ba$0r; } ``` ```rust - // size = 0, align = 1 struct Bar ``` @@ -2604,7 +2705,6 @@ fn foo() { let bar = Ba$0r; } ``` ```rust - // size = 0, align = 1 struct Bar ``` @@ -2633,12 +2733,15 @@ pub struct B$0ar ``` ```rust - // size = 0, align = 1 pub struct Bar ``` --- + size = 0, align = 1 + + --- + [external](https://www.google.com) "#]], ); @@ -2661,12 +2764,15 @@ pub struct B$0ar ``` ```rust - // size = 0, align = 1 pub struct Bar ``` --- + size = 0, align = 1 + + --- + [baz](Baz) "#]], ); @@ -2751,9 +2857,12 @@ fn test_hover_layout_of_variant() { ``` ```rust - // size = 4, align = 2 Variant1(u8, u16) ``` + + --- + + size = 4, align = 2 "#]], ); } @@ -2794,9 +2903,12 @@ struct S$0<T>(core::marker::PhantomData<T>); ``` ```rust - // size = 0, align = 1 struct S<T>(PhantomData<T>) ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -2816,12 +2928,15 @@ fn test_hover_layout_of_enum() { ``` ```rust - // size = 16 (0x10), align = 8, niches = 254 enum Foo { Variant1( /* … */ ), Variant2( /* … */ ), } ``` + + --- + + size = 16 (0x10), align = 8, niches = 254 "#]], ); } @@ -4133,9 +4248,12 @@ fn main() { *f* ```rust - // size = 8, align = 8, niches = 1 let f: &i32 ``` + + --- + + size = 8, align = 8, niches = 1 --- ```rust @@ -4143,9 +4261,12 @@ fn main() { ``` ```rust - // size = 4, align = 4, offset = 0 f: i32 ``` + + --- + + size = 4, align = 4, offset = 0 "#]], ); } @@ -4165,9 +4286,12 @@ struct S$0T<const C: usize = 1, T = Foo>(T); ``` ```rust - // size = 0, align = 1 struct ST<const C: usize = 1, T = Foo>(T) ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4187,9 +4311,12 @@ struct S$0T<const C: usize = {40 + 2}, T = Foo>(T); ``` ```rust - // size = 0, align = 1 struct ST<const C: usize = {const}, T = Foo>(T) ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4210,9 +4337,12 @@ struct S$0T<const C: usize = VAL, T = Foo>(T); ``` ```rust - // size = 0, align = 1 struct ST<const C: usize = VAL, T = Foo>(T) ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4231,9 +4361,12 @@ fn main() { *value* ```rust - // size = 0, align = 1 let value: Const<1> ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4252,9 +4385,12 @@ fn main() { *value* ```rust - // size = 0, align = 1 let value: Const<0> ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4273,9 +4409,12 @@ fn main() { *value* ```rust - // size = 0, align = 1 let value: Const<-1> ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4294,9 +4433,12 @@ fn main() { *value* ```rust - // size = 0, align = 1 let value: Const<true> ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4315,9 +4457,12 @@ fn main() { *value* ```rust - // size = 0, align = 1 let value: Const<'🦀'> ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4335,9 +4480,12 @@ impl Foo { *self* ```rust - // size = 8, align = 8, niches = 1 self: &Foo ``` + + --- + + size = 8, align = 8, niches = 1 "#]], ); } @@ -4356,9 +4504,12 @@ impl Foo { *self* ```rust - // size = 0, align = 1 self: Arc<Foo> ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4755,9 +4906,12 @@ type Fo$0o2 = Foo<2>; ``` ```rust - // size = 0, align = 1 type Foo2 = Foo<2> ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -4798,12 +4952,15 @@ enum E { ``` ```rust - // size = 1, align = 1 A = 8 ``` --- + size = 1, align = 1 + + --- + This is a doc "#]], ); @@ -4824,12 +4981,15 @@ enum E { ``` ```rust - // size = 1, align = 1 A = 12 (0xC) ``` --- + size = 1, align = 1 + + --- + This is a doc "#]], ); @@ -4851,12 +5011,15 @@ enum E { ``` ```rust - // size = 1, align = 1 B = 2 ``` --- + size = 1, align = 1 + + --- + This is a doc "#]], ); @@ -4878,12 +5041,15 @@ enum E { ``` ```rust - // size = 1, align = 1 B = 5 ``` --- + size = 1, align = 1 + + --- + This is a doc "#]], ); @@ -5750,7 +5916,6 @@ fn foo(e: E) { ``` ```rust - // size = 0, align = 1 A = 3 ``` @@ -5799,9 +5964,12 @@ fn main() { *tile4* ```rust - // size = 32 (0x20), align = 4 let tile4: [u32; 8] ``` + + --- + + size = 32 (0x20), align = 4 "#]], ); } @@ -6036,7 +6204,6 @@ pub fn gimme() -> theitem::TheItem { ``` ```rust - // size = 0, align = 1 pub struct TheItem ``` @@ -6185,7 +6352,6 @@ mod string { ``` ```rust - // size = 0, align = 1 struct String ``` @@ -6948,7 +7114,6 @@ foo_macro!( ``` ```rust - // size = 0, align = 1 pub struct Foo ``` @@ -6974,7 +7139,6 @@ pub struct Foo(i32); ``` ```rust - // size = 4, align = 4 pub struct Foo(i32) ``` @@ -7099,9 +7263,12 @@ enum Enum { ``` ```rust - // size = 4, align = 4 RecordV { field: u32, } ``` + + --- + + size = 4, align = 4 "#]], ); } @@ -7122,9 +7289,12 @@ enum Enum { ``` ```rust - // size = 4, align = 4 field: u32 ``` + + --- + + size = 4, align = 4 "#]], ); } @@ -7175,7 +7345,6 @@ impl T$0 for () {} ``` ```rust - // Dyn Compatible: Yes trait T {} ``` "#]], @@ -7195,7 +7364,6 @@ impl T$0 for () {} ``` ```rust - // Dyn Compatible: Yes trait T {} ``` "#]], @@ -7219,9 +7387,6 @@ impl T$0 for () {} ``` ```rust - // Dyn Compatible: No - // - Reason: has a method `func` that is non dispatchable because of: - // - missing a receiver trait T { /* … */ } ``` "#]], @@ -7245,9 +7410,6 @@ impl T$0 for () {} ``` ```rust - // Dyn Compatible: No - // - Reason: has a method `func` that is non dispatchable because of: - // - missing a receiver trait T { fn func(); const FLAG: i32; @@ -7275,9 +7437,6 @@ impl T$0 for () {} ``` ```rust - // Dyn Compatible: No - // - Reason: has a method `func` that is non dispatchable because of: - // - missing a receiver trait T { fn func(); const FLAG: i32; @@ -7305,9 +7464,6 @@ impl T$0 for () {} ``` ```rust - // Dyn Compatible: No - // - Reason: has a method `func` that is non dispatchable because of: - // - missing a receiver trait T { fn func(); const FLAG: i32; @@ -7784,7 +7940,6 @@ fn test() { ``` ```rust - // size = 4, align = 4, offset = 0 f: u32 ``` "#]], @@ -7804,9 +7959,12 @@ fn test() { *s* ```rust - // size = 0, align = 1 let s: S ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -7825,7 +7983,6 @@ fn test() { *foo* ```rust - // size = 4, align = 4 let foo: i32 ``` "#]], @@ -7846,7 +8003,6 @@ format_args!("{aaaaa$0}"); *aaaaa* ```rust - // size = 16 (0x10), align = 8, niches = 1 let aaaaa: &str ``` "#]], @@ -7867,7 +8023,6 @@ format_args!("{$0aaaaa}"); *aaaaa* ```rust - // size = 16 (0x10), align = 8, niches = 1 let aaaaa: &str ``` "#]], @@ -7888,7 +8043,6 @@ format_args!(r"{$0aaaaa}"); *aaaaa* ```rust - // size = 16 (0x10), align = 8, niches = 1 let aaaaa: &str ``` "#]], @@ -7914,7 +8068,6 @@ foo!(r"{$0aaaaa}"); *aaaaa* ```rust - // size = 16 (0x10), align = 8, niches = 1 let aaaaa: &str ``` "#]], @@ -8386,10 +8539,16 @@ fn main(notable$0: u32) {} *notable* ```rust - // Implements notable traits: Notable<Assoc = &str, Assoc2 = char> - // size = 4, align = 4 notable: u32 ``` + + --- + + Implements notable traits: Notable\<Assoc = &str, Assoc2 = char> + + --- + + size = 4, align = 4 "#]], ); } @@ -8418,8 +8577,6 @@ impl Iterator for S { ``` ```rust - // Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S> - // size = 0, align = 1 struct S ``` "#]], @@ -8478,9 +8635,12 @@ extern "C" { ``` ```rust - // size = 0, align = 1 type Ty ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -8506,9 +8666,10 @@ fn main() { "#, expect![[r#" ```rust - // Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S> S - ```"#]], + ``` + ___ + Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S>"#]], ); } @@ -8618,11 +8779,14 @@ struct Pedro$0<'a> { ``` ```rust - // size = 16 (0x10), align = 8, niches = 1 struct Pedro<'a> { hola: &str, } ``` + + --- + + size = 16 (0x10), align = 8, niches = 1 "#]], ) } @@ -8655,9 +8819,12 @@ fn main(a$0: T) {} *a* ```rust - // size = 0, align = 1 a: T ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -8678,7 +8845,6 @@ fn test() { *f* ```rust - // size = 0, align = 1 let f: fn bar<3>(bool) ``` "#]], @@ -8706,9 +8872,12 @@ fn main() { *x* ```rust - // size = 0, align = 1 let x: fn f<S, i32>() ``` + + --- + + size = 0, align = 1 "#]], ); } @@ -9037,12 +9206,15 @@ type A$0 = B; ``` ```rust - // size = 0, align = 1 type A = B ``` --- + size = 0, align = 1 + + --- + *This is the documentation for* `struct B` Docs for B @@ -9067,12 +9239,15 @@ type A$0 = B; ``` ```rust - // size = 0, align = 1 type A = B ``` --- + size = 0, align = 1 + + --- + *This is the documentation for* `struct C` Docs for C @@ -9098,12 +9273,15 @@ type A$0 = B; ``` ```rust - // size = 0, align = 1 type A = B ``` --- + size = 0, align = 1 + + --- + *This is the documentation for* `struct C` Docs for C @@ -9127,9 +9305,12 @@ type A$0 = B; ``` ```rust - // size = 0, align = 1 type A = B ``` + + --- + + size = 0, align = 1 "#]], ); @@ -9159,7 +9340,6 @@ use a::A$0; ``` ```rust - // size = 0, align = 1 pub type A = B ``` @@ -9171,3 +9351,68 @@ use a::A$0; "#]], ); } + +#[test] +fn dyn_compat() { + check( + r#" +trait Compat$0 {} +"#, + expect![[r#" + *Compat* + + ```rust + test + ``` + + ```rust + trait Compat + ``` + + --- + + Is Dyn compatible + "#]], + ); + check( + r#" +trait UnCompat$0 { + fn f<T>() {} +} +"#, + expect![[r#" + *UnCompat* + + ```rust + test + ``` + + ```rust + trait UnCompat + ``` + + --- + + Is not Dyn compatible due to having a method `f` that is not dispatchable due to missing a receiver + "#]], + ); + check( + r#" +trait UnCompat { + fn f<T>() {} +} +fn f<T: UnCompat$0> +"#, + expect![[r#" + *UnCompat* + + ```rust + test + ``` + + ```rust + trait UnCompat + ``` + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide/src/interpret.rs b/src/tools/rust-analyzer/crates/ide/src/interpret.rs new file mode 100644 index 00000000000..5fa6f4e4842 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/interpret.rs @@ -0,0 +1,64 @@ +use hir::{DefWithBody, Semantics}; +use ide_db::{base_db::SourceRootDatabase, FilePosition, LineIndexDatabase, RootDatabase}; +use std::time::{Duration, Instant}; +use stdx::format_to; +use syntax::{algo::ancestors_at_offset, ast, AstNode, TextRange}; + +// Feature: Interpret A Function, Static Or Const. +// +// |=== +// | Editor | Action Name +// +// | VS Code | **rust-analyzer: Interpret** +// |=== +pub(crate) fn interpret(db: &RootDatabase, position: FilePosition) -> String { + match find_and_interpret(db, position) { + Some((duration, mut result)) => { + result.push('\n'); + format_to!(result, "----------------------\n"); + format_to!(result, " Finished in {}s\n", duration.as_secs_f32()); + result + } + _ => "Not inside a function, const or static".to_owned(), + } +} + +fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Duration, String)> { + let sema = Semantics::new(db); + let source_file = sema.parse_guess_edition(position.file_id); + + let item = ancestors_at_offset(source_file.syntax(), position.offset) + .filter(|it| !ast::MacroCall::can_cast(it.kind())) + .find_map(ast::Item::cast)?; + let def: DefWithBody = match item { + ast::Item::Fn(it) => sema.to_def(&it)?.into(), + ast::Item::Const(it) => sema.to_def(&it)?.into(), + ast::Item::Static(it) => sema.to_def(&it)?.into(), + _ => return None, + }; + let span_formatter = |file_id, text_range: TextRange| { + let path = &db + .source_root(db.file_source_root(file_id)) + .path_for_file(&file_id) + .map(|x| x.to_string()); + let path = path.as_deref().unwrap_or("<unknown file>"); + match db.line_index(file_id).try_line_col(text_range.start()) { + Some(line_col) => format!("file://{path}:{}:{}", line_col.line + 1, line_col.col), + None => format!("file://{path} range {text_range:?}"), + } + }; + let start_time = Instant::now(); + let res = match def { + DefWithBody::Function(it) => it.eval(db, span_formatter), + DefWithBody::Static(it) => it.eval(db), + DefWithBody::Const(it) => it.eval(db), + _ => unreachable!(), + }; + let res = res.unwrap_or_else(|e| { + let mut r = String::new(); + _ = e.pretty_print(&mut r, db, span_formatter, def.module(db).krate().edition(db)); + r + }); + let duration = Instant::now() - start_time; + Some((duration, res)) +} diff --git a/src/tools/rust-analyzer/crates/ide/src/interpret_function.rs b/src/tools/rust-analyzer/crates/ide/src/interpret_function.rs deleted file mode 100644 index ff1317d135c..00000000000 --- a/src/tools/rust-analyzer/crates/ide/src/interpret_function.rs +++ /dev/null @@ -1,47 +0,0 @@ -use hir::Semantics; -use ide_db::{base_db::SourceRootDatabase, FilePosition, LineIndexDatabase, RootDatabase}; -use std::{fmt::Write, time::Instant}; -use syntax::{algo::ancestors_at_offset, ast, AstNode, TextRange}; - -// Feature: Interpret Function -// -// |=== -// | Editor | Action Name -// -// | VS Code | **rust-analyzer: Interpret Function** -// |=== -pub(crate) fn interpret_function(db: &RootDatabase, position: FilePosition) -> String { - let start_time = Instant::now(); - let mut result = - find_and_interpret(db, position).unwrap_or_else(|| "Not inside a function body".to_owned()); - let duration = Instant::now() - start_time; - writeln!(result).unwrap(); - writeln!(result, "----------------------").unwrap(); - writeln!(result, " Finished in {}s", duration.as_secs_f32()).unwrap(); - result -} - -fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<String> { - let sema = Semantics::new(db); - let source_file = sema.parse_guess_edition(position.file_id); - - let item = ancestors_at_offset(source_file.syntax(), position.offset) - .filter(|it| !ast::MacroCall::can_cast(it.kind())) - .find_map(ast::Item::cast)?; - let def = match item { - ast::Item::Fn(it) => sema.to_def(&it)?, - _ => return None, - }; - let span_formatter = |file_id, text_range: TextRange| { - let path = &db - .source_root(db.file_source_root(file_id)) - .path_for_file(&file_id) - .map(|x| x.to_string()); - let path = path.as_deref().unwrap_or("<unknown file>"); - match db.line_index(file_id).try_line_col(text_range.start()) { - Some(line_col) => format!("file://{path}#{}:{}", line_col.line + 1, line_col.col), - None => format!("file://{path} range {text_range:?}"), - } - }; - Some(def.eval(db, span_formatter)) -} diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index d053c4b3c93..d4ef9570e1a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -33,7 +33,7 @@ mod goto_type_definition; mod highlight_related; mod hover; mod inlay_hints; -mod interpret_function; +mod interpret; mod join_lines; mod markdown_remove; mod matching_brace; @@ -350,7 +350,7 @@ impl Analysis { } pub fn interpret_function(&self, position: FilePosition) -> Cancellable<String> { - self.with_db(|db| interpret_function::interpret_function(db, position)) + self.with_db(|db| interpret::interpret(db, position)) } pub fn view_item_tree(&self, file_id: FileId) -> Cancellable<String> { diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index 1cbe8c62a81..0f4b5e7d87a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -212,6 +212,7 @@ impl StaticIndex<'_> { def, &node, None, + false, &hover_config, edition, )), diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index a62cbc7fb29..aecafb444c3 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -398,6 +398,8 @@ define_symbols! { rustc_const_panic_str, rustc_deprecated_safe_2024, rustc_has_incoherent_inherent_impls, + rustc_intrinsic, + rustc_intrinsic_must_be_overridden, rustc_layout_scalar_valid_range_end, rustc_layout_scalar_valid_range_start, rustc_legacy_const_generics, diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs index 7ae1e5f82e5..a50a2182a7b 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs @@ -67,7 +67,7 @@ pub(crate) mod entry { } pub(crate) fn pat_top(p: &mut Parser<'_>) { - patterns::pattern_top(p); + patterns::pattern(p); } pub(crate) fn ty(p: &mut Parser<'_>) { @@ -80,7 +80,8 @@ pub(crate) mod entry { paths::type_path(p); } pub(crate) fn item(p: &mut Parser<'_>) { - items::item_or_macro(p, true); + // We can set `is_in_extern=true`, because it only allows `safe fn`, and there is no ambiguity here. + items::item_or_macro(p, true, true); } // Parse a meta item , which excluded [], e.g : #[ MetaItem ] pub(crate) fn meta_item(p: &mut Parser<'_>) { @@ -116,7 +117,7 @@ pub(crate) mod entry { pub(crate) fn pattern(p: &mut Parser<'_>) { let m = p.start(); - patterns::pattern_top(p); + patterns::pattern(p); if p.at(EOF) { m.abandon(p); return; diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs index 861fcedda2a..e565874a421 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs @@ -66,7 +66,7 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) { // test block_items // fn a() { fn b() {} } - let m = match items::opt_item(p, m) { + let m = match items::opt_item(p, m, false) { Ok(()) => return, Err(m) => m, }; diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index 2333e6c862b..97e0392ce15 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -660,7 +660,7 @@ fn for_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker { fn let_expr(p: &mut Parser<'_>) -> CompletedMarker { let m = p.start(); p.bump(T![let]); - patterns::pattern_top(p); + patterns::pattern(p); p.expect(T![=]); expr_let(p); m.complete(p, LET_EXPR) diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs index c4dce0daa5b..7d98499008d 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs @@ -20,7 +20,8 @@ use super::*; pub(super) fn mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool) { attributes::inner_attrs(p); while !(p.at(EOF) || (p.at(T!['}']) && stop_on_r_curly)) { - item_or_macro(p, stop_on_r_curly); + // We can set `is_in_extern=true`, because it only allows `safe fn`, and there is no ambiguity here. + item_or_macro(p, stop_on_r_curly, true); } } @@ -41,11 +42,11 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[ T![;], ]); -pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) { +pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool, is_in_extern: bool) { let m = p.start(); attributes::outer_attrs(p); - let m = match opt_item(p, m) { + let m = match opt_item(p, m, is_in_extern) { Ok(()) => { if p.at(T![;]) { p.err_and_bump( @@ -91,7 +92,7 @@ pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) { } /// Try to parse an item, completing `m` in case of success. -pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> { +pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker, is_in_extern: bool) -> Result<(), Marker> { // test_err pub_expr // fn foo() { pub 92; } let has_visibility = opt_visibility(p, false); @@ -135,7 +136,9 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> { has_mods = true; } - if p.at_contextual_kw(T![safe]) { + // test safe_outside_of_extern + // fn foo() { safe = true; } + if is_in_extern && p.at_contextual_kw(T![safe]) { p.eat_contextual_kw(T![safe]); has_mods = true; } diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs index c215185d632..47f86ce8c6c 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs @@ -94,7 +94,7 @@ pub(crate) fn assoc_item_list(p: &mut Parser<'_>) { error_block(p, "expected an item"); continue; } - item_or_macro(p, true); + item_or_macro(p, true, false); } p.expect(T!['}']); m.complete(p, ASSOC_ITEM_LIST); diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs index ed01fca2acd..460051a0f4a 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs @@ -20,14 +20,9 @@ const PAT_TOP_FIRST: TokenSet = PATTERN_FIRST.union(TokenSet::new(&[T![|]])); const RANGE_PAT_END_FIRST: TokenSet = expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[T![-], T![const]])); -pub(crate) fn pattern(p: &mut Parser<'_>) { - let m = p.start(); - pattern_r(p, m, false, PAT_RECOVERY_SET); -} - /// Parses a pattern list separated by pipes `|`. -pub(super) fn pattern_top(p: &mut Parser<'_>) { - pattern_top_r(p, PAT_RECOVERY_SET); +pub(crate) fn pattern(p: &mut Parser<'_>) { + pattern_r(p, PAT_RECOVERY_SET); } pub(crate) fn pattern_single(p: &mut Parser<'_>) { @@ -37,9 +32,7 @@ pub(crate) fn pattern_single(p: &mut Parser<'_>) { /// Parses a pattern list separated by pipes `|` /// using the given `recovery_set`. pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) { - let m = p.start(); - let has_leading_pipe = p.eat(T![|]); - pattern_r(p, m, has_leading_pipe, recovery_set); + pattern_r(p, recovery_set); } // test or_pattern @@ -53,7 +46,10 @@ pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) { // } /// Parses a pattern list separated by pipes `|`, with no leading `|`,using the /// given `recovery_set`. -fn pattern_r(p: &mut Parser<'_>, m: Marker, has_leading_pipe: bool, recovery_set: TokenSet) { +fn pattern_r(p: &mut Parser<'_>, recovery_set: TokenSet) { + let m = p.start(); + let has_leading_pipe = p.eat(T![|]); + pattern_single_r(p, recovery_set); if !p.at(T![|]) && !has_leading_pipe { @@ -319,6 +315,8 @@ fn record_pat_field(p: &mut Parser<'_>) { IDENT | INT_NUMBER if p.nth(1) == T![:] => { name_ref_or_index(p); p.bump(T![:]); + // test record_field_pat_leading_or + // fn foo() { let R { a: | 1 | 2 } = 0; } pattern(p); } // test_err record_pat_field_eq_recovery @@ -438,7 +436,7 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker { } has_rest |= p.at(T![..]); - pattern_top(p); + pattern(p); if !p.at(T![')']) { has_comma = true; p.expect(T![,]); @@ -465,7 +463,7 @@ fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker { fn pat_list(p: &mut Parser<'_>, ket: SyntaxKind) { while !p.at(EOF) && !p.at(ket) { - pattern_top(p); + pattern(p); if !p.eat(T![,]) { if p.at_ts(PAT_TOP_FIRST) { p.error(format!("expected {:?}, got {:?}", T![,], p.current())); diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs index 164d0f36f1b..62b381b6688 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs @@ -493,6 +493,10 @@ mod ok { run_and_expect_no_errors("test_data/parser/inline/ok/record_field_list.rs"); } #[test] + fn record_field_pat_leading_or() { + run_and_expect_no_errors("test_data/parser/inline/ok/record_field_pat_leading_or.rs"); + } + #[test] fn record_lit() { run_and_expect_no_errors("test_data/parser/inline/ok/record_lit.rs"); } #[test] fn record_literal_field_with_attr() { @@ -527,6 +531,10 @@ mod ok { run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs"); } #[test] + fn safe_outside_of_extern() { + run_and_expect_no_errors("test_data/parser/inline/ok/safe_outside_of_extern.rs"); + } + #[test] fn self_param() { run_and_expect_no_errors("test_data/parser/inline/ok/self_param.rs"); } #[test] fn self_param_outer_attr() { diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rast new file mode 100644 index 00000000000..4ef6c1c45f5 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rast @@ -0,0 +1,54 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE " " + LET_STMT + LET_KW "let" + WHITESPACE " " + RECORD_PAT + PATH + PATH_SEGMENT + NAME_REF + IDENT "R" + WHITESPACE " " + RECORD_PAT_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + RECORD_PAT_FIELD + NAME_REF + IDENT "a" + COLON ":" + WHITESPACE " " + OR_PAT + PIPE "|" + WHITESPACE " " + LITERAL_PAT + LITERAL + INT_NUMBER "1" + WHITESPACE " " + PIPE "|" + WHITESPACE " " + LITERAL_PAT + LITERAL + INT_NUMBER "2" + WHITESPACE " " + R_CURLY "}" + WHITESPACE " " + EQ "=" + WHITESPACE " " + LITERAL + INT_NUMBER "0" + SEMICOLON ";" + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rs new file mode 100644 index 00000000000..a5e7510c140 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rs @@ -0,0 +1 @@ +fn foo() { let R { a: | 1 | 2 } = 0; } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rast new file mode 100644 index 00000000000..c9398eaa993 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rast @@ -0,0 +1,30 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE " " + EXPR_STMT + BIN_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "safe" + WHITESPACE " " + EQ "=" + WHITESPACE " " + LITERAL + TRUE_KW "true" + SEMICOLON ";" + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rs new file mode 100644 index 00000000000..a4d75e63ea7 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rs @@ -0,0 +1 @@ +fn foo() { safe = true; } diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs index c965257a5c5..4045e25fdf1 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs @@ -56,8 +56,8 @@ impl ProcMacroProcessSrv { match srv.version_check() { Ok(v) if v > CURRENT_API_VERSION => Err(io::Error::new( io::ErrorKind::Other, - format!( - "proc-macro server's api version ({v}) is newer than rust-analyzer's ({CURRENT_API_VERSION})" + format!( "The version of the proc-macro server ({v}) in your Rust toolchain is newer than the version supported by your rust-analyzer ({CURRENT_API_VERSION}). + This will prevent proc-macro expansion from working. Please consider updating your rust-analyzer to ensure compatibility with your current toolchain." ), )), Ok(v) => { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 51c81a0d1a6..155fb6f7c88 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -172,7 +172,6 @@ impl flags::AnalysisStats { let mut num_decls = 0; let mut bodies = Vec::new(); let mut adts = Vec::new(); - let mut consts = Vec::new(); let mut file_ids = Vec::new(); while let Some(module) = visit_queue.pop() { if visited_modules.insert(module) { @@ -193,7 +192,6 @@ impl flags::AnalysisStats { } ModuleDef::Const(c) => { bodies.push(DefWithBody::from(c)); - consts.push(c) } ModuleDef::Static(s) => bodies.push(DefWithBody::from(s)), _ => (), @@ -207,7 +205,6 @@ impl flags::AnalysisStats { AssocItem::Function(f) => bodies.push(DefWithBody::from(f)), AssocItem::Const(c) => { bodies.push(DefWithBody::from(c)); - consts.push(c); } _ => (), } @@ -220,7 +217,10 @@ impl flags::AnalysisStats { visited_modules.len(), bodies.len(), adts.len(), - consts.len(), + bodies + .iter() + .filter(|it| matches!(it, DefWithBody::Const(_) | DefWithBody::Static(_))) + .count(), ); let crate_def_map_time = crate_def_map_sw.elapsed(); eprintln!("{:<20} {}", "Item Collection:", crate_def_map_time); @@ -247,7 +247,7 @@ impl flags::AnalysisStats { } if !self.skip_const_eval { - self.run_const_eval(db, &consts, verbosity); + self.run_const_eval(db, &bodies, verbosity); } if self.run_all_ide_things { @@ -320,18 +320,23 @@ impl flags::AnalysisStats { report_metric("data layout time", data_layout_time.time.as_millis() as u64, "ms"); } - fn run_const_eval(&self, db: &RootDatabase, consts: &[hir::Const], verbosity: Verbosity) { + fn run_const_eval(&self, db: &RootDatabase, bodies: &[DefWithBody], verbosity: Verbosity) { let mut sw = self.stop_watch(); let mut all = 0; let mut fail = 0; - for &c in consts { + for &b in bodies { + let res = match b { + DefWithBody::Const(c) => c.render_eval(db, Edition::LATEST), + DefWithBody::Static(s) => s.render_eval(db, Edition::LATEST), + _ => continue, + }; all += 1; - let Err(error) = c.render_eval(db, Edition::LATEST) else { + let Err(error) = res else { continue; }; if verbosity.is_spammy() { let full_name = - full_name_of_item(db, c.module(db), c.name(db).unwrap_or(Name::missing())); + full_name_of_item(db, b.module(db), b.name(db).unwrap_or(Name::missing())); println!("Const eval for {full_name} failed due {error:?}"); } fail += 1; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs index 11534bbeba9..7398b9a9ef0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs @@ -61,12 +61,11 @@ impl flags::RunTests { } let mut sw_one = StopWatch::start(); let result = test.eval(db, span_formatter); - if result.trim() == "pass" { - pass_count += 1; - } else { - fail_count += 1; + match &result { + Ok(result) if result.trim() == "pass" => pass_count += 1, + _ => fail_count += 1, } - println!("{result}"); + println!("{result:?}"); eprintln!("{:<20} {}", format!("test {}", full_name), sw_one.elapsed()); } println!("{pass_count} passed, {fail_count} failed, {ignore_count} ignored"); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs index 271a9c0f3d1..1db616898e8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs @@ -463,6 +463,11 @@ impl ClientCapabilities { .unwrap_or_default() } + pub fn diagnostics_refresh(&self) -> bool { + (|| -> _ { self.0.workspace.as_ref()?.diagnostic.as_ref()?.refresh_support })() + .unwrap_or_default() + } + pub fn inlay_hint_resolve_support_properties(&self) -> FxHashSet<&str> { self.0 .text_document diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 9a51df80fe1..73fce42437f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -417,8 +417,6 @@ impl GlobalState { } } - let supports_diagnostic_pull_model = self.config.text_document_diagnostic(); - let client_refresh = became_quiescent || state_changed; if client_refresh { // Refresh semantic tokens if the client supports it. @@ -437,7 +435,7 @@ impl GlobalState { self.send_request::<lsp_types::request::InlayHintRefreshRequest>((), |_, _| ()); } - if supports_diagnostic_pull_model { + if self.config.diagnostics_refresh() { self.send_request::<lsp_types::request::WorkspaceDiagnosticRefresh>( (), |_, _| (), @@ -448,7 +446,7 @@ impl GlobalState { let project_or_mem_docs_changed = became_quiescent || state_changed || memdocs_added_or_removed; if project_or_mem_docs_changed - && !supports_diagnostic_pull_model + && !self.config.text_document_diagnostic() && self.config.publish_diagnostics(None) { self.update_diagnostics(); diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index fcdc97ce327..2ec83d23b27 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -15,7 +15,11 @@ use parser::{Edition, T}; use rowan::NodeOrToken; use stdx::{format_to, format_to_acc, never}; -use crate::{ast, utils::is_raw_identifier, AstNode, SourceFile, SyntaxKind, SyntaxToken}; +use crate::{ + ast::{self, Param}, + utils::is_raw_identifier, + AstNode, SourceFile, SyntaxKind, SyntaxToken, +}; /// While the parent module defines basic atomic "constructors", the `ext` /// module defines shortcuts for common things. @@ -198,6 +202,38 @@ pub fn ty_alias( ast_from_text(&s) } +pub fn ty_fn_ptr<I: Iterator<Item = Param>>( + for_lifetime_list: Option<ast::GenericParamList>, + is_unsafe: bool, + abi: Option<ast::Abi>, + params: I, + ret_type: Option<ast::RetType>, +) -> ast::FnPtrType { + let mut s = String::from("type __ = "); + + if let Some(list) = for_lifetime_list { + format_to!(s, "for{} ", list); + } + + if is_unsafe { + s.push_str("unsafe "); + } + + if let Some(abi) = abi { + format_to!(s, "{} ", abi) + } + + s.push_str("fn"); + + format_to!(s, "({})", params.map(|p| p.to_string()).join(", ")); + + if let Some(ret_type) = ret_type { + format_to!(s, " {}", ret_type); + } + + ast_from_text(&s) +} + pub fn assoc_item_list() -> ast::AssocItemList { ast_from_text("impl C for D {}") } @@ -862,6 +898,10 @@ pub fn item_const( ast_from_text(&format!("{visibility} const {name}: {ty} = {expr};")) } +pub fn unnamed_param(ty: ast::Type) -> ast::Param { + ast_from_text(&format!("fn f({ty}) {{ }}")) +} + pub fn param(pat: ast::Pat, ty: ast::Type) -> ast::Param { ast_from_text(&format!("fn f({pat}: {ty}) {{ }}")) } diff --git a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml index f9565721dd5..c860e7b1183 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml @@ -5,7 +5,6 @@ rust-version.workspace = true edition.workspace = true license.workspace = true authors.workspace = true -publish = false [dependencies] hir-expand.workspace = true diff --git a/src/tools/rust-analyzer/docs/dev/setup.md b/src/tools/rust-analyzer/docs/dev/setup.md new file mode 100644 index 00000000000..d8a7840d376 --- /dev/null +++ b/src/tools/rust-analyzer/docs/dev/setup.md @@ -0,0 +1,57 @@ +# Setup Guide + +This guide gives a simplified opinionated setup for developers contributing to rust-analyzer using Visual Studio Code to make changes and Visual Studio Code Insiders to test those changes. This guide will assume you have Visual Studio Code and Visual Studio Code Insiders installed. + +## Prerequisites + +Since rust-analyzer is a Rust project, you will need to install Rust. You can download and install the latest stable version of Rust [here](https://www.rust-lang.org/tools/install). + +## Step-by-Step Setup + +**Step 01**: Fork the rust-analyzer repository and clone the fork to your local machine. + +**Step 02**: Open the project in Visual Studio Code. + +**Step 03**: Open a terminal and run `cargo build` to build the project. + +**Step 04**: Install the language server locally by running the following command: + +```sh +cargo xtask install --server --code-bin code-insiders --dev-rel +``` + +In the output of this command, there should be a file path provided to the installed binary on your local machine. +It should look something like the following output below: + +``` +Installing <path-to-rust-analyzer-binary> +Installed package `rust-analyzer v0.0.0 (<path-to-rust-analyzer-binary>)` (executable `rust-analyzer.exe`) +``` + +In Visual Studio Code Insiders, you will want to open your User Settings (JSON) from the Command Palette. From there you should ensure that the `rust-analyzer.server.path` key is set to the `<path-to-rust-analyzer-binary>`. This will tell Visual Studio Code Insiders to use the locally installed version that you can debug. + +The User Settings (JSON) file should contain the following: + +```json +{ + "rust-analyzer.server.path": "<path-to-rust-analyzer-binary>" +} +``` + +Now you should be able to make changes to rust-analyzer in Visual Studio Code and then view the changes in Visual Studio Code Insiders. + +## Debugging rust-analyzer +The simplest way to debug rust-analyzer is to use the `eprintln!` macro. The reason why we use `eprintln!` instead of `println!` is because the language server uses `stdout` to send messages. So instead we will debug using `stderr`. + +An example debugging statement could go into the `main_loop.rs` file which can be found at `crates/rust-analyzer/src/main_loop.rs`. Inside the `main_loop` we will add the following `eprintln!` to test debugging rust-analyzer: + +```rs +eprintln!("Hello, world!"); +``` + +Now we run `cargo build` and `sh +cargo xtask install --server --code-bin code-insiders --dev-rel` to reinstall the server. + +Now on Visual Studio Code Insiders, we should be able to open the Output tab on our terminal and switch to Rust Analyzer Language Server to see the `eprintln!` statement we just wrote. + +If you are able to see your output, you now have a complete workflow for debugging rust-analyzer. diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 6eebdf9f016..ccc8c0e3842 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -125,7 +125,7 @@ }, { "command": "rust-analyzer.interpretFunction", - "title": "Interpret Function", + "title": "Interpret", "category": "rust-analyzer (debug command)" }, { diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index ffb312d06e6..00f4f743a7c 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -a9d17627d241645a54c1134a20f1596127fedb60 +145f9cf95de1fbde3fa11e98461310e0373253e6 diff --git a/src/tools/rust-analyzer/xtask/src/tidy.rs b/src/tools/rust-analyzer/xtask/src/tidy.rs index c3d531344a1..35412be8764 100644 --- a/src/tools/rust-analyzer/xtask/src/tidy.rs +++ b/src/tools/rust-analyzer/xtask/src/tidy.rs @@ -135,7 +135,6 @@ Apache-2.0 WITH LLVM-exception Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT Apache-2.0/MIT BSD-2-Clause OR Apache-2.0 OR MIT -BSD-3-Clause CC0-1.0 ISC MIT diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index fc043a697e0..327a547b295 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -2009,6 +2009,7 @@ pub(crate) struct StaticParts<'a> { safety: ast::Safety, vis: &'a ast::Visibility, ident: symbol::Ident, + generics: Option<&'a ast::Generics>, ty: &'a ast::Ty, mutability: ast::Mutability, expr_opt: Option<&'a ptr::P<ast::Expr>>, @@ -2018,8 +2019,10 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (defaultness, prefix, safety, ty, mutability, expr) = match &item.kind { - ast::ItemKind::Static(s) => (None, "static", s.safety, &s.ty, s.mutability, &s.expr), + let (defaultness, prefix, safety, ty, mutability, expr, generics) = match &item.kind { + ast::ItemKind::Static(s) => { + (None, "static", s.safety, &s.ty, s.mutability, &s.expr, None) + } ast::ItemKind::Const(c) => ( Some(c.defaultness), "const", @@ -2027,6 +2030,7 @@ impl<'a> StaticParts<'a> { &c.ty, ast::Mutability::Not, &c.expr, + Some(&c.generics), ), _ => unreachable!(), }; @@ -2035,6 +2039,7 @@ impl<'a> StaticParts<'a> { safety, vis: &item.vis, ident: item.ident, + generics, ty, mutability, expr_opt: expr.as_ref(), @@ -2044,8 +2049,8 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { - let (defaultness, ty, expr_opt) = match &ti.kind { - ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr), + let (defaultness, ty, expr_opt, generics) = match &ti.kind { + ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)), _ => unreachable!(), }; StaticParts { @@ -2053,6 +2058,7 @@ impl<'a> StaticParts<'a> { safety: ast::Safety::Default, vis: &ti.vis, ident: ti.ident, + generics, ty, mutability: ast::Mutability::Not, expr_opt: expr_opt.as_ref(), @@ -2062,8 +2068,8 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { - let (defaultness, ty, expr) = match &ii.kind { - ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr), + let (defaultness, ty, expr, generics) = match &ii.kind { + ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)), _ => unreachable!(), }; StaticParts { @@ -2071,6 +2077,7 @@ impl<'a> StaticParts<'a> { safety: ast::Safety::Default, vis: &ii.vis, ident: ii.ident, + generics, ty, mutability: ast::Mutability::Not, expr_opt: expr.as_ref(), @@ -2085,6 +2092,14 @@ fn rewrite_static( static_parts: &StaticParts<'_>, offset: Indent, ) -> Option<String> { + // For now, if this static (or const) has generics, then bail. + if static_parts + .generics + .is_some_and(|g| !g.params.is_empty() || !g.where_clause.is_empty()) + { + return None; + } + let colon = colon_spaces(context.config); let mut prefix = format!( "{}{}{}{} {}{}{}", diff --git a/src/tools/rustfmt/tests/target/const-generics.rs b/src/tools/rustfmt/tests/target/const-generics.rs new file mode 100644 index 00000000000..94f76643664 --- /dev/null +++ b/src/tools/rustfmt/tests/target/const-generics.rs @@ -0,0 +1,25 @@ +// Make sure we don't mess up the formatting of generic consts + +#![feature(generic_const_items)] + +const GENERIC<N, const M: usize>: i32 = 0; + +const WHERECLAUSE: i32 = 0 +where + i32:; + +trait Foo { + const GENERIC<N, const M: usize>: i32; + + const WHERECLAUSE: i32 + where + i32:; +} + +impl Foo for () { + const GENERIC<N, const M: usize>: i32 = 0; + + const WHERECLAUSE: i32 = 0 + where + i32:; +} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index f3bd72fe647..8e12db409ec 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -65,9 +65,6 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>, ), // tidy-alphabetical-start ("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None, &[]), - //("library/backtrace", &[], None), // FIXME uncomment once rust-lang/backtrace#562 has been synced back to the rust repo - //("library/portable-simd", &[], None), // FIXME uncomment once rust-lang/portable-simd#363 has been synced back to the rust repo - //("library/stdarch", EXCEPTIONS_STDARCH, None), // FIXME uncomment once rust-lang/stdarch#1462 has been synced back to the rust repo ("src/bootstrap", EXCEPTIONS_BOOTSTRAP, None, &[]), ("src/ci/docker/host-x86_64/test-various/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None, &[]), ("src/etc/test-float-parse", EXCEPTIONS, None, &[]), @@ -116,17 +113,6 @@ const EXCEPTIONS_STDLIB: ExceptionList = &[ // tidy-alphabetical-end ]; -// FIXME uncomment once rust-lang/stdarch#1462 lands -/* -const EXCEPTIONS_STDARCH: ExceptionList = &[ - // tidy-alphabetical-start - ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 - ("wasmparser", "Apache-2.0 WITH LLVM-exception"), - ("wasmprinter", "Apache-2.0 WITH LLVM-exception"), - // tidy-alphabetical-end -]; -*/ - const EXCEPTIONS_CARGO: ExceptionList = &[ // tidy-alphabetical-start ("arrayref", "BSD-2-Clause"), @@ -203,7 +189,7 @@ const EXCEPTIONS_CRANELIFT: ExceptionList = &[ ("cranelift-module", "Apache-2.0 WITH LLVM-exception"), ("cranelift-native", "Apache-2.0 WITH LLVM-exception"), ("cranelift-object", "Apache-2.0 WITH LLVM-exception"), - ("mach", "BSD-2-Clause"), + ("mach2", "BSD-2-Clause OR MIT OR Apache-2.0"), ("regalloc2", "Apache-2.0 WITH LLVM-exception"), ("target-lexicon", "Apache-2.0 WITH LLVM-exception"), ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"), @@ -537,7 +523,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "libc", "libloading", "log", - "mach", + "mach2", "memchr", "object", "once_cell", @@ -554,9 +540,6 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "unicode-ident", "version_check", "wasmtime-jit-icache-coherence", - "winapi", - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", "windows-sys", "windows-targets", "windows_aarch64_gnullvm", diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index 8cbc263689b..edf7658d25f 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -7,7 +7,6 @@ use ignore::DirEntry; /// The default directory filter. pub fn filter_dirs(path: &Path) -> bool { - // FIXME: sync submodule exclusion list with rustfmt.toml // bootstrap/etc let skip = [ "tidy-test-file", diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs index 036f0bd7eac..1eb35e819c0 100644 --- a/src/tools/unicode-table-generator/src/cascading_map.rs +++ b/src/tools/unicode-table-generator/src/cascading_map.rs @@ -65,7 +65,7 @@ impl RawEmitter { self.bytes_used += 256; writeln!(&mut self.file, "#[inline]").unwrap(); - writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); + writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap(); writeln!(&mut self.file, " match c as u32 >> 8 {{").unwrap(); for arm in arms { writeln!(&mut self.file, " {},", arm).unwrap(); diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index e1832091d70..415db2c4dbc 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -268,7 +268,7 @@ fn main() { let mut table_file = String::new(); table_file.push_str( - "///! This file is generated by src/tools/unicode-table-generator; do not edit manually!\n", + "///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually!\n", ); // Include the range search function diff --git a/tests/assembly/aarch64-pointer-auth.rs b/tests/assembly/aarch64-pointer-auth.rs index 1e53878a2cc..344e9e74bc2 100644 --- a/tests/assembly/aarch64-pointer-auth.rs +++ b/tests/assembly/aarch64-pointer-auth.rs @@ -1,9 +1,13 @@ // Test that PAC instructions are emitted when branch-protection is specified. +//@ revisions: PACRET PAUTHLR_NOP PAUTHLR //@ assembly-output: emit-asm -//@ compile-flags: --target aarch64-unknown-linux-gnu -//@ compile-flags: -Z branch-protection=pac-ret,leaf //@ needs-llvm-components: aarch64 +//@ compile-flags: --target aarch64-unknown-linux-gnu +//@ [PACRET] compile-flags: -Z branch-protection=pac-ret,leaf +//@ [PAUTHLR_NOP] compile-flags: -Z branch-protection=pac-ret,pc,leaf +//@ [PAUTHLR] compile-flags: -C target-feature=+pauth-lr -Z branch-protection=pac-ret,pc,leaf +//@ min-llvm-version: 19 #![feature(no_core, lang_items)] #![no_std] @@ -13,8 +17,13 @@ #[lang = "sized"] trait Sized {} -// CHECK: hint #25 -// CHECK: hint #29 +// PACRET: hint #25 +// PACRET: hint #29 +// PAUTHLR_NOP: hint #25 +// PAUTHLR_NOP: hint #39 +// PAUTHLR_NOP: hint #29 +// PAUTHLR: paciasppc +// PAUTHLR: autiasppc #[no_mangle] pub fn test() -> u8 { 42 diff --git a/tests/assembly/asm/sparc-types.rs b/tests/assembly/asm/sparc-types.rs new file mode 100644 index 00000000000..2270679e837 --- /dev/null +++ b/tests/assembly/asm/sparc-types.rs @@ -0,0 +1,168 @@ +//@ revisions: sparc sparcv8plus sparc64 +//@ assembly-output: emit-asm +//@[sparc] compile-flags: --target sparc-unknown-none-elf +//@[sparc] needs-llvm-components: sparc +//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu +//@[sparcv8plus] needs-llvm-components: sparc +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparc64] needs-llvm-components: sparc +//@ compile-flags: -Zmerge-functions=disabled + +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *const i32; + +impl Copy for i8 {} +impl Copy for u8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for i64 {} +impl Copy for f32 {} +impl Copy for f64 {} +impl Copy for ptr {} + +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + let y; + asm!(concat!($mov," {}, {}"), in($class) x, out($class) y); + y + } +};} + +macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + let y; + asm!(concat!($mov, " %", $reg, ", %", $reg), in($reg) x, lateout($reg) y); + y + } +};} + +// CHECK-LABEL: sym_fn_32: +// CHECK: !APP +// CHECK-NEXT: call extern_func +// CHECK-NEXT: !NO_APP +#[no_mangle] +pub unsafe fn sym_fn_32() { + asm!("call {}", sym extern_func); +} + +// CHECK-LABEL: sym_static: +// CHECK: !APP +// CHECK-NEXT: call extern_static +// CHECK-NEXT: !NO_APP +#[no_mangle] +pub unsafe fn sym_static() { + asm!("call {}", sym extern_static); +} + +// CHECK-LABEL: reg_i8: +// CHECK: !APP +// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}} +// CHECK-NEXT: !NO_APP +check!(reg_i8, i8, reg, "mov"); + +// CHECK-LABEL: reg_i16: +// CHECK: !APP +// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}} +// CHECK-NEXT: !NO_APP +check!(reg_i16, i16, reg, "mov"); + +// CHECK-LABEL: reg_i32: +// CHECK: !APP +// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}} +// CHECK-NEXT: !NO_APP +check!(reg_i32, i32, reg, "mov"); + +// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM +// sparc64-LABEL: reg_i64: +// sparc64: !APP +// sparc64-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}} +// sparc64-NEXT: !NO_APP +#[cfg(sparc64)] +check!(reg_i64, i64, reg, "mov"); + +// CHECK-LABEL: reg_ptr: +// CHECK: !APP +// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}} +// CHECK-NEXT: !NO_APP +check!(reg_ptr, ptr, reg, "mov"); + +// CHECK-LABEL: o0_i8: +// CHECK: !APP +// CHECK-NEXT: mov %o0, %o0 +// CHECK-NEXT: !NO_APP +check_reg!(o0_i8, i8, "o0", "mov"); + +// CHECK-LABEL: o0_i16: +// CHECK: !APP +// CHECK-NEXT: mov %o0, %o0 +// CHECK-NEXT: !NO_APP +check_reg!(o0_i16, i16, "o0", "mov"); + +// CHECK-LABEL: o0_i32: +// CHECK: !APP +// CHECK-NEXT: mov %o0, %o0 +// CHECK-NEXT: !NO_APP +check_reg!(o0_i32, i32, "o0", "mov"); + +// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM +// sparc64-LABEL: o0_i64: +// sparc64: !APP +// sparc64-NEXT: mov %o0, %o0 +// sparc64-NEXT: !NO_APP +#[cfg(sparc64)] +check_reg!(o0_i64, i64, "o0", "mov"); + +// CHECK-LABEL: r9_i8: +// CHECK: !APP +// CHECK-NEXT: mov %o1, %o1 +// CHECK-NEXT: !NO_APP +check_reg!(r9_i8, i8, "r9", "mov"); + +// CHECK-LABEL: r9_i16: +// CHECK: !APP +// CHECK-NEXT: mov %o1, %o1 +// CHECK-NEXT: !NO_APP +check_reg!(r9_i16, i16, "r9", "mov"); + +// CHECK-LABEL: r9_i32: +// CHECK: !APP +// CHECK-NEXT: mov %o1, %o1 +// CHECK-NEXT: !NO_APP +check_reg!(r9_i32, i32, "r9", "mov"); + +// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM +// sparc64-LABEL: r9_i64: +// sparc64: !APP +// sparc64-NEXT: mov %o1, %o1 +// sparc64-NEXT: !NO_APP +#[cfg(sparc64)] +check_reg!(r9_i64, i64, "r9", "mov"); diff --git a/tests/assembly/rust-abi-arg-attr.rs b/tests/assembly/rust-abi-arg-attr.rs index 2a113eed4ba..e55a53fbdeb 100644 --- a/tests/assembly/rust-abi-arg-attr.rs +++ b/tests/assembly/rust-abi-arg-attr.rs @@ -50,9 +50,10 @@ enum Ordering { Greater = 1, } -extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering; +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering { + loop {} } // ^^^^^ core diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 1857633a8bf..7d50647bed1 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -525,9 +525,6 @@ //@ revisions: wasm32v1_none //@ [wasm32v1_none] compile-flags: --target wasm32v1-none //@ [wasm32v1_none] needs-llvm-components: webassembly -//@ revisions: wasm32_wasi -//@ [wasm32_wasi] compile-flags: --target wasm32-wasi -//@ [wasm32_wasi] needs-llvm-components: webassembly //@ revisions: wasm32_wasip1 //@ [wasm32_wasip1] compile-flags: --target wasm32-wasip1 //@ [wasm32_wasip1] needs-llvm-components: webassembly diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 49a7580eccc..1e9f2ee59b4 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -6,6 +6,7 @@ //! //! - `minicore` is **only** intended for `core` items, and the stubs should match the actual `core` //! items. +//! - Be careful of adding new features and things that are only available for a subset of targets. //! //! # References //! @@ -13,8 +14,9 @@ //! <https://github.com/rust-lang/rust/blob/c0b5cc9003f6464c11ae1c0662c6a7e06f6f5cab/compiler/rustc_codegen_cranelift/example/mini_core.rs>. // ignore-tidy-linelength -#![feature(no_core, lang_items, rustc_attrs)] +#![feature(no_core, lang_items, rustc_attrs, decl_macro)] #![allow(unused, improper_ctypes_definitions, internal_features)] +#![feature(asm_experimental_arch)] #![no_std] #![no_core] @@ -37,7 +39,9 @@ impl<T: ?Sized> LegacyReceiver for &mut T {} #[lang = "copy"] pub trait Copy: Sized {} -impl_marker_trait!(Copy => [ bool, char, isize, usize, i8, i16, i32, i64, u8, u16, u32, u64 ]); +impl_marker_trait!( + Copy => [ bool, char, isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64 ] +); impl<'a, T: ?Sized> Copy for &'a T {} impl<T: ?Sized> Copy for *const T {} impl<T: ?Sized> Copy for *mut T {} @@ -70,3 +74,8 @@ impl<T: Copy + ?Sized> Copy for ManuallyDrop<T> {} pub struct UnsafeCell<T: ?Sized> { value: T, } + +#[rustc_builtin_macro] +pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} diff --git a/tests/codegen/asm/powerpc-clobbers.rs b/tests/codegen/asm/powerpc-clobbers.rs index 0be1b66bd99..e97e8300ca7 100644 --- a/tests/codegen/asm/powerpc-clobbers.rs +++ b/tests/codegen/asm/powerpc-clobbers.rs @@ -1,10 +1,12 @@ -//@ revisions: powerpc powerpc64 powerpc64le +//@ revisions: powerpc powerpc64 powerpc64le aix64 //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu //@[powerpc] needs-llvm-components: powerpc //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu //@[powerpc64] needs-llvm-components: powerpc //@[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu //@[powerpc64le] needs-llvm-components: powerpc +//@[aix64] compile-flags: --target powerpc64-ibm-aix +//@[aix64] needs-llvm-components: powerpc #![crate_type = "rlib"] #![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] @@ -22,26 +24,40 @@ macro_rules! asm { // CHECK: call void asm sideeffect "", "~{cr}"() #[no_mangle] pub unsafe fn cr_clobber() { - asm!("", out("cr") _, options(nostack, nomem)); + asm!("", out("cr") _, options(nostack, nomem, preserves_flags)); } // CHECK-LABEL: @cr0_clobber // CHECK: call void asm sideeffect "", "~{cr0}"() #[no_mangle] pub unsafe fn cr0_clobber() { - asm!("", out("cr0") _, options(nostack, nomem)); + asm!("", out("cr0") _, options(nostack, nomem, preserves_flags)); } // CHECK-LABEL: @cr5_clobber // CHECK: call void asm sideeffect "", "~{cr5}"() #[no_mangle] pub unsafe fn cr5_clobber() { - asm!("", out("cr5") _, options(nostack, nomem)); + asm!("", out("cr5") _, options(nostack, nomem, preserves_flags)); } // CHECK-LABEL: @xer_clobber // CHECK: call void asm sideeffect "", "~{xer}"() #[no_mangle] pub unsafe fn xer_clobber() { - asm!("", out("xer") _, options(nostack, nomem)); + asm!("", out("xer") _, options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @v0_clobber +// CHECK: call void asm sideeffect "", "~{v0}"() +#[no_mangle] +pub unsafe fn v0_clobber() { + asm!("", out("v0") _, options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// CHECK: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); } diff --git a/tests/codegen/asm/sparc-clobbers.rs b/tests/codegen/asm/sparc-clobbers.rs new file mode 100644 index 00000000000..843abd55352 --- /dev/null +++ b/tests/codegen/asm/sparc-clobbers.rs @@ -0,0 +1,40 @@ +//@ revisions: sparc sparcv8plus sparc64 +//@[sparc] compile-flags: --target sparc-unknown-none-elf +//@[sparc] needs-llvm-components: sparc +//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu +//@[sparcv8plus] needs-llvm-components: sparc +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparc64] needs-llvm-components: sparc + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @cc_clobber +// CHECK: call void asm sideeffect "", "~{icc},~{fcc0},~{fcc1},~{fcc2},~{fcc3}"() +#[no_mangle] +pub unsafe fn cc_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @y_clobber +// CHECK: call void asm sideeffect "", "~{y}"() +#[no_mangle] +pub unsafe fn y_clobber() { + asm!("", out("y") _, options(nostack, nomem, preserves_flags)); +} diff --git a/tests/codegen/binary-heap-peek-mut-pop-no-panic.rs b/tests/codegen/binary-heap-peek-mut-pop-no-panic.rs index 9cf4f210e52..e3bc9a4761c 100644 --- a/tests/codegen/binary-heap-peek-mut-pop-no-panic.rs +++ b/tests/codegen/binary-heap-peek-mut-pop-no-panic.rs @@ -1,5 +1,5 @@ //@ compile-flags: -O -//@ ignore-debug +//@ ignore-std-debug-assertions #![crate_type = "lib"] use std::collections::binary_heap::PeekMut; diff --git a/tests/codegen/branch-protection.rs b/tests/codegen/branch-protection.rs index 2f5ff9e98c2..945bad05625 100644 --- a/tests/codegen/branch-protection.rs +++ b/tests/codegen/branch-protection.rs @@ -1,11 +1,15 @@ // Test that the correct module flags are emitted with different branch protection flags. -//@ revisions: BTI PACRET LEAF BKEY NONE +//@ revisions: BTI PACRET LEAF BKEY PAUTHLR PAUTHLR_BKEY PAUTHLR_LEAF PAUTHLR_BTI NONE //@ needs-llvm-components: aarch64 //@ [BTI] compile-flags: -Z branch-protection=bti //@ [PACRET] compile-flags: -Z branch-protection=pac-ret //@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf //@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key +//@ [PAUTHLR] compile-flags: -Z branch-protection=pac-ret,pc +//@ [PAUTHLR_BKEY] compile-flags: -Z branch-protection=pac-ret,pc,b-key +//@ [PAUTHLR_LEAF] compile-flags: -Z branch-protection=pac-ret,pc,leaf +//@ [PAUTHLR_BTI] compile-flags: -Z branch-protection=bti,pac-ret,pc //@ compile-flags: --target aarch64-unknown-linux-gnu //@ min-llvm-version: 19 @@ -24,6 +28,7 @@ pub fn test() {} // BTI: attributes [[ATTR]] = {{.*}} "branch-target-enforcement" // BTI: !"branch-target-enforcement", i32 1 // BTI: !"sign-return-address", i32 0 +// BTI: !"branch-protection-pauth-lr", i32 0 // BTI: !"sign-return-address-all", i32 0 // BTI: !"sign-return-address-with-bkey", i32 0 @@ -31,6 +36,7 @@ pub fn test() {} // PACRET-SAME: "sign-return-address-key"="a_key" // PACRET: !"branch-target-enforcement", i32 0 // PACRET: !"sign-return-address", i32 1 +// PACRET: !"branch-protection-pauth-lr", i32 0 // PACRET: !"sign-return-address-all", i32 0 // PACRET: !"sign-return-address-with-bkey", i32 0 @@ -38,6 +44,7 @@ pub fn test() {} // LEAF-SAME: "sign-return-address-key"="a_key" // LEAF: !"branch-target-enforcement", i32 0 // LEAF: !"sign-return-address", i32 1 +// LEAF: !"branch-protection-pauth-lr", i32 0 // LEAF: !"sign-return-address-all", i32 1 // LEAF: !"sign-return-address-with-bkey", i32 0 @@ -45,9 +52,42 @@ pub fn test() {} // BKEY-SAME: "sign-return-address-key"="b_key" // BKEY: !"branch-target-enforcement", i32 0 // BKEY: !"sign-return-address", i32 1 +// BKEY: !"branch-protection-pauth-lr", i32 0 // BKEY: !"sign-return-address-all", i32 0 // BKEY: !"sign-return-address-with-bkey", i32 1 +// PAUTHLR: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf" +// PAUTHLR-SAME: "sign-return-address-key"="a_key" +// PAUTHLR: !"branch-target-enforcement", i32 0 +// PAUTHLR: !"sign-return-address", i32 1 +// PAUTHLR: !"branch-protection-pauth-lr", i32 1 +// PAUTHLR: !"sign-return-address-all", i32 0 +// PAUTHLR: !"sign-return-address-with-bkey", i32 0 + +// PAUTHLR_BKEY: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf" +// PAUTHLR_BKEY-SAME: "sign-return-address-key"="b_key" +// PAUTHLR_BKEY: !"branch-target-enforcement", i32 0 +// PAUTHLR_BKEY: !"sign-return-address", i32 1 +// PAUTHLR_BKEY: !"branch-protection-pauth-lr", i32 1 +// PAUTHLR_BKEY: !"sign-return-address-all", i32 0 +// PAUTHLR_BKEY: !"sign-return-address-with-bkey", i32 1 + +// PAUTHLR_LEAF: attributes [[ATTR]] = {{.*}} "sign-return-address"="all" +// PAUTHLR_LEAF-SAME: "sign-return-address-key"="a_key" +// PAUTHLR_LEAF: !"branch-target-enforcement", i32 0 +// PAUTHLR_LEAF: !"sign-return-address", i32 1 +// PAUTHLR_LEAF: !"branch-protection-pauth-lr", i32 1 +// PAUTHLR_LEAF: !"sign-return-address-all", i32 1 +// PAUTHLR_LEAF: !"sign-return-address-with-bkey", i32 0 + +// PAUTHLR_BTI: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf" +// PAUTHLR_BTI-SAME: "sign-return-address-key"="a_key" +// PAUTHLR_BTI: !"branch-target-enforcement", i32 1 +// PAUTHLR_BTI: !"sign-return-address", i32 1 +// PAUTHLR_BTI: !"branch-protection-pauth-lr", i32 1 +// PAUTHLR_BTI: !"sign-return-address-all", i32 0 +// PAUTHLR_BTI: !"sign-return-address-with-bkey", i32 0 + // NONE-NOT: branch-target-enforcement // NONE-NOT: sign-return-address // NONE-NOT: sign-return-address-all diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs index e62f1a953df..e62adfa0ba6 100644 --- a/tests/codegen/mem-replace-big-type.rs +++ b/tests/codegen/mem-replace-big-type.rs @@ -4,7 +4,8 @@ // known to be `1` after inlining). //@ compile-flags: -C no-prepopulate-passes -Zinline-mir=no -//@ ignore-debug: precondition checks in ptr::read make them a bad candidate for MIR inlining +//@ ignore-std-debug-assertions +// Reason: precondition checks in ptr::read make them a bad candidate for MIR inlining //@ needs-deterministic-layouts #![crate_type = "lib"] diff --git a/tests/codegen/mem-replace-simple-type.rs b/tests/codegen/mem-replace-simple-type.rs index 7209fa21925..41c3660dc15 100644 --- a/tests/codegen/mem-replace-simple-type.rs +++ b/tests/codegen/mem-replace-simple-type.rs @@ -1,6 +1,7 @@ //@ compile-flags: -O -C no-prepopulate-passes //@ only-x86_64 (to not worry about usize differing) -//@ ignore-debug: precondition checks make mem::replace not a candidate for MIR inlining +//@ ignore-std-debug-assertions +// Reason: precondition checks make mem::replace not a candidate for MIR inlining #![crate_type = "lib"] diff --git a/tests/codegen/repr/transparent-opaque-ptr.rs b/tests/codegen/repr/transparent-opaque-ptr.rs index 4e7b38bca39..29c03f0d5d9 100644 --- a/tests/codegen/repr/transparent-opaque-ptr.rs +++ b/tests/codegen/repr/transparent-opaque-ptr.rs @@ -1,12 +1,12 @@ -//@ revisions: aarch64-linux aarch64-darwin wasm32-wasi +//@ revisions: aarch64-linux aarch64-darwin wasm32-wasip1 //@ compile-flags: -O -C no-prepopulate-passes //@[aarch64-linux] compile-flags: --target aarch64-unknown-linux-gnu //@[aarch64-linux] needs-llvm-components: aarch64 //@[aarch64-darwin] compile-flags: --target aarch64-apple-darwin //@[aarch64-darwin] needs-llvm-components: aarch64 -//@[wasm32-wasi] compile-flags: --target wasm32-wasi -//@[wasm32-wasi] needs-llvm-components: webassembly +//@[wasm32-wasip1] compile-flags: --target wasm32-wasip1 +//@[wasm32-wasip1] needs-llvm-components: webassembly // See ./transparent.rs // Some platforms pass large aggregates using immediate arrays in LLVMIR diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs index 81ac90269b7..e9112f1f321 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs @@ -31,7 +31,7 @@ extern "rust-intrinsic" { // CHECK-LABEL: @bitmask_int #[no_mangle] pub unsafe fn bitmask_int(x: i32x2) -> u8 { - // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31> + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, {{<i32 31, i32 31>|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2 // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8 @@ -41,7 +41,7 @@ pub unsafe fn bitmask_int(x: i32x2) -> u8 { // CHECK-LABEL: @bitmask_uint #[no_mangle] pub unsafe fn bitmask_uint(x: u32x2) -> u8 { - // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31> + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, {{<i32 31, i32 31>|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2 // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8 @@ -51,7 +51,7 @@ pub unsafe fn bitmask_uint(x: u32x2) -> u8 { // CHECK-LABEL: @bitmask_int16 #[no_mangle] pub unsafe fn bitmask_int16(x: i8x16) -> u16 { - // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1|2}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7> + // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1|2}}, {{<i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>|splat \(i8 7\)}} // CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1> // CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16 // CHECK-NOT: zext diff --git a/tests/codegen/slice-reverse.rs b/tests/codegen/slice-reverse.rs index 21add929f05..87cdad47962 100644 --- a/tests/codegen/slice-reverse.rs +++ b/tests/codegen/slice-reverse.rs @@ -1,6 +1,6 @@ //@ compile-flags: -O //@ only-x86_64 -//@ ignore-debug: debug assertions prevent generating shufflevector +//@ ignore-std-debug-assertions (debug assertions prevent generating shufflevector) #![crate_type = "lib"] diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs index c6b77363a4e..5d05f242617 100644 --- a/tests/codegen/vec-in-place.rs +++ b/tests/codegen/vec-in-place.rs @@ -1,4 +1,4 @@ -//@ ignore-debug: FIXME: checks for call detect scoped noalias metadata +//@ ignore-std-debug-assertions (FIXME: checks for call detect scoped noalias metadata) //@ compile-flags: -O -Z merge-functions=disabled #![crate_type = "lib"] diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs index 4b798fe6c9c..873904c2569 100644 --- a/tests/codegen/vec-shrink-panik.rs +++ b/tests/codegen/vec-shrink-panik.rs @@ -1,7 +1,7 @@ // LLVM 17 realizes double panic is not possible and doesn't generate calls // to panic_cannot_unwind. //@ compile-flags: -O -//@ ignore-debug: plain old debug assertions +//@ ignore-std-debug-assertions (plain old debug assertions) //@ needs-unwind #![crate_type = "lib"] #![feature(shrink_to)] diff --git a/tests/codegen/vec-with-capacity.rs b/tests/codegen/vec-with-capacity.rs index 47051f2eef8..e8c5bc88bd0 100644 --- a/tests/codegen/vec-with-capacity.rs +++ b/tests/codegen/vec-with-capacity.rs @@ -1,5 +1,5 @@ //@ compile-flags: -O -//@ ignore-debug +//@ ignore-std-debug-assertions // (with debug assertions turned on, `assert_unchecked` generates a real assertion) #![crate_type = "lib"] diff --git a/tests/codegen/vecdeque-drain.rs b/tests/codegen/vecdeque-drain.rs index fca1ed367e6..8a34ba0674b 100644 --- a/tests/codegen/vecdeque-drain.rs +++ b/tests/codegen/vecdeque-drain.rs @@ -2,7 +2,7 @@ //@ compile-flags: -O //@ needs-deterministic-layouts -//@ ignore-debug: FIXME: checks for call detect scoped noalias metadata +//@ ignore-std-debug-assertions (FIXME: checks for call detect scoped noalias metadata) #![crate_type = "lib"] diff --git a/tests/codegen/vecdeque_no_panic.rs b/tests/codegen/vecdeque_no_panic.rs index be2c4810ebc..da948d12254 100644 --- a/tests/codegen/vecdeque_no_panic.rs +++ b/tests/codegen/vecdeque_no_panic.rs @@ -1,7 +1,7 @@ // This test checks that `VecDeque::front[_mut]()` and `VecDeque::back[_mut]()` can't panic. //@ compile-flags: -O -//@ ignore-debug: plain old debug assertions +//@ ignore-std-debug-assertions (plain old debug assertions) #![crate_type = "lib"] diff --git a/tests/coverage/auxiliary/inline_mixed_helper.rs b/tests/coverage/auxiliary/inline_mixed_helper.rs new file mode 100644 index 00000000000..1e91ab8ce7c --- /dev/null +++ b/tests/coverage/auxiliary/inline_mixed_helper.rs @@ -0,0 +1,13 @@ +//@ edition: 2021 +//@ compile-flags: -Cinstrument-coverage=on + +#[inline] +pub fn inline_me() {} + +#[inline(never)] +pub fn no_inlining_please() {} + +pub fn generic<T>() {} + +// FIXME(#132436): Even though this doesn't ICE, it still produces coverage +// reports that undercount the affected code. diff --git a/tests/coverage/inline_mixed.rs b/tests/coverage/inline_mixed.rs new file mode 100644 index 00000000000..163cc7d7d6c --- /dev/null +++ b/tests/coverage/inline_mixed.rs @@ -0,0 +1,19 @@ +//@ edition: 2021 +//@ compile-flags: -Cinstrument-coverage=off +//@ ignore-coverage-run +//@ aux-crate: inline_mixed_helper=inline_mixed_helper.rs + +// Regression test for <https://github.com/rust-lang/rust/pull/132395>. +// Various forms of cross-crate inlining can cause coverage statements to be +// inlined into crates that are being built without coverage instrumentation. +// At the very least, we need to not ICE when that happens. + +fn main() { + inline_mixed_helper::inline_me(); + inline_mixed_helper::no_inlining_please(); + inline_mixed_helper::generic::<u32>(); +} + +// FIXME(#132437): We currently don't test this in coverage-run mode, because +// whether or not it produces a `.profraw` file appears to differ between +// platforms. diff --git a/tests/crashes/112623.rs b/tests/crashes/112623.rs index fc7361bfcb2..592ad742e5f 100644 --- a/tests/crashes/112623.rs +++ b/tests/crashes/112623.rs @@ -1,6 +1,6 @@ //@ known-bug: #112623 -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Value { diff --git a/tests/crashes/119701.rs b/tests/crashes/119701.rs index 5f681bb8da8..bdb326ea76b 100644 --- a/tests/crashes/119701.rs +++ b/tests/crashes/119701.rs @@ -1,5 +1,5 @@ //@ known-bug: #119701 -#![feature(const_trait_impl, effects, generic_const_exprs)] +#![feature(const_trait_impl, generic_const_exprs)] fn main() { let _ = process::<()>([()]); diff --git a/tests/crashes/121411.rs b/tests/crashes/121411.rs index ef7b16579dd..2456910e6fa 100644 --- a/tests/crashes/121411.rs +++ b/tests/crashes/121411.rs @@ -1,5 +1,5 @@ //@ known-bug: #121411 -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Foo { diff --git a/tests/crashes/132127.rs b/tests/crashes/132127.rs new file mode 100644 index 00000000000..cca354b9876 --- /dev/null +++ b/tests/crashes/132127.rs @@ -0,0 +1,9 @@ +//@ known-bug: #132127 +#![feature(dyn_star)] + +trait Trait {} + +fn main() { + let x: dyn* Trait + Send = 1usize; + x as dyn* Trait; +} diff --git a/tests/crashes/132142.rs b/tests/crashes/132142.rs new file mode 100644 index 00000000000..9a026f3bca7 --- /dev/null +++ b/tests/crashes/132142.rs @@ -0,0 +1,3 @@ +//@ known-bug: #132142 + +async extern "C-cmse-nonsecure-entry" fn fun(...) {} diff --git a/tests/crashes/132320.rs b/tests/crashes/132320.rs new file mode 100644 index 00000000000..79181c3a2c5 --- /dev/null +++ b/tests/crashes/132320.rs @@ -0,0 +1,15 @@ +//@ known-bug: #132320 +//@ compile-flags: -Znext-solver=globally + +trait Foo { + type Item; + fn foo(&mut self); +} + +impl Foo for () { + type Item = Option<()>; + + fn foo(&mut self) { + let _ = Self::Item::None; + } +} diff --git a/tests/crashes/132330.rs b/tests/crashes/132330.rs new file mode 100644 index 00000000000..3432685749d --- /dev/null +++ b/tests/crashes/132330.rs @@ -0,0 +1,28 @@ +//@ known-bug: #132330 +//@compile-flags: -Znext-solver=globally + +trait Service { + type S; +} + +trait Framing { + type F; +} + +impl Framing for () { + type F = (); +} + +trait HttpService<F: Framing>: Service<S = F::F> {} + +type BoxService = Box<dyn HttpService<(), S = ()>>; + +fn build_server<F: FnOnce() -> BoxService>(_: F) {} + +fn make_server<F: Framing>() -> Box<dyn HttpService<F, S = F::F>> { + unimplemented!() +} + +fn main() { + build_server(|| make_server()) +} diff --git a/tests/crashes/132335.rs b/tests/crashes/132335.rs new file mode 100644 index 00000000000..2294539cfcf --- /dev/null +++ b/tests/crashes/132335.rs @@ -0,0 +1,13 @@ +//@ known-bug: #132335 +//@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018 +use core::future::Future; +use core::pin::Pin; + +pub trait Unit {} +impl Unit for () {} + +pub fn get_all_files_in_dir() -> Pin<Box<dyn Future<Output = impl Unit>>> { + Box::pin(async { + get_all_files_in_dir().await; + }) +} diff --git a/tests/crashes/132391.rs b/tests/crashes/132391.rs new file mode 100644 index 00000000000..6c8c2c3a878 --- /dev/null +++ b/tests/crashes/132391.rs @@ -0,0 +1,8 @@ +//@ known-bug: #123291 + +trait MyTrait { + #[repr(align)] + fn myfun(); +} + +pub fn main() {} diff --git a/tests/crashes/132430.rs b/tests/crashes/132430.rs new file mode 100644 index 00000000000..995bdf06224 --- /dev/null +++ b/tests/crashes/132430.rs @@ -0,0 +1,9 @@ +//@ known-bug: #132430 + +//@compile-flags: --edition=2018 --crate-type=lib +#![feature(cmse_nonsecure_entry)] +struct Test; + +impl Test { + pub async unsafe extern "C-cmse-nonsecure-entry" fn test(val: &str) {} +} diff --git a/tests/crashes/132530.rs b/tests/crashes/132530.rs new file mode 100644 index 00000000000..b43da62bfc1 --- /dev/null +++ b/tests/crashes/132530.rs @@ -0,0 +1,9 @@ +//@ known-bug: #132530 + +#![feature(non_lifetime_binders)] + +trait Trait<'a, A> { + type Assoc<'a> = i32; +} + +fn a() -> impl for<T> Trait<Assoc = impl Trait<T>> {} diff --git a/tests/crashes/README.md b/tests/crashes/README.md index 71ce9b2eca6..2dc81a115df 100644 --- a/tests/crashes/README.md +++ b/tests/crashes/README.md @@ -8,7 +8,7 @@ A test will "pass" if rustc exits with something other than 1 or 0. When adding crashes from https://github.com/rust-lang/rust/issues, the issue number should be noted in the file name (12345.rs should suffice) -and perhaps also inside the file via `//@ known-bug #4321` +and also inside the file via `//@ known-bug #4321` if possible. If you happen to fix one of the crashes, please move it to a fitting subdirectory in `tests/ui` and give it a meaningful name. @@ -21,3 +21,5 @@ to the description of your pull request will ensure the corresponding tickets will be closed automatically upon merge. The ticket ids can be found in the file name or the `known-bug` annotation inside the testfile. + +Please do not re-report any crashes that you find here! diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs index a68fe31f609..be23dcdb22a 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.rs +++ b/tests/mir-opt/pre-codegen/mem_replace.rs @@ -1,6 +1,7 @@ // skip-filecheck //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir -//@ ignore-debug: precondition checks on ptr::read/write are under cfg(debug_assertions) +//@ ignore-std-debug-assertions +// Reason: precondition checks on ptr::read/write are under cfg(debug_assertions) // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/ptr_offset.rs b/tests/mir-opt/pre-codegen/ptr_offset.rs index 88ee00296a0..120be99fc94 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.rs +++ b/tests/mir-opt/pre-codegen/ptr_offset.rs @@ -1,6 +1,6 @@ // skip-filecheck //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir -//@ ignore-debug: precondition checks are under cfg(debug_assertions) +//@ ignore-std-debug-assertions (precondition checks are under cfg(debug_assertions)) // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/slice_iter.rs b/tests/mir-opt/pre-codegen/slice_iter.rs index fee4214982d..46ded729852 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.rs +++ b/tests/mir-opt/pre-codegen/slice_iter.rs @@ -1,7 +1,7 @@ // skip-filecheck //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 //@ only-64bit (constants for `None::<&T>` show in the output) -//@ ignore-debug: precondition checks on ptr::add are under cfg(debug_assertions) +//@ ignore-std-debug-assertions (precondition checks on ptr::add are under cfg(debug_assertions)) // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/run-make/crate-loading/multiple-dep-versions-3.rs b/tests/run-make/crate-loading/multiple-dep-versions-3.rs index 07d888e9f10..f5c4d1baa81 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-3.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-3.rs @@ -3,3 +3,8 @@ extern crate dependency; pub use dependency::Type; +pub struct OtherType; +impl dependency::Trait for OtherType { + fn foo(&self) {} + fn bar() {} +} diff --git a/tests/run-make/crate-loading/multiple-dep-versions.rs b/tests/run-make/crate-loading/multiple-dep-versions.rs index 113af9c3025..c68a9e6489f 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions.rs @@ -1,10 +1,11 @@ extern crate dep_2_reexport; extern crate dependency; -use dep_2_reexport::Type; +use dep_2_reexport::{OtherType, Type}; use dependency::{Trait, do_something}; fn main() { do_something(Type); Type.foo(); Type::bar(); + do_something(OtherType); } diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 5d3302c7b02..2d5913c4bcb 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -18,47 +18,39 @@ fn main() { .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("foo")) .run_fail() - .assert_stderr_contains( - r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied - --> multiple-dep-versions.rs:7:18 - | -7 | do_something(Type); - | ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` - | | - | required by a bound introduced by this call - | -help: there are multiple different versions of crate `dependency` in the dependency graph - --> multiple-dep-versions.rs:1:1 - | -1 | extern crate dep_2_reexport; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `dependency` is used here, as a dependency of crate `foo` -2 | extern crate dependency; - | ^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `dependency` is used here, as a direct dependency of the current crate"#, - ) - .assert_stderr_contains( - r#" -3 | pub struct Type(pub i32); - | ^^^^^^^^^^^^^^^ this type implements the required trait -4 | pub trait Trait { - | --------------- this is the required trait"#, - ) - .assert_stderr_contains( - r#" -3 | pub struct Type; - | ^^^^^^^^^^^^^^^ this type doesn't implement the required trait"#, - ) - .assert_stderr_contains( - r#" -error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope + .assert_stderr_contains(r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied because the trait comes from a different crate version + --> multiple-dep-versions.rs:7:18 + | +7 | do_something(Type); + | ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph"#) + .assert_stderr_contains(r#" +3 | pub struct Type(pub i32); + | --------------- this type implements the required trait +4 | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the required trait +"#) + .assert_stderr_contains(r#" +1 | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` +2 | extern crate dependency; + | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate"#) + .assert_stderr_contains(r#" +3 | pub struct Type; + | --------------- this type doesn't implement the required trait +4 | pub trait Trait { + | --------------- this is the found trait + = note: two types coming from two different versions of the same crate are different types even if they look the same + = help: you can use `cargo tree` to explore your dependency tree"#) + .assert_stderr_contains(r#"error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope --> multiple-dep-versions.rs:8:10 | 8 | Type.foo(); | ^^^ method not found in `Type` | -note: there are multiple different versions of crate `dependency` in the dependency graph"#, - ) - .assert_stderr_contains( - r#" +note: there are multiple different versions of crate `dependency` in the dependency graph"#) + .assert_stderr_contains(r#" 4 | pub trait Trait { | ^^^^^^^^^^^^^^^ this is the trait that is needed 5 | fn foo(&self); @@ -67,25 +59,19 @@ note: there are multiple different versions of crate `dependency` in the depende ::: multiple-dep-versions.rs:4:18 | 4 | use dependency::{Trait, do_something}; - | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#, - ) - .assert_stderr_contains( - r#" + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#) + .assert_stderr_contains(r#" 4 | pub trait Trait { - | --------------- this is the trait that was imported"#, - ) - .assert_stderr_contains( - r#" + | --------------- this is the trait that was imported"#) + .assert_stderr_contains(r#" error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope --> multiple-dep-versions.rs:9:11 | 9 | Type::bar(); | ^^^ function or associated item not found in `Type` | -note: there are multiple different versions of crate `dependency` in the dependency graph"#, - ) - .assert_stderr_contains( - r#" +note: there are multiple different versions of crate `dependency` in the dependency graph"#) + .assert_stderr_contains(r#" 4 | pub trait Trait { | ^^^^^^^^^^^^^^^ this is the trait that is needed 5 | fn foo(&self); @@ -95,6 +81,9 @@ note: there are multiple different versions of crate `dependency` in the depende ::: multiple-dep-versions.rs:4:18 | 4 | use dependency::{Trait, do_something}; - | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#, - ); + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#) + .assert_stderr_contains( + r#" +6 | pub struct OtherType; + | -------------------- this type doesn't implement the required trait"#); } diff --git a/tests/run-make/pointer-auth-link-with-c/rmake.rs b/tests/run-make/pointer-auth-link-with-c/rmake.rs index 960eafa546b..7b6dff10eae 100644 --- a/tests/run-make/pointer-auth-link-with-c/rmake.rs +++ b/tests/run-make/pointer-auth-link-with-c/rmake.rs @@ -1,7 +1,7 @@ // `-Z branch protection` is an unstable compiler feature which adds pointer-authentication // code (PAC), a useful hashing measure for verifying that pointers have not been modified. // This test checks that compilation and execution is successful when this feature is activated, -// with some of its possible extra arguments (bti, pac-ret, leaf). +// with some of its possible extra arguments (bti, pac-ret, pc, leaf, b-key). // See https://github.com/rust-lang/rust/pull/88354 //@ only-aarch64 @@ -25,4 +25,16 @@ fn main() { llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); rustc().arg("-Zbranch-protection=bti,pac-ret,leaf").input("test.rs").run(); run("test"); + + // FIXME: +pc was only recently added to LLVM + // cc().arg("-v") + // .arg("-c") + // .out_exe("test") + // .input("test.c") + // .arg("-mbranch-protection=bti+pac-ret+pc+leaf") + // .run(); + // let obj_file = if is_msvc() { "test.obj" } else { "test" }; + // llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); + // rustc().arg("-Zbranch-protection=bti,pac-ret,pc,leaf").input("test.rs").run(); + // run("test"); } diff --git a/tests/run-make/print-target-cpus-native/rmake.rs b/tests/run-make/print-target-cpus-native/rmake.rs new file mode 100644 index 00000000000..3bd210654db --- /dev/null +++ b/tests/run-make/print-target-cpus-native/rmake.rs @@ -0,0 +1,39 @@ +//@ ignore-cross-compile +//@ needs-llvm-components: aarch64 x86 +// FIXME(#132514): Is needs-llvm-components actually necessary for this test? + +use run_make_support::{assert_contains_regex, rfs, rustc, target}; + +// Test that when querying `--print=target-cpus` for a target with the same +// architecture as the host, the first CPU is "native" with a suitable remark. + +fn main() { + let expected = r"^Available CPUs for this target: + native +- Select the CPU of the current host \(currently [^ )]+\)\. +"; + + // Without an explicit target. + rustc().print("target-cpus").run().assert_stdout_contains_regex(expected); + + // With an explicit target that happens to be the host. + let host = target(); // Because of ignore-cross-compile, assume host == target. + rustc().print("target-cpus").target(host).run().assert_stdout_contains_regex(expected); + + // With an explicit output path. + rustc().print("target-cpus=./xyzzy.txt").run().assert_stdout_equals(""); + assert_contains_regex(rfs::read_to_string("./xyzzy.txt"), expected); + + // Now try some cross-target queries with the same arch as the host. + // (Specify multiple targets so that at least one of them is not the host.) + let cross_targets: &[&str] = if cfg!(target_arch = "aarch64") { + &["aarch64-unknown-linux-gnu", "aarch64-apple-darwin"] + } else if cfg!(target_arch = "x86_64") { + &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"] + } else { + &[] + }; + for target in cross_targets { + println!("Trying target: {target}"); + rustc().print("target-cpus").target(target).run().assert_stdout_contains_regex(expected); + } +} diff --git a/tests/run-make/target-specs/definitely-not-builtin-target.json b/tests/run-make/target-specs/definitely-not-builtin-target.json deleted file mode 100644 index b36fa993d97..00000000000 --- a/tests/run-make/target-specs/definitely-not-builtin-target.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "arch": "x86_64", - "is-builtin": true, - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", - "llvm-target": "x86_64-unknown-unknown-gnu", - "target-pointer-width": "64" -} diff --git a/tests/run-make/target-specs/rmake.rs b/tests/run-make/target-specs/rmake.rs index 499c6c2079a..79c888ab340 100644 --- a/tests/run-make/target-specs/rmake.rs +++ b/tests/run-make/target-specs/rmake.rs @@ -54,11 +54,6 @@ fn main() { .run(); rustc() .input("foo.rs") - .target("definitely-not-builtin-target") - .run_fail() - .assert_stderr_contains("may not set is_builtin"); - rustc() - .input("foo.rs") .target("endianness-mismatch") .run_fail() .assert_stderr_contains(r#""data-layout" claims architecture is little-endian"#); diff --git a/tests/rustdoc-ui/show-coverage-json.rs b/tests/rustdoc-ui/show-coverage-json.rs new file mode 100644 index 00000000000..3851e34fe35 --- /dev/null +++ b/tests/rustdoc-ui/show-coverage-json.rs @@ -0,0 +1,13 @@ +//@ compile-flags: -Z unstable-options --show-coverage --output-format=json +//@ check-pass + +mod bar { + /// a + /// + /// ``` + /// let x = 0; + /// ``` + pub struct Foo; +} + +pub use bar::Foo; diff --git a/tests/rustdoc-ui/show-coverage-json.stdout b/tests/rustdoc-ui/show-coverage-json.stdout new file mode 100644 index 00000000000..ed5b5a60212 --- /dev/null +++ b/tests/rustdoc-ui/show-coverage-json.stdout @@ -0,0 +1 @@ +{"$DIR/show-coverage-json.rs":{"total":2,"with_docs":1,"total_examples":2,"with_examples":1}} diff --git a/tests/rustdoc-ui/show-coverage.rs b/tests/rustdoc-ui/show-coverage.rs new file mode 100644 index 00000000000..00bb1606a82 --- /dev/null +++ b/tests/rustdoc-ui/show-coverage.rs @@ -0,0 +1,13 @@ +//@ compile-flags: -Z unstable-options --show-coverage +//@ check-pass + +mod bar { + /// a + /// + /// ``` + /// let x = 0; + /// ``` + pub struct Foo; +} + +pub use bar::Foo; diff --git a/tests/rustdoc-ui/show-coverage.stdout b/tests/rustdoc-ui/show-coverage.stdout new file mode 100644 index 00000000000..b3b7679771f --- /dev/null +++ b/tests/rustdoc-ui/show-coverage.stdout @@ -0,0 +1,7 @@ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...ests/rustdoc-ui/show-coverage.rs | 1 | 50.0% | 1 | 50.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 1 | 50.0% | 1 | 50.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/tests/rustdoc/const-effect-param.rs b/tests/rustdoc/const-effect-param.rs index 3c81700ba83..cceb0adac30 100644 --- a/tests/rustdoc/const-effect-param.rs +++ b/tests/rustdoc/const-effect-param.rs @@ -1,8 +1,7 @@ // Check that we don't render host effect parameters & arguments. #![crate_name = "foo"] -#![feature(effects, const_trait_impl)] -#![allow(incomplete_features)] +#![feature(const_trait_impl)] #[const_trait] pub trait Tr { diff --git a/tests/rustdoc/const-fn-effects.rs b/tests/rustdoc/const-fn-effects.rs index 4523870c8a5..df060a1aa1a 100644 --- a/tests/rustdoc/const-fn-effects.rs +++ b/tests/rustdoc/const-fn-effects.rs @@ -1,6 +1,4 @@ #![crate_name = "foo"] -#![feature(effects)] -#![allow(incomplete_features)] //@ has foo/fn.bar.html //@ has - '//pre[@class="rust item-decl"]' 'pub const fn bar() -> ' diff --git a/tests/rustdoc/const-intrinsic.rs b/tests/rustdoc/const-intrinsic.rs index 520e253469c..8444d4a3aa7 100644 --- a/tests/rustdoc/const-intrinsic.rs +++ b/tests/rustdoc/const-intrinsic.rs @@ -1,20 +1,26 @@ -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![feature(staged_api)] #![crate_name = "foo"] #![stable(since="1.0.0", feature="rust1")] -extern "rust-intrinsic" { - //@ has 'foo/fn.transmute.html' - //@ has - '//pre[@class="rust item-decl"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U' - #[stable(since="1.0.0", feature="rust1")] - #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] - pub fn transmute<T, U>(_: T) -> U; +//@ has 'foo/fn.transmute.html' +//@ has - '//pre[@class="rust item-decl"]' 'pub const unsafe fn transmute<T, U>(_: T) -> U' +#[stable(since="1.0.0", feature="rust1")] +#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn transmute<T, U>(_: T) -> U { + loop {} +} - //@ has 'foo/fn.unreachable.html' - //@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !' - #[stable(since="1.0.0", feature="rust1")] - pub fn unreachable() -> !; +//@ has 'foo/fn.unreachable.html' +//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe fn unreachable() -> !' +#[stable(since="1.0.0", feature="rust1")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub unsafe fn unreachable() -> ! { + loop {} } extern "C" { diff --git a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs index 346f7120b5b..d301c355994 100644 --- a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs +++ b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs @@ -22,6 +22,7 @@ extern crate assoc_item_trait_bounds as aux; //@ has - '//*[@id="associatedtype.Out12"]' "type Out12: for<'w> Helper<B<'w> = Cow<'w, str>, A<'w> = bool>" //@ has - '//*[@id="associatedtype.Out13"]' "type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>" //@ has - '//*[@id="associatedtype.Out14"]' "type Out14<P: Copy + Eq, Q: ?Sized>" +//@ has - '//*[@id="associatedtype.Out15"]' "type Out15: AsyncFnMut(i32) -> bool" // // Snapshots: // Check that we don't render any where-clauses for the following associated types since diff --git a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs index 551e97a2fa9..56708ec9310 100644 --- a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs +++ b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs @@ -1,3 +1,7 @@ +#![feature(async_closure)] + +use std::ops::AsyncFnMut; + pub trait Main { type Item; @@ -16,6 +20,7 @@ pub trait Main { type Out12: for<'w> Helper<B<'w> = std::borrow::Cow<'w, str>, A<'w> = bool>; type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>; type Out14<P: Copy + Eq, Q: ?Sized>; + type Out15: AsyncFnMut(i32) -> bool; fn make<F>(_: F, _: impl FnMut(&str) -> bool) where diff --git a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs index 161d0c9d54e..db198e0fce9 100644 --- a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs +++ b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(effects, const_trait_impl)] -#![allow(incomplete_features)] +#![feature(const_trait_impl)] #[const_trait] pub trait Resource {} diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs index eb3e00af3b0..8a86e3e5e97 100644 --- a/tests/rustdoc/rfc-2632-const-trait-impl.rs +++ b/tests/rustdoc/rfc-2632-const-trait-impl.rs @@ -6,10 +6,9 @@ // stabilized when changing `@!has` to `@has`, and please do // not remove this test. // -// FIXME(effects) add `const_trait` to `Fn` so we use `~const` -// FIXME(effects) restore `const_trait` to `Destruct` -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +// FIXME(const_trait_impl) add `const_trait` to `Fn` so we use `~const` +// FIXME(const_trait_impl) restore `const_trait` to `Destruct` +#![feature(const_trait_impl)] #![crate_name = "foo"] use std::marker::Destruct; diff --git a/tests/rustdoc/safe-intrinsic.rs b/tests/rustdoc/safe-intrinsic.rs index b46ffed99c3..07af04ace60 100644 --- a/tests/rustdoc/safe-intrinsic.rs +++ b/tests/rustdoc/safe-intrinsic.rs @@ -5,18 +5,17 @@ #![no_core] #![crate_name = "foo"] -extern "rust-intrinsic" { - //@ has 'foo/fn.abort.html' - //@ has - '//pre[@class="rust item-decl"]' 'pub extern "rust-intrinsic" fn abort() -> !' - #[rustc_safe_intrinsic] - pub fn abort() -> !; - //@ has 'foo/fn.unreachable.html' - //@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !' - pub fn unreachable() -> !; +//@ has 'foo/fn.abort.html' +//@ has - '//pre[@class="rust item-decl"]' 'pub fn abort() -> !' +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub fn abort() -> ! { + loop {} } - -extern "C" { - //@ has 'foo/fn.needs_drop.html' - //@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !' - pub fn needs_drop() -> !; +//@ has 'foo/fn.unreachable.html' +//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe fn unreachable() -> !' +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub unsafe fn unreachable() -> ! { + loop {} } diff --git a/tests/ui-fulldeps/hash-stable-is-unstable.rs b/tests/ui-fulldeps/hash-stable-is-unstable.rs index e5d158a2661..dc778695287 100644 --- a/tests/ui-fulldeps/hash-stable-is-unstable.rs +++ b/tests/ui-fulldeps/hash-stable-is-unstable.rs @@ -1,24 +1,25 @@ +//@ ignore-stage1 FIXME: this line can be removed once these new error messages are in stage 0 rustc //@ compile-flags: -Zdeduplicate-diagnostics=yes extern crate rustc_data_structures; -//~^ use of unstable library feature 'rustc_private' +//~^ use of unstable library feature `rustc_private` //~| NOTE: issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date extern crate rustc_macros; -//~^ use of unstable library feature 'rustc_private' +//~^ use of unstable library feature `rustc_private` //~| NOTE: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date extern crate rustc_query_system; -//~^ use of unstable library feature 'rustc_private' +//~^ use of unstable library feature `rustc_private` //~| NOTE: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date use rustc_macros::HashStable; -//~^ use of unstable library feature 'rustc_private' +//~^ use of unstable library feature `rustc_private` //~| NOTE: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date #[derive(HashStable)] -//~^ use of unstable library feature 'rustc_private' +//~^ use of unstable library feature `rustc_private` //~| NOTE: in this expansion of #[derive(HashStable)] //~| NOTE: in this expansion of #[derive(HashStable)] //~| NOTE: in this expansion of #[derive(HashStable)] diff --git a/tests/ui-fulldeps/hash-stable-is-unstable.stderr b/tests/ui-fulldeps/hash-stable-is-unstable.stderr index c9aac624cbb..8d809175875 100644 --- a/tests/ui-fulldeps/hash-stable-is-unstable.stderr +++ b/tests/ui-fulldeps/hash-stable-is-unstable.stderr @@ -1,5 +1,5 @@ -error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? - --> $DIR/hash-stable-is-unstable.rs:2:1 +error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/hash-stable-is-unstable.rs:3:1 | LL | extern crate rustc_data_structures; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,8 +8,8 @@ LL | extern crate rustc_data_structures; = help: add `#![feature(rustc_private)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? - --> $DIR/hash-stable-is-unstable.rs:6:1 +error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/hash-stable-is-unstable.rs:7:1 | LL | extern crate rustc_macros; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,8 +18,8 @@ LL | extern crate rustc_macros; = help: add `#![feature(rustc_private)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? - --> $DIR/hash-stable-is-unstable.rs:10:1 +error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/hash-stable-is-unstable.rs:11:1 | LL | extern crate rustc_query_system; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,8 +28,8 @@ LL | extern crate rustc_query_system; = help: add `#![feature(rustc_private)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? - --> $DIR/hash-stable-is-unstable.rs:15:5 +error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/hash-stable-is-unstable.rs:16:5 | LL | use rustc_macros::HashStable; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,8 +38,8 @@ LL | use rustc_macros::HashStable; = help: add `#![feature(rustc_private)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? - --> $DIR/hash-stable-is-unstable.rs:20:10 +error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/hash-stable-is-unstable.rs:21:10 | LL | #[derive(HashStable)] | ^^^^^^^^^^ diff --git a/tests/ui-fulldeps/pathless-extern-unstable.rs b/tests/ui-fulldeps/pathless-extern-unstable.rs index 2da1a7f0ddc..27272135696 100644 --- a/tests/ui-fulldeps/pathless-extern-unstable.rs +++ b/tests/ui-fulldeps/pathless-extern-unstable.rs @@ -1,9 +1,10 @@ +//@ ignore-stage1 FIXME: this line can be removed once these new error messages are in stage 0 rustc //@ edition:2018 //@ compile-flags:--extern rustc_middle // Test that `--extern rustc_middle` fails with `rustc_private`. pub use rustc_middle; -//~^ ERROR use of unstable library feature 'rustc_private' +//~^ ERROR use of unstable library feature `rustc_private` fn main() {} diff --git a/tests/ui-fulldeps/pathless-extern-unstable.stderr b/tests/ui-fulldeps/pathless-extern-unstable.stderr index 36e56adfdbd..a78b69f4d20 100644 --- a/tests/ui-fulldeps/pathless-extern-unstable.stderr +++ b/tests/ui-fulldeps/pathless-extern-unstable.stderr @@ -1,5 +1,5 @@ -error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? - --> $DIR/pathless-extern-unstable.rs:6:9 +error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/pathless-extern-unstable.rs:7:9 | LL | pub use rustc_middle; | ^^^^^^^^^^^^ diff --git a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs new file mode 100644 index 00000000000..e039ca07dd4 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs @@ -0,0 +1,149 @@ +//@ run-pass +//! Test information about crate definitions (local and external). + +//@ ignore-stage1 +//@ ignore-cross-compile +//@ ignore-remote +//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 + +#![feature(rustc_private)] +#![feature(assert_matches)] + +extern crate rustc_hir; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use rustc_smir::rustc_internal; +use stable_mir::CrateDef; +use std::collections::HashSet; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "crate_defs"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_stable_mir() -> ControlFlow<()> { + // Find items in the local crate. + let local = stable_mir::local_crate(); + check_items(&local.statics(), &["PRIVATE_STATIC", "dummy::PUBLIC_STATIC"]); + check_items( + &local.fn_defs(), + &[ + "top_level", + "dummy::public_fn", + "dummy::private_fn", + "dummy::PrivateStruct::new", + "<dummy::PrivateStruct as std::ops::Drop>::drop", + "DummyTrait::method", + "<T as DummyTrait>::method", + ], + ); + + // Find items inside core crate. + // FIXME: We are currently missing primitive type methods and trait implementations for external + // crates. + let core = stable_mir::find_crates("core").pop().expect("Cannot find `core` crate"); + contains( + &core.fn_defs(), + &[ + "std::fmt::Debug::fmt", + "std::option::Option::<T>::is_some", + "std::ptr::swap", + "<std::slice::Iter<'a, T> as std::iter::Iterator>::next", + "core::num::<impl u8>::abs_diff", + ], + ); + // Ensure nothing crashes. There is no public static in core that we can test here. + let _ = core.statics(); + + ControlFlow::Continue(()) +} + +/// Check if the list of definitions matches the expected list. +/// Note that order doesn't matter. +fn check_items<T: CrateDef>(items: &[T], expected: &[&str]) { + let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect(); + let item_names: HashSet<_> = items.iter().map(|item| item.name()).collect(); + assert_eq!(item_names, expected); +} + +/// Check that the list contains the expected items. +fn contains<T: CrateDef + std::fmt::Debug>(items: &[T], expected: &[&str]) { + let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect(); + let item_names = items.iter().map(|item| item.name()).collect(); + let not_found: Vec<_> = expected.difference(&item_names).collect(); + assert!(not_found.is_empty(), "Missing items: {:?}", not_found); +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "crate_definitions.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, test_stable_mir).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + #![allow(dead_code, unused_variables)] + static PRIVATE_STATIC: u8 = 0; + fn top_level() -> &'static str {{ + "hello" + }} + + pub trait DummyTrait {{ + fn method(&self) -> Self; + }} + + impl<T: Copy> DummyTrait for T {{ + fn method(&self) -> T {{ + *self + }} + }} + + pub mod dummy {{ + pub static mut PUBLIC_STATIC: Option<char> = None; + + pub fn public_fn(input: bool) -> bool {{ + private_fn(!input) + }} + + fn private_fn(input: bool) -> bool {{ + todo!() + }} + + struct PrivateStruct {{ + field: u32, + }} + + impl PrivateStruct {{ + fn new() -> Self {{ + Self {{ field: 42 }} + }} + }} + + impl Drop for PrivateStruct {{ + fn drop(&mut self) {{ + println!("Dropping PrivateStruct"); + }} + }} + }} + "# + )?; + Ok(()) +} diff --git a/tests/ui/asm/bad-arch.rs b/tests/ui/asm/bad-arch.rs deleted file mode 100644 index f84b9944b36..00000000000 --- a/tests/ui/asm/bad-arch.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ compile-flags: --target sparc-unknown-linux-gnu -//@ needs-llvm-components: sparc - -#![feature(no_core, lang_items, rustc_attrs)] -#![no_core] - -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} -#[rustc_builtin_macro] -macro_rules! global_asm { - () => {}; -} -#[lang = "sized"] -trait Sized {} - -fn main() { - unsafe { - asm!(""); - //~^ ERROR inline assembly is unsupported on this target - } -} - -global_asm!(""); -//~^ ERROR inline assembly is unsupported on this target diff --git a/tests/ui/asm/bad-arch.stderr b/tests/ui/asm/bad-arch.stderr deleted file mode 100644 index c6f726600eb..00000000000 --- a/tests/ui/asm/bad-arch.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0472]: inline assembly is unsupported on this target - --> $DIR/bad-arch.rs:20:9 - | -LL | asm!(""); - | ^^^^^^^^ - -error[E0472]: inline assembly is unsupported on this target - --> $DIR/bad-arch.rs:25:1 - | -LL | global_asm!(""); - | ^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0472`. diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr new file mode 100644 index 00000000000..34105ceac04 --- /dev/null +++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr @@ -0,0 +1,264 @@ +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("r2") _); + | ^^^^^^^^^^^ + +error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("r29") _); + | ^^^^^^^^^^^^ + +error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("r30") _); + | ^^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `lr`: the link register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("lr") _); + | ^^^^^^^^^^^ + +error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("ctr") _); + | ^^^^^^^^^^^^ + +error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", out("vrsave") _); + | ^^^^^^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:66:18 + | +LL | asm!("", in("cr") x); + | ^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:69:18 + | +LL | asm!("", out("cr") x); + | ^^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:72:26 + | +LL | asm!("/* {} */", in(cr) x); + | ^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:75:26 + | +LL | asm!("/* {} */", out(cr) _); + | ^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:79:18 + | +LL | asm!("", in("xer") x); + | ^^^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:82:18 + | +LL | asm!("", out("xer") x); + | ^^^^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:85:26 + | +LL | asm!("/* {} */", in(xer) x); + | ^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:88:26 + | +LL | asm!("/* {} */", out(xer) _); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:93:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:96:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:99:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:102:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: register `cr0` conflicts with register `cr` + --> $DIR/bad-reg.rs:106:31 + | +LL | asm!("", out("cr") _, out("cr0") _); + | ----------- ^^^^^^^^^^^^ register `cr0` + | | + | register `cr` + +error: register `cr1` conflicts with register `cr` + --> $DIR/bad-reg.rs:108:31 + | +LL | asm!("", out("cr") _, out("cr1") _); + | ----------- ^^^^^^^^^^^^ register `cr1` + | | + | register `cr` + +error: register `cr2` conflicts with register `cr` + --> $DIR/bad-reg.rs:110:31 + | +LL | asm!("", out("cr") _, out("cr2") _); + | ----------- ^^^^^^^^^^^^ register `cr2` + | | + | register `cr` + +error: register `cr3` conflicts with register `cr` + --> $DIR/bad-reg.rs:112:31 + | +LL | asm!("", out("cr") _, out("cr3") _); + | ----------- ^^^^^^^^^^^^ register `cr3` + | | + | register `cr` + +error: register `cr4` conflicts with register `cr` + --> $DIR/bad-reg.rs:114:31 + | +LL | asm!("", out("cr") _, out("cr4") _); + | ----------- ^^^^^^^^^^^^ register `cr4` + | | + | register `cr` + +error: register `cr5` conflicts with register `cr` + --> $DIR/bad-reg.rs:116:31 + | +LL | asm!("", out("cr") _, out("cr5") _); + | ----------- ^^^^^^^^^^^^ register `cr5` + | | + | register `cr` + +error: register `cr6` conflicts with register `cr` + --> $DIR/bad-reg.rs:118:31 + | +LL | asm!("", out("cr") _, out("cr6") _); + | ----------- ^^^^^^^^^^^^ register `cr6` + | | + | register `cr` + +error: register `cr7` conflicts with register `cr` + --> $DIR/bad-reg.rs:120:31 + | +LL | asm!("", out("cr") _, out("cr7") _); + | ----------- ^^^^^^^^^^^^ register `cr7` + | | + | register `cr` + +error: cannot use register `r13`: r13 is a reserved register on this target + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("r13") _); + | ^^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:66:27 + | +LL | asm!("", in("cr") x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:69:28 + | +LL | asm!("", out("cr") x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:72:33 + | +LL | asm!("/* {} */", in(cr) x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", in("xer") x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:82:29 + | +LL | asm!("", out("xer") x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:85:34 + | +LL | asm!("/* {} */", in(xer) x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:93:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:96:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:99:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 38 previous errors + diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr new file mode 100644 index 00000000000..34105ceac04 --- /dev/null +++ b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr @@ -0,0 +1,264 @@ +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("r2") _); + | ^^^^^^^^^^^ + +error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("r29") _); + | ^^^^^^^^^^^^ + +error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("r30") _); + | ^^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `lr`: the link register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("lr") _); + | ^^^^^^^^^^^ + +error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("ctr") _); + | ^^^^^^^^^^^^ + +error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", out("vrsave") _); + | ^^^^^^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:66:18 + | +LL | asm!("", in("cr") x); + | ^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:69:18 + | +LL | asm!("", out("cr") x); + | ^^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:72:26 + | +LL | asm!("/* {} */", in(cr) x); + | ^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:75:26 + | +LL | asm!("/* {} */", out(cr) _); + | ^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:79:18 + | +LL | asm!("", in("xer") x); + | ^^^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:82:18 + | +LL | asm!("", out("xer") x); + | ^^^^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:85:26 + | +LL | asm!("/* {} */", in(xer) x); + | ^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:88:26 + | +LL | asm!("/* {} */", out(xer) _); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:93:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:96:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:99:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:102:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: register `cr0` conflicts with register `cr` + --> $DIR/bad-reg.rs:106:31 + | +LL | asm!("", out("cr") _, out("cr0") _); + | ----------- ^^^^^^^^^^^^ register `cr0` + | | + | register `cr` + +error: register `cr1` conflicts with register `cr` + --> $DIR/bad-reg.rs:108:31 + | +LL | asm!("", out("cr") _, out("cr1") _); + | ----------- ^^^^^^^^^^^^ register `cr1` + | | + | register `cr` + +error: register `cr2` conflicts with register `cr` + --> $DIR/bad-reg.rs:110:31 + | +LL | asm!("", out("cr") _, out("cr2") _); + | ----------- ^^^^^^^^^^^^ register `cr2` + | | + | register `cr` + +error: register `cr3` conflicts with register `cr` + --> $DIR/bad-reg.rs:112:31 + | +LL | asm!("", out("cr") _, out("cr3") _); + | ----------- ^^^^^^^^^^^^ register `cr3` + | | + | register `cr` + +error: register `cr4` conflicts with register `cr` + --> $DIR/bad-reg.rs:114:31 + | +LL | asm!("", out("cr") _, out("cr4") _); + | ----------- ^^^^^^^^^^^^ register `cr4` + | | + | register `cr` + +error: register `cr5` conflicts with register `cr` + --> $DIR/bad-reg.rs:116:31 + | +LL | asm!("", out("cr") _, out("cr5") _); + | ----------- ^^^^^^^^^^^^ register `cr5` + | | + | register `cr` + +error: register `cr6` conflicts with register `cr` + --> $DIR/bad-reg.rs:118:31 + | +LL | asm!("", out("cr") _, out("cr6") _); + | ----------- ^^^^^^^^^^^^ register `cr6` + | | + | register `cr` + +error: register `cr7` conflicts with register `cr` + --> $DIR/bad-reg.rs:120:31 + | +LL | asm!("", out("cr") _, out("cr7") _); + | ----------- ^^^^^^^^^^^^ register `cr7` + | | + | register `cr` + +error: cannot use register `r13`: r13 is a reserved register on this target + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("r13") _); + | ^^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:66:27 + | +LL | asm!("", in("cr") x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:69:28 + | +LL | asm!("", out("cr") x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:72:33 + | +LL | asm!("/* {} */", in(cr) x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", in("xer") x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:82:29 + | +LL | asm!("", out("xer") x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:85:34 + | +LL | asm!("/* {} */", in(xer) x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:93:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:96:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:99:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 38 previous errors + diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr new file mode 100644 index 00000000000..34105ceac04 --- /dev/null +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr @@ -0,0 +1,264 @@ +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("r2") _); + | ^^^^^^^^^^^ + +error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("r29") _); + | ^^^^^^^^^^^^ + +error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("r30") _); + | ^^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `lr`: the link register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("lr") _); + | ^^^^^^^^^^^ + +error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("ctr") _); + | ^^^^^^^^^^^^ + +error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", out("vrsave") _); + | ^^^^^^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:66:18 + | +LL | asm!("", in("cr") x); + | ^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:69:18 + | +LL | asm!("", out("cr") x); + | ^^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:72:26 + | +LL | asm!("/* {} */", in(cr) x); + | ^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:75:26 + | +LL | asm!("/* {} */", out(cr) _); + | ^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:79:18 + | +LL | asm!("", in("xer") x); + | ^^^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:82:18 + | +LL | asm!("", out("xer") x); + | ^^^^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:85:26 + | +LL | asm!("/* {} */", in(xer) x); + | ^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:88:26 + | +LL | asm!("/* {} */", out(xer) _); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:93:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:96:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:99:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:102:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: register `cr0` conflicts with register `cr` + --> $DIR/bad-reg.rs:106:31 + | +LL | asm!("", out("cr") _, out("cr0") _); + | ----------- ^^^^^^^^^^^^ register `cr0` + | | + | register `cr` + +error: register `cr1` conflicts with register `cr` + --> $DIR/bad-reg.rs:108:31 + | +LL | asm!("", out("cr") _, out("cr1") _); + | ----------- ^^^^^^^^^^^^ register `cr1` + | | + | register `cr` + +error: register `cr2` conflicts with register `cr` + --> $DIR/bad-reg.rs:110:31 + | +LL | asm!("", out("cr") _, out("cr2") _); + | ----------- ^^^^^^^^^^^^ register `cr2` + | | + | register `cr` + +error: register `cr3` conflicts with register `cr` + --> $DIR/bad-reg.rs:112:31 + | +LL | asm!("", out("cr") _, out("cr3") _); + | ----------- ^^^^^^^^^^^^ register `cr3` + | | + | register `cr` + +error: register `cr4` conflicts with register `cr` + --> $DIR/bad-reg.rs:114:31 + | +LL | asm!("", out("cr") _, out("cr4") _); + | ----------- ^^^^^^^^^^^^ register `cr4` + | | + | register `cr` + +error: register `cr5` conflicts with register `cr` + --> $DIR/bad-reg.rs:116:31 + | +LL | asm!("", out("cr") _, out("cr5") _); + | ----------- ^^^^^^^^^^^^ register `cr5` + | | + | register `cr` + +error: register `cr6` conflicts with register `cr` + --> $DIR/bad-reg.rs:118:31 + | +LL | asm!("", out("cr") _, out("cr6") _); + | ----------- ^^^^^^^^^^^^ register `cr6` + | | + | register `cr` + +error: register `cr7` conflicts with register `cr` + --> $DIR/bad-reg.rs:120:31 + | +LL | asm!("", out("cr") _, out("cr7") _); + | ----------- ^^^^^^^^^^^^ register `cr7` + | | + | register `cr` + +error: cannot use register `r13`: r13 is a reserved register on this target + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("r13") _); + | ^^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:66:27 + | +LL | asm!("", in("cr") x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:69:28 + | +LL | asm!("", out("cr") x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:72:33 + | +LL | asm!("/* {} */", in(cr) x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", in("xer") x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:82:29 + | +LL | asm!("", out("xer") x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:85:34 + | +LL | asm!("/* {} */", in(xer) x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:93:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:96:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:99:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 38 previous errors + diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr new file mode 100644 index 00000000000..34105ceac04 --- /dev/null +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr @@ -0,0 +1,264 @@ +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("r2") _); + | ^^^^^^^^^^^ + +error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("r29") _); + | ^^^^^^^^^^^^ + +error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("r30") _); + | ^^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `lr`: the link register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("lr") _); + | ^^^^^^^^^^^ + +error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("ctr") _); + | ^^^^^^^^^^^^ + +error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", out("vrsave") _); + | ^^^^^^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:66:18 + | +LL | asm!("", in("cr") x); + | ^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:69:18 + | +LL | asm!("", out("cr") x); + | ^^^^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:72:26 + | +LL | asm!("/* {} */", in(cr) x); + | ^^^^^^^^ + +error: register class `cr` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:75:26 + | +LL | asm!("/* {} */", out(cr) _); + | ^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:79:18 + | +LL | asm!("", in("xer") x); + | ^^^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:82:18 + | +LL | asm!("", out("xer") x); + | ^^^^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:85:26 + | +LL | asm!("/* {} */", in(xer) x); + | ^^^^^^^^^ + +error: register class `xer` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:88:26 + | +LL | asm!("/* {} */", out(xer) _); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:93:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:96:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:99:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:102:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: register `cr0` conflicts with register `cr` + --> $DIR/bad-reg.rs:106:31 + | +LL | asm!("", out("cr") _, out("cr0") _); + | ----------- ^^^^^^^^^^^^ register `cr0` + | | + | register `cr` + +error: register `cr1` conflicts with register `cr` + --> $DIR/bad-reg.rs:108:31 + | +LL | asm!("", out("cr") _, out("cr1") _); + | ----------- ^^^^^^^^^^^^ register `cr1` + | | + | register `cr` + +error: register `cr2` conflicts with register `cr` + --> $DIR/bad-reg.rs:110:31 + | +LL | asm!("", out("cr") _, out("cr2") _); + | ----------- ^^^^^^^^^^^^ register `cr2` + | | + | register `cr` + +error: register `cr3` conflicts with register `cr` + --> $DIR/bad-reg.rs:112:31 + | +LL | asm!("", out("cr") _, out("cr3") _); + | ----------- ^^^^^^^^^^^^ register `cr3` + | | + | register `cr` + +error: register `cr4` conflicts with register `cr` + --> $DIR/bad-reg.rs:114:31 + | +LL | asm!("", out("cr") _, out("cr4") _); + | ----------- ^^^^^^^^^^^^ register `cr4` + | | + | register `cr` + +error: register `cr5` conflicts with register `cr` + --> $DIR/bad-reg.rs:116:31 + | +LL | asm!("", out("cr") _, out("cr5") _); + | ----------- ^^^^^^^^^^^^ register `cr5` + | | + | register `cr` + +error: register `cr6` conflicts with register `cr` + --> $DIR/bad-reg.rs:118:31 + | +LL | asm!("", out("cr") _, out("cr6") _); + | ----------- ^^^^^^^^^^^^ register `cr6` + | | + | register `cr` + +error: register `cr7` conflicts with register `cr` + --> $DIR/bad-reg.rs:120:31 + | +LL | asm!("", out("cr") _, out("cr7") _); + | ----------- ^^^^^^^^^^^^ register `cr7` + | | + | register `cr` + +error: cannot use register `r13`: r13 is a reserved register on this target + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("r13") _); + | ^^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:66:27 + | +LL | asm!("", in("cr") x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:69:28 + | +LL | asm!("", out("cr") x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:72:33 + | +LL | asm!("/* {} */", in(cr) x); + | ^ + | + = note: register class `cr` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", in("xer") x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:82:29 + | +LL | asm!("", out("xer") x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:85:34 + | +LL | asm!("/* {} */", in(xer) x); + | ^ + | + = note: register class `xer` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:93:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:96:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:99:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 38 previous errors + diff --git a/tests/ui/asm/powerpc/bad-reg.rs b/tests/ui/asm/powerpc/bad-reg.rs new file mode 100644 index 00000000000..5023ad51838 --- /dev/null +++ b/tests/ui/asm/powerpc/bad-reg.rs @@ -0,0 +1,124 @@ +//@ revisions: powerpc powerpc64 powerpc64le aix64 +//@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu +//@[powerpc] needs-llvm-components: powerpc +//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[powerpc64] needs-llvm-components: powerpc +//@[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu +//@[powerpc64le] needs-llvm-components: powerpc +//@[aix64] compile-flags: --target powerpc64-ibm-aix +//@[aix64] needs-llvm-components: powerpc +//@ needs-asm-support + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +impl Copy for i32 {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +fn f() { + let mut x = 0; + unsafe { + // Unsupported registers + asm!("", out("sp") _); + //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + asm!("", out("r2") _); + //~^ ERROR invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm + asm!("", out("r13") _); + //~^ ERROR cannot use register `r13`: r13 is a reserved register on this target + asm!("", out("r29") _); + //~^ ERROR invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm + asm!("", out("r30") _); + //~^ ERROR invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm + asm!("", out("fp") _); + //~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + asm!("", out("lr") _); + //~^ ERROR invalid register `lr`: the link register cannot be used as an operand for inline asm + asm!("", out("ctr") _); + //~^ ERROR invalid register `ctr`: the counter register cannot be used as an operand for inline asm + asm!("", out("vrsave") _); + //~^ ERROR invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm + asm!("", out("v20") _); + asm!("", out("v21") _); + asm!("", out("v22") _); + asm!("", out("v23") _); + asm!("", out("v24") _); + asm!("", out("v25") _); + asm!("", out("v26") _); + asm!("", out("v27") _); + asm!("", out("v28") _); + asm!("", out("v29") _); + asm!("", out("v30") _); + asm!("", out("v31") _); + + // Clobber-only registers + // cr + asm!("", out("cr") _); // ok + asm!("", in("cr") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("cr") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(cr) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(cr) _); + //~^ ERROR can only be used as a clobber + // xer + asm!("", out("xer") _); // ok + asm!("", in("xer") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("xer") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(xer) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(xer) _); + //~^ ERROR can only be used as a clobber + // vreg + asm!("", out("v0") _); // ok + // FIXME: will be supported in the subsequent patch: https://github.com/rust-lang/rust/pull/131551 + asm!("", in("v0") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("v0") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(vreg) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(vreg) _); + //~^ ERROR can only be used as a clobber + + // Overlapping-only registers + asm!("", out("cr") _, out("cr0") _); + //~^ ERROR register `cr0` conflicts with register `cr` + asm!("", out("cr") _, out("cr1") _); + //~^ ERROR register `cr1` conflicts with register `cr` + asm!("", out("cr") _, out("cr2") _); + //~^ ERROR register `cr2` conflicts with register `cr` + asm!("", out("cr") _, out("cr3") _); + //~^ ERROR register `cr3` conflicts with register `cr` + asm!("", out("cr") _, out("cr4") _); + //~^ ERROR register `cr4` conflicts with register `cr` + asm!("", out("cr") _, out("cr5") _); + //~^ ERROR register `cr5` conflicts with register `cr` + asm!("", out("cr") _, out("cr6") _); + //~^ ERROR register `cr6` conflicts with register `cr` + asm!("", out("cr") _, out("cr7") _); + //~^ ERROR register `cr7` conflicts with register `cr` + asm!("", out("f0") _, out("v0") _); // ok + } +} diff --git a/tests/ui/asm/riscv/bad-reg.riscv32e.stderr b/tests/ui/asm/riscv/bad-reg.riscv32e.stderr new file mode 100644 index 00000000000..0ca566b7933 --- /dev/null +++ b/tests/ui/asm/riscv/bad-reg.riscv32e.stderr @@ -0,0 +1,212 @@ +error: invalid register `s1`: s1 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("s1") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `tp`: the thread pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("tp") _); + | ^^^^^^^^^^^ + +error: invalid register `zero`: the zero register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("zero") _); + | ^^^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:97:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:100:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:103:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:106:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: cannot use register `x16`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:49:18 + | +LL | asm!("", out("x16") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x17`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:51:18 + | +LL | asm!("", out("x17") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x18`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:53:18 + | +LL | asm!("", out("x18") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x19`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:55:18 + | +LL | asm!("", out("x19") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x20`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:57:18 + | +LL | asm!("", out("x20") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x21`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:59:18 + | +LL | asm!("", out("x21") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x22`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:61:18 + | +LL | asm!("", out("x22") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x23`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:63:18 + | +LL | asm!("", out("x23") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x24`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:65:18 + | +LL | asm!("", out("x24") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x25`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:67:18 + | +LL | asm!("", out("x25") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x26`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:69:18 + | +LL | asm!("", out("x26") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x27`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:71:18 + | +LL | asm!("", out("x27") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x28`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:73:18 + | +LL | asm!("", out("x28") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x29`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:75:18 + | +LL | asm!("", out("x29") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x30`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:77:18 + | +LL | asm!("", out("x30") _); + | ^^^^^^^^^^^^ + +error: cannot use register `x31`: register can't be used with the `e` target feature + --> $DIR/bad-reg.rs:79:18 + | +LL | asm!("", out("x31") _); + | ^^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:83:26 + | +LL | asm!("/* {} */", in(freg) f); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:85:26 + | +LL | asm!("/* {} */", out(freg) _); + | ^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:87:26 + | +LL | asm!("/* {} */", in(freg) d); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:90:26 + | +LL | asm!("/* {} */", out(freg) d); + | ^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:97:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:100:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:103:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 34 previous errors + diff --git a/tests/ui/asm/riscv/bad-reg.riscv32gc.stderr b/tests/ui/asm/riscv/bad-reg.riscv32gc.stderr new file mode 100644 index 00000000000..81b72884a12 --- /dev/null +++ b/tests/ui/asm/riscv/bad-reg.riscv32gc.stderr @@ -0,0 +1,92 @@ +error: invalid register `s1`: s1 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("s1") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `tp`: the thread pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("tp") _); + | ^^^^^^^^^^^ + +error: invalid register `zero`: the zero register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("zero") _); + | ^^^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:97:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:100:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:103:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:106:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:97:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:100:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:103:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 14 previous errors + diff --git a/tests/ui/asm/riscv/bad-reg.riscv32i.stderr b/tests/ui/asm/riscv/bad-reg.riscv32i.stderr new file mode 100644 index 00000000000..b951ffb3982 --- /dev/null +++ b/tests/ui/asm/riscv/bad-reg.riscv32i.stderr @@ -0,0 +1,116 @@ +error: invalid register `s1`: s1 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("s1") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `tp`: the thread pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("tp") _); + | ^^^^^^^^^^^ + +error: invalid register `zero`: the zero register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("zero") _); + | ^^^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:97:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:100:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:103:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:106:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:83:26 + | +LL | asm!("/* {} */", in(freg) f); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:85:26 + | +LL | asm!("/* {} */", out(freg) _); + | ^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:87:26 + | +LL | asm!("/* {} */", in(freg) d); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:90:26 + | +LL | asm!("/* {} */", out(freg) d); + | ^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:97:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:100:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:103:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 18 previous errors + diff --git a/tests/ui/asm/riscv/bad-reg.riscv32imafc.stderr b/tests/ui/asm/riscv/bad-reg.riscv32imafc.stderr new file mode 100644 index 00000000000..aba4ecc1886 --- /dev/null +++ b/tests/ui/asm/riscv/bad-reg.riscv32imafc.stderr @@ -0,0 +1,108 @@ +error: invalid register `s1`: s1 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("s1") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `tp`: the thread pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("tp") _); + | ^^^^^^^^^^^ + +error: invalid register `zero`: the zero register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("zero") _); + | ^^^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:97:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:100:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:103:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:106:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: `d` target feature is not enabled + --> $DIR/bad-reg.rs:87:35 + | +LL | asm!("/* {} */", in(freg) d); + | ^ + | + = note: this is required to use type `f64` with register class `freg` + +error: `d` target feature is not enabled + --> $DIR/bad-reg.rs:90:36 + | +LL | asm!("/* {} */", out(freg) d); + | ^ + | + = note: this is required to use type `f64` with register class `freg` + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:97:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:100:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:103:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 16 previous errors + diff --git a/tests/ui/asm/riscv/bad-reg.riscv64gc.stderr b/tests/ui/asm/riscv/bad-reg.riscv64gc.stderr new file mode 100644 index 00000000000..81b72884a12 --- /dev/null +++ b/tests/ui/asm/riscv/bad-reg.riscv64gc.stderr @@ -0,0 +1,92 @@ +error: invalid register `s1`: s1 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("s1") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `tp`: the thread pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("tp") _); + | ^^^^^^^^^^^ + +error: invalid register `zero`: the zero register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("zero") _); + | ^^^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:97:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:100:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:103:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:106:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:97:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:100:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:103:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 14 previous errors + diff --git a/tests/ui/asm/riscv/bad-reg.riscv64imac.stderr b/tests/ui/asm/riscv/bad-reg.riscv64imac.stderr new file mode 100644 index 00000000000..b951ffb3982 --- /dev/null +++ b/tests/ui/asm/riscv/bad-reg.riscv64imac.stderr @@ -0,0 +1,116 @@ +error: invalid register `s1`: s1 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", out("s1") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("gp") _); + | ^^^^^^^^^^^ + +error: invalid register `tp`: the thread pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("tp") _); + | ^^^^^^^^^^^ + +error: invalid register `zero`: the zero register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("zero") _); + | ^^^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:97:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:100:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:103:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:106:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:83:26 + | +LL | asm!("/* {} */", in(freg) f); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:85:26 + | +LL | asm!("/* {} */", out(freg) _); + | ^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:87:26 + | +LL | asm!("/* {} */", in(freg) d); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:90:26 + | +LL | asm!("/* {} */", out(freg) d); + | ^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:97:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:100:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:103:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 18 previous errors + diff --git a/tests/ui/asm/riscv/bad-reg.rs b/tests/ui/asm/riscv/bad-reg.rs new file mode 100644 index 00000000000..7bf25b6e0b5 --- /dev/null +++ b/tests/ui/asm/riscv/bad-reg.rs @@ -0,0 +1,109 @@ +//@ add-core-stubs +//@ needs-asm-support +//@ revisions: riscv32i riscv32imafc riscv32gc riscv32e riscv64imac riscv64gc +//@[riscv32i] compile-flags: --target riscv32i-unknown-none-elf +//@[riscv32i] needs-llvm-components: riscv +//@[riscv32imafc] compile-flags: --target riscv32imafc-unknown-none-elf +//@[riscv32imafc] needs-llvm-components: riscv +//@[riscv32gc] compile-flags: --target riscv32gc-unknown-linux-gnu +//@[riscv32gc] needs-llvm-components: riscv +//@[riscv32e] compile-flags: --target riscv32e-unknown-none-elf +//@[riscv32e] needs-llvm-components: riscv +//@[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf +//@[riscv64imac] needs-llvm-components: riscv +//@[riscv64gc] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64gc] needs-llvm-components: riscv + +// Unlike riscv32e-registers.rs, this tests if the rustc can reject invalid registers +// usage in the asm! API (in, out, inout, etc.). + +#![crate_type = "lib"] +#![feature(no_core, rustc_attrs)] +#![feature(asm_experimental_arch)] +#![no_core] + +extern crate minicore; +use minicore::*; + +fn f() { + let mut x = 0; + let mut f = 0.0_f32; + let mut d = 0.0_f64; + unsafe { + // Unsupported registers + asm!("", out("s1") _); + //~^ ERROR invalid register `s1`: s1 is used internally by LLVM and cannot be used as an operand for inline asm + asm!("", out("fp") _); + //~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + asm!("", out("sp") _); + //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + asm!("", out("gp") _); + //~^ ERROR invalid register `gp`: the global pointer cannot be used as an operand for inline asm + asm!("", out("gp") _); + //~^ ERROR invalid register `gp`: the global pointer cannot be used as an operand for inline asm + asm!("", out("tp") _); + //~^ ERROR invalid register `tp`: the thread pointer cannot be used as an operand for inline asm + asm!("", out("zero") _); + //~^ ERROR invalid register `zero`: the zero register cannot be used as an operand for inline asm + + asm!("", out("x16") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x17") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x18") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x19") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x20") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x21") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x22") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x23") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x24") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x25") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x26") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x27") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x28") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x29") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x30") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + asm!("", out("x31") _); + //[riscv32e]~^ ERROR register can't be used with the `e` target feature + + asm!("", out("f0") _); // ok + asm!("/* {} */", in(freg) f); + //[riscv32i,riscv32e,riscv64imac]~^ ERROR register class `freg` requires at least one of the following target features: d, f + asm!("/* {} */", out(freg) _); + //[riscv32i,riscv32e,riscv64imac]~^ ERROR register class `freg` requires at least one of the following target features: d, f + asm!("/* {} */", in(freg) d); + //[riscv32i,riscv32e,riscv64imac]~^ ERROR register class `freg` requires at least one of the following target features: d, f + //[riscv32imafc]~^^ ERROR `d` target feature is not enabled + asm!("/* {} */", out(freg) d); + //[riscv32i,riscv32e,riscv64imac]~^ ERROR register class `freg` requires at least one of the following target features: d, f + //[riscv32imafc]~^^ ERROR `d` target feature is not enabled + + // Clobber-only registers + // vreg + asm!("", out("v0") _); // ok + asm!("", in("v0") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("v0") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(vreg) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(vreg) _); + //~^ ERROR can only be used as a clobber + } +} diff --git a/tests/ui/abi/riscv32e-registers.riscv32e.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr index e3894431eb4..e7a86805b26 100644 --- a/tests/ui/abi/riscv32e-registers.riscv32e.stderr +++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32e.stderr @@ -1,5 +1,5 @@ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:43:11 + --> $DIR/riscv32e-registers.rs:46:11 | LL | asm!("li x16, 0"); | ^ @@ -11,7 +11,7 @@ LL | li x16, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:46:11 + --> $DIR/riscv32e-registers.rs:49:11 | LL | asm!("li x17, 0"); | ^ @@ -23,7 +23,7 @@ LL | li x17, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:49:11 + --> $DIR/riscv32e-registers.rs:52:11 | LL | asm!("li x18, 0"); | ^ @@ -35,7 +35,7 @@ LL | li x18, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:52:11 + --> $DIR/riscv32e-registers.rs:55:11 | LL | asm!("li x19, 0"); | ^ @@ -47,7 +47,7 @@ LL | li x19, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:55:11 + --> $DIR/riscv32e-registers.rs:58:11 | LL | asm!("li x20, 0"); | ^ @@ -59,7 +59,7 @@ LL | li x20, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:58:11 + --> $DIR/riscv32e-registers.rs:61:11 | LL | asm!("li x21, 0"); | ^ @@ -71,7 +71,7 @@ LL | li x21, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:61:11 + --> $DIR/riscv32e-registers.rs:64:11 | LL | asm!("li x22, 0"); | ^ @@ -83,7 +83,7 @@ LL | li x22, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:64:11 + --> $DIR/riscv32e-registers.rs:67:11 | LL | asm!("li x23, 0"); | ^ @@ -95,7 +95,7 @@ LL | li x23, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:67:11 + --> $DIR/riscv32e-registers.rs:70:11 | LL | asm!("li x24, 0"); | ^ @@ -107,7 +107,7 @@ LL | li x24, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:70:11 + --> $DIR/riscv32e-registers.rs:73:11 | LL | asm!("li x25, 0"); | ^ @@ -119,7 +119,7 @@ LL | li x25, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:73:11 + --> $DIR/riscv32e-registers.rs:76:11 | LL | asm!("li x26, 0"); | ^ @@ -131,7 +131,7 @@ LL | li x26, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:76:11 + --> $DIR/riscv32e-registers.rs:79:11 | LL | asm!("li x27, 0"); | ^ @@ -143,7 +143,7 @@ LL | li x27, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:79:11 + --> $DIR/riscv32e-registers.rs:82:11 | LL | asm!("li x28, 0"); | ^ @@ -155,7 +155,7 @@ LL | li x28, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:82:11 + --> $DIR/riscv32e-registers.rs:85:11 | LL | asm!("li x29, 0"); | ^ @@ -167,7 +167,7 @@ LL | li x29, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:85:11 + --> $DIR/riscv32e-registers.rs:88:11 | LL | asm!("li x30, 0"); | ^ @@ -179,7 +179,7 @@ LL | li x30, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:88:11 + --> $DIR/riscv32e-registers.rs:91:11 | LL | asm!("li x31, 0"); | ^ diff --git a/tests/ui/abi/riscv32e-registers.riscv32em.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr index e3894431eb4..e7a86805b26 100644 --- a/tests/ui/abi/riscv32e-registers.riscv32em.stderr +++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32em.stderr @@ -1,5 +1,5 @@ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:43:11 + --> $DIR/riscv32e-registers.rs:46:11 | LL | asm!("li x16, 0"); | ^ @@ -11,7 +11,7 @@ LL | li x16, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:46:11 + --> $DIR/riscv32e-registers.rs:49:11 | LL | asm!("li x17, 0"); | ^ @@ -23,7 +23,7 @@ LL | li x17, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:49:11 + --> $DIR/riscv32e-registers.rs:52:11 | LL | asm!("li x18, 0"); | ^ @@ -35,7 +35,7 @@ LL | li x18, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:52:11 + --> $DIR/riscv32e-registers.rs:55:11 | LL | asm!("li x19, 0"); | ^ @@ -47,7 +47,7 @@ LL | li x19, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:55:11 + --> $DIR/riscv32e-registers.rs:58:11 | LL | asm!("li x20, 0"); | ^ @@ -59,7 +59,7 @@ LL | li x20, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:58:11 + --> $DIR/riscv32e-registers.rs:61:11 | LL | asm!("li x21, 0"); | ^ @@ -71,7 +71,7 @@ LL | li x21, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:61:11 + --> $DIR/riscv32e-registers.rs:64:11 | LL | asm!("li x22, 0"); | ^ @@ -83,7 +83,7 @@ LL | li x22, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:64:11 + --> $DIR/riscv32e-registers.rs:67:11 | LL | asm!("li x23, 0"); | ^ @@ -95,7 +95,7 @@ LL | li x23, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:67:11 + --> $DIR/riscv32e-registers.rs:70:11 | LL | asm!("li x24, 0"); | ^ @@ -107,7 +107,7 @@ LL | li x24, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:70:11 + --> $DIR/riscv32e-registers.rs:73:11 | LL | asm!("li x25, 0"); | ^ @@ -119,7 +119,7 @@ LL | li x25, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:73:11 + --> $DIR/riscv32e-registers.rs:76:11 | LL | asm!("li x26, 0"); | ^ @@ -131,7 +131,7 @@ LL | li x26, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:76:11 + --> $DIR/riscv32e-registers.rs:79:11 | LL | asm!("li x27, 0"); | ^ @@ -143,7 +143,7 @@ LL | li x27, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:79:11 + --> $DIR/riscv32e-registers.rs:82:11 | LL | asm!("li x28, 0"); | ^ @@ -155,7 +155,7 @@ LL | li x28, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:82:11 + --> $DIR/riscv32e-registers.rs:85:11 | LL | asm!("li x29, 0"); | ^ @@ -167,7 +167,7 @@ LL | li x29, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:85:11 + --> $DIR/riscv32e-registers.rs:88:11 | LL | asm!("li x30, 0"); | ^ @@ -179,7 +179,7 @@ LL | li x30, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:88:11 + --> $DIR/riscv32e-registers.rs:91:11 | LL | asm!("li x31, 0"); | ^ diff --git a/tests/ui/abi/riscv32e-registers.riscv32emc.stderr b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr index e3894431eb4..e7a86805b26 100644 --- a/tests/ui/abi/riscv32e-registers.riscv32emc.stderr +++ b/tests/ui/asm/riscv/riscv32e-registers.riscv32emc.stderr @@ -1,5 +1,5 @@ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:43:11 + --> $DIR/riscv32e-registers.rs:46:11 | LL | asm!("li x16, 0"); | ^ @@ -11,7 +11,7 @@ LL | li x16, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:46:11 + --> $DIR/riscv32e-registers.rs:49:11 | LL | asm!("li x17, 0"); | ^ @@ -23,7 +23,7 @@ LL | li x17, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:49:11 + --> $DIR/riscv32e-registers.rs:52:11 | LL | asm!("li x18, 0"); | ^ @@ -35,7 +35,7 @@ LL | li x18, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:52:11 + --> $DIR/riscv32e-registers.rs:55:11 | LL | asm!("li x19, 0"); | ^ @@ -47,7 +47,7 @@ LL | li x19, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:55:11 + --> $DIR/riscv32e-registers.rs:58:11 | LL | asm!("li x20, 0"); | ^ @@ -59,7 +59,7 @@ LL | li x20, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:58:11 + --> $DIR/riscv32e-registers.rs:61:11 | LL | asm!("li x21, 0"); | ^ @@ -71,7 +71,7 @@ LL | li x21, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:61:11 + --> $DIR/riscv32e-registers.rs:64:11 | LL | asm!("li x22, 0"); | ^ @@ -83,7 +83,7 @@ LL | li x22, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:64:11 + --> $DIR/riscv32e-registers.rs:67:11 | LL | asm!("li x23, 0"); | ^ @@ -95,7 +95,7 @@ LL | li x23, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:67:11 + --> $DIR/riscv32e-registers.rs:70:11 | LL | asm!("li x24, 0"); | ^ @@ -107,7 +107,7 @@ LL | li x24, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:70:11 + --> $DIR/riscv32e-registers.rs:73:11 | LL | asm!("li x25, 0"); | ^ @@ -119,7 +119,7 @@ LL | li x25, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:73:11 + --> $DIR/riscv32e-registers.rs:76:11 | LL | asm!("li x26, 0"); | ^ @@ -131,7 +131,7 @@ LL | li x26, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:76:11 + --> $DIR/riscv32e-registers.rs:79:11 | LL | asm!("li x27, 0"); | ^ @@ -143,7 +143,7 @@ LL | li x27, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:79:11 + --> $DIR/riscv32e-registers.rs:82:11 | LL | asm!("li x28, 0"); | ^ @@ -155,7 +155,7 @@ LL | li x28, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:82:11 + --> $DIR/riscv32e-registers.rs:85:11 | LL | asm!("li x29, 0"); | ^ @@ -167,7 +167,7 @@ LL | li x29, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:85:11 + --> $DIR/riscv32e-registers.rs:88:11 | LL | asm!("li x30, 0"); | ^ @@ -179,7 +179,7 @@ LL | li x30, 0 | ^ error: invalid operand for instruction - --> $DIR/riscv32e-registers.rs:88:11 + --> $DIR/riscv32e-registers.rs:91:11 | LL | asm!("li x31, 0"); | ^ diff --git a/tests/ui/abi/riscv32e-registers.rs b/tests/ui/asm/riscv/riscv32e-registers.rs index 714b0ee4633..57b1e169a04 100644 --- a/tests/ui/abi/riscv32e-registers.rs +++ b/tests/ui/asm/riscv/riscv32e-registers.rs @@ -11,6 +11,9 @@ //@ [riscv32emc] needs-llvm-components: riscv //@ [riscv32emc] compile-flags: --target=riscv32emc-unknown-none-elf +// Unlike bad-reg.rs, this tests if the assembler can reject invalid registers +// usage in assembly code. + #![no_core] #![feature(no_core, lang_items, rustc_attrs)] diff --git a/tests/ui/asm/s390x/bad-reg.rs b/tests/ui/asm/s390x/bad-reg.rs new file mode 100644 index 00000000000..6de43fdfe5e --- /dev/null +++ b/tests/ui/asm/s390x/bad-reg.rs @@ -0,0 +1,128 @@ +//@ add-core-stubs +//@ needs-asm-support +//@ revisions: s390x +//@[s390x] compile-flags: --target s390x-unknown-linux-gnu +//@[s390x] needs-llvm-components: systemz + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs)] +#![feature(asm_experimental_arch)] +#![no_core] + +extern crate minicore; +use minicore::*; + +fn f() { + let mut x = 0; + unsafe { + // Unsupported registers + asm!("", out("r11") _); + //~^ ERROR invalid register `r11`: The frame pointer cannot be used as an operand for inline asm + asm!("", out("r15") _); + //~^ ERROR invalid register `r15`: The stack pointer cannot be used as an operand for inline asm + asm!("", out("c0") _); + //~^ ERROR invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c1") _); + //~^ ERROR invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c2") _); + //~^ ERROR invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c3") _); + //~^ ERROR invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c4") _); + //~^ ERROR invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c5") _); + //~^ ERROR invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c6") _); + //~^ ERROR invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c7") _); + //~^ ERROR invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c8") _); + //~^ ERROR invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c9") _); + //~^ ERROR invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c10") _); + //~^ ERROR invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c11") _); + //~^ ERROR invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c12") _); + //~^ ERROR invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c13") _); + //~^ ERROR invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c14") _); + //~^ ERROR invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("c15") _); + //~^ ERROR invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm + asm!("", out("a0") _); + //~^ ERROR invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + asm!("", out("a1") _); + //~^ ERROR invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + + // Clobber-only registers + // areg + asm!("", out("a2") _); // ok + asm!("", in("a2") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("a2") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(areg) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(areg) _); + //~^ ERROR can only be used as a clobber + + // vreg + asm!("", out("v0") _); // ok + // FIXME: will be supported in https://github.com/rust-lang/rust/pull/131664 + asm!("", in("v0") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("v0") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(vreg) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(vreg) _); + //~^ ERROR can only be used as a clobber + + // Overlapping registers + // vreg/freg + asm!("", out("v0") _, out("f0") _); + //~^ ERROR register `f0` conflicts with register `v0` + asm!("", out("v1") _, out("f1") _); + //~^ ERROR register `f1` conflicts with register `v1` + asm!("", out("v2") _, out("f2") _); + //~^ ERROR register `f2` conflicts with register `v2` + asm!("", out("v3") _, out("f3") _); + //~^ ERROR register `f3` conflicts with register `v3` + asm!("", out("v4") _, out("f4") _); + //~^ ERROR register `f4` conflicts with register `v4` + asm!("", out("v5") _, out("f5") _); + //~^ ERROR register `f5` conflicts with register `v5` + asm!("", out("v6") _, out("f6") _); + //~^ ERROR register `f6` conflicts with register `v6` + asm!("", out("v7") _, out("f7") _); + //~^ ERROR register `f7` conflicts with register `v7` + asm!("", out("v8") _, out("f8") _); + //~^ ERROR register `f8` conflicts with register `v8` + asm!("", out("v9") _, out("f9") _); + //~^ ERROR register `f9` conflicts with register `v9` + asm!("", out("v10") _, out("f10") _); + //~^ ERROR register `f10` conflicts with register `v10` + asm!("", out("v11") _, out("f11") _); + //~^ ERROR register `f11` conflicts with register `v11` + asm!("", out("v12") _, out("f12") _); + //~^ ERROR register `f12` conflicts with register `v12` + asm!("", out("v13") _, out("f13") _); + //~^ ERROR register `f13` conflicts with register `v13` + asm!("", out("v14") _, out("f14") _); + //~^ ERROR register `f14` conflicts with register `v14` + asm!("", out("v15") _, out("f15") _); + //~^ ERROR register `f15` conflicts with register `v15` + // no %f16 + asm!("", out("v16") _, out("f16") _); + //~^ ERROR invalid register `f16`: unknown register + } +} diff --git a/tests/ui/asm/s390x/bad-reg.s390x.stderr b/tests/ui/asm/s390x/bad-reg.s390x.stderr new file mode 100644 index 00000000000..460d7c15de1 --- /dev/null +++ b/tests/ui/asm/s390x/bad-reg.s390x.stderr @@ -0,0 +1,352 @@ +error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:19:18 + | +LL | asm!("", out("r11") _); + | ^^^^^^^^^^^^ + +error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:21:18 + | +LL | asm!("", out("r15") _); + | ^^^^^^^^^^^^ + +error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:23:18 + | +LL | asm!("", out("c0") _); + | ^^^^^^^^^^^ + +error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:25:18 + | +LL | asm!("", out("c1") _); + | ^^^^^^^^^^^ + +error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:27:18 + | +LL | asm!("", out("c2") _); + | ^^^^^^^^^^^ + +error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:29:18 + | +LL | asm!("", out("c3") _); + | ^^^^^^^^^^^ + +error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:31:18 + | +LL | asm!("", out("c4") _); + | ^^^^^^^^^^^ + +error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:33:18 + | +LL | asm!("", out("c5") _); + | ^^^^^^^^^^^ + +error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:35:18 + | +LL | asm!("", out("c6") _); + | ^^^^^^^^^^^ + +error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:37:18 + | +LL | asm!("", out("c7") _); + | ^^^^^^^^^^^ + +error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:39:18 + | +LL | asm!("", out("c8") _); + | ^^^^^^^^^^^ + +error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:41:18 + | +LL | asm!("", out("c9") _); + | ^^^^^^^^^^^ + +error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:43:18 + | +LL | asm!("", out("c10") _); + | ^^^^^^^^^^^^ + +error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:45:18 + | +LL | asm!("", out("c11") _); + | ^^^^^^^^^^^^ + +error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:47:18 + | +LL | asm!("", out("c12") _); + | ^^^^^^^^^^^^ + +error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:49:18 + | +LL | asm!("", out("c13") _); + | ^^^^^^^^^^^^ + +error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:51:18 + | +LL | asm!("", out("c14") _); + | ^^^^^^^^^^^^ + +error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:53:18 + | +LL | asm!("", out("c15") _); + | ^^^^^^^^^^^^ + +error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:55:18 + | +LL | asm!("", out("a0") _); + | ^^^^^^^^^^^ + +error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm + --> $DIR/bad-reg.rs:57:18 + | +LL | asm!("", out("a1") _); + | ^^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:63:18 + | +LL | asm!("", in("a2") x); + | ^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:66:18 + | +LL | asm!("", out("a2") x); + | ^^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:69:26 + | +LL | asm!("/* {} */", in(areg) x); + | ^^^^^^^^^^ + +error: register class `areg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:72:26 + | +LL | asm!("/* {} */", out(areg) _); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:78:18 + | +LL | asm!("", in("v0") x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:81:18 + | +LL | asm!("", out("v0") x); + | ^^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:84:26 + | +LL | asm!("/* {} */", in(vreg) x); + | ^^^^^^^^^^ + +error: register class `vreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:87:26 + | +LL | asm!("/* {} */", out(vreg) _); + | ^^^^^^^^^^^ + +error: register `f0` conflicts with register `v0` + --> $DIR/bad-reg.rs:92:31 + | +LL | asm!("", out("v0") _, out("f0") _); + | ----------- ^^^^^^^^^^^ register `f0` + | | + | register `v0` + +error: register `f1` conflicts with register `v1` + --> $DIR/bad-reg.rs:94:31 + | +LL | asm!("", out("v1") _, out("f1") _); + | ----------- ^^^^^^^^^^^ register `f1` + | | + | register `v1` + +error: register `f2` conflicts with register `v2` + --> $DIR/bad-reg.rs:96:31 + | +LL | asm!("", out("v2") _, out("f2") _); + | ----------- ^^^^^^^^^^^ register `f2` + | | + | register `v2` + +error: register `f3` conflicts with register `v3` + --> $DIR/bad-reg.rs:98:31 + | +LL | asm!("", out("v3") _, out("f3") _); + | ----------- ^^^^^^^^^^^ register `f3` + | | + | register `v3` + +error: register `f4` conflicts with register `v4` + --> $DIR/bad-reg.rs:100:31 + | +LL | asm!("", out("v4") _, out("f4") _); + | ----------- ^^^^^^^^^^^ register `f4` + | | + | register `v4` + +error: register `f5` conflicts with register `v5` + --> $DIR/bad-reg.rs:102:31 + | +LL | asm!("", out("v5") _, out("f5") _); + | ----------- ^^^^^^^^^^^ register `f5` + | | + | register `v5` + +error: register `f6` conflicts with register `v6` + --> $DIR/bad-reg.rs:104:31 + | +LL | asm!("", out("v6") _, out("f6") _); + | ----------- ^^^^^^^^^^^ register `f6` + | | + | register `v6` + +error: register `f7` conflicts with register `v7` + --> $DIR/bad-reg.rs:106:31 + | +LL | asm!("", out("v7") _, out("f7") _); + | ----------- ^^^^^^^^^^^ register `f7` + | | + | register `v7` + +error: register `f8` conflicts with register `v8` + --> $DIR/bad-reg.rs:108:31 + | +LL | asm!("", out("v8") _, out("f8") _); + | ----------- ^^^^^^^^^^^ register `f8` + | | + | register `v8` + +error: register `f9` conflicts with register `v9` + --> $DIR/bad-reg.rs:110:31 + | +LL | asm!("", out("v9") _, out("f9") _); + | ----------- ^^^^^^^^^^^ register `f9` + | | + | register `v9` + +error: register `f10` conflicts with register `v10` + --> $DIR/bad-reg.rs:112:32 + | +LL | asm!("", out("v10") _, out("f10") _); + | ------------ ^^^^^^^^^^^^ register `f10` + | | + | register `v10` + +error: register `f11` conflicts with register `v11` + --> $DIR/bad-reg.rs:114:32 + | +LL | asm!("", out("v11") _, out("f11") _); + | ------------ ^^^^^^^^^^^^ register `f11` + | | + | register `v11` + +error: register `f12` conflicts with register `v12` + --> $DIR/bad-reg.rs:116:32 + | +LL | asm!("", out("v12") _, out("f12") _); + | ------------ ^^^^^^^^^^^^ register `f12` + | | + | register `v12` + +error: register `f13` conflicts with register `v13` + --> $DIR/bad-reg.rs:118:32 + | +LL | asm!("", out("v13") _, out("f13") _); + | ------------ ^^^^^^^^^^^^ register `f13` + | | + | register `v13` + +error: register `f14` conflicts with register `v14` + --> $DIR/bad-reg.rs:120:32 + | +LL | asm!("", out("v14") _, out("f14") _); + | ------------ ^^^^^^^^^^^^ register `f14` + | | + | register `v14` + +error: register `f15` conflicts with register `v15` + --> $DIR/bad-reg.rs:122:32 + | +LL | asm!("", out("v15") _, out("f15") _); + | ------------ ^^^^^^^^^^^^ register `f15` + | | + | register `v15` + +error: invalid register `f16`: unknown register + --> $DIR/bad-reg.rs:125:32 + | +LL | asm!("", out("v16") _, out("f16") _); + | ^^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:63:27 + | +LL | asm!("", in("a2") x); + | ^ + | + = note: register class `areg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:66:28 + | +LL | asm!("", out("a2") x); + | ^ + | + = note: register class `areg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:69:35 + | +LL | asm!("/* {} */", in(areg) x); + | ^ + | + = note: register class `areg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:78:27 + | +LL | asm!("", in("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:81:28 + | +LL | asm!("", out("v0") x); + | ^ + | + = note: register class `vreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:84:35 + | +LL | asm!("/* {} */", in(vreg) x); + | ^ + | + = note: register class `vreg` supports these types: + +error: aborting due to 51 previous errors + diff --git a/tests/ui/asm/sparc/bad-reg.rs b/tests/ui/asm/sparc/bad-reg.rs new file mode 100644 index 00000000000..b824f5adf3a --- /dev/null +++ b/tests/ui/asm/sparc/bad-reg.rs @@ -0,0 +1,66 @@ +//@ revisions: sparc sparcv8plus sparc64 +//@[sparc] compile-flags: --target sparc-unknown-none-elf +//@[sparc] needs-llvm-components: sparc +//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu +//@[sparcv8plus] needs-llvm-components: sparc +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparc64] needs-llvm-components: sparc +//@ needs-asm-support + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +impl Copy for i32 {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +fn f() { + let mut x = 0; + unsafe { + // Unsupported registers + asm!("", out("g0") _); + //~^ ERROR invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm + // FIXME: see FIXME in compiler/rustc_target/src/asm/sparc.rs. + asm!("", out("g1") _); + //~^ ERROR invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm + asm!("", out("g2") _); + asm!("", out("g3") _); + asm!("", out("g4") _); + asm!("", out("g5") _); + //[sparc,sparcv8plus]~^ ERROR cannot use register `r5`: g5 is reserved for system on SPARC32 + asm!("", out("g6") _); + //~^ ERROR invalid register `g6`: reserved for system and cannot be used as an operand for inline asm + asm!("", out("g7") _); + //~^ ERROR invalid register `g7`: reserved for system and cannot be used as an operand for inline asm + asm!("", out("sp") _); + //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + asm!("", out("fp") _); + //~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + asm!("", out("i7") _); + //~^ ERROR invalid register `i7`: the return address register cannot be used as an operand for inline asm + + // Clobber-only registers + // yreg + asm!("", out("y") _); // ok + asm!("", in("y") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("y") x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(yreg) x); + //~^ ERROR can only be used as a clobber + //~| ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(yreg) _); + //~^ ERROR can only be used as a clobber + } +} diff --git a/tests/ui/asm/sparc/bad-reg.sparc.stderr b/tests/ui/asm/sparc/bad-reg.sparc.stderr new file mode 100644 index 00000000000..cb7558c0f43 --- /dev/null +++ b/tests/ui/asm/sparc/bad-reg.sparc.stderr @@ -0,0 +1,98 @@ +error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", out("g0") _); + | ^^^^^^^^^^^ + +error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:33:18 + | +LL | asm!("", out("g1") _); + | ^^^^^^^^^^^ + +error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("g6") _); + | ^^^^^^^^^^^ + +error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("g7") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `i7`: the return address register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", out("i7") _); + | ^^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:54:18 + | +LL | asm!("", in("y") x); + | ^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:57:18 + | +LL | asm!("", out("y") x); + | ^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:60:26 + | +LL | asm!("/* {} */", in(yreg) x); + | ^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:63:26 + | +LL | asm!("/* {} */", out(yreg) _); + | ^^^^^^^^^^^ + +error: cannot use register `r5`: g5 is reserved for system on SPARC32 + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("g5") _); + | ^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:54:26 + | +LL | asm!("", in("y") x); + | ^ + | + = note: register class `yreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:57:27 + | +LL | asm!("", out("y") x); + | ^ + | + = note: register class `yreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:60:35 + | +LL | asm!("/* {} */", in(yreg) x); + | ^ + | + = note: register class `yreg` supports these types: + +error: aborting due to 15 previous errors + diff --git a/tests/ui/asm/sparc/bad-reg.sparc64.stderr b/tests/ui/asm/sparc/bad-reg.sparc64.stderr new file mode 100644 index 00000000000..e5606ab3124 --- /dev/null +++ b/tests/ui/asm/sparc/bad-reg.sparc64.stderr @@ -0,0 +1,92 @@ +error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", out("g0") _); + | ^^^^^^^^^^^ + +error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:33:18 + | +LL | asm!("", out("g1") _); + | ^^^^^^^^^^^ + +error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("g6") _); + | ^^^^^^^^^^^ + +error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("g7") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `i7`: the return address register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", out("i7") _); + | ^^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:54:18 + | +LL | asm!("", in("y") x); + | ^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:57:18 + | +LL | asm!("", out("y") x); + | ^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:60:26 + | +LL | asm!("/* {} */", in(yreg) x); + | ^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:63:26 + | +LL | asm!("/* {} */", out(yreg) _); + | ^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:54:26 + | +LL | asm!("", in("y") x); + | ^ + | + = note: register class `yreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:57:27 + | +LL | asm!("", out("y") x); + | ^ + | + = note: register class `yreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:60:35 + | +LL | asm!("/* {} */", in(yreg) x); + | ^ + | + = note: register class `yreg` supports these types: + +error: aborting due to 14 previous errors + diff --git a/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr b/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr new file mode 100644 index 00000000000..cb7558c0f43 --- /dev/null +++ b/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr @@ -0,0 +1,98 @@ +error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", out("g0") _); + | ^^^^^^^^^^^ + +error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:33:18 + | +LL | asm!("", out("g1") _); + | ^^^^^^^^^^^ + +error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:40:18 + | +LL | asm!("", out("g6") _); + | ^^^^^^^^^^^ + +error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:42:18 + | +LL | asm!("", out("g7") _); + | ^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:44:18 + | +LL | asm!("", out("sp") _); + | ^^^^^^^^^^^ + +error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:46:18 + | +LL | asm!("", out("fp") _); + | ^^^^^^^^^^^ + +error: invalid register `i7`: the return address register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:48:18 + | +LL | asm!("", out("i7") _); + | ^^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:54:18 + | +LL | asm!("", in("y") x); + | ^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:57:18 + | +LL | asm!("", out("y") x); + | ^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:60:26 + | +LL | asm!("/* {} */", in(yreg) x); + | ^^^^^^^^^^ + +error: register class `yreg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:63:26 + | +LL | asm!("/* {} */", out(yreg) _); + | ^^^^^^^^^^^ + +error: cannot use register `r5`: g5 is reserved for system on SPARC32 + --> $DIR/bad-reg.rs:38:18 + | +LL | asm!("", out("g5") _); + | ^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:54:26 + | +LL | asm!("", in("y") x); + | ^ + | + = note: register class `yreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:57:27 + | +LL | asm!("", out("y") x); + | ^ + | + = note: register class `yreg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:60:35 + | +LL | asm!("/* {} */", in(yreg) x); + | ^ + | + = note: register class `yreg` supports these types: + +error: aborting due to 15 previous errors + diff --git a/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs b/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs index ddb9278bafa..91641489cc9 100644 --- a/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs +++ b/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs @@ -4,6 +4,6 @@ #![feature(inherent_associated_types)] #![allow(incomplete_features)] -type Data = aux::Owner::Data; //~ ERROR use of unstable library feature 'data' +type Data = aux::Owner::Data; //~ ERROR use of unstable library feature `data` fn main() {} diff --git a/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr b/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr index ab8cdb6f80a..132d566fecd 100644 --- a/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr +++ b/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'data' +error[E0658]: use of unstable library feature `data` --> $DIR/assoc-inherent-unstable.rs:7:13 | LL | type Data = aux::Owner::Data; diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs index 50448313b30..e38179758f6 100644 --- a/tests/ui/async-await/async-fn/edition-2015.rs +++ b/tests/ui/async-await/async-fn/edition-2015.rs @@ -3,7 +3,7 @@ fn foo(x: impl async Fn()) -> impl async Fn() { x } //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later //~| ERROR async closures are unstable //~| ERROR async closures are unstable -//~| ERROR use of unstable library feature 'async_closure' -//~| ERROR use of unstable library feature 'async_closure' +//~| ERROR use of unstable library feature `async_closure` +//~| ERROR use of unstable library feature `async_closure` fn main() {} diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr index 358bb3e112e..25101cb65df 100644 --- a/tests/ui/async-await/async-fn/edition-2015.stderr +++ b/tests/ui/async-await/async-fn/edition-2015.stderr @@ -38,7 +38,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: to use an async block, remove the `||`: `async {` -error[E0658]: use of unstable library feature 'async_closure' +error[E0658]: use of unstable library feature `async_closure` --> $DIR/edition-2015.rs:1:42 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } @@ -48,7 +48,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } = help: add `#![feature(async_closure)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'async_closure' +error[E0658]: use of unstable library feature `async_closure` --> $DIR/edition-2015.rs:1:22 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } diff --git a/tests/ui/box/alloc-unstable-fail.rs b/tests/ui/box/alloc-unstable-fail.rs index 9427571648c..e209af97d7f 100644 --- a/tests/ui/box/alloc-unstable-fail.rs +++ b/tests/ui/box/alloc-unstable-fail.rs @@ -2,5 +2,5 @@ use std::boxed::Box; fn main() { let _boxed: Box<u32, _> = Box::new(10); - //~^ ERROR use of unstable library feature 'allocator_api' + //~^ ERROR use of unstable library feature `allocator_api` } diff --git a/tests/ui/box/alloc-unstable-fail.stderr b/tests/ui/box/alloc-unstable-fail.stderr index 9e1e12a2b6a..6ce63a79966 100644 --- a/tests/ui/box/alloc-unstable-fail.stderr +++ b/tests/ui/box/alloc-unstable-fail.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'allocator_api' +error[E0658]: use of unstable library feature `allocator_api` --> $DIR/alloc-unstable-fail.rs:4:26 | LL | let _boxed: Box<u32, _> = Box::new(10); diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 7589551a87c..43766788de7 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 246 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 247 more = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 37d2b0343c9..224313c6c8d 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -174,7 +174,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs index c194cea2e37..27b17a56f12 100644 --- a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs +++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs @@ -13,10 +13,10 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: m[0] += 10; - //~^ NOTE: Capturing m[] -> MutBorrow - //~| NOTE: Min Capture m[] -> MutBorrow + //~^ NOTE: Capturing m[] -> Mutable + //~| NOTE: Min Capture m[] -> Mutable m[1] += 40; - //~^ NOTE: Capturing m[] -> MutBorrow + //~^ NOTE: Capturing m[] -> Mutable }; c(); diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr index d7582dcfcc7..3c4f2de73a4 100644 --- a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr +++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr @@ -20,12 +20,12 @@ LL | | LL | | }; | |_____^ | -note: Capturing m[] -> MutBorrow +note: Capturing m[] -> Mutable --> $DIR/arrays-completely-captured.rs:15:9 | LL | m[0] += 10; | ^ -note: Capturing m[] -> MutBorrow +note: Capturing m[] -> Mutable --> $DIR/arrays-completely-captured.rs:18:9 | LL | m[1] += 40; @@ -43,7 +43,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture m[] -> MutBorrow +note: Min Capture m[] -> Mutable --> $DIR/arrays-completely-captured.rs:15:9 | LL | m[0] += 10; diff --git a/tests/ui/closures/2229_closure_analysis/by_value.rs b/tests/ui/closures/2229_closure_analysis/by_value.rs index 3fa28a1c6e9..2c9202fd617 100644 --- a/tests/ui/closures/2229_closure_analysis/by_value.rs +++ b/tests/ui/closures/2229_closure_analysis/by_value.rs @@ -26,8 +26,8 @@ fn big_box() { //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue //~| NOTE: Min Capture t[(0, 0)] -> ByValue println!("{} {:?}", t.1, p); - //~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow - //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow + //~^ NOTE: Capturing t[(1, 0)] -> Immutable + //~| NOTE: Min Capture t[(1, 0)] -> Immutable }; c(); diff --git a/tests/ui/closures/2229_closure_analysis/by_value.stderr b/tests/ui/closures/2229_closure_analysis/by_value.stderr index 0dd9991cf84..f843b76d723 100644 --- a/tests/ui/closures/2229_closure_analysis/by_value.stderr +++ b/tests/ui/closures/2229_closure_analysis/by_value.stderr @@ -25,7 +25,7 @@ note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue | LL | let p = t.0.0; | ^^^^^ -note: Capturing t[(1, 0)] -> ImmBorrow +note: Capturing t[(1, 0)] -> Immutable --> $DIR/by_value.rs:28:29 | LL | println!("{} {:?}", t.1, p); @@ -48,7 +48,7 @@ note: Min Capture t[(0, 0)] -> ByValue | LL | let p = t.0.0; | ^^^^^ -note: Min Capture t[(1, 0)] -> ImmBorrow +note: Min Capture t[(1, 0)] -> Immutable --> $DIR/by_value.rs:28:29 | LL | println!("{} {:?}", t.1, p); diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs index fa1ddeb0176..0c42e66a2fa 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs @@ -20,15 +20,15 @@ fn main() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: println!("{:?}", p); - //~^ NOTE: Capturing p[] -> ImmBorrow - //~| NOTE: Min Capture p[] -> ImmBorrow + //~^ NOTE: Capturing p[] -> Immutable + //~| NOTE: Min Capture p[] -> Immutable println!("{:?}", p.x); - //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing p[(0, 0)] -> Immutable println!("{:?}", q.x); - //~^ NOTE: Capturing q[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing q[(0, 0)] -> Immutable println!("{:?}", q); - //~^ NOTE: Capturing q[] -> ImmBorrow - //~| NOTE: Min Capture q[] -> ImmBorrow + //~^ NOTE: Capturing q[] -> Immutable + //~| NOTE: Min Capture q[] -> Immutable }; } diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr index d2409c9367c..64ae704bc90 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr @@ -20,22 +20,22 @@ LL | | LL | | }; | |_____^ | -note: Capturing p[] -> ImmBorrow +note: Capturing p[] -> Immutable --> $DIR/capture-analysis-1.rs:22:26 | LL | println!("{:?}", p); | ^ -note: Capturing p[(0, 0)] -> ImmBorrow +note: Capturing p[(0, 0)] -> Immutable --> $DIR/capture-analysis-1.rs:25:26 | LL | println!("{:?}", p.x); | ^^^ -note: Capturing q[(0, 0)] -> ImmBorrow +note: Capturing q[(0, 0)] -> Immutable --> $DIR/capture-analysis-1.rs:28:26 | LL | println!("{:?}", q.x); | ^^^ -note: Capturing q[] -> ImmBorrow +note: Capturing q[] -> Immutable --> $DIR/capture-analysis-1.rs:30:26 | LL | println!("{:?}", q); @@ -53,12 +53,12 @@ LL | | LL | | }; | |_____^ | -note: Min Capture p[] -> ImmBorrow +note: Min Capture p[] -> Immutable --> $DIR/capture-analysis-1.rs:22:26 | LL | println!("{:?}", p); | ^ -note: Min Capture q[] -> ImmBorrow +note: Min Capture q[] -> Immutable --> $DIR/capture-analysis-1.rs:30:26 | LL | println!("{:?}", q); diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs index eb342b303f9..adb618d1771 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs @@ -22,7 +22,7 @@ fn main() { //~^ NOTE: Capturing p[(0, 0)] -> ByValue //~| NOTE: p[] captured as ByValue here println!("{:?}", p); - //~^ NOTE: Capturing p[] -> ImmBorrow + //~^ NOTE: Capturing p[] -> Immutable //~| NOTE: Min Capture p[] -> ByValue //~| NOTE: p[] used here }; diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr index 7049c708bb8..40c075f3cc8 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr @@ -25,7 +25,7 @@ note: Capturing p[(0, 0)] -> ByValue | LL | let _x = p.x; | ^^^ -note: Capturing p[] -> ImmBorrow +note: Capturing p[] -> Immutable --> $DIR/capture-analysis-2.rs:24:26 | LL | println!("{:?}", p); diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs index e1476e415d9..0a21eaaaa12 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs @@ -27,7 +27,7 @@ fn main() { //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ByValue //~| NOTE: a[(0, 0)] captured as ByValue here println!("{:?}", a.b); - //~^ NOTE: Capturing a[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing a[(0, 0)] -> Immutable //~| NOTE: Min Capture a[(0, 0)] -> ByValue //~| NOTE: a[(0, 0)] used here }; diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr index 698b51a4fdb..a4689f2ea96 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr @@ -25,7 +25,7 @@ note: Capturing a[(0, 0),(0, 0)] -> ByValue | LL | let _x = a.b.c; | ^^^^^ -note: Capturing a[(0, 0)] -> ImmBorrow +note: Capturing a[(0, 0)] -> Immutable --> $DIR/capture-analysis-3.rs:29:26 | LL | println!("{:?}", a.b); diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs index 6d53a0ac634..790dad0710b 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs @@ -27,6 +27,6 @@ fn main() { //~^ NOTE: Capturing a[(0, 0)] -> ByValue //~| NOTE: Min Capture a[(0, 0)] -> ByValue println!("{:?}", a.b.c); - //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> Immutable }; } diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr index 9cd0dcf720e..9d3004dbbb0 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr @@ -25,7 +25,7 @@ note: Capturing a[(0, 0)] -> ByValue | LL | let _x = a.b; | ^^^ -note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow +note: Capturing a[(0, 0),(0, 0)] -> Immutable --> $DIR/capture-analysis-4.rs:29:26 | LL | println!("{:?}", a.b.c); diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs index 68703333fa8..af12e0b259d 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs @@ -18,8 +18,8 @@ fn main() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: println!("{}", p.x); - //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing p[(0, 0)] -> Immutable + //~| NOTE: Min Capture p[(0, 0)] -> Immutable }; // `c` should only capture `p.x`, therefore mutating `p.y` is allowed. diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr index 92a719d6098..48fbd682a5b 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr @@ -20,7 +20,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing p[(0, 0)] -> ImmBorrow +note: Capturing p[(0, 0)] -> Immutable --> $DIR/capture-disjoint-field-struct.rs:20:24 | LL | println!("{}", p.x); @@ -38,7 +38,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture p[(0, 0)] -> ImmBorrow +note: Min Capture p[(0, 0)] -> Immutable --> $DIR/capture-disjoint-field-struct.rs:20:24 | LL | println!("{}", p.x); diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs index 0c006ffdd72..ccd26049264 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs @@ -13,8 +13,8 @@ fn main() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: println!("{}", t.0); - //~^ NOTE: Capturing t[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture t[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing t[(0, 0)] -> Immutable + //~| NOTE: Min Capture t[(0, 0)] -> Immutable }; // `c` only captures t.0, therefore mutating t.1 is allowed. diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr index d5333bf71db..496511d6025 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr @@ -20,7 +20,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0)] -> ImmBorrow +note: Capturing t[(0, 0)] -> Immutable --> $DIR/capture-disjoint-field-tuple.rs:15:24 | LL | println!("{}", t.0); @@ -38,7 +38,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture t[(0, 0)] -> ImmBorrow +note: Min Capture t[(0, 0)] -> Immutable --> $DIR/capture-disjoint-field-tuple.rs:15:24 | LL | println!("{}", t.0); diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.rs b/tests/ui/closures/2229_closure_analysis/capture-enums.rs index 6f973739e66..b1e21bd0f8d 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-enums.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.rs @@ -21,14 +21,14 @@ fn multi_variant_enum() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: if let Info::Point(_, _, str) = point { - //~^ NOTE: Capturing point[] -> ImmBorrow + //~^ NOTE: Capturing point[] -> Immutable //~| NOTE: Capturing point[(2, 0)] -> ByValue //~| NOTE: Min Capture point[] -> ByValue println!("{}", str); } if let Info::Meta(_, v) = meta { - //~^ NOTE: Capturing meta[] -> ImmBorrow + //~^ NOTE: Capturing meta[] -> Immutable //~| NOTE: Capturing meta[(1, 1)] -> ByValue //~| NOTE: Min Capture meta[] -> ByValue println!("{:?}", v); diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr index 8b258569d95..2d70b614858 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr @@ -30,7 +30,7 @@ LL | | } LL | | }; | |_____^ | -note: Capturing point[] -> ImmBorrow +note: Capturing point[] -> Immutable --> $DIR/capture-enums.rs:23:41 | LL | if let Info::Point(_, _, str) = point { @@ -40,7 +40,7 @@ note: Capturing point[(2, 0)] -> ByValue | LL | if let Info::Point(_, _, str) = point { | ^^^^^ -note: Capturing meta[] -> ImmBorrow +note: Capturing meta[] -> Immutable --> $DIR/capture-enums.rs:30:35 | LL | if let Info::Meta(_, v) = meta { diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs index 5143836ad6b..61b707605c2 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs @@ -39,13 +39,13 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let x = &p.a.p.x; - //~^ NOTE: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing p[(0, 0),(0, 0),(0, 0)] -> Immutable p.b.q.y = 9; - //~^ NOTE: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow - //~| NOTE: p[] captured as MutBorrow here + //~^ NOTE: Capturing p[(1, 0),(1, 0),(1, 0)] -> Mutable + //~| NOTE: p[] captured as Mutable here println!("{:?}", p); - //~^ NOTE: Capturing p[] -> ImmBorrow - //~| NOTE: Min Capture p[] -> MutBorrow + //~^ NOTE: Capturing p[] -> Immutable + //~| NOTE: Min Capture p[] -> Mutable //~| NOTE: p[] used here }; } diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr index 55ba416dfd9..d118f7573a4 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr @@ -20,17 +20,17 @@ LL | | LL | | }; | |_____^ | -note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow +note: Capturing p[(0, 0),(0, 0),(0, 0)] -> Immutable --> $DIR/deep-multilevel-struct.rs:41:18 | LL | let x = &p.a.p.x; | ^^^^^^^ -note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow +note: Capturing p[(1, 0),(1, 0),(1, 0)] -> Mutable --> $DIR/deep-multilevel-struct.rs:43:9 | LL | p.b.q.y = 9; | ^^^^^^^ -note: Capturing p[] -> ImmBorrow +note: Capturing p[] -> Immutable --> $DIR/deep-multilevel-struct.rs:46:26 | LL | println!("{:?}", p); @@ -48,11 +48,11 @@ LL | | LL | | }; | |_____^ | -note: Min Capture p[] -> MutBorrow +note: Min Capture p[] -> Mutable --> $DIR/deep-multilevel-struct.rs:43:9 | LL | p.b.q.y = 9; - | ^^^^^^^ p[] captured as MutBorrow here + | ^^^^^^^ p[] captured as Mutable here ... LL | println!("{:?}", p); | ^ p[] used here diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs index 0cb0aeb824e..6c7eab1eeb7 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs @@ -13,13 +13,13 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let x = &t.0.0.0; - //~^ NOTE: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing t[(0, 0),(0, 0),(0, 0)] -> Immutable t.1.1.1 = 9; - //~^ NOTE: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow - //~| NOTE: t[] captured as MutBorrow here + //~^ NOTE: Capturing t[(1, 0),(1, 0),(1, 0)] -> Mutable + //~| NOTE: t[] captured as Mutable here println!("{:?}", t); - //~^ NOTE: Min Capture t[] -> MutBorrow - //~| NOTE: Capturing t[] -> ImmBorrow + //~^ NOTE: Min Capture t[] -> Mutable + //~| NOTE: Capturing t[] -> Immutable //~| NOTE: t[] used here }; } diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr index 5e45fe1ca8b..cc5f74613e4 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr @@ -20,17 +20,17 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow +note: Capturing t[(0, 0),(0, 0),(0, 0)] -> Immutable --> $DIR/deep-multilevel-tuple.rs:15:18 | LL | let x = &t.0.0.0; | ^^^^^^^ -note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow +note: Capturing t[(1, 0),(1, 0),(1, 0)] -> Mutable --> $DIR/deep-multilevel-tuple.rs:17:9 | LL | t.1.1.1 = 9; | ^^^^^^^ -note: Capturing t[] -> ImmBorrow +note: Capturing t[] -> Immutable --> $DIR/deep-multilevel-tuple.rs:20:26 | LL | println!("{:?}", t); @@ -48,11 +48,11 @@ LL | | LL | | }; | |_____^ | -note: Min Capture t[] -> MutBorrow +note: Min Capture t[] -> Mutable --> $DIR/deep-multilevel-tuple.rs:17:9 | LL | t.1.1.1 = 9; - | ^^^^^^^ t[] captured as MutBorrow here + | ^^^^^^^ t[] captured as Mutable here ... LL | println!("{:?}", t); | ^ t[] used here diff --git a/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs b/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs index 3106c478d00..68e8d66762d 100644 --- a/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs +++ b/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs @@ -44,9 +44,9 @@ fn structs() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let Point { x: ref mut x, y: _, id: moved_id } = p; - //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow + //~^ NOTE: Capturing p[(0, 0)] -> Mutable //~| NOTE: Capturing p[(2, 0)] -> ByValue - //~| NOTE: Min Capture p[(0, 0)] -> MutBorrow + //~| NOTE: Min Capture p[(0, 0)] -> Mutable //~| NOTE: Min Capture p[(2, 0)] -> ByValue println!("{}, {}", x, moved_id); @@ -65,11 +65,11 @@ fn tuples() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let (ref mut x, ref ref_str, (moved_s, _)) = t; - //~^ NOTE: Capturing t[(0, 0)] -> MutBorrow - //~| NOTE: Capturing t[(1, 0)] -> ImmBorrow + //~^ NOTE: Capturing t[(0, 0)] -> Mutable + //~| NOTE: Capturing t[(1, 0)] -> Immutable //~| NOTE: Capturing t[(2, 0),(0, 0)] -> ByValue - //~| NOTE: Min Capture t[(0, 0)] -> MutBorrow - //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(0, 0)] -> Mutable + //~| NOTE: Min Capture t[(1, 0)] -> Immutable //~| NOTE: Min Capture t[(2, 0),(0, 0)] -> ByValue println!("{}, {} {}", x, ref_str, moved_s); diff --git a/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr b/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr index 7fc85de499f..6f8295ac095 100644 --- a/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr +++ b/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr @@ -86,7 +86,7 @@ LL | | println!("{}, {}", x, moved_id); LL | | }; | |_____^ | -note: Capturing p[(0, 0)] -> MutBorrow +note: Capturing p[(0, 0)] -> Mutable --> $DIR/destructure_patterns.rs:46:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; @@ -109,7 +109,7 @@ LL | | println!("{}, {}", x, moved_id); LL | | }; | |_____^ | -note: Min Capture p[(0, 0)] -> MutBorrow +note: Min Capture p[(0, 0)] -> Mutable --> $DIR/destructure_patterns.rs:46:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; @@ -132,12 +132,12 @@ LL | | println!("{}, {} {}", x, ref_str, moved_s); LL | | }; | |_____^ | -note: Capturing t[(0, 0)] -> MutBorrow +note: Capturing t[(0, 0)] -> Mutable --> $DIR/destructure_patterns.rs:67:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ -note: Capturing t[(1, 0)] -> ImmBorrow +note: Capturing t[(1, 0)] -> Immutable --> $DIR/destructure_patterns.rs:67:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; @@ -160,12 +160,12 @@ LL | | println!("{}, {} {}", x, ref_str, moved_s); LL | | }; | |_____^ | -note: Min Capture t[(0, 0)] -> MutBorrow +note: Min Capture t[(0, 0)] -> Mutable --> $DIR/destructure_patterns.rs:67:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ -note: Min Capture t[(1, 0)] -> ImmBorrow +note: Min Capture t[(1, 0)] -> Immutable --> $DIR/destructure_patterns.rs:67:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs index 059c248a3e8..7467c13b337 100644 --- a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs +++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs @@ -13,7 +13,7 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("This uses new capture analyysis to capture s={}", s); - //~^ NOTE: Capturing s[] -> ImmBorrow - //~| NOTE: Min Capture s[] -> ImmBorrow + //~^ NOTE: Capturing s[] -> Immutable + //~| NOTE: Min Capture s[] -> Immutable }; } diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr index 4e76070dcf7..6dbe8c153c0 100644 --- a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr +++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr @@ -20,7 +20,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing s[] -> ImmBorrow +note: Capturing s[] -> Immutable --> $DIR/feature-gate-capture_disjoint_fields.rs:15:69 | LL | println!("This uses new capture analyysis to capture s={}", s); @@ -38,7 +38,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture s[] -> ImmBorrow +note: Min Capture s[] -> Immutable --> $DIR/feature-gate-capture_disjoint_fields.rs:15:69 | LL | println!("This uses new capture analyysis to capture s={}", s); diff --git a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs index 11ef92367ca..feef8cabb39 100644 --- a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs +++ b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs @@ -24,8 +24,8 @@ impl Data { |v| self.filter.allowed(*v), //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: - //~| NOTE: Capturing self[Deref,(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture self[Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Capturing self[Deref,(0, 0)] -> Immutable + //~| NOTE: Min Capture self[Deref,(0, 0)] -> Immutable ); } } diff --git a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr index 10e0d076b42..ffe7dd4d108 100644 --- a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr +++ b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr @@ -4,7 +4,7 @@ error: First Pass analysis includes: LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: Capturing self[Deref,(0, 0)] -> ImmBorrow +note: Capturing self[Deref,(0, 0)] -> Immutable --> $DIR/filter-on-struct-member.rs:24:17 | LL | |v| self.filter.allowed(*v), @@ -16,7 +16,7 @@ error: Min Capture analysis includes: LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: Min Capture self[Deref,(0, 0)] -> ImmBorrow +note: Min Capture self[Deref,(0, 0)] -> Immutable --> $DIR/filter-on-struct-member.rs:24:17 | LL | |v| self.filter.allowed(*v), diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.rs b/tests/ui/closures/2229_closure_analysis/issue-87378.rs index 0a771466e1e..9c89a4538be 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-87378.rs +++ b/tests/ui/closures/2229_closure_analysis/issue-87378.rs @@ -19,8 +19,8 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: unsafe { u.value } - //~^ NOTE: Capturing u[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture u[] -> ImmBorrow + //~^ NOTE: Capturing u[(0, 0)] -> Immutable + //~| NOTE: Min Capture u[] -> Immutable }; c(); diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr index 19c0c59170b..3273e92d9d1 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr +++ b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr @@ -20,7 +20,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing u[(0, 0)] -> ImmBorrow +note: Capturing u[(0, 0)] -> Immutable --> $DIR/issue-87378.rs:21:17 | LL | unsafe { u.value } @@ -38,7 +38,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture u[] -> ImmBorrow +note: Min Capture u[] -> Immutable --> $DIR/issue-87378.rs:21:17 | LL | unsafe { u.value } diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.rs b/tests/ui/closures/2229_closure_analysis/issue-88476.rs index 7f833839d56..45fe73b76e2 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-88476.rs +++ b/tests/ui/closures/2229_closure_analysis/issue-88476.rs @@ -24,7 +24,7 @@ pub fn test1() { //~| ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{:?}", f.0); - //~^ NOTE: Capturing f[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing f[(0, 0)] -> Immutable //~| NOTE: Min Capture f[] -> ByValue }; @@ -52,7 +52,7 @@ fn test2() { //~| ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", character.hp) - //~^ NOTE: Capturing character[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing character[(0, 0)] -> Immutable //~| NOTE: Min Capture character[(0, 0)] -> ByValue }; diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr index d0201757157..1c0e254dbf7 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr +++ b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr @@ -31,7 +31,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing f[(0, 0)] -> ImmBorrow +note: Capturing f[(0, 0)] -> Immutable --> $DIR/issue-88476.rs:26:26 | LL | println!("{:?}", f.0); @@ -69,7 +69,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing character[(0, 0)] -> ImmBorrow +note: Capturing character[(0, 0)] -> Immutable --> $DIR/issue-88476.rs:54:24 | LL | println!("{}", character.hp) diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs index 8dd20fc2a74..9c7b70457d9 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs @@ -13,8 +13,8 @@ fn test_1_should_capture() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: match variant { - //~^ NOTE: Capturing variant[] -> ImmBorrow - //~| NOTE: Min Capture variant[] -> ImmBorrow + //~^ NOTE: Capturing variant[] -> Immutable + //~| NOTE: Min Capture variant[] -> Immutable Some(_) => {} _ => {} } @@ -64,9 +64,9 @@ fn test_6_should_capture_single_variant() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: match variant { - //~^ NOTE: Capturing variant[] -> ImmBorrow - //~| NOTE: Capturing variant[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture variant[] -> ImmBorrow + //~^ NOTE: Capturing variant[] -> Immutable + //~| NOTE: Capturing variant[(0, 0)] -> Immutable + //~| NOTE: Min Capture variant[] -> Immutable SingleVariant::Points(a) => { println!("{:?}", a); } @@ -131,8 +131,8 @@ fn test_5_should_capture_multi_variant() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: match variant { - //~^ NOTE: Capturing variant[] -> ImmBorrow - //~| NOTE: Min Capture variant[] -> ImmBorrow + //~^ NOTE: Capturing variant[] -> Immutable + //~| NOTE: Min Capture variant[] -> Immutable MVariant::A => {} _ => {} } @@ -149,8 +149,8 @@ fn test_7_should_capture_slice_len() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> ImmBorrow - //~| NOTE: Min Capture slice[] -> ImmBorrow + //~^ NOTE: Capturing slice[] -> Immutable + //~| NOTE: Min Capture slice[] -> Immutable [_,_,_] => {}, _ => {} } @@ -161,8 +161,8 @@ fn test_7_should_capture_slice_len() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> ImmBorrow - //~| NOTE: Min Capture slice[] -> ImmBorrow + //~^ NOTE: Capturing slice[] -> Immutable + //~| NOTE: Min Capture slice[] -> Immutable [] => {}, _ => {} } @@ -173,8 +173,8 @@ fn test_7_should_capture_slice_len() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> ImmBorrow - //~| NOTE: Min Capture slice[] -> ImmBorrow + //~^ NOTE: Capturing slice[] -> Immutable + //~| NOTE: Min Capture slice[] -> Immutable [_, .. ,_] => {}, _ => {} } diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr index c3c3f8b8477..7125bfa3101 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr @@ -10,7 +10,7 @@ LL | | } LL | | }; | |_____^ | -note: Capturing variant[] -> ImmBorrow +note: Capturing variant[] -> Immutable --> $DIR/patterns-capture-analysis.rs:15:15 | LL | match variant { @@ -28,7 +28,7 @@ LL | | } LL | | }; | |_____^ | -note: Min Capture variant[] -> ImmBorrow +note: Min Capture variant[] -> Immutable --> $DIR/patterns-capture-analysis.rs:15:15 | LL | match variant { @@ -68,12 +68,12 @@ LL | | } LL | | }; | |_____^ | -note: Capturing variant[] -> ImmBorrow +note: Capturing variant[] -> Immutable --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { | ^^^^^^^ -note: Capturing variant[(0, 0)] -> ImmBorrow +note: Capturing variant[(0, 0)] -> Immutable --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { @@ -91,7 +91,7 @@ LL | | } LL | | }; | |_____^ | -note: Min Capture variant[] -> ImmBorrow +note: Min Capture variant[] -> Immutable --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { @@ -142,7 +142,7 @@ LL | | } LL | | }; | |_____^ | -note: Capturing variant[] -> ImmBorrow +note: Capturing variant[] -> Immutable --> $DIR/patterns-capture-analysis.rs:133:15 | LL | match variant { @@ -160,7 +160,7 @@ LL | | } LL | | }; | |_____^ | -note: Min Capture variant[] -> ImmBorrow +note: Min Capture variant[] -> Immutable --> $DIR/patterns-capture-analysis.rs:133:15 | LL | match variant { @@ -178,7 +178,7 @@ LL | | } LL | | }; | |_____^ | -note: Capturing slice[] -> ImmBorrow +note: Capturing slice[] -> Immutable --> $DIR/patterns-capture-analysis.rs:151:15 | LL | match slice { @@ -196,7 +196,7 @@ LL | | } LL | | }; | |_____^ | -note: Min Capture slice[] -> ImmBorrow +note: Min Capture slice[] -> Immutable --> $DIR/patterns-capture-analysis.rs:151:15 | LL | match slice { @@ -214,7 +214,7 @@ LL | | } LL | | }; | |_____^ | -note: Capturing slice[] -> ImmBorrow +note: Capturing slice[] -> Immutable --> $DIR/patterns-capture-analysis.rs:163:15 | LL | match slice { @@ -232,7 +232,7 @@ LL | | } LL | | }; | |_____^ | -note: Min Capture slice[] -> ImmBorrow +note: Min Capture slice[] -> Immutable --> $DIR/patterns-capture-analysis.rs:163:15 | LL | match slice { @@ -250,7 +250,7 @@ LL | | } LL | | }; | |_____^ | -note: Capturing slice[] -> ImmBorrow +note: Capturing slice[] -> Immutable --> $DIR/patterns-capture-analysis.rs:175:15 | LL | match slice { @@ -268,7 +268,7 @@ LL | | } LL | | }; | |_____^ | -note: Min Capture slice[] -> ImmBorrow +note: Min Capture slice[] -> Immutable --> $DIR/patterns-capture-analysis.rs:175:15 | LL | match slice { diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.rs b/tests/ui/closures/2229_closure_analysis/move_closure.rs index 3b7f036dfe7..b6690d06011 100644 --- a/tests/ui/closures/2229_closure_analysis/move_closure.rs +++ b/tests/ui/closures/2229_closure_analysis/move_closure.rs @@ -17,7 +17,7 @@ fn simple_move_closure() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: t.0.0 = "new S".into(); - //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow + //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> Mutable //~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue }; c(); @@ -36,7 +36,7 @@ fn simple_ref() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: *ref_s += 10; - //~^ NOTE: Capturing ref_s[Deref] -> MutBorrow + //~^ NOTE: Capturing ref_s[Deref] -> Mutable //~| NOTE: Min Capture ref_s[] -> ByValue }; c(); @@ -58,7 +58,7 @@ fn struct_contains_ref_to_another_struct_1() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: t.0.0 = "new s".into(); - //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> Mutable //~| NOTE: Min Capture t[(0, 0)] -> ByValue }; @@ -82,7 +82,7 @@ fn struct_contains_ref_to_another_struct_2() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let _t = t.0.0; - //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable //~| NOTE: Min Capture t[(0, 0)] -> ByValue }; @@ -127,7 +127,7 @@ fn truncate_box_derefs() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let _t = b.0; - //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing b[Deref,(0, 0)] -> Immutable //~| NOTE: Min Capture b[] -> ByValue }; @@ -144,7 +144,7 @@ fn truncate_box_derefs() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", b.0); - //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing b[Deref,(0, 0)] -> Immutable //~| NOTE: Min Capture b[] -> ByValue }; @@ -162,7 +162,7 @@ fn truncate_box_derefs() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", t.1.0); - //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> Immutable //~| NOTE: Min Capture t[(1, 0)] -> ByValue }; } @@ -182,7 +182,7 @@ fn box_mut_1() { //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date //~| First Pass analysis includes: - //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow + //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> Mutable //~| Min Capture analysis includes: //~| NOTE: Min Capture box_p_foo[] -> ByValue } @@ -200,7 +200,7 @@ fn box_mut_2() { //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date //~| First Pass analysis includes: - //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow + //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> Mutable //~| Min Capture analysis includes: //~| NOTE: Min Capture p_foo[] -> ByValue } @@ -214,7 +214,7 @@ fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 { //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date //~| First Pass analysis includes: - //~| NOTE: Capturing x[] -> ImmBorrow + //~| NOTE: Capturing x[] -> Immutable //~| Min Capture analysis includes: //~| NOTE: Min Capture x[] -> ByValue diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.stderr b/tests/ui/closures/2229_closure_analysis/move_closure.stderr index 7e9e3c5fed3..68754b8f7be 100644 --- a/tests/ui/closures/2229_closure_analysis/move_closure.stderr +++ b/tests/ui/closures/2229_closure_analysis/move_closure.stderr @@ -114,7 +114,7 @@ error: First Pass analysis includes: LL | let c = #[rustc_capture_analysis] move || x; | ^^^^^^^^^ | -note: Capturing x[] -> ImmBorrow +note: Capturing x[] -> Immutable --> $DIR/move_closure.rs:212:47 | LL | let c = #[rustc_capture_analysis] move || x; @@ -144,7 +144,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0),(0, 0)] -> MutBorrow +note: Capturing t[(0, 0),(0, 0)] -> Mutable --> $DIR/move_closure.rs:19:9 | LL | t.0.0 = "new S".into(); @@ -180,7 +180,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing ref_s[Deref] -> MutBorrow +note: Capturing ref_s[Deref] -> Mutable --> $DIR/move_closure.rs:38:9 | LL | *ref_s += 10; @@ -216,7 +216,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow +note: Capturing t[(0, 0),Deref,(0, 0)] -> Mutable --> $DIR/move_closure.rs:60:9 | LL | t.0.0 = "new s".into(); @@ -252,7 +252,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow +note: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable --> $DIR/move_closure.rs:84:18 | LL | let _t = t.0.0; @@ -324,7 +324,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing b[Deref,(0, 0)] -> ImmBorrow +note: Capturing b[Deref,(0, 0)] -> Immutable --> $DIR/move_closure.rs:129:18 | LL | let _t = b.0; @@ -360,7 +360,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing b[Deref,(0, 0)] -> ImmBorrow +note: Capturing b[Deref,(0, 0)] -> Immutable --> $DIR/move_closure.rs:146:24 | LL | println!("{}", b.0); @@ -396,7 +396,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow +note: Capturing t[(1, 0),Deref,(0, 0)] -> Immutable --> $DIR/move_closure.rs:164:24 | LL | println!("{}", t.1.0); @@ -426,7 +426,7 @@ error: First Pass analysis includes: LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow +note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> Mutable --> $DIR/move_closure.rs:180:47 | LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; @@ -450,7 +450,7 @@ error: First Pass analysis includes: LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; | ^^^^^^^^^^^^^^^^^^^^^ | -note: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow +note: Capturing p_foo[Deref,Deref,(0, 0)] -> Mutable --> $DIR/move_closure.rs:198:47 | LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs index 2d7c26074cb..501aebe725a 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs @@ -27,8 +27,8 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let wp = &w.p; - //~^ NOTE: Capturing w[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture w[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing w[(0, 0)] -> Immutable + //~| NOTE: Min Capture w[(0, 0)] -> Immutable println!("{}", wp.x); }; diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr index 118a7dacec6..000d929f07f 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr @@ -20,7 +20,7 @@ LL | | println!("{}", wp.x); LL | | }; | |_____^ | -note: Capturing w[(0, 0)] -> ImmBorrow +note: Capturing w[(0, 0)] -> Immutable --> $DIR/multilevel-path-1.rs:29:19 | LL | let wp = &w.p; @@ -38,7 +38,7 @@ LL | | println!("{}", wp.x); LL | | }; | |_____^ | -note: Min Capture w[(0, 0)] -> ImmBorrow +note: Min Capture w[(0, 0)] -> Immutable --> $DIR/multilevel-path-1.rs:29:19 | LL | let wp = &w.p; diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs index bcf0ed35137..f73627d14da 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs @@ -22,8 +22,8 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", w.p.x); - //~^ NOTE: Capturing w[(0, 0),(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing w[(0, 0),(0, 0)] -> Immutable + //~| NOTE: Min Capture w[(0, 0),(0, 0)] -> Immutable }; // `c` only captures `w.p.x`, therefore it's safe to mutate `w.p.y`. diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr index a7112531d9a..97f53e490e8 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr @@ -20,7 +20,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing w[(0, 0),(0, 0)] -> ImmBorrow +note: Capturing w[(0, 0),(0, 0)] -> Immutable --> $DIR/multilevel-path-2.rs:24:24 | LL | println!("{}", w.p.x); @@ -38,7 +38,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow +note: Min Capture w[(0, 0),(0, 0)] -> Immutable --> $DIR/multilevel-path-2.rs:24:24 | LL | println!("{}", w.p.x); diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.rs b/tests/ui/closures/2229_closure_analysis/nested-closure.rs index c481b3d853b..54166d068cb 100644 --- a/tests/ui/closures/2229_closure_analysis/nested-closure.rs +++ b/tests/ui/closures/2229_closure_analysis/nested-closure.rs @@ -24,8 +24,8 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", p.x); - //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing p[(0, 0)] -> Immutable + //~| NOTE: Min Capture p[(0, 0)] -> Immutable let incr = 10; let mut c2 = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental @@ -34,15 +34,15 @@ fn main() { || p.y += incr; //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: - //~| NOTE: Capturing p[(1, 0)] -> MutBorrow - //~| NOTE: Capturing incr[] -> ImmBorrow - //~| NOTE: Min Capture p[(1, 0)] -> MutBorrow - //~| NOTE: Min Capture incr[] -> ImmBorrow - //~| NOTE: Capturing p[(1, 0)] -> MutBorrow - //~| NOTE: Min Capture p[(1, 0)] -> MutBorrow + //~| NOTE: Capturing p[(1, 0)] -> Mutable + //~| NOTE: Capturing incr[] -> Immutable + //~| NOTE: Min Capture p[(1, 0)] -> Mutable + //~| NOTE: Min Capture incr[] -> Immutable + //~| NOTE: Capturing p[(1, 0)] -> Mutable + //~| NOTE: Min Capture p[(1, 0)] -> Mutable c2(); println!("{}", p.y); - //~^ NOTE: Capturing p[(1, 0)] -> ImmBorrow + //~^ NOTE: Capturing p[(1, 0)] -> Immutable }; c1(); diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr index 256bfd58597..03550cb2d35 100644 --- a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr +++ b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr @@ -24,12 +24,12 @@ error: First Pass analysis includes: LL | || p.y += incr; | ^^^^^^^^^^^^^^ | -note: Capturing p[(1, 0)] -> MutBorrow +note: Capturing p[(1, 0)] -> Mutable --> $DIR/nested-closure.rs:34:12 | LL | || p.y += incr; | ^^^ -note: Capturing incr[] -> ImmBorrow +note: Capturing incr[] -> Immutable --> $DIR/nested-closure.rs:34:19 | LL | || p.y += incr; @@ -41,12 +41,12 @@ error: Min Capture analysis includes: LL | || p.y += incr; | ^^^^^^^^^^^^^^ | -note: Min Capture p[(1, 0)] -> MutBorrow +note: Min Capture p[(1, 0)] -> Mutable --> $DIR/nested-closure.rs:34:12 | LL | || p.y += incr; | ^^^ -note: Min Capture incr[] -> ImmBorrow +note: Min Capture incr[] -> Immutable --> $DIR/nested-closure.rs:34:19 | LL | || p.y += incr; @@ -64,17 +64,17 @@ LL | | LL | | }; | |_____^ | -note: Capturing p[(0, 0)] -> ImmBorrow +note: Capturing p[(0, 0)] -> Immutable --> $DIR/nested-closure.rs:26:24 | LL | println!("{}", p.x); | ^^^ -note: Capturing p[(1, 0)] -> MutBorrow +note: Capturing p[(1, 0)] -> Mutable --> $DIR/nested-closure.rs:34:12 | LL | || p.y += incr; | ^^^ -note: Capturing p[(1, 0)] -> ImmBorrow +note: Capturing p[(1, 0)] -> Immutable --> $DIR/nested-closure.rs:44:24 | LL | println!("{}", p.y); @@ -92,12 +92,12 @@ LL | | LL | | }; | |_____^ | -note: Min Capture p[(0, 0)] -> ImmBorrow +note: Min Capture p[(0, 0)] -> Immutable --> $DIR/nested-closure.rs:26:24 | LL | println!("{}", p.x); | ^^^ -note: Min Capture p[(1, 0)] -> MutBorrow +note: Min Capture p[(1, 0)] -> Mutable --> $DIR/nested-closure.rs:34:12 | LL | || p.y += incr; diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs index 8df0eeb0eb4..70c20cf5aef 100644 --- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs +++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs @@ -23,8 +23,8 @@ fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static { //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date //~| ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: - //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow + //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> Immutable + //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> Immutable c } diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr index 99159ab58a2..86f7a6a6bca 100644 --- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr +++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr @@ -14,7 +14,7 @@ error: First Pass analysis includes: LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); | ^^^^^^^^^^^^^^^ | -note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow +note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> Immutable --> $DIR/edge_case.rs:20:48 | LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); @@ -26,7 +26,7 @@ error: Min Capture analysis includes: LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); | ^^^^^^^^^^^^^^^ | -note: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow +note: Min Capture m[Deref,(0, 0),Deref] -> Immutable --> $DIR/edge_case.rs:20:48 | LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs b/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs index 2d3db4fde72..ed740f3a167 100644 --- a/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs +++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs @@ -28,7 +28,7 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", pent.points[5].x); - //~^ NOTE: Capturing pent[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture pent[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing pent[(0, 0)] -> Immutable + //~| NOTE: Min Capture pent[(0, 0)] -> Immutable }; } diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr index 22bd13617c1..e82295f047b 100644 --- a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr +++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr @@ -20,7 +20,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing pent[(0, 0)] -> ImmBorrow +note: Capturing pent[(0, 0)] -> Immutable --> $DIR/path-with-array-access.rs:30:24 | LL | println!("{}", pent.points[5].x); @@ -38,7 +38,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture pent[(0, 0)] -> ImmBorrow +note: Min Capture pent[(0, 0)] -> Immutable --> $DIR/path-with-array-access.rs:30:24 | LL | println!("{}", pent.points[5].x); diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs index c30eaf8fb1b..159be843edb 100644 --- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs @@ -28,17 +28,17 @@ fn test_one() { //~^ ERROR: Min Capture analysis includes: //~| ERROR println!("{:?}", a.0); - //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow + //~^ NOTE: Min Capture a[(0, 0)] -> Immutable //~| NOTE println!("{:?}", a.1); - //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow + //~^ NOTE: Min Capture a[(1, 0)] -> Immutable //~| NOTE println!("{:?}", b.0); - //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow + //~^ NOTE: Min Capture b[(0, 0)] -> Immutable //~| NOTE println!("{:?}", b.1); - //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow + //~^ NOTE: Min Capture b[(1, 0)] -> Immutable //~| NOTE }; } @@ -55,17 +55,17 @@ fn test_two() { //~^ ERROR: Min Capture analysis includes: //~| ERROR println!("{:?}", a.1); - //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow + //~^ NOTE: Min Capture a[(1, 0)] -> Immutable //~| NOTE println!("{:?}", a.0); - //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow + //~^ NOTE: Min Capture a[(0, 0)] -> Immutable //~| NOTE println!("{:?}", b.1); - //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow + //~^ NOTE: Min Capture b[(1, 0)] -> Immutable //~| NOTE println!("{:?}", b.0); - //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow + //~^ NOTE: Min Capture b[(0, 0)] -> Immutable //~| NOTE }; } @@ -82,17 +82,17 @@ fn test_three() { //~^ ERROR: Min Capture analysis includes: //~| ERROR println!("{:?}", b.1); - //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow + //~^ NOTE: Min Capture b[(1, 0)] -> Immutable //~| NOTE println!("{:?}", a.1); - //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow + //~^ NOTE: Min Capture a[(1, 0)] -> Immutable //~| NOTE println!("{:?}", a.0); - //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow + //~^ NOTE: Min Capture a[(0, 0)] -> Immutable //~| NOTE println!("{:?}", b.0); - //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow + //~^ NOTE: Min Capture b[(0, 0)] -> Immutable //~| NOTE }; } diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr index 82f770eafed..65a0a317ab6 100644 --- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr @@ -40,22 +40,22 @@ LL | | LL | | }; | |_____^ | -note: Capturing a[(0, 0)] -> ImmBorrow +note: Capturing a[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:30:26 | LL | println!("{:?}", a.0); | ^^^ -note: Capturing a[(1, 0)] -> ImmBorrow +note: Capturing a[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:33:26 | LL | println!("{:?}", a.1); | ^^^ -note: Capturing b[(0, 0)] -> ImmBorrow +note: Capturing b[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:37:26 | LL | println!("{:?}", b.0); | ^^^ -note: Capturing b[(1, 0)] -> ImmBorrow +note: Capturing b[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:40:26 | LL | println!("{:?}", b.1); @@ -73,22 +73,22 @@ LL | | LL | | }; | |_____^ | -note: Min Capture a[(0, 0)] -> ImmBorrow +note: Min Capture a[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:30:26 | LL | println!("{:?}", a.0); | ^^^ -note: Min Capture a[(1, 0)] -> ImmBorrow +note: Min Capture a[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:33:26 | LL | println!("{:?}", a.1); | ^^^ -note: Min Capture b[(0, 0)] -> ImmBorrow +note: Min Capture b[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:37:26 | LL | println!("{:?}", b.0); | ^^^ -note: Min Capture b[(1, 0)] -> ImmBorrow +note: Min Capture b[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:40:26 | LL | println!("{:?}", b.1); @@ -106,22 +106,22 @@ LL | | LL | | }; | |_____^ | -note: Capturing a[(1, 0)] -> ImmBorrow +note: Capturing a[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:57:26 | LL | println!("{:?}", a.1); | ^^^ -note: Capturing a[(0, 0)] -> ImmBorrow +note: Capturing a[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:60:26 | LL | println!("{:?}", a.0); | ^^^ -note: Capturing b[(1, 0)] -> ImmBorrow +note: Capturing b[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:64:26 | LL | println!("{:?}", b.1); | ^^^ -note: Capturing b[(0, 0)] -> ImmBorrow +note: Capturing b[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:67:26 | LL | println!("{:?}", b.0); @@ -139,22 +139,22 @@ LL | | LL | | }; | |_____^ | -note: Min Capture a[(0, 0)] -> ImmBorrow +note: Min Capture a[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:60:26 | LL | println!("{:?}", a.0); | ^^^ -note: Min Capture a[(1, 0)] -> ImmBorrow +note: Min Capture a[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:57:26 | LL | println!("{:?}", a.1); | ^^^ -note: Min Capture b[(0, 0)] -> ImmBorrow +note: Min Capture b[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:67:26 | LL | println!("{:?}", b.0); | ^^^ -note: Min Capture b[(1, 0)] -> ImmBorrow +note: Min Capture b[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:64:26 | LL | println!("{:?}", b.1); @@ -172,22 +172,22 @@ LL | | LL | | }; | |_____^ | -note: Capturing b[(1, 0)] -> ImmBorrow +note: Capturing b[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:84:26 | LL | println!("{:?}", b.1); | ^^^ -note: Capturing a[(1, 0)] -> ImmBorrow +note: Capturing a[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:87:26 | LL | println!("{:?}", a.1); | ^^^ -note: Capturing a[(0, 0)] -> ImmBorrow +note: Capturing a[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:90:26 | LL | println!("{:?}", a.0); | ^^^ -note: Capturing b[(0, 0)] -> ImmBorrow +note: Capturing b[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:94:26 | LL | println!("{:?}", b.0); @@ -205,22 +205,22 @@ LL | | LL | | }; | |_____^ | -note: Min Capture b[(0, 0)] -> ImmBorrow +note: Min Capture b[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:94:26 | LL | println!("{:?}", b.0); | ^^^ -note: Min Capture b[(1, 0)] -> ImmBorrow +note: Min Capture b[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:84:26 | LL | println!("{:?}", b.1); | ^^^ -note: Min Capture a[(0, 0)] -> ImmBorrow +note: Min Capture a[(0, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:90:26 | LL | println!("{:?}", a.0); | ^^^ -note: Min Capture a[(1, 0)] -> ImmBorrow +note: Min Capture a[(1, 0)] -> Immutable --> $DIR/preserve_field_drop_order.rs:87:26 | LL | println!("{:?}", a.1); diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.rs b/tests/ui/closures/2229_closure_analysis/repr_packed.rs index 0dde2b12b87..2525af37eaa 100644 --- a/tests/ui/closures/2229_closure_analysis/repr_packed.rs +++ b/tests/ui/closures/2229_closure_analysis/repr_packed.rs @@ -19,10 +19,10 @@ fn test_alignment_not_affected() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let z1: &u8 = &foo.x; - //~^ NOTE: Capturing foo[] -> ImmBorrow + //~^ NOTE: Capturing foo[] -> Immutable let z2: &mut u8 = &mut foo.y; - //~^ NOTE: Capturing foo[] -> MutBorrow - //~| NOTE: Min Capture foo[] -> MutBorrow + //~^ NOTE: Capturing foo[] -> Mutable + //~| NOTE: Min Capture foo[] -> Mutable *z2 = 42; @@ -50,10 +50,10 @@ fn test_alignment_affected() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let z1: &String = &foo.x; - //~^ NOTE: Capturing foo[] -> ImmBorrow + //~^ NOTE: Capturing foo[] -> Immutable let z2: &mut u16 = &mut foo.y; - //~^ NOTE: Capturing foo[] -> MutBorrow - //~| NOTE: Min Capture foo[] -> MutBorrow + //~^ NOTE: Capturing foo[] -> Mutable + //~| NOTE: Min Capture foo[] -> Mutable *z2 = 42; @@ -86,7 +86,7 @@ fn test_truncation_when_ref_and_move() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", foo.x); - //~^ NOTE: Capturing foo[] -> ImmBorrow + //~^ NOTE: Capturing foo[] -> Immutable //~| NOTE: Min Capture foo[] -> ByValue //~| NOTE: foo[] used here let _z = foo.x; diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr index 3bac41d60d5..d4b2f8bfeae 100644 --- a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr +++ b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr @@ -40,12 +40,12 @@ LL | | println!("({}, {})", z1, z2); LL | | }; | |_____^ | -note: Capturing foo[] -> ImmBorrow +note: Capturing foo[] -> Immutable --> $DIR/repr_packed.rs:21:24 | LL | let z1: &u8 = &foo.x; | ^^^^^ -note: Capturing foo[] -> MutBorrow +note: Capturing foo[] -> Mutable --> $DIR/repr_packed.rs:23:32 | LL | let z2: &mut u8 = &mut foo.y; @@ -63,7 +63,7 @@ LL | | println!("({}, {})", z1, z2); LL | | }; | |_____^ | -note: Min Capture foo[] -> MutBorrow +note: Min Capture foo[] -> Mutable --> $DIR/repr_packed.rs:23:32 | LL | let z2: &mut u8 = &mut foo.y; @@ -81,12 +81,12 @@ LL | | println!("({}, {})", z1, z2); LL | | }; | |_____^ | -note: Capturing foo[] -> ImmBorrow +note: Capturing foo[] -> Immutable --> $DIR/repr_packed.rs:52:28 | LL | let z1: &String = &foo.x; | ^^^^^ -note: Capturing foo[] -> MutBorrow +note: Capturing foo[] -> Mutable --> $DIR/repr_packed.rs:54:33 | LL | let z2: &mut u16 = &mut foo.y; @@ -104,7 +104,7 @@ LL | | println!("({}, {})", z1, z2); LL | | }; | |_____^ | -note: Min Capture foo[] -> MutBorrow +note: Min Capture foo[] -> Mutable --> $DIR/repr_packed.rs:54:33 | LL | let z2: &mut u16 = &mut foo.y; @@ -122,7 +122,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing foo[] -> ImmBorrow +note: Capturing foo[] -> Immutable --> $DIR/repr_packed.rs:88:24 | LL | println!("{}", foo.x); diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs index 4b749a70577..38aa76999fb 100644 --- a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs +++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs @@ -16,7 +16,7 @@ fn main() { // // Requirements: // p.x -> MutBoorrow - // p -> ImmBorrow + // p -> Immutable // // Requirements met when p is captured via MutBorrow // @@ -28,11 +28,11 @@ fn main() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: p.x += 10; - //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow - //~| NOTE: p[] captured as MutBorrow here + //~^ NOTE: Capturing p[(0, 0)] -> Mutable + //~| NOTE: p[] captured as Mutable here println!("{:?}", p); - //~^ NOTE: Capturing p[] -> ImmBorrow - //~| NOTE: Min Capture p[] -> MutBorrow + //~^ NOTE: Capturing p[] -> Immutable + //~| NOTE: Min Capture p[] -> Mutable //~| NOTE: p[] used here }; diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr index 247dcbe94bc..a88bd01093a 100644 --- a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr +++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr @@ -20,12 +20,12 @@ LL | | LL | | }; | |_____^ | -note: Capturing p[(0, 0)] -> MutBorrow +note: Capturing p[(0, 0)] -> Mutable --> $DIR/simple-struct-min-capture.rs:30:9 | LL | p.x += 10; | ^^^ -note: Capturing p[] -> ImmBorrow +note: Capturing p[] -> Immutable --> $DIR/simple-struct-min-capture.rs:33:26 | LL | println!("{:?}", p); @@ -43,11 +43,11 @@ LL | | LL | | }; | |_____^ | -note: Min Capture p[] -> MutBorrow +note: Min Capture p[] -> Mutable --> $DIR/simple-struct-min-capture.rs:30:9 | LL | p.x += 10; - | ^^^ p[] captured as MutBorrow here + | ^^^ p[] captured as Mutable here ... LL | println!("{:?}", p); | ^ p[] used here diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs index 33d43c5f526..667f244f612 100644 --- a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs +++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs @@ -30,8 +30,8 @@ fn unsafe_imm() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{:?}", (*t.0).s); - //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture t[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable + //~| NOTE: Min Capture t[(0, 0)] -> Immutable }; c(); @@ -51,8 +51,8 @@ fn unsafe_mut() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let x = unsafe { &mut (*p).s }; - //~^ NOTE: Capturing p[Deref,(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture p[] -> ImmBorrow + //~^ NOTE: Capturing p[Deref,(0, 0)] -> Immutable + //~| NOTE: Min Capture p[] -> Immutable *x = "s".into(); }; c(); diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr index 4f3de075054..54463c5277d 100644 --- a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr +++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr @@ -30,7 +30,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow +note: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable --> $DIR/unsafe_ptr.rs:32:26 | LL | println!("{:?}", (*t.0).s); @@ -48,7 +48,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture t[(0, 0)] -> ImmBorrow +note: Min Capture t[(0, 0)] -> Immutable --> $DIR/unsafe_ptr.rs:32:26 | LL | println!("{:?}", (*t.0).s); @@ -66,7 +66,7 @@ LL | | *x = "s".into(); LL | | }; | |_____^ | -note: Capturing p[Deref,(0, 0)] -> ImmBorrow +note: Capturing p[Deref,(0, 0)] -> Immutable --> $DIR/unsafe_ptr.rs:53:31 | LL | let x = unsafe { &mut (*p).s }; @@ -84,7 +84,7 @@ LL | | *x = "s".into(); LL | | }; | |_____^ | -note: Min Capture p[] -> ImmBorrow +note: Min Capture p[] -> Immutable --> $DIR/unsafe_ptr.rs:53:31 | LL | let x = unsafe { &mut (*p).s }; diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.rs b/tests/ui/closures/2229_closure_analysis/wild_patterns.rs index 9adf20c21d5..d220cfce9ce 100644 --- a/tests/ui/closures/2229_closure_analysis/wild_patterns.rs +++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.rs @@ -28,8 +28,8 @@ fn wild_struct() { //~| ERROR: Min Capture analysis includes: // FIXME(arora-aman): Change `_x` to `_` let Point { x: _x, y: _ } = p; - //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow + //~^ NOTE: Capturing p[(0, 0)] -> Immutable + //~| NOTE: Min Capture p[(0, 0)] -> Immutable }; c(); diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr index 88b48aaaf8c..4d6d85649da 100644 --- a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr +++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr @@ -40,7 +40,7 @@ LL | | LL | | }; | |_____^ | -note: Capturing p[(0, 0)] -> ImmBorrow +note: Capturing p[(0, 0)] -> Immutable --> $DIR/wild_patterns.rs:30:37 | LL | let Point { x: _x, y: _ } = p; @@ -58,7 +58,7 @@ LL | | LL | | }; | |_____^ | -note: Min Capture p[(0, 0)] -> ImmBorrow +note: Min Capture p[(0, 0)] -> Immutable --> $DIR/wild_patterns.rs:30:37 | LL | let Point { x: _x, y: _ } = p; diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr index 2538fc0361c..013b9009da4 100644 --- a/tests/ui/closures/coerce-unsafe-to-closure.stderr +++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` +error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` --> $DIR/coerce-unsafe-to-closure.rs:2:44 | LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); @@ -6,7 +6,7 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); | | | required by a bound introduced by this call | - = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` + = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `Option::<T>::map` --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/conditional-compilation/cfg_accessible-unstable.rs b/tests/ui/conditional-compilation/cfg_accessible-unstable.rs index e9247e67a2a..9ac98dbd6e7 100644 --- a/tests/ui/conditional-compilation/cfg_accessible-unstable.rs +++ b/tests/ui/conditional-compilation/cfg_accessible-unstable.rs @@ -1,2 +1,2 @@ -#[cfg_accessible(std)] //~ ERROR use of unstable library feature 'cfg_accessible' +#[cfg_accessible(std)] //~ ERROR use of unstable library feature `cfg_accessible` fn main() {} diff --git a/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr b/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr index 201f6a13f1f..c994f4e67ac 100644 --- a/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr +++ b/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'cfg_accessible': `cfg_accessible` is not fully implemented +error[E0658]: use of unstable library feature `cfg_accessible`: `cfg_accessible` is not fully implemented --> $DIR/cfg_accessible-unstable.rs:1:3 | LL | #[cfg_accessible(std)] diff --git a/tests/ui/const-generics/const_trait_fn-issue-88433.rs b/tests/ui/const-generics/const_trait_fn-issue-88433.rs index 5e0ea6fc168..bc91fc1700e 100644 --- a/tests/ui/const-generics/const_trait_fn-issue-88433.rs +++ b/tests/ui/const-generics/const_trait_fn-issue-88433.rs @@ -1,8 +1,7 @@ //@ build-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Func<T> { diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs index 818b5d6ca93..6c0ac639612 100644 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -1,6 +1,6 @@ //@ known-bug: #110395 //@ compile-flags: -Znext-solver -#![feature(generic_const_exprs, adt_const_params, const_trait_impl, effects)] +#![feature(generic_const_exprs, adt_const_params, const_trait_impl)] #![allow(incomplete_features)] // test `N + N` unifies with explicit function calls for non-builtin-types diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr index b8d7c94bddc..882fdf0b228 100644 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -1,7 +1,7 @@ error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed --> $DIR/unify-op-with-fn-call.rs:3:12 | -LL | #![feature(generic_const_exprs, adt_const_params, const_trait_impl, effects)] +LL | #![feature(generic_const_exprs, adt_const_params, const_trait_impl)] | ^^^^^^^^^^^^^^^^^^^ | = help: remove one of these features diff --git a/tests/ui/const-generics/issues/issue-88119.rs b/tests/ui/const-generics/issues/issue-88119.rs index 12cb7ee7f55..a49b2ab8b03 100644 --- a/tests/ui/const-generics/issues/issue-88119.rs +++ b/tests/ui/const-generics/issues/issue-88119.rs @@ -1,7 +1,7 @@ //@ known-bug: #110395 //@ compile-flags: -Znext-solver #![allow(incomplete_features)] -#![feature(const_trait_impl, effects, generic_const_exprs)] +#![feature(const_trait_impl, generic_const_exprs)] #[const_trait] trait ConstName { diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr index a0ca33e38ef..370244fe8c9 100644 --- a/tests/ui/const-generics/issues/issue-88119.stderr +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -1,8 +1,8 @@ error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed - --> $DIR/issue-88119.rs:4:39 + --> $DIR/issue-88119.rs:4:30 | -LL | #![feature(const_trait_impl, effects, generic_const_exprs)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![feature(const_trait_impl, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ | = help: remove one of these features diff --git a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs index a4dd3ee2e7e..8804772e282 100644 --- a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs +++ b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs @@ -1,7 +1,6 @@ //@ compile-flags: -Znext-solver #![crate_type = "lib"] -#![feature(const_closures, const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(const_closures, const_trait_impl)] pub const fn test() { let cl = const || {}; diff --git a/tests/ui/consts/auxiliary/unstable_intrinsic.rs b/tests/ui/consts/auxiliary/unstable_intrinsic.rs index edef499dbb1..9e53a8feb5d 100644 --- a/tests/ui/consts/auxiliary/unstable_intrinsic.rs +++ b/tests/ui/consts/auxiliary/unstable_intrinsic.rs @@ -1,26 +1,13 @@ #![feature(staged_api, rustc_attrs, intrinsics)] #![stable(since="1.0.0", feature = "stable")] -#[stable(since="1.0.0", feature = "stable")] -pub mod old_way { - extern "rust-intrinsic" { - #[unstable(feature = "unstable", issue = "42")] - pub fn size_of_val<T>(x: *const T) -> usize; - - #[unstable(feature = "unstable", issue = "42")] - #[rustc_const_unstable(feature = "unstable", issue = "42")] - pub fn min_align_of_val<T>(x: *const T) -> usize; - } -} - -#[stable(since="1.0.0", feature = "stable")] -pub mod new_way { - #[unstable(feature = "unstable", issue = "42")] - #[rustc_intrinsic] - pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 } - - #[unstable(feature = "unstable", issue = "42")] - #[rustc_const_unstable(feature = "unstable", issue = "42")] - #[rustc_intrinsic] - pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 } -} +#[unstable(feature = "unstable", issue = "42")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 } + +#[unstable(feature = "unstable", issue = "42")] +#[rustc_const_unstable(feature = "unstable", issue = "42")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 } diff --git a/tests/ui/consts/closure-in-foreign-crate.rs b/tests/ui/consts/closure-in-foreign-crate.rs index 94e40fcf1e4..423cd582e5e 100644 --- a/tests/ui/consts/closure-in-foreign-crate.rs +++ b/tests/ui/consts/closure-in-foreign-crate.rs @@ -1,8 +1,8 @@ -// FIXME(effects) aux-build:closure-in-foreign-crate.rs +// FIXME(const_trait_impl) aux-build:closure-in-foreign-crate.rs //@ build-pass -// FIXME(effects) extern crate closure_in_foreign_crate; +// FIXME(const_trait_impl) extern crate closure_in_foreign_crate; -// FIXME(effects) const _: () = closure_in_foreign_crate::test(); +// FIXME(const_trait_impl) const _: () = closure_in_foreign_crate::test(); fn main() {} diff --git a/tests/ui/consts/const-compare-bytes-ub.rs b/tests/ui/consts/const-compare-bytes-ub.rs index 903ba15e622..9dafae1efd1 100644 --- a/tests/ui/consts/const-compare-bytes-ub.rs +++ b/tests/ui/consts/const-compare-bytes-ub.rs @@ -1,7 +1,6 @@ //@ check-fail #![feature(core_intrinsics)] -#![feature(const_intrinsic_compare_bytes)] use std::intrinsics::compare_bytes; use std::mem::MaybeUninit; diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr index 7f83dee6409..9ef5c8ad43a 100644 --- a/tests/ui/consts/const-compare-bytes-ub.stderr +++ b/tests/ui/consts/const-compare-bytes-ub.stderr @@ -1,47 +1,47 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const-compare-bytes-ub.rs:10:9 + --> $DIR/const-compare-bytes-ub.rs:9:9 | LL | compare_bytes(0 as *const u8, 2 as *const u8, 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got a null pointer error[E0080]: evaluation of constant value failed - --> $DIR/const-compare-bytes-ub.rs:14:9 + --> $DIR/const-compare-bytes-ub.rs:13:9 | LL | compare_bytes(1 as *const u8, 0 as *const u8, 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance) error[E0080]: evaluation of constant value failed - --> $DIR/const-compare-bytes-ub.rs:18:9 + --> $DIR/const-compare-bytes-ub.rs:17:9 | LL | compare_bytes(1 as *const u8, 2 as *const u8, 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance) error[E0080]: evaluation of constant value failed - --> $DIR/const-compare-bytes-ub.rs:22:9 + --> $DIR/const-compare-bytes-ub.rs:21:9 | LL | compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0 which is only 3 bytes from the end of the allocation error[E0080]: evaluation of constant value failed - --> $DIR/const-compare-bytes-ub.rs:26:9 + --> $DIR/const-compare-bytes-ub.rs:25:9 | LL | compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC1 which is only 3 bytes from the end of the allocation error[E0080]: evaluation of constant value failed - --> $DIR/const-compare-bytes-ub.rs:30:9 + --> $DIR/const-compare-bytes-ub.rs:29:9 | LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory error[E0080]: evaluation of constant value failed - --> $DIR/const-compare-bytes-ub.rs:34:9 + --> $DIR/const-compare-bytes-ub.rs:33:9 | LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory error[E0080]: evaluation of constant value failed - --> $DIR/const-compare-bytes-ub.rs:38:9 + --> $DIR/const-compare-bytes-ub.rs:37:9 | LL | compare_bytes([&1].as_ptr().cast(), [&2].as_ptr().cast(), std::mem::size_of::<usize>()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer diff --git a/tests/ui/consts/const-compare-bytes.rs b/tests/ui/consts/const-compare-bytes.rs index 8596a2d9df9..cd5cdfd0400 100644 --- a/tests/ui/consts/const-compare-bytes.rs +++ b/tests/ui/consts/const-compare-bytes.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(core_intrinsics)] -#![feature(const_intrinsic_compare_bytes)] use std::intrinsics::compare_bytes; fn main() { diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr index 3426a768cb6..c3360c8b3e2 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr +++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr @@ -11,12 +11,12 @@ LL | *ptr = 0; | ^^^^^^^^ accessing memory based on pointer with alignment 1, but alignment 4 is required error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL | = note: accessing memory with alignment 1, but alignment 4 is required | note: inside `copy_nonoverlapping::<u32>` - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL note: inside `std::ptr::const_ptr::<impl *const u32>::copy_to_nonoverlapping` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `MISALIGNED_COPY` diff --git a/tests/ui/consts/const-eval/simd/insert_extract.rs b/tests/ui/consts/const-eval/simd/insert_extract.rs index 57d4b4888ca..e5873ea26e8 100644 --- a/tests/ui/consts/const-eval/simd/insert_extract.rs +++ b/tests/ui/consts/const-eval/simd/insert_extract.rs @@ -1,6 +1,6 @@ //@ run-pass #![feature(repr_simd)] -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![feature(staged_api)] #![stable(feature = "foo", since = "1.3.37")] #![allow(non_camel_case_types)] @@ -10,14 +10,18 @@ #[repr(simd)] struct u16x2([u16; 2]); #[repr(simd)] struct f32x4([f32; 4]); -extern "rust-intrinsic" { - #[stable(feature = "foo", since = "1.3.37")] - #[rustc_const_stable(feature = "foo", since = "1.3.37")] - fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T; +#[stable(feature = "foo", since = "1.3.37")] +#[rustc_const_stable(feature = "foo", since = "1.3.37")] +#[rustc_intrinsic] +const unsafe fn simd_insert<T, U>(_x: T, _idx: u32, _val: U) -> T { + unimplemented!() +} - #[stable(feature = "foo", since = "1.3.37")] - #[rustc_const_stable(feature = "foo", since = "1.3.37")] - fn simd_extract<T, U>(x: T, idx: u32) -> U; +#[stable(feature = "foo", since = "1.3.37")] +#[rustc_const_stable(feature = "foo", since = "1.3.37")] +#[rustc_intrinsic] +const unsafe fn simd_extract<T, U>(_x: T, _idx: u32) -> U { + unimplemented!() } fn main() { diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr index 20e44a1401f..5fd35142818 100644 --- a/tests/ui/consts/const-ptr-is-null.stderr +++ b/tests/ui/consts/const-ptr-is-null.stderr @@ -3,7 +3,7 @@ error[E0080]: evaluation of constant value failed | = note: the evaluated program panicked at 'null-ness of this pointer cannot be determined in const context', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | -note: inside `std::ptr::const_ptr::<impl *const T>::is_null::const_impl` +note: inside `std::ptr::const_ptr::<impl *const T>::is_null::compiletime` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `std::ptr::const_ptr::<impl *const i32>::is_null` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -12,7 +12,7 @@ note: inside `MAYBE_NULL` | LL | assert!(!ptr.wrapping_sub(512).is_null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `const_eval_select` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs index 758c4dd1e8c..d30b22accef 100644 --- a/tests/ui/consts/const-try.rs +++ b/tests/ui/consts/const-try.rs @@ -4,9 +4,8 @@ #![crate_type = "lib"] #![feature(try_trait_v2)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #![feature(const_try)] -#![allow(incomplete_features)] use std::ops::{ControlFlow, FromResidual, Try}; diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr index abb1a921cfa..1f4f814cb93 100644 --- a/tests/ui/consts/const-try.stderr +++ b/tests/ui/consts/const-try.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` - --> $DIR/const-try.rs:16:12 + --> $DIR/const-try.rs:15:12 | LL | impl const FromResidual<Error> for TryMe { | ^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | impl const FromResidual<Error> for TryMe { = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Try` which is not marked with `#[const_trait]` - --> $DIR/const-try.rs:23:12 + --> $DIR/const-try.rs:22:12 | LL | impl const Try for TryMe { | ^^^ @@ -17,7 +17,7 @@ LL | impl const Try for TryMe { = note: adding a non-const method body in the future would be a breaking change error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions - --> $DIR/const-try.rs:36:5 + --> $DIR/const-try.rs:35:5 | LL | TryMe?; | ^^^^^^ @@ -25,7 +25,7 @@ LL | TryMe?; = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions - --> $DIR/const-try.rs:36:5 + --> $DIR/const-try.rs:35:5 | LL | TryMe?; | ^^^^^^ diff --git a/tests/ui/consts/const-unstable-intrinsic.rs b/tests/ui/consts/const-unstable-intrinsic.rs index 050abc6dd46..56b552b6a3f 100644 --- a/tests/ui/consts/const-unstable-intrinsic.rs +++ b/tests/ui/consts/const-unstable-intrinsic.rs @@ -14,63 +14,51 @@ fn main() { const fn const_main() { let x = 42; unsafe { - unstable_intrinsic::old_way::size_of_val(&x); - //~^ERROR: unstable library feature 'unstable' - //~|ERROR: cannot call non-const intrinsic - unstable_intrinsic::old_way::min_align_of_val(&x); - //~^ERROR: unstable library feature 'unstable' - //~|ERROR: not yet stable as a const intrinsic - unstable_intrinsic::new_way::size_of_val(&x); - //~^ERROR: unstable library feature 'unstable' + unstable_intrinsic::size_of_val(&x); + //~^ERROR: unstable library feature `unstable` //~|ERROR: cannot be (indirectly) exposed to stable - unstable_intrinsic::new_way::min_align_of_val(&x); - //~^ERROR: unstable library feature 'unstable' + unstable_intrinsic::min_align_of_val(&x); + //~^ERROR: unstable library feature `unstable` //~|ERROR: not yet stable as a const intrinsic - old_way::size_of_val(&x); - //~^ERROR: cannot call non-const intrinsic - old_way::min_align_of_val(&x); - //~^ERROR: cannot use `#[feature(local)]` - new_way::size_of_val(&x); + size_of_val(&x); //~^ERROR: cannot be (indirectly) exposed to stable - new_way::min_align_of_val(&x); + min_align_of_val(&x); //~^ERROR: cannot use `#[feature(local)]` } } -#[stable(since="1.0.0", feature = "stable")] -pub mod old_way { - extern "rust-intrinsic" { - #[unstable(feature = "local", issue = "42")] - pub fn size_of_val<T>(x: *const T) -> usize; - - #[unstable(feature = "local", issue = "42")] - #[rustc_const_unstable(feature = "local", issue = "42")] - pub fn min_align_of_val<T>(x: *const T) -> usize; - } -} - -#[stable(since="1.0.0", feature = "stable")] -pub mod new_way { - #[unstable(feature = "local", issue = "42")] - #[rustc_intrinsic] - pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 } +#[unstable(feature = "local", issue = "42")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 } - #[unstable(feature = "local", issue = "42")] - #[rustc_const_unstable(feature = "local", issue = "42")] - #[rustc_intrinsic] - pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 } -} +#[unstable(feature = "local", issue = "42")] +#[rustc_const_unstable(feature = "local", issue = "42")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] #[inline] pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { // Const stability attributes are not inherited from parent items. - extern "rust-intrinsic" { - fn copy<T>(src: *const T, dst: *mut T, count: usize); + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { + unimplemented!() } unsafe { copy(src, dst, count) } - //~^ ERROR cannot call non-const intrinsic + //~^ ERROR cannot be (indirectly) exposed to stable +} + +// Ensure that a fallback body is recursively-const-checked. +mod fallback { + #[rustc_intrinsic] + const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) { + super::size_of_val(src); + //~^ ERROR cannot be (indirectly) exposed to stable + } } diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr index 33a434c503d..3e605f3d003 100644 --- a/tests/ui/consts/const-unstable-intrinsic.stderr +++ b/tests/ui/consts/const-unstable-intrinsic.stderr @@ -1,84 +1,52 @@ -error[E0658]: use of unstable library feature 'unstable' +error[E0658]: use of unstable library feature `unstable` --> $DIR/const-unstable-intrinsic.rs:17:9 | -LL | unstable_intrinsic::old_way::size_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unstable_intrinsic::size_of_val(&x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information = help: add `#![feature(unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable' +error[E0658]: use of unstable library feature `unstable` --> $DIR/const-unstable-intrinsic.rs:20:9 | -LL | unstable_intrinsic::old_way::min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information - = help: add `#![feature(unstable)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature 'unstable' - --> $DIR/const-unstable-intrinsic.rs:23:9 - | -LL | unstable_intrinsic::new_way::size_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information - = help: add `#![feature(unstable)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature 'unstable' - --> $DIR/const-unstable-intrinsic.rs:26:9 - | -LL | unstable_intrinsic::new_way::min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unstable_intrinsic::min_align_of_val(&x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information = help: add `#![feature(unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: cannot call non-const intrinsic `size_of_val` in constant functions +error: intrinsic `unstable_intrinsic::size_of_val` cannot be (indirectly) exposed to stable --> $DIR/const-unstable-intrinsic.rs:17:9 | -LL | unstable_intrinsic::old_way::size_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unstable_intrinsic::size_of_val(&x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) error: `min_align_of_val` is not yet stable as a const intrinsic --> $DIR/const-unstable-intrinsic.rs:20:9 | -LL | unstable_intrinsic::old_way::min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unstable_intrinsic::min_align_of_val(&x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(unstable)]` to the crate attributes to enable -error: intrinsic `unstable_intrinsic::new_way::size_of_val` cannot be (indirectly) exposed to stable - --> $DIR/const-unstable-intrinsic.rs:23:9 +error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable + --> $DIR/const-unstable-intrinsic.rs:24:9 | -LL | unstable_intrinsic::new_way::size_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | size_of_val(&x); + | ^^^^^^^^^^^^^^^ | - = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval) - -error: `min_align_of_val` is not yet stable as a const intrinsic - --> $DIR/const-unstable-intrinsic.rs:26:9 - | -LL | unstable_intrinsic::new_way::min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable)]` to the crate attributes to enable - -error: cannot call non-const intrinsic `size_of_val` in constant functions - --> $DIR/const-unstable-intrinsic.rs:30:9 - | -LL | old_way::size_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]` - --> $DIR/const-unstable-intrinsic.rs:32:9 + --> $DIR/const-unstable-intrinsic.rs:26:9 | -LL | old_way::min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | min_align_of_val(&x); + | ^^^^^^^^^^^^^^^^^^^^ | help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | @@ -91,37 +59,22 @@ LL + #[rustc_allow_const_fn_unstable(local)] LL | const fn const_main() { | -error: intrinsic `new_way::size_of_val` cannot be (indirectly) exposed to stable - --> $DIR/const-unstable-intrinsic.rs:34:9 +error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable + --> $DIR/const-unstable-intrinsic.rs:53:14 | -LL | new_way::size_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe { copy(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^ | - = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval) + = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) -error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]` - --> $DIR/const-unstable-intrinsic.rs:36:9 - | -LL | new_way::min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable + --> $DIR/const-unstable-intrinsic.rs:61:9 | -help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) +LL | super::size_of_val(src); + | ^^^^^^^^^^^^^^^^^^^^^^^ | -LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_main() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local)] -LL | const fn const_main() { - | - -error: cannot call non-const intrinsic `copy` in constant functions - --> $DIR/const-unstable-intrinsic.rs:74:14 - | -LL | unsafe { copy(src, dst, count) } - | ^^^^^^^^^^^^^^^^^^^^^ + = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) -error: aborting due to 13 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const_cmp_type_id.rs b/tests/ui/consts/const_cmp_type_id.rs index 3a54764f422..e89b8d37787 100644 --- a/tests/ui/consts/const_cmp_type_id.rs +++ b/tests/ui/consts/const_cmp_type_id.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(const_type_id, const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(const_type_id, const_trait_impl)] use std::any::TypeId; @@ -13,6 +12,6 @@ fn main() { let _a = TypeId::of::<u8>() < TypeId::of::<u16>(); //~^ ERROR cannot call non-const operator in constants // can't assert `_a` because it is not deterministic - // FIXME(effects) make it pass + // FIXME(const_trait_impl) make it pass } } diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr index 12f35361b80..2e9a8024eae 100644 --- a/tests/ui/consts/const_cmp_type_id.stderr +++ b/tests/ui/consts/const_cmp_type_id.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const operator in constants - --> $DIR/const_cmp_type_id.rs:9:17 + --> $DIR/const_cmp_type_id.rs:8:17 | LL | assert!(TypeId::of::<u8>() == TypeId::of::<u8>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ note: impl defined here, but it is not `const` = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const operator in constants - --> $DIR/const_cmp_type_id.rs:11:17 + --> $DIR/const_cmp_type_id.rs:10:17 | LL | assert!(TypeId::of::<()>() != TypeId::of::<u8>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ note: impl defined here, but it is not `const` = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const operator in constants - --> $DIR/const_cmp_type_id.rs:13:18 + --> $DIR/const_cmp_type_id.rs:12:18 | LL | let _a = TypeId::of::<u8>() < TypeId::of::<u16>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/constifconst-call-in-const-position.rs b/tests/ui/consts/constifconst-call-in-const-position.rs index 757e35bbab2..80e47c2230f 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.rs +++ b/tests/ui/consts/constifconst-call-in-const-position.rs @@ -1,6 +1,6 @@ //@ known-bug: #102498 -#![feature(const_trait_impl, effects, generic_const_exprs)] +#![feature(const_trait_impl, generic_const_exprs)] #![allow(incomplete_features)] #[const_trait] diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs index 62917c0b98b..08fbcc107e7 100644 --- a/tests/ui/consts/copy-intrinsic.rs +++ b/tests/ui/consts/copy-intrinsic.rs @@ -1,17 +1,21 @@ #![stable(feature = "dummy", since = "1.0.0")] // ignore-tidy-linelength -#![feature(intrinsics, staged_api)] +#![feature(intrinsics, staged_api, rustc_attrs)] use std::mem; -extern "rust-intrinsic" { - #[stable(feature = "dummy", since = "1.0.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] - fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); +#[stable(feature = "dummy", since = "1.0.0")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[rustc_intrinsic] +const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) { + unimplemented!() +} - #[stable(feature = "dummy", since = "1.0.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] - fn copy<T>(src: *const T, dst: *mut T, count: usize); +#[stable(feature = "dummy", since = "1.0.0")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[rustc_intrinsic] +const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { + unimplemented!() } const COPY_ZERO: () = unsafe { diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr index 29a88f6270b..41af3a2cd2d 100644 --- a/tests/ui/consts/copy-intrinsic.stderr +++ b/tests/ui/consts/copy-intrinsic.stderr @@ -1,23 +1,23 @@ error[E0080]: evaluation of constant value failed - --> $DIR/copy-intrinsic.rs:30:5 + --> $DIR/copy-intrinsic.rs:34:5 | LL | copy_nonoverlapping(0x100 as *const i32, dangle, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance) error[E0080]: evaluation of constant value failed - --> $DIR/copy-intrinsic.rs:39:5 + --> $DIR/copy-intrinsic.rs:43:5 | LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes error[E0080]: evaluation of constant value failed - --> $DIR/copy-intrinsic.rs:46:5 + --> $DIR/copy-intrinsic.rs:50:5 | LL | copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy` error[E0080]: evaluation of constant value failed - --> $DIR/copy-intrinsic.rs:52:5 + --> $DIR/copy-intrinsic.rs:56:5 | LL | copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping` diff --git a/tests/ui/consts/rustc-impl-const-stability.rs b/tests/ui/consts/rustc-impl-const-stability.rs index af3262ca575..0df8482bec1 100644 --- a/tests/ui/consts/rustc-impl-const-stability.rs +++ b/tests/ui/consts/rustc-impl-const-stability.rs @@ -2,8 +2,7 @@ //@ known-bug: #110395 #![crate_type = "lib"] -#![feature(staged_api, const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(staged_api, const_trait_impl)] #![stable(feature = "foo", since = "1.0.0")] #[stable(feature = "potato", since = "1.27.0")] diff --git a/tests/ui/consts/rustc-impl-const-stability.stderr b/tests/ui/consts/rustc-impl-const-stability.stderr index 4a534b3ca14..4a58b5c8603 100644 --- a/tests/ui/consts/rustc-impl-const-stability.stderr +++ b/tests/ui/consts/rustc-impl-const-stability.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `Default` which is not marked with `#[const_trait]` - --> $DIR/rustc-impl-const-stability.rs:16:12 + --> $DIR/rustc-impl-const-stability.rs:15:12 | LL | impl const Default for Data { | ^^^^^^^ diff --git a/tests/ui/coroutine/clone-impl-async.rs b/tests/ui/coroutine/clone-impl-async.rs index d7ba1143b5c..2794b167aa2 100644 --- a/tests/ui/coroutine/clone-impl-async.rs +++ b/tests/ui/coroutine/clone-impl-async.rs @@ -1,4 +1,5 @@ //@ edition:2021 +//@compile-flags: --diagnostic-width=300 // gate-test-coroutine_clone // Verifies that feature(coroutine_clone) doesn't allow async blocks to be cloned/copied. diff --git a/tests/ui/coroutine/clone-impl-async.stderr b/tests/ui/coroutine/clone-impl-async.stderr index b5074911aa9..62bcce2fbcb 100644 --- a/tests/ui/coroutine/clone-impl-async.stderr +++ b/tests/ui/coroutine/clone-impl-async.stderr @@ -1,89 +1,89 @@ -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:17:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:18:16 | LL | check_copy(&inner_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}` + | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:69:18 + --> $DIR/clone-impl-async.rs:70:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:19:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:20:17 | LL | check_clone(&inner_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:12:27: 12:32}` + | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:13:27: 13:32}` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:70:19 + --> $DIR/clone-impl-async.rs:71:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:26:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:27:16 | LL | check_copy(&outer_non_clone); - | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}` + | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:69:18 + --> $DIR/clone-impl-async.rs:70:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:28:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:29:17 | LL | check_clone(&outer_non_clone); - | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:23:27: 23:37}` + | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:24:27: 24:37}` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:70:19 + --> $DIR/clone-impl-async.rs:71:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:32:16 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:33:16 | LL | check_copy(&maybe_copy_clone); - | ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}` + | ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:69:18 + --> $DIR/clone-impl-async.rs:70:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:34:17 +error[E0277]: the trait bound `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:35:17 | LL | check_clone(&maybe_copy_clone); - | ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:31:28: 31:38}` + | ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `{async block@$DIR/clone-impl-async.rs:32:28: 32:38}` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:70:19 + --> $DIR/clone-impl-async.rs:71:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:38:16 + --> $DIR/clone-impl-async.rs:39:16 | LL | check_copy(&inner_non_clone_fn); | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` @@ -91,13 +91,13 @@ LL | check_copy(&inner_non_clone_fn); | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:69:18 + --> $DIR/clone-impl-async.rs:70:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:40:17 + --> $DIR/clone-impl-async.rs:41:17 | LL | check_clone(&inner_non_clone_fn); | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` @@ -105,13 +105,13 @@ LL | check_clone(&inner_non_clone_fn); | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:70:19 + --> $DIR/clone-impl-async.rs:71:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:44:16 + --> $DIR/clone-impl-async.rs:45:16 | LL | check_copy(&outer_non_clone_fn); | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` @@ -119,13 +119,13 @@ LL | check_copy(&outer_non_clone_fn); | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:69:18 + --> $DIR/clone-impl-async.rs:70:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:46:17 + --> $DIR/clone-impl-async.rs:47:17 | LL | check_clone(&outer_non_clone_fn); | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` @@ -133,13 +133,13 @@ LL | check_clone(&outer_non_clone_fn); | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:70:19 + --> $DIR/clone-impl-async.rs:71:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied - --> $DIR/clone-impl-async.rs:50:16 + --> $DIR/clone-impl-async.rs:51:16 | LL | check_copy(&maybe_copy_clone_fn); | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>` @@ -147,13 +147,13 @@ LL | check_copy(&maybe_copy_clone_fn); | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-async.rs:69:18 + --> $DIR/clone-impl-async.rs:70:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied - --> $DIR/clone-impl-async.rs:52:17 + --> $DIR/clone-impl-async.rs:53:17 | LL | check_clone(&maybe_copy_clone_fn); | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>` @@ -161,7 +161,7 @@ LL | check_clone(&maybe_copy_clone_fn); | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-async.rs:70:19 + --> $DIR/clone-impl-async.rs:71:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` diff --git a/tests/ui/coroutine/clone-impl-static.rs b/tests/ui/coroutine/clone-impl-static.rs index 56d1ccac703..62d4392e30c 100644 --- a/tests/ui/coroutine/clone-impl-static.rs +++ b/tests/ui/coroutine/clone-impl-static.rs @@ -1,3 +1,4 @@ +//@compile-flags: --diagnostic-width=300 // gate-test-coroutine_clone // Verifies that static coroutines cannot be cloned/copied. diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr index 43920326d5d..bf16b166960 100644 --- a/tests/ui/coroutine/clone-impl-static.stderr +++ b/tests/ui/coroutine/clone-impl-static.stderr @@ -1,27 +1,27 @@ -error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}: Copy` is not satisfied - --> $DIR/clone-impl-static.rs:11:16 +error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}: Copy` is not satisfied + --> $DIR/clone-impl-static.rs:12:16 | LL | check_copy(&gen); - | ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}` + | ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-static.rs:17:18 + --> $DIR/clone-impl-static.rs:18:18 | LL | fn check_copy<T: Copy>(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}: Clone` is not satisfied - --> $DIR/clone-impl-static.rs:13:17 +error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}: Clone` is not satisfied + --> $DIR/clone-impl-static.rs:14:17 | LL | check_clone(&gen); - | ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}` + | ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:9:5: 9:19}` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-static.rs:18:19 + --> $DIR/clone-impl-static.rs:19:19 | LL | fn check_clone<T: Clone>(_x: &T) {} | ^^^^^ required by this bound in `check_clone` diff --git a/tests/ui/coroutine/gen_block_is_coro.rs b/tests/ui/coroutine/gen_block_is_coro.rs index 970646ac470..c98e1e60388 100644 --- a/tests/ui/coroutine/gen_block_is_coro.rs +++ b/tests/ui/coroutine/gen_block_is_coro.rs @@ -1,4 +1,4 @@ -//@compile-flags: --edition 2024 -Zunstable-options +//@compile-flags: --edition 2024 -Zunstable-options --diagnostic-width=300 #![feature(coroutines, coroutine_trait, gen_blocks)] use std::ops::Coroutine; diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs index 56296db85a3..b35af76da3e 100644 --- a/tests/ui/delegation/unsupported.rs +++ b/tests/ui/delegation/unsupported.rs @@ -1,6 +1,5 @@ #![feature(const_trait_impl)] #![feature(c_variadic)] -#![feature(effects)] #![feature(fn_delegation)] #![allow(incomplete_features)] diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr index 2f64d23b8d2..9391763dca2 100644 --- a/tests/ui/delegation/unsupported.stderr +++ b/tests/ui/delegation/unsupported.stderr @@ -1,24 +1,24 @@ -error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}` - --> $DIR/unsupported.rs:27:25 +error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:25:5: 25:24>::{synthetic#0}` + --> $DIR/unsupported.rs:26:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/unsupported.rs:27:25 + --> $DIR/unsupported.rs:26:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>` is well-formed - --> $DIR/unsupported.rs:26:5 + = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:25:5: 25:24>::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:25:5: 25:24>` is well-formed + --> $DIR/unsupported.rs:25:5 | LL | impl ToReuse for u8 { | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information warning: this function depends on never type fallback being `()` - --> $DIR/unsupported.rs:14:9 + --> $DIR/unsupported.rs:13:9 | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,14 +27,14 @@ LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748> = help: specify the types explicitly note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/unsupported.rs:14:32 + --> $DIR/unsupported.rs:13:32 | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default warning: this function depends on never type fallback being `()` - --> $DIR/unsupported.rs:20:9 + --> $DIR/unsupported.rs:19:9 | LL | fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,32 +43,32 @@ LL | fn opaque_ret() -> impl Trait { unimplemented!() } = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748> = help: specify the types explicitly note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/unsupported.rs:20:28 + --> $DIR/unsupported.rs:19:28 | LL | fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ -error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}` - --> $DIR/unsupported.rs:30:24 +error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:28:5: 28:25>::{synthetic#0}` + --> $DIR/unsupported.rs:29:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/unsupported.rs:30:24 + --> $DIR/unsupported.rs:29:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>` is well-formed - --> $DIR/unsupported.rs:29:5 + = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:28:5: 28:25>::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:28:5: 28:25>` is well-formed + --> $DIR/unsupported.rs:28:5 | LL | impl ToReuse for u16 { | ^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: recursive delegation is not supported yet - --> $DIR/unsupported.rs:43:22 + --> $DIR/unsupported.rs:42:22 | LL | pub reuse to_reuse2::foo; | --- callee defined here @@ -77,7 +77,7 @@ LL | reuse to_reuse1::foo; | ^^^ error[E0283]: type annotations needed - --> $DIR/unsupported.rs:53:18 + --> $DIR/unsupported.rs:52:18 | LL | reuse Trait::foo; | ^^^ cannot infer type diff --git a/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs new file mode 100644 index 00000000000..c4fb620fea4 --- /dev/null +++ b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs @@ -0,0 +1,11 @@ +// Duplicate implementations of Copy/Clone should not trigger +// borrow check warnings +// See #131083 + +#[derive(Copy, Clone)] +#[derive(Copy, Clone)] +//~^ ERROR conflicting implementations of trait `Clone` for type `E` +//~| ERROR conflicting implementations of trait `Copy` for type `E` +enum E {} + +fn main() {} diff --git a/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr new file mode 100644 index 00000000000..f8e1db33f53 --- /dev/null +++ b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr @@ -0,0 +1,23 @@ +error[E0119]: conflicting implementations of trait `Copy` for type `E` + --> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:10 + | +LL | #[derive(Copy, Clone)] + | ---- first implementation here +LL | #[derive(Copy, Clone)] + | ^^^^ conflicting implementation for `E` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0119]: conflicting implementations of trait `Clone` for type `E` + --> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16 + | +LL | #[derive(Copy, Clone)] + | ----- first implementation here +LL | #[derive(Copy, Clone)] + | ^^^^^ conflicting implementation for `E` + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/derives/rustc-decodable-issue-123156.stderr b/tests/ui/derives/rustc-decodable-issue-123156.stderr index ee7b33d59bb..93a993b90d8 100644 --- a/tests/ui/derives/rustc-decodable-issue-123156.stderr +++ b/tests/ui/derives/rustc-decodable-issue-123156.stderr @@ -1,5 +1,5 @@ Future incompatibility report: Future breakage diagnostic: -warning: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code +warning: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code --> $DIR/rustc-decodable-issue-123156.rs:10:10 | LL | #[derive(RustcDecodable)] diff --git a/tests/ui/destructuring-assignment/struct_destructure_fail.stderr b/tests/ui/destructuring-assignment/struct_destructure_fail.stderr index 57851ed417e..4c4f0663eeb 100644 --- a/tests/ui/destructuring-assignment/struct_destructure_fail.stderr +++ b/tests/ui/destructuring-assignment/struct_destructure_fail.stderr @@ -41,6 +41,10 @@ LL | Struct { a, b } = Struct { a: 1, b: 2 }; | ~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | Struct { a, b: _ } = Struct { a: 1, b: 2 }; + | ~~~~~~~~ +help: or always ignore missing fields here + | LL | Struct { a, .. } = Struct { a: 1, b: 2 }; | ~~~~~~ diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr index e56af28f3fb..be17476524a 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr @@ -15,6 +15,10 @@ note: required by a bound in `check` | LL | fn check(a: impl Foo) {} | ^^^ required by this bound in `check` +help: use a unary tuple instead + | +LL | check(((),)); + | + ++ error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr index 629fc59361d..ca9a6ebc1c4 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr @@ -12,6 +12,10 @@ note: required by a bound in `check` | LL | fn check(a: impl Foo) {} | ^^^ required by this bound in `check` +help: use a unary tuple instead + | +LL | check(((),)); + | + ++ error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr index 629fc59361d..ca9a6ebc1c4 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr @@ -12,6 +12,10 @@ note: required by a bound in `check` | LL | fn check(a: impl Foo) {} | ^^^ required by this bound in `check` +help: use a unary tuple instead + | +LL | check(((),)); + | + ++ error: aborting due to 1 previous error diff --git a/tests/ui/dropck/const_drop_is_valid.rs b/tests/ui/dropck/const_drop_is_valid.rs index 0441b6ed067..26ef2d61deb 100644 --- a/tests/ui/dropck/const_drop_is_valid.rs +++ b/tests/ui/dropck/const_drop_is_valid.rs @@ -1,6 +1,3 @@ -#![feature(effects)] -//~^ WARN: the feature `effects` is incomplete - struct A(); impl const Drop for A {} diff --git a/tests/ui/dropck/const_drop_is_valid.stderr b/tests/ui/dropck/const_drop_is_valid.stderr index 2383a6668a8..5837e1623a1 100644 --- a/tests/ui/dropck/const_drop_is_valid.stderr +++ b/tests/ui/dropck/const_drop_is_valid.stderr @@ -1,5 +1,5 @@ error[E0658]: const trait impls are experimental - --> $DIR/const_drop_is_valid.rs:6:6 + --> $DIR/const_drop_is_valid.rs:3:6 | LL | impl const Drop for A {} | ^^^^^ @@ -8,17 +8,8 @@ LL | impl const Drop for A {} = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const_drop_is_valid.rs:1:12 - | -LL | #![feature(effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` - --> $DIR/const_drop_is_valid.rs:6:12 + --> $DIR/const_drop_is_valid.rs:3:12 | LL | impl const Drop for A {} | ^^^^ @@ -27,14 +18,14 @@ LL | impl const Drop for A {} = note: adding a non-const method body in the future would be a breaking change error[E0046]: not all trait items implemented, missing: `drop` - --> $DIR/const_drop_is_valid.rs:6:1 + --> $DIR/const_drop_is_valid.rs:3:1 | LL | impl const Drop for A {} | ^^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation | = help: implement the missing item: `fn drop(&mut self) { todo!() }` -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors Some errors have detailed explanations: E0046, E0658. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs index 43c1c775978..17b76b6c832 100644 --- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs @@ -21,6 +21,6 @@ enum FingerTree<T:'static> { } fn main() { - let ft = //~ ERROR overflow while adding drop-check rules for FingerTree + let ft = //~ ERROR overflow while adding drop-check rules for `FingerTree FingerTree::Single(1); } diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr index 8f4d301b5ca..9360f4a98e9 100644 --- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr @@ -1,10 +1,10 @@ -error[E0320]: overflow while adding drop-check rules for FingerTree<i32> +error[E0320]: overflow while adding drop-check rules for `FingerTree<i32>` --> $DIR/dropck_no_diverge_on_nonregular_1.rs:24:9 | LL | let ft = | ^^ | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + = note: overflowed on `FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` error: aborting due to 1 previous error diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs index edd07652e53..d731ab09e7e 100644 --- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs @@ -20,6 +20,6 @@ enum FingerTree<T:'static> { } fn main() { - let ft = //~ ERROR overflow while adding drop-check rules for FingerTree + let ft = //~ ERROR overflow while adding drop-check rules for `FingerTree FingerTree::Single(1); } diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr index 4ef7aa61db7..88162989dee 100644 --- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr @@ -1,10 +1,10 @@ -error[E0320]: overflow while adding drop-check rules for FingerTree<i32> +error[E0320]: overflow while adding drop-check rules for `FingerTree<i32>` --> $DIR/dropck_no_diverge_on_nonregular_2.rs:23:9 | LL | let ft = | ^^ | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + = note: overflowed on `FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` error: aborting due to 1 previous error diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs index af7402ca4a1..d318bdcde92 100644 --- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs @@ -29,7 +29,7 @@ enum Wrapper<T:'static> { } fn main() { - let w = //~ ERROR overflow while adding drop-check rules for Option + let w = //~ ERROR overflow while adding drop-check rules for `Option Some(Wrapper::Simple::<u32>); - //~^ ERROR overflow while adding drop-check rules for Wrapper + //~^ ERROR overflow while adding drop-check rules for `Wrapper } diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr index deaf116b647..54cf20a3520 100644 --- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr @@ -1,18 +1,18 @@ -error[E0320]: overflow while adding drop-check rules for Option<Wrapper<u32>> +error[E0320]: overflow while adding drop-check rules for `Option<Wrapper<u32>>` --> $DIR/dropck_no_diverge_on_nonregular_3.rs:32:9 | LL | let w = | ^ | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + = note: overflowed on `FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` -error[E0320]: overflow while adding drop-check rules for Wrapper<u32> +error[E0320]: overflow while adding drop-check rules for `Wrapper<u32>` --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:14 | LL | Some(Wrapper::Simple::<u32>); | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + = note: overflowed on `FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` error: aborting due to 2 previous errors diff --git a/tests/ui/enum/assoc-fn-call-on-variant.rs b/tests/ui/enum/assoc-fn-call-on-variant.rs new file mode 100644 index 00000000000..7fa8eb2da41 --- /dev/null +++ b/tests/ui/enum/assoc-fn-call-on-variant.rs @@ -0,0 +1,15 @@ +#[derive(Default)] +enum E { + A {}, + B {}, + #[default] + C, +} + +impl E { + fn f() {} +} + +fn main() { + E::A::f(); //~ ERROR failed to resolve: `A` is a variant, not a module +} diff --git a/tests/ui/enum/assoc-fn-call-on-variant.stderr b/tests/ui/enum/assoc-fn-call-on-variant.stderr new file mode 100644 index 00000000000..47fc630c923 --- /dev/null +++ b/tests/ui/enum/assoc-fn-call-on-variant.stderr @@ -0,0 +1,14 @@ +error[E0433]: failed to resolve: `A` is a variant, not a module + --> $DIR/assoc-fn-call-on-variant.rs:14:8 + | +LL | E::A::f(); + | ^ `A` is a variant, not a module + | +help: there is an enum variant `E::A`; try using the variant's enum + | +LL | E::f(); + | ~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/error-codes/E0027.stderr b/tests/ui/error-codes/E0027.stderr index 9ae97e4a994..7bbafcf0a27 100644 --- a/tests/ui/error-codes/E0027.stderr +++ b/tests/ui/error-codes/E0027.stderr @@ -10,6 +10,10 @@ LL | Dog { age: x, name } => {} | ~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | Dog { age: x, name: _ } => {} + | ~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | Dog { age: x, .. } => {} | ~~~~~~ @@ -25,6 +29,10 @@ LL | Dog { name: x, age } => {} | ~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | Dog { name: x, age: _ } => {} + | ~~~~~~~~~~ +help: or always ignore missing fields here + | LL | Dog { name: x, .. } => {} | ~~~~~~ @@ -40,6 +48,10 @@ LL | Dog { name: x, age } => {} | ~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | Dog { name: x, age: _ } => {} + | ~~~~~~~~~~ +help: or always ignore missing fields here + | LL | Dog { name: x, .. } => {} | ~~~~~~ @@ -55,6 +67,10 @@ LL | Dog { name, age } => {} | ~~~~~~~~~~~~~ help: if you don't care about these missing fields, you can explicitly ignore them | +LL | Dog { name: _, age: _ } => {} + | ~~~~~~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | Dog { .. } => {} | ~~~~~~ diff --git a/tests/ui/error-codes/E0094.rs b/tests/ui/error-codes/E0094.rs index 97ebcff99dc..da59d3decac 100644 --- a/tests/ui/error-codes/E0094.rs +++ b/tests/ui/error-codes/E0094.rs @@ -1,9 +1,10 @@ -#![feature(intrinsics, rustc_attrs)] +#![feature(intrinsics)] -extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - fn size_of<T, U>() -> usize; //~ ERROR E0094 +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +fn size_of<T, U>() -> usize { + //~^ ERROR E0094 + loop {} } -fn main() { -} +fn main() {} diff --git a/tests/ui/error-codes/E0094.stderr b/tests/ui/error-codes/E0094.stderr index 1bad5bd950e..e45cc0ea063 100644 --- a/tests/ui/error-codes/E0094.stderr +++ b/tests/ui/error-codes/E0094.stderr @@ -1,8 +1,8 @@ error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 - --> $DIR/E0094.rs:5:15 + --> $DIR/E0094.rs:5:11 | -LL | fn size_of<T, U>() -> usize; - | ^^^^^^ expected 1 type parameter +LL | fn size_of<T, U>() -> usize { + | ^^^^^^ expected 1 type parameter error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0308.rs b/tests/ui/error-codes/E0308.rs index dd9e0b284ea..f8f93d49a8e 100644 --- a/tests/ui/error-codes/E0308.rs +++ b/tests/ui/error-codes/E0308.rs @@ -1,10 +1,11 @@ #![feature(intrinsics)] #![feature(rustc_attrs)] -extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - fn size_of<T>(); //~ ERROR E0308 +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +fn size_of<T>() { + //~^ ERROR E0308 + loop {} } -fn main() { -} +fn main() {} diff --git a/tests/ui/error-codes/E0308.stderr b/tests/ui/error-codes/E0308.stderr index 709b3119276..77e5c06e06a 100644 --- a/tests/ui/error-codes/E0308.stderr +++ b/tests/ui/error-codes/E0308.stderr @@ -1,11 +1,11 @@ error[E0308]: intrinsic has wrong type - --> $DIR/E0308.rs:6:20 + --> $DIR/E0308.rs:6:16 | -LL | fn size_of<T>(); - | ^ expected `usize`, found `()` +LL | fn size_of<T>() { + | ^ expected `usize`, found `()` | - = note: expected signature `extern "rust-intrinsic" fn() -> usize` - found signature `extern "rust-intrinsic" fn() -> ()` + = note: expected signature `fn() -> usize` + found signature `fn() -> ()` error: aborting due to 1 previous error diff --git a/tests/ui/error-festival.stderr b/tests/ui/error-festival.stderr index 26393352b2b..f71fa7e685c 100644 --- a/tests/ui/error-festival.stderr +++ b/tests/ui/error-festival.stderr @@ -2,7 +2,16 @@ error[E0425]: cannot find value `y` in this scope --> $DIR/error-festival.rs:14:5 | LL | y = 2; - | ^ help: a local variable with a similar name exists: `x` + | ^ + | +help: a local variable with a similar name exists + | +LL | x = 2; + | ~ +help: you might have meant to introduce a new binding + | +LL | let y = 2; + | +++ error[E0603]: constant `FOO` is private --> $DIR/error-festival.rs:22:10 diff --git a/tests/ui/explore-issue-38412.rs b/tests/ui/explore-issue-38412.rs index 836cb98b5b3..e1295a96ba5 100644 --- a/tests/ui/explore-issue-38412.rs +++ b/tests/ui/explore-issue-38412.rs @@ -18,7 +18,7 @@ fn main() { let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } = Record::new(); - //~^^ ERROR use of unstable library feature 'unstable_undeclared' + //~^^ ERROR use of unstable library feature `unstable_undeclared` let r = Record::new(); let t = Tuple::new(); diff --git a/tests/ui/explore-issue-38412.stderr b/tests/ui/explore-issue-38412.stderr index a45ec688855..884184ec16e 100644 --- a/tests/ui/explore-issue-38412.stderr +++ b/tests/ui/explore-issue-38412.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_undeclared' +error[E0658]: use of unstable library feature `unstable_undeclared` --> $DIR/explore-issue-38412.rs:19:63 | LL | let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } = @@ -8,7 +8,7 @@ LL | let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_un = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_undeclared' +error[E0658]: use of unstable library feature `unstable_undeclared` --> $DIR/explore-issue-38412.rs:28:5 | LL | r.a_unstable_undeclared_pub; @@ -36,7 +36,7 @@ error[E0616]: field `d_priv` of struct `Record` is private LL | r.d_priv; | ^^^^^^ private field -error[E0658]: use of unstable library feature 'unstable_undeclared' +error[E0658]: use of unstable library feature `unstable_undeclared` --> $DIR/explore-issue-38412.rs:35:5 | LL | t.2; @@ -64,7 +64,7 @@ error[E0616]: field `5` of struct `pub_and_stability::Tuple` is private LL | t.5; | ^ private field -error[E0658]: use of unstable library feature 'unstable_undeclared' +error[E0658]: use of unstable library feature `unstable_undeclared` --> $DIR/explore-issue-38412.rs:42:7 | LL | r.unstable_undeclared_trait_method(); @@ -74,7 +74,7 @@ LL | r.unstable_undeclared_trait_method(); = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_undeclared' +error[E0658]: use of unstable library feature `unstable_undeclared` --> $DIR/explore-issue-38412.rs:46:7 | LL | r.unstable_undeclared(); @@ -117,7 +117,7 @@ LL | r.private(); LL | fn private(&self) -> i32 { self.d_priv } | ------------------------ private method defined here -error[E0658]: use of unstable library feature 'unstable_undeclared' +error[E0658]: use of unstable library feature `unstable_undeclared` --> $DIR/explore-issue-38412.rs:55:7 | LL | t.unstable_undeclared_trait_method(); @@ -127,7 +127,7 @@ LL | t.unstable_undeclared_trait_method(); = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_undeclared' +error[E0658]: use of unstable library feature `unstable_undeclared` --> $DIR/explore-issue-38412.rs:59:7 | LL | t.unstable_undeclared(); diff --git a/tests/ui/extern/extern-with-type-bounds.rs b/tests/ui/extern/extern-with-type-bounds.rs index 99e9801fd40..3fbddfc99a6 100644 --- a/tests/ui/extern/extern-with-type-bounds.rs +++ b/tests/ui/extern/extern-with-type-bounds.rs @@ -1,18 +1,17 @@ #![feature(intrinsics, rustc_attrs)] -extern "rust-intrinsic" { - // Real example from libcore - #[rustc_safe_intrinsic] - fn type_id<T: ?Sized + 'static>() -> u64; +// Intrinsics are the only (?) extern blocks supporting generics. +// Once intrinsics have to be declared via `#[rustc_intrinsic]`, +// the entire support for generics in extern fn can probably be removed. +extern "rust-intrinsic" { // Silent bounds made explicit to make sure they are actually // resolved. fn transmute<T: Sized, U: Sized>(val: T) -> U; // Bounds aren't checked right now, so this should work // even though it's incorrect. - #[rustc_safe_intrinsic] - fn size_of<T: Clone>() -> usize; + fn size_of_val<T: Clone>(x: *const T) -> usize; // Unresolved bounds should still error. fn align_of<T: NoSuchTrait>() -> usize; diff --git a/tests/ui/extern/extern-with-type-bounds.stderr b/tests/ui/extern/extern-with-type-bounds.stderr index 42448d9e924..893947e831f 100644 --- a/tests/ui/extern/extern-with-type-bounds.stderr +++ b/tests/ui/extern/extern-with-type-bounds.stderr @@ -1,5 +1,5 @@ error[E0405]: cannot find trait `NoSuchTrait` in this scope - --> $DIR/extern-with-type-bounds.rs:18:20 + --> $DIR/extern-with-type-bounds.rs:17:20 | LL | fn align_of<T: NoSuchTrait>() -> usize; | ^^^^^^^^^^^ not found in this scope diff --git a/tests/ui/feature-gates/bench.rs b/tests/ui/feature-gates/bench.rs index 2ce1d50fbb0..12e646f7a32 100644 --- a/tests/ui/feature-gates/bench.rs +++ b/tests/ui/feature-gates/bench.rs @@ -1,9 +1,9 @@ //@ edition:2018 -#[bench] //~ ERROR use of unstable library feature 'test' +#[bench] //~ ERROR use of unstable library feature `test` //~| WARN this was previously accepted fn bench() {} -use bench as _; //~ ERROR use of unstable library feature 'test' +use bench as _; //~ ERROR use of unstable library feature `test` //~| WARN this was previously accepted fn main() {} diff --git a/tests/ui/feature-gates/bench.stderr b/tests/ui/feature-gates/bench.stderr index df935560fd6..de78e863012 100644 --- a/tests/ui/feature-gates/bench.stderr +++ b/tests/ui/feature-gates/bench.stderr @@ -1,4 +1,4 @@ -error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable +error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable --> $DIR/bench.rs:3:3 | LL | #[bench] @@ -8,7 +8,7 @@ LL | #[bench] = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266> = note: `#[deny(soft_unstable)]` on by default -error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable +error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable --> $DIR/bench.rs:7:5 | LL | use bench as _; @@ -20,7 +20,7 @@ LL | use bench as _; error: aborting due to 2 previous errors Future incompatibility report: Future breakage diagnostic: -error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable +error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable --> $DIR/bench.rs:3:3 | LL | #[bench] @@ -31,7 +31,7 @@ LL | #[bench] = note: `#[deny(soft_unstable)]` on by default Future breakage diagnostic: -error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable +error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable --> $DIR/bench.rs:7:5 | LL | use bench as _; diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs b/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs index 2d099e24db8..a2a4b3f19d9 100644 --- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs +++ b/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs @@ -5,7 +5,7 @@ use core::alloc::Layout; -#[alloc_error_handler] //~ ERROR use of unstable library feature 'alloc_error_handler' +#[alloc_error_handler] //~ ERROR use of unstable library feature `alloc_error_handler` fn oom(info: Layout) -> ! { loop {} } diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr index 2ebd7cd9b02..ae41ee55d3d 100644 --- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr +++ b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'alloc_error_handler' +error[E0658]: use of unstable library feature `alloc_error_handler` --> $DIR/feature-gate-alloc-error-handler.rs:8:3 | LL | #[alloc_error_handler] diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr index 36a017dd53c..15ef257fbd8 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'autodiff' +error[E0658]: use of unstable library feature `autodiff` --> $DIR/feature-gate-autodiff-use.rs:13:3 | LL | #[autodiff(dfoo, Reverse)] @@ -8,7 +8,7 @@ LL | #[autodiff(dfoo, Reverse)] = help: add `#![feature(autodiff)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'autodiff' +error[E0658]: use of unstable library feature `autodiff` --> $DIR/feature-gate-autodiff-use.rs:9:5 | LL | use std::autodiff::autodiff; diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr index 4b767f824c8..f59e4955452 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'autodiff' +error[E0658]: use of unstable library feature `autodiff` --> $DIR/feature-gate-autodiff-use.rs:13:3 | LL | #[autodiff(dfoo, Reverse)] @@ -14,7 +14,7 @@ error: this rustc version does not support autodiff LL | #[autodiff(dfoo, Reverse)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0658]: use of unstable library feature 'autodiff' +error[E0658]: use of unstable library feature `autodiff` --> $DIR/feature-gate-autodiff-use.rs:9:5 | LL | use std::autodiff::autodiff; diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.rs b/tests/ui/feature-gates/feature-gate-autodiff-use.rs index 2276a79d6e2..602e830b0b2 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.rs +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.rs @@ -7,11 +7,11 @@ #![crate_type = "lib"] use std::autodiff::autodiff; -//[has_support]~^ ERROR use of unstable library feature 'autodiff' -//[no_support]~^^ ERROR use of unstable library feature 'autodiff' +//[has_support]~^ ERROR use of unstable library feature `autodiff` +//[no_support]~^^ ERROR use of unstable library feature `autodiff` #[autodiff(dfoo, Reverse)] -//[has_support]~^ ERROR use of unstable library feature 'autodiff' [E0658] -//[no_support]~^^ ERROR use of unstable library feature 'autodiff' [E0658] +//[has_support]~^ ERROR use of unstable library feature `autodiff` [E0658] +//[no_support]~^^ ERROR use of unstable library feature `autodiff` [E0658] //[no_support]~| ERROR this rustc version does not support autodiff fn foo() {} diff --git a/tests/ui/feature-gates/feature-gate-concat_bytes.rs b/tests/ui/feature-gates/feature-gate-concat_bytes.rs index 07d63cb11e0..abdaa725784 100644 --- a/tests/ui/feature-gates/feature-gate-concat_bytes.rs +++ b/tests/ui/feature-gates/feature-gate-concat_bytes.rs @@ -1,4 +1,4 @@ fn main() { - let a = concat_bytes!(b'A', b"BC"); //~ ERROR use of unstable library feature 'concat_bytes' + let a = concat_bytes!(b'A', b"BC"); //~ ERROR use of unstable library feature `concat_bytes` assert_eq!(a, &[65, 66, 67]); } diff --git a/tests/ui/feature-gates/feature-gate-concat_bytes.stderr b/tests/ui/feature-gates/feature-gate-concat_bytes.stderr index ed9692d3693..4f75e143e9a 100644 --- a/tests/ui/feature-gates/feature-gate-concat_bytes.stderr +++ b/tests/ui/feature-gates/feature-gate-concat_bytes.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'concat_bytes' +error[E0658]: use of unstable library feature `concat_bytes` --> $DIR/feature-gate-concat_bytes.rs:2:13 | LL | let a = concat_bytes!(b'A', b"BC"); diff --git a/tests/ui/feature-gates/feature-gate-concat_idents.stderr b/tests/ui/feature-gates/feature-gate-concat_idents.stderr index eaaef0f2539..d0f4fe62d04 100644 --- a/tests/ui/feature-gates/feature-gate-concat_idents.stderr +++ b/tests/ui/feature-gates/feature-gate-concat_idents.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change --> $DIR/feature-gate-concat_idents.rs:5:13 | LL | let a = concat_idents!(X, Y_1); @@ -8,7 +8,7 @@ LL | let a = concat_idents!(X, Y_1); = help: add `#![feature(concat_idents)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change --> $DIR/feature-gate-concat_idents.rs:6:13 | LL | let b = concat_idents!(X, Y_2); diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr index 2fe786ff406..2052813ea4a 100644 --- a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr +++ b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change --> $DIR/feature-gate-concat_idents2.rs:2:5 | LL | concat_idents!(a, b); diff --git a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr index a7daa1f949f..b186601d0ed 100644 --- a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr +++ b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change --> $DIR/feature-gate-concat_idents3.rs:5:20 | LL | assert_eq!(10, concat_idents!(X, Y_1)); @@ -8,7 +8,7 @@ LL | assert_eq!(10, concat_idents!(X, Y_1)); = help: add `#![feature(concat_idents)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change --> $DIR/feature-gate-concat_idents3.rs:6:20 | LL | assert_eq!(20, concat_idents!(X, Y_2)); diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.stderr b/tests/ui/feature-gates/feature-gate-custom_mir.stderr index 118eab144bf..eeceb0355ee 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.stderr +++ b/tests/ui/feature-gates/feature-gate-custom_mir.stderr @@ -7,7 +7,7 @@ LL | #[custom_mir(dialect = "built")] = help: add `#![feature(custom_mir)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable +error[E0658]: use of unstable library feature `custom_mir`: MIR is an implementation detail and extremely unstable --> $DIR/feature-gate-custom_mir.rs:4:5 | LL | use core::intrinsics::mir::*; @@ -16,7 +16,7 @@ LL | use core::intrinsics::mir::*; = help: add `#![feature(custom_mir)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable +error[E0658]: use of unstable library feature `custom_mir`: MIR is an implementation detail and extremely unstable --> $DIR/feature-gate-custom_mir.rs:10:13 | LL | Return() diff --git a/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr index 016be980d4d..7744759be57 100644 --- a/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr +++ b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'custom_test_frameworks': custom test frameworks are an unstable feature +error[E0658]: use of unstable library feature `custom_test_frameworks`: custom test frameworks are an unstable feature --> $DIR/feature-gate-custom_test_frameworks.rs:3:3 | LL | #[test_case] diff --git a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs index 69bc70e8666..d730849dcf6 100644 --- a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs +++ b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs @@ -1,6 +1,6 @@ -use std::marker::CoercePointee; //~ ERROR use of unstable library feature 'derive_coerce_pointee' +use std::marker::CoercePointee; //~ ERROR use of unstable library feature `derive_coerce_pointee` -#[derive(CoercePointee)] //~ ERROR use of unstable library feature 'derive_coerce_pointee' +#[derive(CoercePointee)] //~ ERROR use of unstable library feature `derive_coerce_pointee` #[repr(transparent)] struct MyPointer<'a, #[pointee] T: ?Sized> { ptr: &'a T, diff --git a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr index 0b52ceb782a..19babe149d9 100644 --- a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr +++ b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'derive_coerce_pointee' +error[E0658]: use of unstable library feature `derive_coerce_pointee` --> $DIR/feature-gate-derive-coerce-pointee.rs:3:10 | LL | #[derive(CoercePointee)] @@ -8,7 +8,7 @@ LL | #[derive(CoercePointee)] = help: add `#![feature(derive_coerce_pointee)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'derive_coerce_pointee' +error[E0658]: use of unstable library feature `derive_coerce_pointee` --> $DIR/feature-gate-derive-coerce-pointee.rs:1:5 | LL | use std::marker::CoercePointee; diff --git a/tests/ui/feature-gates/feature-gate-format_args_nl.stderr b/tests/ui/feature-gates/feature-gate-format_args_nl.stderr index f72d34d9b0b..c7e8f8c686f 100644 --- a/tests/ui/feature-gates/feature-gate-format_args_nl.stderr +++ b/tests/ui/feature-gates/feature-gate-format_args_nl.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'format_args_nl': `format_args_nl` is only for internal language use and is subject to change +error[E0658]: use of unstable library feature `format_args_nl`: `format_args_nl` is only for internal language use and is subject to change --> $DIR/feature-gate-format_args_nl.rs:2:5 | LL | format_args_nl!(""); diff --git a/tests/ui/feature-gates/feature-gate-log_syntax.stderr b/tests/ui/feature-gates/feature-gate-log_syntax.stderr index 0eba231a287..78152b50e89 100644 --- a/tests/ui/feature-gates/feature-gate-log_syntax.stderr +++ b/tests/ui/feature-gates/feature-gate-log_syntax.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `log_syntax`: `log_syntax!` is not stable enough for use and is subject to change --> $DIR/feature-gate-log_syntax.rs:2:5 | LL | log_syntax!() diff --git a/tests/ui/feature-gates/feature-gate-log_syntax2.stderr b/tests/ui/feature-gates/feature-gate-log_syntax2.stderr index e1f92dd60a3..8875de2281b 100644 --- a/tests/ui/feature-gates/feature-gate-log_syntax2.stderr +++ b/tests/ui/feature-gates/feature-gate-log_syntax2.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `log_syntax`: `log_syntax!` is not stable enough for use and is subject to change --> $DIR/feature-gate-log_syntax2.rs:2:22 | LL | println!("{:?}", log_syntax!()); diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs index 5fe0bbdc774..abb55b9a557 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.rs +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -1,13 +1,13 @@ //@ needs-asm-support use std::arch::naked_asm; -//~^ ERROR use of unstable library feature 'naked_functions' +//~^ ERROR use of unstable library feature `naked_functions` #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked() { naked_asm!("") - //~^ ERROR use of unstable library feature 'naked_functions' + //~^ ERROR use of unstable library feature `naked_functions` //~| ERROR: requires unsafe } @@ -15,7 +15,7 @@ extern "C" fn naked() { //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked_2() -> isize { naked_asm!("") - //~^ ERROR use of unstable library feature 'naked_functions' + //~^ ERROR use of unstable library feature `naked_functions` //~| ERROR: requires unsafe } diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr index 709234eb023..9bfb9275bb2 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.stderr +++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'naked_functions' +error[E0658]: use of unstable library feature `naked_functions` --> $DIR/feature-gate-naked_functions.rs:9:5 | LL | naked_asm!("") @@ -8,7 +8,7 @@ LL | naked_asm!("") = help: add `#![feature(naked_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'naked_functions' +error[E0658]: use of unstable library feature `naked_functions` --> $DIR/feature-gate-naked_functions.rs:17:5 | LL | naked_asm!("") @@ -38,7 +38,7 @@ LL | #[naked] = help: add `#![feature(naked_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'naked_functions' +error[E0658]: use of unstable library feature `naked_functions` --> $DIR/feature-gate-naked_functions.rs:3:5 | LL | use std::arch::naked_asm; diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs index 13f8fd5fe22..71caf43806d 100644 --- a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs +++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs @@ -5,11 +5,11 @@ extern crate rustc_serialize; //~ERROR can't find crate for `rustc_serialize` #[derive( RustcEncodable, - //~^ ERROR use of unstable library feature 'rustc_encodable_decodable' + //~^ ERROR use of unstable library feature `rustc_encodable_decodable` //~^^ WARNING this was previously accepted by the compiler //~^^^ WARNING use of deprecated macro `RustcEncodable` RustcDecodable, - //~^ ERROR use of unstable library feature 'rustc_encodable_decodable' + //~^ ERROR use of unstable library feature `rustc_encodable_decodable` //~^^ WARNING this was previously accepted by the compiler //~^^^ WARNING use of deprecated macro `RustcDecodable` )] diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr index 02b74dacf4d..b949dbb9da2 100644 --- a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr @@ -6,7 +6,7 @@ LL | extern crate rustc_serialize; | = help: maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview` -error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code +error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5 | LL | RustcEncodable, @@ -24,7 +24,7 @@ LL | RustcEncodable, | = note: `#[warn(deprecated)]` on by default -error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code +error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 | LL | RustcDecodable, @@ -43,7 +43,7 @@ error: aborting due to 3 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0463`. Future incompatibility report: Future breakage diagnostic: -error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code +error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5 | LL | RustcEncodable, @@ -54,7 +54,7 @@ LL | RustcEncodable, = note: `#[deny(soft_unstable)]` on by default Future breakage diagnostic: -error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code +error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 | LL | RustcDecodable, diff --git a/tests/ui/feature-gates/feature-gate-trace_macros.stderr b/tests/ui/feature-gates/feature-gate-trace_macros.stderr index 68d3f75e995..4c6cfce7d3d 100644 --- a/tests/ui/feature-gates/feature-gate-trace_macros.stderr +++ b/tests/ui/feature-gates/feature-gate-trace_macros.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change --> $DIR/feature-gate-trace_macros.rs:2:5 | LL | trace_macros!(true); diff --git a/tests/ui/feature-gates/feature-gate-type_ascription.rs b/tests/ui/feature-gates/feature-gate-type_ascription.rs index 5c3f0e37df6..ef3923b6ff2 100644 --- a/tests/ui/feature-gates/feature-gate-type_ascription.rs +++ b/tests/ui/feature-gates/feature-gate-type_ascription.rs @@ -1,5 +1,5 @@ // Type ascription is unstable fn main() { - let a = type_ascribe!(10, u8); //~ ERROR use of unstable library feature 'type_ascription': placeholder syntax for type ascription + let a = type_ascribe!(10, u8); //~ ERROR use of unstable library feature `type_ascription`: placeholder syntax for type ascription } diff --git a/tests/ui/feature-gates/feature-gate-type_ascription.stderr b/tests/ui/feature-gates/feature-gate-type_ascription.stderr index 88da58d07e1..f59e6435c8e 100644 --- a/tests/ui/feature-gates/feature-gate-type_ascription.stderr +++ b/tests/ui/feature-gates/feature-gate-type_ascription.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'type_ascription': placeholder syntax for type ascription +error[E0658]: use of unstable library feature `type_ascription`: placeholder syntax for type ascription --> $DIR/feature-gate-type_ascription.rs:4:13 | LL | let a = type_ascribe!(10, u8); diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs index 42f7c5f0fba..bc5b48741b0 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs @@ -1,9 +1,9 @@ #![allow(dead_code)] fn foo<F: Fn()>(mut f: F) { - f.call(()); //~ ERROR use of unstable library feature 'fn_traits' - f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits' - f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits' + f.call(()); //~ ERROR use of unstable library feature `fn_traits` + f.call_mut(()); //~ ERROR use of unstable library feature `fn_traits` + f.call_once(()); //~ ERROR use of unstable library feature `fn_traits` } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr index 0ef732d391b..6a5f0c8e6a6 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'fn_traits' +error[E0658]: use of unstable library feature `fn_traits` --> $DIR/feature-gate-unboxed-closures-method-calls.rs:4:7 | LL | f.call(()); @@ -8,7 +8,7 @@ LL | f.call(()); = help: add `#![feature(fn_traits)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'fn_traits' +error[E0658]: use of unstable library feature `fn_traits` --> $DIR/feature-gate-unboxed-closures-method-calls.rs:5:7 | LL | f.call_mut(()); @@ -18,7 +18,7 @@ LL | f.call_mut(()); = help: add `#![feature(fn_traits)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'fn_traits' +error[E0658]: use of unstable library feature `fn_traits` --> $DIR/feature-gate-unboxed-closures-method-calls.rs:6:7 | LL | f.call_once(()); diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs index 25c90492eb8..137e7d71e91 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs @@ -1,9 +1,9 @@ #![allow(dead_code)] fn foo<F: Fn()>(mut f: F) { - Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits' - FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits' - FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits' + Fn::call(&f, ()); //~ ERROR use of unstable library feature `fn_traits` + FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature `fn_traits` + FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature `fn_traits` } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr index f4d75fc6a86..90695fa4c46 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'fn_traits' +error[E0658]: use of unstable library feature `fn_traits` --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:4:5 | LL | Fn::call(&f, ()); @@ -8,7 +8,7 @@ LL | Fn::call(&f, ()); = help: add `#![feature(fn_traits)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'fn_traits' +error[E0658]: use of unstable library feature `fn_traits` --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:5:5 | LL | FnMut::call_mut(&mut f, ()); @@ -18,7 +18,7 @@ LL | FnMut::call_mut(&mut f, ()); = help: add `#![feature(fn_traits)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'fn_traits' +error[E0658]: use of unstable library feature `fn_traits` --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:6:5 | LL | FnOnce::call_once(f, ()); diff --git a/tests/ui/feature-gates/issue-49983-see-issue-0.stderr b/tests/ui/feature-gates/issue-49983-see-issue-0.stderr index 8f090c9eef9..29a2845852e 100644 --- a/tests/ui/feature-gates/issue-49983-see-issue-0.stderr +++ b/tests/ui/feature-gates/issue-49983-see-issue-0.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'ptr_internals': use `NonNull` instead and consider `PhantomData<T>` (if you also use `#[may_dangle]`), `Send`, and/or `Sync` +error[E0658]: use of unstable library feature `ptr_internals`: use `NonNull` instead and consider `PhantomData<T>` (if you also use `#[may_dangle]`), `Send`, and/or `Sync` --> $DIR/issue-49983-see-issue-0.rs:4:30 | LL | #[allow(unused_imports)] use core::ptr::Unique; diff --git a/tests/ui/feature-gates/rustc-private.rs b/tests/ui/feature-gates/rustc-private.rs index aa44f790c8a..2605f595b6c 100644 --- a/tests/ui/feature-gates/rustc-private.rs +++ b/tests/ui/feature-gates/rustc-private.rs @@ -1,5 +1,5 @@ // gate-test-rustc_private -extern crate cfg_if; //~ ERROR use of unstable library feature 'rustc_private' +extern crate cfg_if; //~ ERROR use of unstable library feature `rustc_private` fn main() {} diff --git a/tests/ui/feature-gates/rustc-private.stderr b/tests/ui/feature-gates/rustc-private.stderr index 96cc98619fd..74594c712f2 100644 --- a/tests/ui/feature-gates/rustc-private.stderr +++ b/tests/ui/feature-gates/rustc-private.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? +error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? --> $DIR/rustc-private.rs:3:1 | LL | extern crate cfg_if; diff --git a/tests/ui/feature-gates/trace_macros-gate.stderr b/tests/ui/feature-gates/trace_macros-gate.stderr index 1313a0e8ae2..6ca9d1573d9 100644 --- a/tests/ui/feature-gates/trace_macros-gate.stderr +++ b/tests/ui/feature-gates/trace_macros-gate.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change --> $DIR/trace_macros-gate.rs:4:5 | LL | trace_macros!(); @@ -14,7 +14,7 @@ error: trace_macros! accepts only `true` or `false` LL | trace_macros!(); | ^^^^^^^^^^^^^^^ -error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change --> $DIR/trace_macros-gate.rs:6:5 | LL | trace_macros!(true); @@ -24,7 +24,7 @@ LL | trace_macros!(true); = help: add `#![feature(trace_macros)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change --> $DIR/trace_macros-gate.rs:7:5 | LL | trace_macros!(false); @@ -34,7 +34,7 @@ LL | trace_macros!(false); = help: add `#![feature(trace_macros)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change +error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change --> $DIR/trace_macros-gate.rs:10:26 | LL | ($x: ident) => { trace_macros!($x) } diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index 51209121bd9..e11d346b712 100644 --- a/tests/ui/generic-const-items/const-trait-impl.rs +++ b/tests/ui/generic-const-items/const-trait-impl.rs @@ -2,7 +2,7 @@ //@ compile-flags: -Znext-solver // Test that we can call methods from const trait impls inside of generic const items. -#![feature(generic_const_items, const_trait_impl, effects)] +#![feature(generic_const_items, const_trait_impl)] #![allow(incomplete_features)] #![crate_type = "lib"] diff --git a/tests/ui/impl-trait/issue-55872-3.rs b/tests/ui/impl-trait/issue-55872-3.rs index 3f931027d9a..50b9eb3ce0e 100644 --- a/tests/ui/impl-trait/issue-55872-3.rs +++ b/tests/ui/impl-trait/issue-55872-3.rs @@ -1,4 +1,5 @@ //@ edition:2018 +//@compile-flags: --diagnostic-width=300 #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/impl-trait/issue-55872-3.stderr b/tests/ui/impl-trait/issue-55872-3.stderr index 98e9fbf4153..827155d48b8 100644 --- a/tests/ui/impl-trait/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issue-55872-3.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}: Copy` is not satisfied - --> $DIR/issue-55872-3.rs:13:20 +error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}: Copy` is not satisfied + --> $DIR/issue-55872-3.rs:14:20 | LL | fn foo<T>() -> Self::E { - | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}` + | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}` LL | LL | async {} - | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}` here + | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:16:9: 16:14}` here error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-37887.stderr b/tests/ui/imports/issue-37887.stderr index 02c2c803262..cc191a17c29 100644 --- a/tests/ui/imports/issue-37887.stderr +++ b/tests/ui/imports/issue-37887.stderr @@ -9,7 +9,7 @@ help: consider importing the `test` crate LL + extern crate test; | -error[E0658]: use of unstable library feature 'test' +error[E0658]: use of unstable library feature `test` --> $DIR/issue-37887.rs:2:5 | LL | extern crate test; diff --git a/tests/ui/imports/resolve-other-libc.rs b/tests/ui/imports/resolve-other-libc.rs index d848f8260aa..e23083276ce 100644 --- a/tests/ui/imports/resolve-other-libc.rs +++ b/tests/ui/imports/resolve-other-libc.rs @@ -6,7 +6,7 @@ // indicates that `libc` was wrongly resolved to `libc` shipped with the // compiler: // -// error[E0658]: use of unstable library feature 'rustc_private': \ +// error[E0658]: use of unstable library feature `rustc_private`: \ // this crate is being loaded from the sysroot // extern crate libc; //~ ERROR: extern location for libc does not exist: test.rlib diff --git a/tests/ui/inference/inference_unstable_forced.stderr b/tests/ui/inference/inference_unstable_forced.stderr index 26eaddd2707..e3b5b292cd4 100644 --- a/tests/ui/inference/inference_unstable_forced.stderr +++ b/tests/ui/inference/inference_unstable_forced.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'ipu_flatten' +error[E0658]: use of unstable library feature `ipu_flatten` --> $DIR/inference_unstable_forced.rs:11:20 | LL | assert_eq!('x'.ipu_flatten(), 0); diff --git a/tests/ui/internal/internal-unstable-noallow.rs b/tests/ui/internal/internal-unstable-noallow.rs index 9d925c86122..57ddb93d880 100644 --- a/tests/ui/internal/internal-unstable-noallow.rs +++ b/tests/ui/internal/internal-unstable-noallow.rs @@ -4,10 +4,10 @@ // the // ~ form. //@ aux-build:internal_unstable.rs -//@ error-pattern:use of unstable library feature 'function' -//@ error-pattern:use of unstable library feature 'struct_field' -//@ error-pattern:use of unstable library feature 'method' -//@ error-pattern:use of unstable library feature 'struct2_field' +//@ error-pattern:use of unstable library feature `function` +//@ error-pattern:use of unstable library feature `struct_field` +//@ error-pattern:use of unstable library feature `method` +//@ error-pattern:use of unstable library feature `struct2_field` #[macro_use] extern crate internal_unstable; diff --git a/tests/ui/internal/internal-unstable-noallow.stderr b/tests/ui/internal/internal-unstable-noallow.stderr index b39456b1cae..22f42abbd11 100644 --- a/tests/ui/internal/internal-unstable-noallow.stderr +++ b/tests/ui/internal/internal-unstable-noallow.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'function' +error[E0658]: use of unstable library feature `function` --> $DIR/internal-unstable-noallow.rs:16:5 | LL | call_unstable_noallow!(); @@ -8,7 +8,7 @@ LL | call_unstable_noallow!(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `call_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: use of unstable library feature 'struct_field' +error[E0658]: use of unstable library feature `struct_field` --> $DIR/internal-unstable-noallow.rs:18:5 | LL | construct_unstable_noallow!(0); @@ -18,7 +18,7 @@ LL | construct_unstable_noallow!(0); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `construct_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: use of unstable library feature 'method' +error[E0658]: use of unstable library feature `method` --> $DIR/internal-unstable-noallow.rs:20:35 | LL | |x: internal_unstable::Foo| { call_method_noallow!(x) }; @@ -28,7 +28,7 @@ LL | |x: internal_unstable::Foo| { call_method_noallow!(x) }; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `call_method_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: use of unstable library feature 'struct2_field' +error[E0658]: use of unstable library feature `struct2_field` --> $DIR/internal-unstable-noallow.rs:22:35 | LL | |x: internal_unstable::Bar| { access_field_noallow!(x) }; diff --git a/tests/ui/internal/internal-unstable-thread-local.stderr b/tests/ui/internal/internal-unstable-thread-local.stderr index 58c7b3f67eb..c0510b39e50 100644 --- a/tests/ui/internal/internal-unstable-thread-local.stderr +++ b/tests/ui/internal/internal-unstable-thread-local.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'function' +error[E0658]: use of unstable library feature `function` --> $DIR/internal-unstable-thread-local.rs:9:32 | LL | thread_local!(static BAR: () = internal_unstable::unstable()); diff --git a/tests/ui/internal/internal-unstable.stderr b/tests/ui/internal/internal-unstable.stderr index 78b9109d1c2..ea74175f09b 100644 --- a/tests/ui/internal/internal-unstable.stderr +++ b/tests/ui/internal/internal-unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'function' +error[E0658]: use of unstable library feature `function` --> $DIR/internal-unstable.rs:48:25 | LL | pass_through_allow!(internal_unstable::unstable()); @@ -7,7 +7,7 @@ LL | pass_through_allow!(internal_unstable::unstable()); = help: add `#![feature(function)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'function' +error[E0658]: use of unstable library feature `function` --> $DIR/internal-unstable.rs:50:27 | LL | pass_through_noallow!(internal_unstable::unstable()); @@ -16,7 +16,7 @@ LL | pass_through_noallow!(internal_unstable::unstable()); = help: add `#![feature(function)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'function' +error[E0658]: use of unstable library feature `function` --> $DIR/internal-unstable.rs:54:22 | LL | println!("{:?}", internal_unstable::unstable()); @@ -25,7 +25,7 @@ LL | println!("{:?}", internal_unstable::unstable()); = help: add `#![feature(function)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'function' +error[E0658]: use of unstable library feature `function` --> $DIR/internal-unstable.rs:56:10 | LL | bar!(internal_unstable::unstable()); @@ -34,7 +34,7 @@ LL | bar!(internal_unstable::unstable()); = help: add `#![feature(function)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'function' +error[E0658]: use of unstable library feature `function` --> $DIR/internal-unstable.rs:18:9 | LL | internal_unstable::unstable(); diff --git a/tests/ui/intrinsics/always-gets-overridden.rs b/tests/ui/intrinsics/always-gets-overridden.rs index ad2c2be4daa..2fb64f96d83 100644 --- a/tests/ui/intrinsics/always-gets-overridden.rs +++ b/tests/ui/intrinsics/always-gets-overridden.rs @@ -1,6 +1,6 @@ //! Check that `vtable_size` gets overridden by llvm backend even if there is no //! `rustc_intrinsic_must_be_overridden` attribute on this usage. -#![feature(rustc_attrs)] +#![feature(intrinsics)] //@run-pass #[rustc_intrinsic] diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr index 50092edda4f..e317ed23ab1 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.stderr +++ b/tests/ui/intrinsics/const-eval-select-bad.stderr @@ -27,7 +27,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF); = help: the trait `FnOnce()` is not implemented for `{integer}` = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `const_eval_select` - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL error[E0277]: expected a `FnOnce()` closure, found `{integer}` --> $DIR/const-eval-select-bad.rs:10:31 @@ -40,7 +40,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF); = help: the trait `FnOnce()` is not implemented for `{integer}` = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `const_eval_select` - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL error: this argument must be a function item --> $DIR/const-eval-select-bad.rs:10:27 @@ -69,7 +69,7 @@ LL | const_eval_select((1,), foo, bar); | required by a bound introduced by this call | note: required by a bound in `const_eval_select` - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL error[E0631]: type mismatch in function arguments --> $DIR/const-eval-select-bad.rs:37:32 @@ -85,7 +85,7 @@ LL | const_eval_select((true,), foo, baz); = note: expected function signature `fn(bool) -> _` found function signature `fn(i32) -> _` note: required by a bound in `const_eval_select` - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL help: consider wrapping the function in a closure | LL | const_eval_select((true,), |arg0: bool| foo(/* i32 */), baz); diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs b/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs deleted file mode 100644 index ffaa4d771d9..00000000000 --- a/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[rustc_safe_intrinsic] -//~^ ERROR the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe -//~| ERROR attribute should be applied to intrinsic functions -fn safe() {} - -fn main() {} diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr b/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr deleted file mode 100644 index e49880e9bb8..00000000000 --- a/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0658]: the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe - --> $DIR/feature-gate-safe-intrinsic.rs:1:1 - | -LL | #[rustc_safe_intrinsic] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: attribute should be applied to intrinsic functions - --> $DIR/feature-gate-safe-intrinsic.rs:1:1 - | -LL | #[rustc_safe_intrinsic] - | ^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn safe() {} - | ------------ not an intrinsic function - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index 4cb05f6a8df..ab99aa5fd03 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -1,14 +1,8 @@ //@ run-pass -#![feature(intrinsics, rustc_attrs)] +#![feature(core_intrinsics, rustc_attrs)] -mod rusti { - extern "rust-intrinsic" { - pub fn pref_align_of<T>() -> usize; - #[rustc_safe_intrinsic] - pub fn min_align_of<T>() -> usize; - } -} +use std::intrinsics as rusti; #[cfg(any( target_os = "android", diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs index 99f98c3f27a..76b6a8c8395 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs @@ -1,5 +1,4 @@ #![feature(core_intrinsics)] -#![feature(const_intrinsic_raw_eq)] const RAW_EQ_PADDING: bool = unsafe { std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index bedfc8283ea..b8fdfe7bef3 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/intrinsic-raw_eq-const-bad.rs:5:5 + --> $DIR/intrinsic-raw_eq-const-bad.rs:4:5 | LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory error[E0080]: evaluation of constant value failed - --> $DIR/intrinsic-raw_eq-const-bad.rs:11:5 + --> $DIR/intrinsic-raw_eq-const-bad.rs:10:5 | LL | std::intrinsics::raw_eq(&(&0), &(&1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer @@ -14,7 +14,7 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1)) = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: evaluation of constant value failed - --> $DIR/intrinsic-raw_eq-const-bad.rs:19:5 + --> $DIR/intrinsic-raw_eq-const-bad.rs:18:5 | LL | std::intrinsics::raw_eq(aref, aref) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const.rs index 47b4e20dfbb..b37def85bb7 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(core_intrinsics)] -#![feature(const_intrinsic_raw_eq)] pub fn main() { use std::intrinsics::raw_eq; diff --git a/tests/ui/intrinsics/intrinsics-integer.rs b/tests/ui/intrinsics/intrinsics-integer.rs index 7dbc4b8b7ce..8eb03924feb 100644 --- a/tests/ui/intrinsics/intrinsics-integer.rs +++ b/tests/ui/intrinsics/intrinsics-integer.rs @@ -1,24 +1,8 @@ //@ run-pass -#![feature(intrinsics)] -#![feature(rustc_attrs)] - -mod rusti { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn ctpop<T>(x: T) -> u32; - #[rustc_safe_intrinsic] - pub fn ctlz<T>(x: T) -> u32; - pub fn ctlz_nonzero<T>(x: T) -> u32; - #[rustc_safe_intrinsic] - pub fn cttz<T>(x: T) -> u32; - pub fn cttz_nonzero<T>(x: T) -> u32; - #[rustc_safe_intrinsic] - pub fn bswap<T>(x: T) -> T; - #[rustc_safe_intrinsic] - pub fn bitreverse<T>(x: T) -> T; - } -} +#![feature(core_intrinsics)] + +use std::intrinsics as rusti; pub fn main() { use rusti::*; diff --git a/tests/ui/intrinsics/not-overridden.rs b/tests/ui/intrinsics/not-overridden.rs index e1f1bbe0951..16f8e9bcf6a 100644 --- a/tests/ui/intrinsics/not-overridden.rs +++ b/tests/ui/intrinsics/not-overridden.rs @@ -1,6 +1,6 @@ //! Check that intrinsics that do not get overridden, but are marked as such, //! cause an error instead of silently invoking the body. -#![feature(rustc_attrs)] +#![feature(intrinsics)] //@ build-fail //@ failure-status:101 //@ normalize-stderr-test: ".*note: .*\n\n" -> "" diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr index 21b7bf4e1cb..7af17147f28 100644 --- a/tests/ui/intrinsics/reify-intrinsic.stderr +++ b/tests/ui/intrinsics/reify-intrinsic.stderr @@ -7,9 +7,9 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr | expected due to this | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize` - found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` + found fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` -error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid +error[E0606]: casting `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid --> $DIR/reify-intrinsic.rs:11:13 | LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr deleted file mode 100644 index c59e357b275..00000000000 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.effects.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` - --> $DIR/safe-intrinsic-mismatch.rs:11:5 - | -LL | fn size_of<T>() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` - --> $DIR/safe-intrinsic-mismatch.rs:11:5 - | -LL | fn size_of<T>() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` - --> $DIR/safe-intrinsic-mismatch.rs:16:1 - | -LL | const fn assume(_b: bool) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0308]: intrinsic has wrong type - --> $DIR/safe-intrinsic-mismatch.rs:16:16 - | -LL | const fn assume(_b: bool) {} - | ^ expected unsafe fn, found safe fn - | - = note: expected signature `unsafe fn(_)` - found signature `fn(_)` - -error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `const_deallocate` - --> $DIR/safe-intrinsic-mismatch.rs:20:1 - | -LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0308]: intrinsic has wrong type - --> $DIR/safe-intrinsic-mismatch.rs:20:26 - | -LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} - | ^ expected unsafe fn, found safe fn - | - = note: expected signature `unsafe fn(_, _, _)` - found signature `fn(_, _, _)` - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs index af563e996c1..915a23b5905 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs @@ -1,11 +1,5 @@ -//@ revisions: stock effects #![feature(intrinsics)] #![feature(rustc_attrs)] -// as effects insert a const generic param to const intrinsics, -// check here that it doesn't report a const param mismatch either -// enabling or disabling effects. -#![cfg_attr(effects, feature(effects))] -#![allow(incomplete_features)] extern "rust-intrinsic" { fn size_of<T>() -> usize; //~ ERROR intrinsic safety mismatch @@ -24,7 +18,6 @@ const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} mod foo { #[rustc_intrinsic] unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} - // FIXME(effects) ~^ ERROR wrong number of const parameters } fn main() {} diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stock.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr index c59e357b275..aa4f294232d 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.stock.stderr +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr @@ -1,11 +1,11 @@ error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` - --> $DIR/safe-intrinsic-mismatch.rs:11:5 + --> $DIR/safe-intrinsic-mismatch.rs:5:5 | LL | fn size_of<T>() -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` - --> $DIR/safe-intrinsic-mismatch.rs:11:5 + --> $DIR/safe-intrinsic-mismatch.rs:5:5 | LL | fn size_of<T>() -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | fn size_of<T>() -> usize; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` - --> $DIR/safe-intrinsic-mismatch.rs:16:1 + --> $DIR/safe-intrinsic-mismatch.rs:10:1 | LL | const fn assume(_b: bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: intrinsic has wrong type - --> $DIR/safe-intrinsic-mismatch.rs:16:16 + --> $DIR/safe-intrinsic-mismatch.rs:10:16 | LL | const fn assume(_b: bool) {} | ^ expected unsafe fn, found safe fn @@ -28,13 +28,13 @@ LL | const fn assume(_b: bool) {} found signature `fn(_)` error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `const_deallocate` - --> $DIR/safe-intrinsic-mismatch.rs:20:1 + --> $DIR/safe-intrinsic-mismatch.rs:14:1 | LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: intrinsic has wrong type - --> $DIR/safe-intrinsic-mismatch.rs:20:26 + --> $DIR/safe-intrinsic-mismatch.rs:14:26 | LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} | ^ expected unsafe fn, found safe fn diff --git a/tests/ui/intrinsics/unchecked_math_unstable.stderr b/tests/ui/intrinsics/unchecked_math_unstable.stderr index c2a116b6200..b284567f8af 100644 --- a/tests/ui/intrinsics/unchecked_math_unstable.stderr +++ b/tests/ui/intrinsics/unchecked_math_unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library +error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library --> $DIR/unchecked_math_unstable.rs:4:19 | LL | let add = std::intrinsics::unchecked_add(x, y); @@ -7,7 +7,7 @@ LL | let add = std::intrinsics::unchecked_add(x, y); = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library +error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library --> $DIR/unchecked_math_unstable.rs:5:19 | LL | let sub = std::intrinsics::unchecked_sub(x, y); @@ -16,7 +16,7 @@ LL | let sub = std::intrinsics::unchecked_sub(x, y); = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library +error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library --> $DIR/unchecked_math_unstable.rs:6:19 | LL | let mul = std::intrinsics::unchecked_mul(x, y); diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr index d0e8d4719d3..dae08119dbc 100644 --- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr @@ -1,2 +1,2 @@ -error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf` was expected +error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf` was expected diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr new file mode 100644 index 00000000000..13f79e94674 --- /dev/null +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr @@ -0,0 +1,2 @@ +error: incorrect value `pc` for unstable option `branch-protection` - a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf` was expected + diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs index c0a4bcac11b..b4025080034 100644 --- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs @@ -1,7 +1,10 @@ -//@ revisions: BADFLAGS BADTARGET +//@ revisions: BADFLAGS BADFLAGSPC BADTARGET //@ [BADFLAGS] compile-flags: --target=aarch64-unknown-linux-gnu -Zbranch-protection=leaf //@ [BADFLAGS] check-fail //@ [BADFLAGS] needs-llvm-components: aarch64 +//@ [BADFLAGSPC] compile-flags: --target=aarch64-unknown-linux-gnu -Zbranch-protection=pc +//@ [BADFLAGSPC] check-fail +//@ [BADFLAGSPC] needs-llvm-components: aarch64 //@ [BADTARGET] compile-flags: --target=x86_64-unknown-linux-gnu -Zbranch-protection=bti //@ [BADTARGET] check-fail //@ [BADTARGET] needs-llvm-components: x86 @@ -10,5 +13,5 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} diff --git a/tests/ui/issues/issue-52489.rs b/tests/ui/issues/issue-52489.rs index 95a3d43105c..c1e1cb41c76 100644 --- a/tests/ui/issues/issue-52489.rs +++ b/tests/ui/issues/issue-52489.rs @@ -3,6 +3,6 @@ //@ compile-flags:--extern issue_52489 use issue_52489; -//~^ ERROR use of unstable library feature 'issue_52489_unstable' +//~^ ERROR use of unstable library feature `issue_52489_unstable` fn main() {} diff --git a/tests/ui/issues/issue-52489.stderr b/tests/ui/issues/issue-52489.stderr index fa88725bceb..8e5b87b7f0f 100644 --- a/tests/ui/issues/issue-52489.stderr +++ b/tests/ui/issues/issue-52489.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'issue_52489_unstable' +error[E0658]: use of unstable library feature `issue_52489_unstable` --> $DIR/issue-52489.rs:5:5 | LL | use issue_52489; diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr index cceaddf7803..206a6801065 100644 --- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr +++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr @@ -71,6 +71,10 @@ LL | cachedcoso.call_once(1); | note: required by a bound in `call_once` --> $SRC_DIR/core/src/ops/function.rs:LL:COL +help: use a unary tuple instead + | +LL | cachedcoso.call_once((1,)); + | + ++ error: aborting due to 6 previous errors diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.rs b/tests/ui/layout/thaw-transmute-invalid-enum.rs index 835dcc04996..a7c2e1a86de 100644 --- a/tests/ui/layout/thaw-transmute-invalid-enum.rs +++ b/tests/ui/layout/thaw-transmute-invalid-enum.rs @@ -2,13 +2,13 @@ mod assert { use std::mem::{Assume, TransmuteFrom}; - //~^ ERROR: use of unstable library feature 'transmutability' - //~| ERROR: use of unstable library feature 'transmutability' + //~^ ERROR: use of unstable library feature `transmutability` + //~| ERROR: use of unstable library feature `transmutability` pub fn is_transmutable<Src, Dst>() where Dst: TransmuteFrom<Src>, - //~^ ERROR: use of unstable library feature 'transmutability' + //~^ ERROR: use of unstable library feature `transmutability` { } } diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.stderr b/tests/ui/layout/thaw-transmute-invalid-enum.stderr index e6a5399c66b..d12fc4694e0 100644 --- a/tests/ui/layout/thaw-transmute-invalid-enum.stderr +++ b/tests/ui/layout/thaw-transmute-invalid-enum.stderr @@ -20,7 +20,7 @@ LL | | V = 0xFF, LL | | } | |_- not a struct or union -error[E0658]: use of unstable library feature 'transmutability' +error[E0658]: use of unstable library feature `transmutability` --> $DIR/thaw-transmute-invalid-enum.rs:4:20 | LL | use std::mem::{Assume, TransmuteFrom}; @@ -30,7 +30,7 @@ LL | use std::mem::{Assume, TransmuteFrom}; = help: add `#![feature(transmutability)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'transmutability' +error[E0658]: use of unstable library feature `transmutability` --> $DIR/thaw-transmute-invalid-enum.rs:4:28 | LL | use std::mem::{Assume, TransmuteFrom}; @@ -40,7 +40,7 @@ LL | use std::mem::{Assume, TransmuteFrom}; = help: add `#![feature(transmutability)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'transmutability' +error[E0658]: use of unstable library feature `transmutability` --> $DIR/thaw-transmute-invalid-enum.rs:10:14 | LL | Dst: TransmuteFrom<Src>, diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs index 1e1f8f9e1b6..d0f26a87385 100644 --- a/tests/ui/lint/expansion-time.rs +++ b/tests/ui/lint/expansion-time.rs @@ -11,7 +11,7 @@ macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier #[warn(soft_unstable)] mod benches { - #[bench] //~ WARN use of unstable library feature 'test' + #[bench] //~ WARN use of unstable library feature `test` //~| WARN this was previously accepted fn foo() {} } diff --git a/tests/ui/lint/expansion-time.stderr b/tests/ui/lint/expansion-time.stderr index e490ae91a48..f65627c2c08 100644 --- a/tests/ui/lint/expansion-time.stderr +++ b/tests/ui/lint/expansion-time.stderr @@ -26,7 +26,7 @@ note: the lint level is defined here LL | #[warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable +warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable --> $DIR/expansion-time.rs:14:7 | LL | #[bench] @@ -70,7 +70,7 @@ LL | #[warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: -warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable +warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable --> $DIR/expansion-time.rs:14:7 | LL | #[bench] diff --git a/tests/ui/lint/lint-output-format.stderr b/tests/ui/lint/lint-output-format.stderr index c399b6cdbc2..23a36eb4c87 100644 --- a/tests/ui/lint/lint-output-format.stderr +++ b/tests/ui/lint/lint-output-format.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-output-format.rs:6:1 | LL | extern crate lint_output_format; @@ -7,7 +7,7 @@ LL | extern crate lint_output_format; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-output-format.rs:7:26 | LL | use lint_output_format::{foo, bar}; @@ -16,7 +16,7 @@ LL | use lint_output_format::{foo, bar}; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-output-format.rs:7:31 | LL | use lint_output_format::{foo, bar}; @@ -25,7 +25,7 @@ LL | use lint_output_format::{foo, bar}; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-output-format.rs:12:14 | LL | let _y = bar(); diff --git a/tests/ui/lint/lint-stability-2.rs b/tests/ui/lint/lint-stability-2.rs index 644b12670a6..50e84a6f4a7 100644 --- a/tests/ui/lint/lint-stability-2.rs +++ b/tests/ui/lint/lint-stability-2.rs @@ -66,15 +66,15 @@ mod cross_crate { <Foo>::trait_unstable(&foo); //~ ERROR use of unstable library feature foo.method_unstable_text(); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text Foo::method_unstable_text(&foo); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text <Foo>::method_unstable_text(&foo); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text foo.trait_unstable_text(); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text <Foo>::trait_unstable_text(&foo); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text stable(); foo.method_stable(); @@ -139,9 +139,9 @@ mod cross_crate { foo.trait_unstable(); //~ ERROR use of unstable library feature <Foo>::trait_unstable(&foo); //~ ERROR use of unstable library feature foo.trait_unstable_text(); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text <Foo>::trait_unstable_text(&foo); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text foo.trait_stable(); Trait::trait_stable(&foo); <Foo>::trait_stable(&foo); @@ -157,7 +157,7 @@ mod cross_crate { //~^ ERROR use of unstable library feature foo.trait_unstable(); //~ ERROR use of unstable library feature foo.trait_unstable_text(); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text foo.trait_stable(); } diff --git a/tests/ui/lint/lint-stability-2.stderr b/tests/ui/lint/lint-stability-2.stderr index 20d49780a91..b3357bfe232 100644 --- a/tests/ui/lint/lint-stability-2.stderr +++ b/tests/ui/lint/lint-stability-2.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:40:13 | LL | foo.method_deprecated_unstable(); @@ -7,7 +7,7 @@ LL | foo.method_deprecated_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:42:9 | LL | Foo::method_deprecated_unstable(&foo); @@ -16,7 +16,7 @@ LL | Foo::method_deprecated_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:44:9 | LL | <Foo>::method_deprecated_unstable(&foo); @@ -25,7 +25,7 @@ LL | <Foo>::method_deprecated_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:46:13 | LL | foo.trait_deprecated_unstable(); @@ -34,7 +34,7 @@ LL | foo.trait_deprecated_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:48:9 | LL | <Foo>::trait_deprecated_unstable(&foo); @@ -43,7 +43,7 @@ LL | <Foo>::trait_deprecated_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:51:13 | LL | foo.method_deprecated_unstable_text(); @@ -52,7 +52,7 @@ LL | foo.method_deprecated_unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:53:9 | LL | Foo::method_deprecated_unstable_text(&foo); @@ -61,7 +61,7 @@ LL | Foo::method_deprecated_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:55:9 | LL | <Foo>::method_deprecated_unstable_text(&foo); @@ -70,7 +70,7 @@ LL | <Foo>::method_deprecated_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:57:13 | LL | foo.trait_deprecated_unstable_text(); @@ -79,7 +79,7 @@ LL | foo.trait_deprecated_unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:59:9 | LL | <Foo>::trait_deprecated_unstable_text(&foo); @@ -88,7 +88,7 @@ LL | <Foo>::trait_deprecated_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:62:13 | LL | foo.method_unstable(); @@ -97,7 +97,7 @@ LL | foo.method_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:63:9 | LL | Foo::method_unstable(&foo); @@ -106,7 +106,7 @@ LL | Foo::method_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:64:9 | LL | <Foo>::method_unstable(&foo); @@ -115,7 +115,7 @@ LL | <Foo>::method_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:65:13 | LL | foo.trait_unstable(); @@ -124,7 +124,7 @@ LL | foo.trait_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:66:9 | LL | <Foo>::trait_unstable(&foo); @@ -133,7 +133,7 @@ LL | <Foo>::trait_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability-2.rs:68:13 | LL | foo.method_unstable_text(); @@ -142,7 +142,7 @@ LL | foo.method_unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability-2.rs:70:9 | LL | Foo::method_unstable_text(&foo); @@ -151,7 +151,7 @@ LL | Foo::method_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability-2.rs:72:9 | LL | <Foo>::method_unstable_text(&foo); @@ -160,7 +160,7 @@ LL | <Foo>::method_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability-2.rs:74:13 | LL | foo.trait_unstable_text(); @@ -169,7 +169,7 @@ LL | foo.trait_unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability-2.rs:76:9 | LL | <Foo>::trait_unstable_text(&foo); @@ -178,7 +178,7 @@ LL | <Foo>::trait_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:131:13 | LL | foo.trait_deprecated_unstable(); @@ -187,7 +187,7 @@ LL | foo.trait_deprecated_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:133:9 | LL | <Foo>::trait_deprecated_unstable(&foo); @@ -196,7 +196,7 @@ LL | <Foo>::trait_deprecated_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:135:13 | LL | foo.trait_deprecated_unstable_text(); @@ -205,7 +205,7 @@ LL | foo.trait_deprecated_unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:137:9 | LL | <Foo>::trait_deprecated_unstable_text(&foo); @@ -214,7 +214,7 @@ LL | <Foo>::trait_deprecated_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:139:13 | LL | foo.trait_unstable(); @@ -223,7 +223,7 @@ LL | foo.trait_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:140:9 | LL | <Foo>::trait_unstable(&foo); @@ -232,7 +232,7 @@ LL | <Foo>::trait_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability-2.rs:141:13 | LL | foo.trait_unstable_text(); @@ -241,7 +241,7 @@ LL | foo.trait_unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability-2.rs:143:9 | LL | <Foo>::trait_unstable_text(&foo); @@ -250,7 +250,7 @@ LL | <Foo>::trait_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:154:13 | LL | foo.trait_deprecated_unstable(); @@ -259,7 +259,7 @@ LL | foo.trait_deprecated_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:156:13 | LL | foo.trait_deprecated_unstable_text(); @@ -268,7 +268,7 @@ LL | foo.trait_deprecated_unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-2.rs:158:13 | LL | foo.trait_unstable(); @@ -277,7 +277,7 @@ LL | foo.trait_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability-2.rs:159:13 | LL | foo.trait_unstable_text(); diff --git a/tests/ui/lint/lint-stability-fields.stderr b/tests/ui/lint/lint-stability-fields.stderr index 9dffe94c12e..9cd3753cc3b 100644 --- a/tests/ui/lint/lint-stability-fields.stderr +++ b/tests/ui/lint/lint-stability-fields.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:56:17 | LL | let x = Unstable { @@ -7,7 +7,7 @@ LL | let x = Unstable { = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:66:13 | LL | let Unstable { @@ -16,7 +16,7 @@ LL | let Unstable { = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:72:13 | LL | let Unstable @@ -25,7 +25,7 @@ LL | let Unstable = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:77:17 | LL | let x = reexport::Unstable2(1, 2, 3); @@ -34,7 +34,7 @@ LL | let x = reexport::Unstable2(1, 2, 3); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:79:17 | LL | let x = Unstable2(1, 2, 3); @@ -43,7 +43,7 @@ LL | let x = Unstable2(1, 2, 3); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:85:13 | LL | let Unstable2 @@ -52,7 +52,7 @@ LL | let Unstable2 = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:90:13 | LL | let Unstable2 @@ -61,7 +61,7 @@ LL | let Unstable2 = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:95:17 | LL | let x = Deprecated { @@ -70,7 +70,7 @@ LL | let x = Deprecated { = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:105:13 | LL | let Deprecated { @@ -79,7 +79,7 @@ LL | let Deprecated { = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:111:13 | LL | let Deprecated @@ -88,7 +88,7 @@ LL | let Deprecated = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:115:17 | LL | let x = Deprecated2(1, 2, 3); @@ -97,7 +97,7 @@ LL | let x = Deprecated2(1, 2, 3); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:121:13 | LL | let Deprecated2 @@ -106,7 +106,7 @@ LL | let Deprecated2 = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:126:13 | LL | let Deprecated2 @@ -115,7 +115,7 @@ LL | let Deprecated2 = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:21:13 | LL | override1: 2, @@ -124,7 +124,7 @@ LL | override1: 2, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:22:13 | LL | override2: 3, @@ -133,7 +133,7 @@ LL | override2: 3, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:27:17 | LL | let _ = x.override1; @@ -142,7 +142,7 @@ LL | let _ = x.override1; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:28:17 | LL | let _ = x.override2; @@ -151,7 +151,7 @@ LL | let _ = x.override2; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:33:13 | LL | override1: _, @@ -160,7 +160,7 @@ LL | override1: _, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:34:13 | LL | override2: _, @@ -169,7 +169,7 @@ LL | override2: _, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:43:17 | LL | let _ = x.1; @@ -178,7 +178,7 @@ LL | let _ = x.1; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:44:17 | LL | let _ = x.2; @@ -187,7 +187,7 @@ LL | let _ = x.2; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:48:20 | LL | _, @@ -196,7 +196,7 @@ LL | _, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:49:20 | LL | _, @@ -205,7 +205,7 @@ LL | _, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:57:13 | LL | inherit: 1, @@ -214,7 +214,7 @@ LL | inherit: 1, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:59:13 | LL | override2: 3, @@ -223,7 +223,7 @@ LL | override2: 3, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:62:17 | LL | let _ = x.inherit; @@ -232,7 +232,7 @@ LL | let _ = x.inherit; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:64:17 | LL | let _ = x.override2; @@ -241,7 +241,7 @@ LL | let _ = x.override2; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:67:13 | LL | inherit: _, @@ -250,7 +250,7 @@ LL | inherit: _, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:69:13 | LL | override2: _ @@ -259,7 +259,7 @@ LL | override2: _ = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:81:17 | LL | let _ = x.0; @@ -268,7 +268,7 @@ LL | let _ = x.0; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:83:17 | LL | let _ = x.2; @@ -277,7 +277,7 @@ LL | let _ = x.2; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:86:14 | LL | (_, @@ -286,7 +286,7 @@ LL | (_, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:88:14 | LL | _) @@ -295,7 +295,7 @@ LL | _) = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:96:13 | LL | inherit: 1, @@ -304,7 +304,7 @@ LL | inherit: 1, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:98:13 | LL | override2: 3, @@ -313,7 +313,7 @@ LL | override2: 3, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:101:17 | LL | let _ = x.inherit; @@ -322,7 +322,7 @@ LL | let _ = x.inherit; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:103:17 | LL | let _ = x.override2; @@ -331,7 +331,7 @@ LL | let _ = x.override2; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:106:13 | LL | inherit: _, @@ -340,7 +340,7 @@ LL | inherit: _, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:108:13 | LL | override2: _ @@ -349,7 +349,7 @@ LL | override2: _ = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:117:17 | LL | let _ = x.0; @@ -358,7 +358,7 @@ LL | let _ = x.0; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:119:17 | LL | let _ = x.2; @@ -367,7 +367,7 @@ LL | let _ = x.2; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:122:14 | LL | (_, @@ -376,7 +376,7 @@ LL | (_, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability-fields.rs:124:14 | LL | _) diff --git a/tests/ui/lint/lint-stability.rs b/tests/ui/lint/lint-stability.rs index eaf9796df6a..f080b5e4bbe 100644 --- a/tests/ui/lint/lint-stability.rs +++ b/tests/ui/lint/lint-stability.rs @@ -61,11 +61,11 @@ mod cross_crate { <Foo as Trait>::trait_unstable(&foo); //~ ERROR use of unstable library feature unstable_text(); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text Trait::trait_unstable_text(&foo); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text <Foo as Trait>::trait_unstable_text(&foo); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text stable(); foo.method_stable(); @@ -152,9 +152,9 @@ mod cross_crate { Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature <Foo as Trait>::trait_unstable(&foo); //~ ERROR use of unstable library feature Trait::trait_unstable_text(&foo); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text <Foo as Trait>::trait_unstable_text(&foo); - //~^ ERROR use of unstable library feature 'unstable_test_feature': text + //~^ ERROR use of unstable library feature `unstable_test_feature`: text foo.trait_stable(); Trait::trait_stable(&foo); <Foo>::trait_stable(&foo); diff --git a/tests/ui/lint/lint-stability.stderr b/tests/ui/lint/lint-stability.stderr index af5816d4564..a22fce70a4a 100644 --- a/tests/ui/lint/lint-stability.stderr +++ b/tests/ui/lint/lint-stability.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:17:5 | LL | extern crate stability_cfg2; @@ -7,7 +7,7 @@ LL | extern crate stability_cfg2; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:45:9 | LL | deprecated_unstable(); @@ -16,7 +16,7 @@ LL | deprecated_unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:47:9 | LL | Trait::trait_deprecated_unstable(&foo); @@ -25,7 +25,7 @@ LL | Trait::trait_deprecated_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:49:9 | LL | <Foo as Trait>::trait_deprecated_unstable(&foo); @@ -34,7 +34,7 @@ LL | <Foo as Trait>::trait_deprecated_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:52:9 | LL | deprecated_unstable_text(); @@ -43,7 +43,7 @@ LL | deprecated_unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:54:9 | LL | Trait::trait_deprecated_unstable_text(&foo); @@ -52,7 +52,7 @@ LL | Trait::trait_deprecated_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:56:9 | LL | <Foo as Trait>::trait_deprecated_unstable_text(&foo); @@ -61,7 +61,7 @@ LL | <Foo as Trait>::trait_deprecated_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:59:9 | LL | unstable(); @@ -70,7 +70,7 @@ LL | unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:60:9 | LL | Trait::trait_unstable(&foo); @@ -79,7 +79,7 @@ LL | Trait::trait_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:61:9 | LL | <Foo as Trait>::trait_unstable(&foo); @@ -88,7 +88,7 @@ LL | <Foo as Trait>::trait_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability.rs:63:9 | LL | unstable_text(); @@ -97,7 +97,7 @@ LL | unstable_text(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability.rs:65:9 | LL | Trait::trait_unstable_text(&foo); @@ -106,7 +106,7 @@ LL | Trait::trait_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability.rs:67:9 | LL | <Foo as Trait>::trait_unstable_text(&foo); @@ -115,7 +115,7 @@ LL | <Foo as Trait>::trait_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:99:17 | LL | let _ = DeprecatedUnstableStruct { @@ -124,7 +124,7 @@ LL | let _ = DeprecatedUnstableStruct { = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:103:17 | LL | let _ = UnstableStruct { i: 0 }; @@ -133,7 +133,7 @@ LL | let _ = UnstableStruct { i: 0 }; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:107:17 | LL | let _ = DeprecatedUnstableUnitStruct; @@ -142,7 +142,7 @@ LL | let _ = DeprecatedUnstableUnitStruct; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:109:17 | LL | let _ = UnstableUnitStruct; @@ -151,7 +151,7 @@ LL | let _ = UnstableUnitStruct; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:113:17 | LL | let _ = Enum::DeprecatedUnstableVariant; @@ -160,7 +160,7 @@ LL | let _ = Enum::DeprecatedUnstableVariant; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:115:17 | LL | let _ = Enum::UnstableVariant; @@ -169,7 +169,7 @@ LL | let _ = Enum::UnstableVariant; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:119:17 | LL | let _ = DeprecatedUnstableTupleStruct (1); @@ -178,7 +178,7 @@ LL | let _ = DeprecatedUnstableTupleStruct (1); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:121:17 | LL | let _ = UnstableTupleStruct (1); @@ -187,7 +187,7 @@ LL | let _ = UnstableTupleStruct (1); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:130:25 | LL | macro_test_arg!(deprecated_unstable_text()); @@ -196,7 +196,7 @@ LL | macro_test_arg!(deprecated_unstable_text()); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:144:9 | LL | Trait::trait_deprecated_unstable(&foo); @@ -205,7 +205,7 @@ LL | Trait::trait_deprecated_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:146:9 | LL | <Foo as Trait>::trait_deprecated_unstable(&foo); @@ -214,7 +214,7 @@ LL | <Foo as Trait>::trait_deprecated_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:148:9 | LL | Trait::trait_deprecated_unstable_text(&foo); @@ -223,7 +223,7 @@ LL | Trait::trait_deprecated_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:150:9 | LL | <Foo as Trait>::trait_deprecated_unstable_text(&foo); @@ -232,7 +232,7 @@ LL | <Foo as Trait>::trait_deprecated_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:152:9 | LL | Trait::trait_unstable(&foo); @@ -241,7 +241,7 @@ LL | Trait::trait_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:153:9 | LL | <Foo as Trait>::trait_unstable(&foo); @@ -250,7 +250,7 @@ LL | <Foo as Trait>::trait_unstable(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability.rs:154:9 | LL | Trait::trait_unstable_text(&foo); @@ -259,7 +259,7 @@ LL | Trait::trait_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/lint-stability.rs:156:9 | LL | <Foo as Trait>::trait_unstable_text(&foo); @@ -268,7 +268,7 @@ LL | <Foo as Trait>::trait_unstable_text(&foo); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:172:10 | LL | impl UnstableTrait for S { } @@ -277,7 +277,7 @@ LL | impl UnstableTrait for S { } = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:174:24 | LL | trait LocalTrait : UnstableTrait { } @@ -286,7 +286,7 @@ LL | trait LocalTrait : UnstableTrait { } = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:179:9 | LL | fn trait_unstable(&self) {} @@ -295,7 +295,7 @@ LL | fn trait_unstable(&self) {} = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:184:5 | LL | extern crate inherited_stability; @@ -304,7 +304,7 @@ LL | extern crate inherited_stability; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:185:9 | LL | use self::inherited_stability::*; @@ -313,7 +313,7 @@ LL | use self::inherited_stability::*; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:188:9 | LL | unstable(); @@ -322,7 +322,7 @@ LL | unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:191:9 | LL | stable_mod::unstable(); @@ -331,7 +331,7 @@ LL | stable_mod::unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:194:9 | LL | unstable_mod::deprecated(); @@ -340,7 +340,7 @@ LL | unstable_mod::deprecated(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:195:9 | LL | unstable_mod::unstable(); @@ -349,7 +349,7 @@ LL | unstable_mod::unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:197:17 | LL | let _ = Unstable::UnstableVariant; @@ -358,7 +358,7 @@ LL | let _ = Unstable::UnstableVariant; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:198:17 | LL | let _ = Unstable::StableVariant; @@ -367,7 +367,7 @@ LL | let _ = Unstable::StableVariant; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:88:48 | LL | struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); @@ -376,7 +376,7 @@ LL | struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:92:13 | LL | TypeUnstable = u8, diff --git a/tests/ui/macros/macro-stability.rs b/tests/ui/macros/macro-stability.rs index a909b14f47b..cd419d51354 100644 --- a/tests/ui/macros/macro-stability.rs +++ b/tests/ui/macros/macro-stability.rs @@ -19,10 +19,10 @@ macro local_unstable_modern() {} macro_rules! local_deprecated{ () => () } fn main() { - local_unstable!(); //~ ERROR use of unstable library feature 'local_unstable' - local_unstable_modern!(); //~ ERROR use of unstable library feature 'local_unstable' - unstable_macro!(); //~ ERROR use of unstable library feature 'unstable_macros' - // unstable_macro_modern!(); // ERROR use of unstable library feature 'unstable_macros' + local_unstable!(); //~ ERROR use of unstable library feature `local_unstable` + local_unstable_modern!(); //~ ERROR use of unstable library feature `local_unstable` + unstable_macro!(); //~ ERROR use of unstable library feature `unstable_macros` + // unstable_macro_modern!(); // ERROR use of unstable library feature `unstable_macros` deprecated_macro!(); //~^ WARN use of deprecated macro `deprecated_macro`: deprecation note diff --git a/tests/ui/macros/macro-stability.stderr b/tests/ui/macros/macro-stability.stderr index 21b6cef5c9c..fd8f029b4c4 100644 --- a/tests/ui/macros/macro-stability.stderr +++ b/tests/ui/macros/macro-stability.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'local_unstable' +error[E0658]: use of unstable library feature `local_unstable` --> $DIR/macro-stability.rs:22:5 | LL | local_unstable!(); @@ -7,7 +7,7 @@ LL | local_unstable!(); = help: add `#![feature(local_unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'local_unstable' +error[E0658]: use of unstable library feature `local_unstable` --> $DIR/macro-stability.rs:23:5 | LL | local_unstable_modern!(); @@ -16,7 +16,7 @@ LL | local_unstable_modern!(); = help: add `#![feature(local_unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_macros' +error[E0658]: use of unstable library feature `unstable_macros` --> $DIR/macro-stability.rs:24:5 | LL | unstable_macro!(); diff --git a/tests/ui/never_type/suggestion-ice-132517.rs b/tests/ui/never_type/suggestion-ice-132517.rs new file mode 100644 index 00000000000..c1730d06f6b --- /dev/null +++ b/tests/ui/never_type/suggestion-ice-132517.rs @@ -0,0 +1,4 @@ +fn main() { + x::<_>(|_| panic!()) + //~^ ERROR cannot find function `x` in this scope +} diff --git a/tests/ui/never_type/suggestion-ice-132517.stderr b/tests/ui/never_type/suggestion-ice-132517.stderr new file mode 100644 index 00000000000..4f280a0e4f1 --- /dev/null +++ b/tests/ui/never_type/suggestion-ice-132517.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `x` in this scope + --> $DIR/suggestion-ice-132517.rs:2:5 + | +LL | x::<_>(|_| panic!()) + | ^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/not-clone-closure.rs b/tests/ui/not-clone-closure.rs index 25635bc8331..976e3b9e81c 100644 --- a/tests/ui/not-clone-closure.rs +++ b/tests/ui/not-clone-closure.rs @@ -1,3 +1,4 @@ +//@compile-flags: --diagnostic-width=300 // Check that closures do not implement `Clone` if their environment is not `Clone`. struct S(i32); diff --git a/tests/ui/not-clone-closure.stderr b/tests/ui/not-clone-closure.stderr index 783c165eeb2..0c95a99d0c0 100644 --- a/tests/ui/not-clone-closure.stderr +++ b/tests/ui/not-clone-closure.stderr @@ -1,14 +1,14 @@ -error[E0277]: the trait bound `S: Clone` is not satisfied in `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}` - --> $DIR/not-clone-closure.rs:11:23 +error[E0277]: the trait bound `S: Clone` is not satisfied in `{closure@$DIR/not-clone-closure.rs:8:17: 8:24}` + --> $DIR/not-clone-closure.rs:12:23 | LL | let hello = move || { - | ------- within this `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}` + | ------- within this `{closure@$DIR/not-clone-closure.rs:8:17: 8:24}` ... LL | let hello = hello.clone(); - | ^^^^^ within `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`, the trait `Clone` is not implemented for `S` + | ^^^^^ within `{closure@$DIR/not-clone-closure.rs:8:17: 8:24}`, the trait `Clone` is not implemented for `S` | note: required because it's used within this closure - --> $DIR/not-clone-closure.rs:7:17 + --> $DIR/not-clone-closure.rs:8:17 | LL | let hello = move || { | ^^^^^^^ diff --git a/tests/ui/offset-of/offset-of-unstable.stderr b/tests/ui/offset-of/offset-of-unstable.stderr index 44ccad3ff39..d249e1b176d 100644 --- a/tests/ui/offset-of/offset-of-unstable.stderr +++ b/tests/ui/offset-of/offset-of-unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/offset-of-unstable.rs:12:9 | LL | Unstable, @@ -7,7 +7,7 @@ LL | Unstable, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/offset-of-unstable.rs:21:9 | LL | UnstableWithStableFieldType, @@ -16,7 +16,7 @@ LL | UnstableWithStableFieldType, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/offset-of-unstable.rs:26:9 | LL | UnstableWithStableFieldType, @@ -25,7 +25,7 @@ LL | UnstableWithStableFieldType, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/offset-of-unstable.rs:10:5 | LL | / offset_of!( @@ -39,7 +39,7 @@ LL | | ); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/offset-of-unstable.rs:16:5 | LL | offset_of!(StableWithUnstableField, unstable); @@ -49,7 +49,7 @@ LL | offset_of!(StableWithUnstableField, unstable); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/offset-of-unstable.rs:18:5 | LL | offset_of!(StableWithUnstableFieldType, stable.unstable); @@ -59,7 +59,7 @@ LL | offset_of!(StableWithUnstableFieldType, stable.unstable); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/offset-of-unstable.rs:19:5 | LL | / offset_of!( @@ -73,7 +73,7 @@ LL | | ); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/offset-of-unstable.rs:24:5 | LL | / offset_of!( diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap.rs b/tests/ui/on-unimplemented/suggest_tuple_wrap.rs new file mode 100644 index 00000000000..010a47aef62 --- /dev/null +++ b/tests/ui/on-unimplemented/suggest_tuple_wrap.rs @@ -0,0 +1,19 @@ +pub trait Argument {} +impl Argument for u8 {} +impl Argument for i8 {} +impl Argument for String {} +impl Argument for &str {} + +pub trait TupleArgs {} +impl<A: Argument> TupleArgs for (A,) {} +impl<A: Argument, B: Argument> TupleArgs for (A, B) {} +impl<A: Argument, B: Argument, C: Argument> TupleArgs for (A, B, C) {} + +fn convert_into_tuple(_x: impl TupleArgs) {} + +fn main() { + convert_into_tuple(42_u8); + //~^ ERROR E0277 + //~| HELP the following other types implement trait `TupleArgs` + //~| HELP use a unary tuple instead +} diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap.stderr b/tests/ui/on-unimplemented/suggest_tuple_wrap.stderr new file mode 100644 index 00000000000..93dd43aafd9 --- /dev/null +++ b/tests/ui/on-unimplemented/suggest_tuple_wrap.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `u8: TupleArgs` is not satisfied + --> $DIR/suggest_tuple_wrap.rs:15:24 + | +LL | convert_into_tuple(42_u8); + | ------------------ ^^^^^ the trait `TupleArgs` is not implemented for `u8` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `TupleArgs`: + (A, B) + (A, B, C) + (A,) +note: required by a bound in `convert_into_tuple` + --> $DIR/suggest_tuple_wrap.rs:12:32 + | +LL | fn convert_into_tuple(_x: impl TupleArgs) {} + | ^^^^^^^^^ required by this bound in `convert_into_tuple` +help: use a unary tuple instead + | +LL | convert_into_tuple((42_u8,)); + | + ++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs new file mode 100644 index 00000000000..e0036d30187 --- /dev/null +++ b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs @@ -0,0 +1,26 @@ +struct Tuple; + +impl From<(u8,)> for Tuple { + fn from(_: (u8,)) -> Self { + todo!() + } +} +impl From<(u8, u8)> for Tuple { + fn from(_: (u8, u8)) -> Self { + todo!() + } +} +impl From<(u8, u8, u8)> for Tuple { + fn from(_: (u8, u8, u8)) -> Self { + todo!() + } +} + +fn convert_into_tuple(_x: impl Into<Tuple>) {} + +fn main() { + convert_into_tuple(42_u8); + //~^ ERROR E0277 + //~| HELP use a unary tuple instead + //~| HELP the following other types implement trait `From<T>` +} diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr new file mode 100644 index 00000000000..6ee08d2cd1b --- /dev/null +++ b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `Tuple: From<u8>` is not satisfied + --> $DIR/suggest_tuple_wrap_root_obligation.rs:22:24 + | +LL | convert_into_tuple(42_u8); + | ------------------ ^^^^^ the trait `From<u8>` is not implemented for `Tuple` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `From<T>`: + `Tuple` implements `From<(u8, u8)>` + `Tuple` implements `From<(u8, u8, u8)>` + `Tuple` implements `From<(u8,)>` + = note: required for `u8` to implement `Into<Tuple>` +note: required by a bound in `convert_into_tuple` + --> $DIR/suggest_tuple_wrap_root_obligation.rs:19:32 + | +LL | fn convert_into_tuple(_x: impl Into<Tuple>) {} + | ^^^^^^^^^^^ required by this bound in `convert_into_tuple` +help: use a unary tuple instead + | +LL | convert_into_tuple((42_u8,)); + | + ++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.stderr b/tests/ui/overloaded/overloaded-calls-nontuple.stderr index 45a84fc4d7b..22598f3a390 100644 --- a/tests/ui/overloaded/overloaded-calls-nontuple.stderr +++ b/tests/ui/overloaded/overloaded-calls-nontuple.stderr @@ -38,6 +38,10 @@ LL | self.call_mut(z) | note: required by a bound in `call_mut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL +help: use a unary tuple instead + | +LL | self.call_mut((z,)) + | + ++ error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit --> $DIR/overloaded-calls-nontuple.rs:29:10 diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs index 92823b05af8..f06d19d7f5e 100644 --- a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs +++ b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs @@ -2,8 +2,7 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Trait { diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.stderr b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr index f277bfbc884..158eac9a1bd 100644 --- a/tests/ui/pattern/usefulness/doc-hidden-fields.stderr +++ b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr @@ -21,6 +21,10 @@ LL | let HiddenStruct { one, two, .. } = HiddenStruct::default(); | ~~~~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | let HiddenStruct { one, two: _, .. } = HiddenStruct::default(); + | ~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let HiddenStruct { one, .. } = HiddenStruct::default(); | ~~~~~~ @@ -36,6 +40,10 @@ LL | let HiddenStruct { one, hide, two } = HiddenStruct::default(); | ~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | let HiddenStruct { one, hide, two: _ } = HiddenStruct::default(); + | ~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let HiddenStruct { one, hide, .. } = HiddenStruct::default(); | ~~~~~~ @@ -51,6 +59,10 @@ LL | let InCrate { a, b, im_hidden } = InCrate { a: 0, b: false, im_hidden: | ~~~~~~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | let InCrate { a, b, im_hidden: _ } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ~~~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let InCrate { a, b, .. } = InCrate { a: 0, b: false, im_hidden: 0 }; | ~~~~~~ diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.stderr b/tests/ui/pattern/usefulness/stable-gated-fields.stderr index cf98c51a2b4..d6e9bac7c13 100644 --- a/tests/ui/pattern/usefulness/stable-gated-fields.stderr +++ b/tests/ui/pattern/usefulness/stable-gated-fields.stderr @@ -10,6 +10,10 @@ LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); | ~~~~~~~~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | let UnstableStruct { stable, stable2: _, .. } = UnstableStruct::default(); + | ~~~~~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let UnstableStruct { stable, .. } = UnstableStruct::default(); | ~~~~~~ diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.stderr b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr index e4f5fa06b3f..bb10e439ee2 100644 --- a/tests/ui/pattern/usefulness/unstable-gated-fields.stderr +++ b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr @@ -10,6 +10,10 @@ LL | let UnstableStruct { stable, stable2, unstable } = UnstableStruct::defa | ~~~~~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | let UnstableStruct { stable, stable2, unstable: _ } = UnstableStruct::default(); + | ~~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); | ~~~~~~ @@ -25,6 +29,10 @@ LL | let UnstableStruct { stable, unstable, stable2 } = UnstableStruct::defa | ~~~~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | let UnstableStruct { stable, unstable, stable2: _ } = UnstableStruct::default(); + | ~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let UnstableStruct { stable, unstable, .. } = UnstableStruct::default(); | ~~~~~~ diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs index 17fe7fa0738..36a47d0fdf9 100644 --- a/tests/ui/pin-macro/cant_access_internals.rs +++ b/tests/ui/pin-macro/cant_access_internals.rs @@ -8,5 +8,5 @@ use core::{ fn main() { let mut phantom_pinned = pin!(PhantomPinned); - mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals' + mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature `unsafe_pin_internals` } diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr index 444314a9d8b..8ad897bbbb9 100644 --- a/tests/ui/pin-macro/cant_access_internals.stderr +++ b/tests/ui/pin-macro/cant_access_internals.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unsafe_pin_internals' +error[E0658]: use of unstable library feature `unsafe_pin_internals` --> $DIR/cant_access_internals.rs:11:15 | LL | mem::take(phantom_pinned.__pointer); diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs index 5dda0da8458..36739e3fc04 100644 --- a/tests/ui/print_type_sizes/niche-filling.rs +++ b/tests/ui/print_type_sizes/niche-filling.rs @@ -9,7 +9,7 @@ //! padding and overall computed sizes can be quite different. //! //@ compile-flags: -Z print-type-sizes --crate-type lib -//@ ignore-debug: debug assertions will print more types +//@ ignore-std-debug-assertions (debug assertions will print more types) //@ build-pass //@ ignore-pass // ^-- needed because `--pass check` does not emit the output needed. diff --git a/tests/ui/proc-macro/expand-to-unstable.stderr b/tests/ui/proc-macro/expand-to-unstable.stderr index 9eb701d9702..563c7ae8f95 100644 --- a/tests/ui/proc-macro/expand-to-unstable.stderr +++ b/tests/ui/proc-macro/expand-to-unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library +error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library --> $DIR/expand-to-unstable.rs:8:10 | LL | #[derive(Unstable)] diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs index c9e93174e20..5c6eef46103 100644 --- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs +++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs @@ -8,7 +8,7 @@ struct S<T> { s: Box<S<fn(u: T)>>, } -fn f(x: S<u32>) {} //~ ERROR overflow while adding drop-check rules for S<u32> +fn f(x: S<u32>) {} //~ ERROR overflow while adding drop-check rules for `S<u32>` fn main() { // Force instantiation. diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index a5bbc5499a8..409f63b91b6 100644 --- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -1,10 +1,10 @@ -error[E0320]: overflow while adding drop-check rules for S<u32> +error[E0320]: overflow while adding drop-check rules for `S<u32>` --> $DIR/issue-38591-non-regular-dropck-recursion.rs:11:6 | LL | fn f(x: S<u32>) {} | ^ | - = note: overflowed on S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))> + = note: overflowed on `S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>` error: aborting due to 1 previous error diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index 2509416ad87..2b6bbf12650 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -21,11 +21,12 @@ enum Foo { Bar, } -extern "rust-intrinsic" { - #[stable(feature = "intrinsics_for_test", since = "3.3.3")] - #[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")] - #[rustc_safe_intrinsic] - fn size_of<T>() -> usize; +#[stable(feature = "intrinsics_for_test", since = "3.3.3")] +#[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +const fn size_of<T>() -> usize { + loop {} } #[lang="sized"] diff --git a/tests/ui/resolve/resolve-variant-assoc-item.stderr b/tests/ui/resolve/resolve-variant-assoc-item.stderr index ed157197d17..9a5a605ac05 100644 --- a/tests/ui/resolve/resolve-variant-assoc-item.stderr +++ b/tests/ui/resolve/resolve-variant-assoc-item.stderr @@ -6,7 +6,7 @@ LL | E::V::associated_item; | help: there is an enum variant `E::V`; try using the variant's enum | -LL | E; +LL | E::associated_item; | ~ error[E0433]: failed to resolve: `V` is a variant, not a module @@ -17,10 +17,6 @@ LL | V::associated_item; | help: there is an enum variant `E::V`; try using the variant's enum | -LL | E; - | ~ -help: an enum with a similar name exists - | LL | E::associated_item; | ~ diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr index af6d05c1f96..08584349626 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'structural_match' +error[E0658]: use of unstable library feature `structural_match` --> $DIR/feature-gate.rs:29:6 | LL | impl std::marker::StructuralPartialEq for Foo { } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs index 839e9085440..711b07fee3b 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs @@ -27,7 +27,7 @@ fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error] } impl std::marker::StructuralPartialEq for Foo { } -//[no_gate]~^ ERROR use of unstable library feature 'structural_match' +//[no_gate]~^ ERROR use of unstable library feature `structural_match` impl PartialEq<Foo> for Foo { fn eq(&self, other: &Self) -> bool { diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs index 4dc5932feab..5d9a8cfcac1 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs @@ -38,3 +38,9 @@ pub enum NonExhaustiveCLikeEnum { Four = 4, Five = 5, } + +#[repr(C)] +pub struct NormalStructWithNonExhaustiveCLikeEnum { + one: u8, + two: NonExhaustiveCLikeEnum, +} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs index c7f470fb787..858e3374eac 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs @@ -8,7 +8,7 @@ extern crate types; use types::{ NonExhaustiveCLikeEnum, NonExhaustiveEnum, NonExhaustiveVariants, - NormalStruct, TupleStruct, UnitStruct, + NormalStruct, TupleStruct, UnitStruct, NormalStructWithNonExhaustiveCLikeEnum }; extern "C" { @@ -27,6 +27,9 @@ extern "C" { // These should pass without remark, as they're C-compatible, despite being "non-exhaustive". extern "C" { pub fn non_exhaustive_c_compat_enum(_: NonExhaustiveCLikeEnum); + pub fn non_exhaustive_c_compat_enum_ret() -> *mut NonExhaustiveCLikeEnum; + pub fn struct_w_non_exhaustive_c_like_enum(_: NormalStructWithNonExhaustiveCLikeEnum); + pub fn struct_w_non_exhaustive_c_like_enum_ret() -> *mut NormalStructWithNonExhaustiveCLikeEnum; } fn main() {} diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index 40ac350980e..607fc06823e 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -40,54 +40,5 @@ LL | impl<T: ~const Default + ~const Sub> const A for T { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0015]: cannot call non-const fn `<() as A>::a` in constants - --> $DIR/const_trait_impl.rs:52:23 - | -LL | const _: () = assert!(<()>::a() == 42); - | ^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error[E0015]: cannot call non-const fn `<u8 as A>::a` in constants - --> $DIR/const_trait_impl.rs:53:23 - | -LL | const _: () = assert!(<u8>::a() == 3); - | ^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error[E0015]: cannot call non-const fn `<u16 as A>::a` in constants - --> $DIR/const_trait_impl.rs:54:23 - | -LL | const _: () = assert!(<u16>::a() == 2); - | ^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error[E0015]: cannot call non-const fn `<T as Sup>::foo` in constant functions - --> $DIR/const_trait_impl.rs:48:9 - | -LL | T::foo() - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 10 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs index 977493c885b..2296cd8a937 100644 --- a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs @@ -2,7 +2,7 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@[next] check-pass -//@[current] known-bug: unknown +//@[current] known-bug: #132519 //@[current] failure-status: 101 //@[current] dont-check-compiler-stderr diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs index f8bbe90cfc5..86a9d2066eb 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs @@ -3,7 +3,7 @@ extern crate core; // Known accidental stabilizations with no known users, slated for un-stabilization // fully stable @ core::char::UNICODE_VERSION -use core::unicode::UNICODE_VERSION; //~ ERROR use of unstable library feature 'unicode_internals' +use core::unicode::UNICODE_VERSION; //~ ERROR use of unstable library feature `unicode_internals` // Known accidental stabilizations with known users // fully stable @ core::mem::transmute diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr index 4abf8243d2f..9943e6d7ac6 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unicode_internals' +error[E0658]: use of unstable library feature `unicode_internals` --> $DIR/accidental-stable-in-unstable.rs:6:5 | LL | use core::unicode::UNICODE_VERSION; diff --git a/tests/ui/stability-attribute/allow-unstable-reexport.rs b/tests/ui/stability-attribute/allow-unstable-reexport.rs index d2f1593c31a..b6ed2110918 100644 --- a/tests/ui/stability-attribute/allow-unstable-reexport.rs +++ b/tests/ui/stability-attribute/allow-unstable-reexport.rs @@ -20,11 +20,11 @@ pub use lint_stability_reexport::unstable_text; // Ensure items which aren't marked as unstable can't re-export unstable items #[stable(feature = "lint_stability", since = "1.0.0")] pub use lint_stability::unstable as unstable2; -//~^ ERROR use of unstable library feature 'unstable_test_feature' +//~^ ERROR use of unstable library feature `unstable_test_feature` fn main() { // Since we didn't enable the feature in this crate, we still can't // use these items, even though they're in scope from the `use`s which are now allowed. - unstable(); //~ ERROR use of unstable library feature 'unstable_test_feature' - unstable_text(); //~ ERROR use of unstable library feature 'unstable_test_feature' + unstable(); //~ ERROR use of unstable library feature `unstable_test_feature` + unstable_text(); //~ ERROR use of unstable library feature `unstable_test_feature` } diff --git a/tests/ui/stability-attribute/allow-unstable-reexport.stderr b/tests/ui/stability-attribute/allow-unstable-reexport.stderr index af75b6afb04..f869eeb790e 100644 --- a/tests/ui/stability-attribute/allow-unstable-reexport.stderr +++ b/tests/ui/stability-attribute/allow-unstable-reexport.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/allow-unstable-reexport.rs:22:9 | LL | pub use lint_stability::unstable as unstable2; @@ -7,7 +7,7 @@ LL | pub use lint_stability::unstable as unstable2; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/allow-unstable-reexport.rs:28:5 | LL | unstable(); @@ -16,7 +16,7 @@ LL | unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': text +error[E0658]: use of unstable library feature `unstable_test_feature`: text --> $DIR/allow-unstable-reexport.rs:29:5 | LL | unstable_text(); diff --git a/tests/ui/stability-attribute/allowed-through-unstable.rs b/tests/ui/stability-attribute/allowed-through-unstable.rs index 6bce5c87ddb..29911a70be9 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.rs +++ b/tests/ui/stability-attribute/allowed-through-unstable.rs @@ -6,4 +6,4 @@ extern crate allowed_through_unstable_core; use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; -use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature 'unstable_test_feature' +use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature `unstable_test_feature` diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr index 5c8e6358b7c..00eea9f730d 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.stderr +++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/allowed-through-unstable.rs:9:5 | LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; diff --git a/tests/ui/stability-attribute/default-body-stability-err.stderr b/tests/ui/stability-attribute/default-body-stability-err.stderr index 9d8ad81f102..6173de5020b 100644 --- a/tests/ui/stability-attribute/default-body-stability-err.stderr +++ b/tests/ui/stability-attribute/default-body-stability-err.stderr @@ -5,7 +5,7 @@ LL | impl JustTrait for Type {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: default implementation of `CONSTANT` is unstable - = note: use of unstable library feature 'constant_default_body' + = note: use of unstable library feature `constant_default_body` = help: add `#![feature(constant_default_body)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -16,7 +16,7 @@ LL | impl JustTrait for Type {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: default implementation of `fun` is unstable - = note: use of unstable library feature 'fun_default_body' + = note: use of unstable library feature `fun_default_body` = help: add `#![feature(fun_default_body)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -27,7 +27,7 @@ LL | impl JustTrait for Type {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: default implementation of `fun2` is unstable - = note: use of unstable library feature 'fun_default_body': reason + = note: use of unstable library feature `fun_default_body`: reason = help: add `#![feature(fun_default_body)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -43,7 +43,7 @@ LL | | } | |_^ | = note: default implementation of `eq` is unstable - = note: use of unstable library feature 'eq_default_body' + = note: use of unstable library feature `eq_default_body` = help: add `#![feature(eq_default_body)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/stability-attribute/generics-default-stability-trait.rs b/tests/ui/stability-attribute/generics-default-stability-trait.rs index ba8ee143d4a..a2302959638 100644 --- a/tests/ui/stability-attribute/generics-default-stability-trait.rs +++ b/tests/ui/stability-attribute/generics-default-stability-trait.rs @@ -13,15 +13,15 @@ impl Trait1 for S { struct S; -impl Trait1<usize> for S { //~ ERROR use of unstable library feature 'unstable_default' +impl Trait1<usize> for S { //~ ERROR use of unstable library feature `unstable_default` fn foo() -> usize { 0 } } -impl Trait1<isize> for S { //~ ERROR use of unstable library feature 'unstable_default' +impl Trait1<isize> for S { //~ ERROR use of unstable library feature `unstable_default` fn foo() -> isize { 0 } } -impl Trait2<usize> for S { //~ ERROR use of unstable library feature 'unstable_default' +impl Trait2<usize> for S { //~ ERROR use of unstable library feature `unstable_default` fn foo() -> usize { 0 } } diff --git a/tests/ui/stability-attribute/generics-default-stability-trait.stderr b/tests/ui/stability-attribute/generics-default-stability-trait.stderr index 699e7c83c70..21b21fdb945 100644 --- a/tests/ui/stability-attribute/generics-default-stability-trait.stderr +++ b/tests/ui/stability-attribute/generics-default-stability-trait.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability-trait.rs:16:13 | LL | impl Trait1<usize> for S { @@ -7,7 +7,7 @@ LL | impl Trait1<usize> for S { = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability-trait.rs:20:13 | LL | impl Trait1<isize> for S { @@ -16,7 +16,7 @@ LL | impl Trait1<isize> for S { = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability-trait.rs:24:13 | LL | impl Trait2<usize> for S { diff --git a/tests/ui/stability-attribute/generics-default-stability-where.rs b/tests/ui/stability-attribute/generics-default-stability-where.rs index f8a2fb4873a..a7bc1756d78 100644 --- a/tests/ui/stability-attribute/generics-default-stability-where.rs +++ b/tests/ui/stability-attribute/generics-default-stability-where.rs @@ -4,7 +4,7 @@ extern crate unstable_generic_param; use unstable_generic_param::*; -impl<T> Trait3<usize> for T where T: Trait2<usize> { //~ ERROR use of unstable library feature 'unstable_default' +impl<T> Trait3<usize> for T where T: Trait2<usize> { //~ ERROR use of unstable library feature `unstable_default` //~^ ERROR `T` must be used as the type parameter for some local type fn foo() -> usize { T::foo() } } diff --git a/tests/ui/stability-attribute/generics-default-stability-where.stderr b/tests/ui/stability-attribute/generics-default-stability-where.stderr index 8e4089970f5..9437f5d65fa 100644 --- a/tests/ui/stability-attribute/generics-default-stability-where.stderr +++ b/tests/ui/stability-attribute/generics-default-stability-where.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability-where.rs:7:45 | LL | impl<T> Trait3<usize> for T where T: Trait2<usize> { diff --git a/tests/ui/stability-attribute/generics-default-stability.rs b/tests/ui/stability-attribute/generics-default-stability.rs index abd45b651ee..e1b3971f70c 100644 --- a/tests/ui/stability-attribute/generics-default-stability.rs +++ b/tests/ui/stability-attribute/generics-default-stability.rs @@ -20,12 +20,12 @@ impl Trait3<usize> for S { fn main() { let _ = S; - let _: Struct1<isize> = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct1<isize> = Struct1 { field: 1 }; //~ ERROR use of unstable library feature `unstable_default` let _ = STRUCT1; // ok let _: Struct1 = STRUCT1; // ok - let _: Struct1<usize> = STRUCT1; //~ ERROR use of unstable library feature 'unstable_default' - let _: Struct1<isize> = Struct1 { field: 0 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct1<usize> = STRUCT1; //~ ERROR use of unstable library feature `unstable_default` + let _: Struct1<isize> = Struct1 { field: 0 }; //~ ERROR use of unstable library feature `unstable_default` // Instability is not enforced for generic type parameters used in public fields. // Note how the unstable type default `usize` leaks, @@ -54,10 +54,10 @@ fn main() { let _ = STRUCT3; let _: Struct3 = STRUCT3; // ok - let _: Struct3<isize, usize> = STRUCT3; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct3<isize, usize> = STRUCT3; //~ ERROR use of unstable library feature `unstable_default` let _: Struct3<isize> = STRUCT3; // ok - let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature 'unstable_default' - let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature `unstable_default` + let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature `unstable_default` let _ = STRUCT3.field1; // ok let _: isize = STRUCT3.field1; // ok let _ = STRUCT3.field1 + 1; // ok @@ -81,15 +81,15 @@ fn main() { //~^^^ use of deprecated field `unstable_generic_param::Struct4::field`: test [deprecated] let _ = STRUCT5; - let _: Struct5<isize> = Struct5 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct5<isize> = Struct5 { field: 1 }; //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] //~^^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] //~^^^ use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated] let _ = STRUCT5; let _: Struct5 = STRUCT5; //~ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] - let _: Struct5<usize> = STRUCT5; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct5<usize> = STRUCT5; //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] - let _: Struct5<isize> = Struct5 { field: 0 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct5<isize> = Struct5 { field: 0 }; //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] //~^^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] //~^^^ use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated] @@ -97,12 +97,12 @@ fn main() { let _: Struct6<isize> = Struct6 { field: 1 }; // ok let _: Struct6<isize> = Struct6 { field: 0 }; // ok - let _: Alias1<isize> = Alias1::Some(1); //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias1<isize> = Alias1::Some(1); //~ ERROR use of unstable library feature `unstable_default` let _ = ALIAS1; // ok let _: Alias1 = ALIAS1; // ok - let _: Alias1<usize> = ALIAS1; //~ ERROR use of unstable library feature 'unstable_default' - let _: Alias1<isize> = Alias1::Some(0); //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias1<usize> = ALIAS1; //~ ERROR use of unstable library feature `unstable_default` + let _: Alias1<isize> = Alias1::Some(0); //~ ERROR use of unstable library feature `unstable_default` // Instability is not enforced for generic type parameters used in public fields. // Note how the unstable type default `usize` leaks, @@ -130,10 +130,10 @@ fn main() { let _ = ALIAS3; let _: Alias3 = ALIAS3; // ok - let _: Alias3<isize, usize> = ALIAS3; //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias3<isize, usize> = ALIAS3; //~ ERROR use of unstable library feature `unstable_default` let _: Alias3<isize> = ALIAS3; // ok - let _: Alias3<isize, isize> = Alias3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default' - let _: Alias3<usize, usize> = Alias3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias3<isize, isize> = Alias3::Ok(0); //~ ERROR use of unstable library feature `unstable_default` + let _: Alias3<usize, usize> = Alias3::Ok(0); //~ ERROR use of unstable library feature `unstable_default` let _ = ALIAS3.unwrap(); // ok let _: isize = ALIAS3.unwrap(); // ok let _ = ALIAS3.unwrap() + 1; // ok @@ -155,26 +155,26 @@ fn main() { //~^^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] let _ = ALIAS5; - let _: Alias5<isize> = Alias5::Some(1); //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias5<isize> = Alias5::Some(1); //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] //~^^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] let _ = ALIAS5; let _: Alias5 = ALIAS5; //~ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] - let _: Alias5<usize> = ALIAS5; //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias5<usize> = ALIAS5; //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] - let _: Alias5<isize> = Alias5::Some(0); //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias5<isize> = Alias5::Some(0); //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] //~^^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] let _: Alias6<isize> = Alias6::Some(1); // ok let _: Alias6<isize> = Alias6::Some(0); // ok - let _: Enum1<isize> = Enum1::Some(1); //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum1<isize> = Enum1::Some(1); //~ ERROR use of unstable library feature `unstable_default` let _ = ENUM1; // ok let _: Enum1 = ENUM1; // ok - let _: Enum1<usize> = ENUM1; //~ ERROR use of unstable library feature 'unstable_default' - let _: Enum1<isize> = Enum1::Some(0); //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum1<usize> = ENUM1; //~ ERROR use of unstable library feature `unstable_default` + let _: Enum1<isize> = Enum1::Some(0); //~ ERROR use of unstable library feature `unstable_default` // Instability is not enforced for generic type parameters used in public fields. // Note how the unstable type default `usize` leaks, @@ -202,10 +202,10 @@ fn main() { let _ = ENUM3; let _: Enum3 = ENUM3; // ok - let _: Enum3<isize, usize> = ENUM3; //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum3<isize, usize> = ENUM3; //~ ERROR use of unstable library feature `unstable_default` let _: Enum3<isize> = ENUM3; // ok - let _: Enum3<isize, isize> = Enum3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default' - let _: Enum3<usize, usize> = Enum3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum3<isize, isize> = Enum3::Ok(0); //~ ERROR use of unstable library feature `unstable_default` + let _: Enum3<usize, usize> = Enum3::Ok(0); //~ ERROR use of unstable library feature `unstable_default` if let Enum3::Ok(x) = ENUM3 {let _ = x;} // ok if let Enum3::Ok(x) = ENUM3 {let _: isize = x;} // ok if let Enum3::Ok(x) = ENUM3 {let _ = x + 1;} // ok @@ -227,21 +227,21 @@ fn main() { //~^^ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] let _ = ENUM5; - let _: Enum5<isize> = Enum5::Some(1); //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum5<isize> = Enum5::Some(1); //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated] //~^^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] let _ = ENUM5; let _: Enum5 = ENUM5; //~ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] - let _: Enum5<usize> = ENUM5; //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum5<usize> = ENUM5; //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] - let _: Enum5<isize> = Enum5::Some(0); //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum5<isize> = Enum5::Some(0); //~ ERROR use of unstable library feature `unstable_default` //~^ use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated] //~^^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] let _: Enum6<isize> = Enum6::Some(1); // ok let _: Enum6<isize> = Enum6::Some(0); // ok - let _: Box1<isize, System> = Box1::new(1); //~ ERROR use of unstable library feature 'box_alloc_param' + let _: Box1<isize, System> = Box1::new(1); //~ ERROR use of unstable library feature `box_alloc_param` let _: Box1<isize> = Box1::new(1); // ok let _: Box2<isize, System> = Box2::new(1); // ok diff --git a/tests/ui/stability-attribute/generics-default-stability.stderr b/tests/ui/stability-attribute/generics-default-stability.stderr index b1b91a850e9..f4f51a14248 100644 --- a/tests/ui/stability-attribute/generics-default-stability.stderr +++ b/tests/ui/stability-attribute/generics-default-stability.stderr @@ -216,7 +216,7 @@ warning: use of deprecated enum `unstable_generic_param::Enum5`: test LL | let _: Enum5<isize> = Enum5::Some(0); | ^^^^^ -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:23:20 | LL | let _: Struct1<isize> = Struct1 { field: 1 }; @@ -225,7 +225,7 @@ LL | let _: Struct1<isize> = Struct1 { field: 1 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:27:20 | LL | let _: Struct1<usize> = STRUCT1; @@ -234,7 +234,7 @@ LL | let _: Struct1<usize> = STRUCT1; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:28:20 | LL | let _: Struct1<isize> = Struct1 { field: 0 }; @@ -243,7 +243,7 @@ LL | let _: Struct1<isize> = Struct1 { field: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:57:27 | LL | let _: Struct3<isize, usize> = STRUCT3; @@ -252,7 +252,7 @@ LL | let _: Struct3<isize, usize> = STRUCT3; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:59:27 | LL | let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 }; @@ -261,7 +261,7 @@ LL | let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:60:27 | LL | let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 }; @@ -270,7 +270,7 @@ LL | let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:84:20 | LL | let _: Struct5<isize> = Struct5 { field: 1 }; @@ -279,7 +279,7 @@ LL | let _: Struct5<isize> = Struct5 { field: 1 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:90:20 | LL | let _: Struct5<usize> = STRUCT5; @@ -288,7 +288,7 @@ LL | let _: Struct5<usize> = STRUCT5; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:92:20 | LL | let _: Struct5<isize> = Struct5 { field: 0 }; @@ -297,7 +297,7 @@ LL | let _: Struct5<isize> = Struct5 { field: 0 }; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:100:19 | LL | let _: Alias1<isize> = Alias1::Some(1); @@ -306,7 +306,7 @@ LL | let _: Alias1<isize> = Alias1::Some(1); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:104:19 | LL | let _: Alias1<usize> = ALIAS1; @@ -315,7 +315,7 @@ LL | let _: Alias1<usize> = ALIAS1; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:105:19 | LL | let _: Alias1<isize> = Alias1::Some(0); @@ -324,7 +324,7 @@ LL | let _: Alias1<isize> = Alias1::Some(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:133:26 | LL | let _: Alias3<isize, usize> = ALIAS3; @@ -333,7 +333,7 @@ LL | let _: Alias3<isize, usize> = ALIAS3; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:135:26 | LL | let _: Alias3<isize, isize> = Alias3::Ok(0); @@ -342,7 +342,7 @@ LL | let _: Alias3<isize, isize> = Alias3::Ok(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:136:26 | LL | let _: Alias3<usize, usize> = Alias3::Ok(0); @@ -351,7 +351,7 @@ LL | let _: Alias3<usize, usize> = Alias3::Ok(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:158:19 | LL | let _: Alias5<isize> = Alias5::Some(1); @@ -360,7 +360,7 @@ LL | let _: Alias5<isize> = Alias5::Some(1); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:163:19 | LL | let _: Alias5<usize> = ALIAS5; @@ -369,7 +369,7 @@ LL | let _: Alias5<usize> = ALIAS5; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:165:19 | LL | let _: Alias5<isize> = Alias5::Some(0); @@ -378,7 +378,7 @@ LL | let _: Alias5<isize> = Alias5::Some(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:172:18 | LL | let _: Enum1<isize> = Enum1::Some(1); @@ -387,7 +387,7 @@ LL | let _: Enum1<isize> = Enum1::Some(1); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:176:18 | LL | let _: Enum1<usize> = ENUM1; @@ -396,7 +396,7 @@ LL | let _: Enum1<usize> = ENUM1; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:177:18 | LL | let _: Enum1<isize> = Enum1::Some(0); @@ -405,7 +405,7 @@ LL | let _: Enum1<isize> = Enum1::Some(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:205:25 | LL | let _: Enum3<isize, usize> = ENUM3; @@ -414,7 +414,7 @@ LL | let _: Enum3<isize, usize> = ENUM3; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:207:25 | LL | let _: Enum3<isize, isize> = Enum3::Ok(0); @@ -423,7 +423,7 @@ LL | let _: Enum3<isize, isize> = Enum3::Ok(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:208:25 | LL | let _: Enum3<usize, usize> = Enum3::Ok(0); @@ -432,7 +432,7 @@ LL | let _: Enum3<usize, usize> = Enum3::Ok(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:230:18 | LL | let _: Enum5<isize> = Enum5::Some(1); @@ -441,7 +441,7 @@ LL | let _: Enum5<isize> = Enum5::Some(1); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:235:18 | LL | let _: Enum5<usize> = ENUM5; @@ -450,7 +450,7 @@ LL | let _: Enum5<usize> = ENUM5; = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_default' +error[E0658]: use of unstable library feature `unstable_default` --> $DIR/generics-default-stability.rs:237:18 | LL | let _: Enum5<isize> = Enum5::Some(0); @@ -459,7 +459,7 @@ LL | let _: Enum5<isize> = Enum5::Some(0); = help: add `#![feature(unstable_default)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'box_alloc_param' +error[E0658]: use of unstable library feature `box_alloc_param` --> $DIR/generics-default-stability.rs:244:24 | LL | let _: Box1<isize, System> = Box1::new(1); diff --git a/tests/ui/stability-attribute/issue-28075.rs b/tests/ui/stability-attribute/issue-28075.rs index 8fc2ffe3dc9..b6b231d4afa 100644 --- a/tests/ui/stability-attribute/issue-28075.rs +++ b/tests/ui/stability-attribute/issue-28075.rs @@ -7,7 +7,7 @@ extern crate lint_stability; use lint_stability::{unstable, deprecated}; -//~^ ERROR use of unstable library feature 'unstable_test_feature' +//~^ ERROR use of unstable library feature `unstable_test_feature` fn main() { } diff --git a/tests/ui/stability-attribute/issue-28075.stderr b/tests/ui/stability-attribute/issue-28075.stderr index 282686d82bb..d10a27b874e 100644 --- a/tests/ui/stability-attribute/issue-28075.stderr +++ b/tests/ui/stability-attribute/issue-28075.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/issue-28075.rs:9:22 | LL | use lint_stability::{unstable, deprecated}; diff --git a/tests/ui/stability-attribute/issue-28388-3.rs b/tests/ui/stability-attribute/issue-28388-3.rs index 2f61146f6e3..7b6b6ce7f4b 100644 --- a/tests/ui/stability-attribute/issue-28388-3.rs +++ b/tests/ui/stability-attribute/issue-28388-3.rs @@ -5,7 +5,7 @@ extern crate lint_stability; use lint_stability::UnstableEnum::{}; -//~^ ERROR use of unstable library feature 'unstable_test_feature' +//~^ ERROR use of unstable library feature `unstable_test_feature` use lint_stability::StableEnum::{}; // OK fn main() {} diff --git a/tests/ui/stability-attribute/issue-28388-3.stderr b/tests/ui/stability-attribute/issue-28388-3.stderr index 56ca57591ce..def27c0b44d 100644 --- a/tests/ui/stability-attribute/issue-28388-3.stderr +++ b/tests/ui/stability-attribute/issue-28388-3.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/issue-28388-3.rs:7:5 | LL | use lint_stability::UnstableEnum::{}; diff --git a/tests/ui/stability-attribute/missing-const-stability.rs b/tests/ui/stability-attribute/missing-const-stability.rs index f1139652550..10c31d79438 100644 --- a/tests/ui/stability-attribute/missing-const-stability.rs +++ b/tests/ui/stability-attribute/missing-const-stability.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Znext-solver #![feature(staged_api)] -#![feature(const_trait_impl, effects, rustc_attrs, intrinsics)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl, rustc_attrs, intrinsics)] #![stable(feature = "stable", since = "1.0.0")] #[stable(feature = "stable", since = "1.0.0")] @@ -36,10 +36,4 @@ impl const Bar for Foo { pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 } //~^ ERROR function has missing const stability attribute -extern "rust-intrinsic" { - #[stable(feature = "stable", since = "1.0.0")] - #[rustc_const_stable_indirect] - pub fn min_align_of_val<T>(x: *const T) -> usize; -} - fn main() {} diff --git a/tests/ui/stability-attribute/missing-const-stability.stderr b/tests/ui/stability-attribute/missing-const-stability.stderr index e62a8b88261..ad8a1fa9d36 100644 --- a/tests/ui/stability-attribute/missing-const-stability.stderr +++ b/tests/ui/stability-attribute/missing-const-stability.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/missing-const-stability.rs:3:30 - | -LL | #![feature(const_trait_impl, effects, rustc_attrs, intrinsics)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: function has missing const stability attribute --> $DIR/missing-const-stability.rs:7:1 | @@ -34,5 +25,5 @@ error: associated function has missing const stability attribute LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 4 previous errors diff --git a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs index 47f885a43d6..0cc1dd20fd8 100644 --- a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs +++ b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs @@ -5,9 +5,9 @@ extern crate stability_attribute_implies; use stability_attribute_implies::{foo, foobar}; -//~^ ERROR use of unstable library feature 'foobar' +//~^ ERROR use of unstable library feature `foobar` fn main() { foo(); // no error - stable - foobar(); //~ ERROR use of unstable library feature 'foobar' + foobar(); //~ ERROR use of unstable library feature `foobar` } diff --git a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr index b35ee6c1291..a625ef504b1 100644 --- a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr +++ b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'foobar' +error[E0658]: use of unstable library feature `foobar` --> $DIR/stability-attribute-implies-no-feature.rs:7:40 | LL | use stability_attribute_implies::{foo, foobar}; @@ -8,7 +8,7 @@ LL | use stability_attribute_implies::{foo, foobar}; = help: add `#![feature(foobar)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'foobar' +error[E0658]: use of unstable library feature `foobar` --> $DIR/stability-attribute-implies-no-feature.rs:12:5 | LL | foobar(); diff --git a/tests/ui/stability-attribute/stability-attribute-issue.rs b/tests/ui/stability-attribute/stability-attribute-issue.rs index 2d25c0c8bd7..e9d1f144e6b 100644 --- a/tests/ui/stability-attribute/stability-attribute-issue.rs +++ b/tests/ui/stability-attribute/stability-attribute-issue.rs @@ -6,7 +6,7 @@ use stability_attribute_issue::*; fn main() { unstable(); - //~^ ERROR use of unstable library feature 'unstable_test_feature' + //~^ ERROR use of unstable library feature `unstable_test_feature` unstable_msg(); - //~^ ERROR use of unstable library feature 'unstable_test_feature': message + //~^ ERROR use of unstable library feature `unstable_test_feature`: message } diff --git a/tests/ui/stability-attribute/stability-attribute-issue.stderr b/tests/ui/stability-attribute/stability-attribute-issue.stderr index 336e0f1718f..9dc6f441987 100644 --- a/tests/ui/stability-attribute/stability-attribute-issue.stderr +++ b/tests/ui/stability-attribute/stability-attribute-issue.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/stability-attribute-issue.rs:8:5 | LL | unstable(); @@ -8,7 +8,7 @@ LL | unstable(); = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature': message +error[E0658]: use of unstable library feature `unstable_test_feature`: message --> $DIR/stability-attribute-issue.rs:10:5 | LL | unstable_msg(); diff --git a/tests/ui/stability-attribute/stable-in-unstable.rs b/tests/ui/stability-attribute/stable-in-unstable.rs index d10845d49a3..1fe084f6e59 100644 --- a/tests/ui/stability-attribute/stable-in-unstable.rs +++ b/tests/ui/stability-attribute/stable-in-unstable.rs @@ -13,8 +13,8 @@ extern crate stable_in_unstable_core; extern crate stable_in_unstable_std; mod isolated1 { - use stable_in_unstable_core::new_unstable_module; //~ ERROR use of unstable library feature 'unstable_test_feature' - use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature' + use stable_in_unstable_core::new_unstable_module; //~ ERROR use of unstable library feature `unstable_test_feature` + use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature `unstable_test_feature` } mod isolated2 { @@ -26,7 +26,7 @@ mod isolated2 { } mod isolated3 { - use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature' + use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature `unstable_test_feature` struct LocalType; @@ -36,7 +36,7 @@ mod isolated3 { mod isolated4 { struct LocalType; - impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} //~ ERROR use of unstable library feature 'unstable_test_feature' + impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} //~ ERROR use of unstable library feature `unstable_test_feature` } mod isolated5 { @@ -46,9 +46,9 @@ mod isolated5 { } mod isolated6 { - use stable_in_unstable_core::new_unstable_module::{OldTrait}; //~ ERROR use of unstable library feature 'unstable_test_feature' + use stable_in_unstable_core::new_unstable_module::{OldTrait}; //~ ERROR use of unstable library feature `unstable_test_feature` } mod isolated7 { - use stable_in_unstable_core::new_unstable_module::*; //~ ERROR use of unstable library feature 'unstable_test_feature' + use stable_in_unstable_core::new_unstable_module::*; //~ ERROR use of unstable library feature `unstable_test_feature` } diff --git a/tests/ui/stability-attribute/stable-in-unstable.stderr b/tests/ui/stability-attribute/stable-in-unstable.stderr index eb73f047acd..b37b4dfd586 100644 --- a/tests/ui/stability-attribute/stable-in-unstable.stderr +++ b/tests/ui/stability-attribute/stable-in-unstable.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/stable-in-unstable.rs:16:9 | LL | use stable_in_unstable_core::new_unstable_module; @@ -8,7 +8,7 @@ LL | use stable_in_unstable_core::new_unstable_module; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/stable-in-unstable.rs:17:9 | LL | use stable_in_unstable_core::new_unstable_module::OldTrait; @@ -18,7 +18,7 @@ LL | use stable_in_unstable_core::new_unstable_module::OldTrait; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/stable-in-unstable.rs:29:9 | LL | use stable_in_unstable_core::new_unstable_module::OldTrait; @@ -28,7 +28,7 @@ LL | use stable_in_unstable_core::new_unstable_module::OldTrait; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/stable-in-unstable.rs:39:10 | LL | impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} @@ -38,7 +38,7 @@ LL | impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalTy = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/stable-in-unstable.rs:49:56 | LL | use stable_in_unstable_core::new_unstable_module::{OldTrait}; @@ -48,7 +48,7 @@ LL | use stable_in_unstable_core::new_unstable_module::{OldTrait}; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'unstable_test_feature' +error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/stable-in-unstable.rs:53:9 | LL | use stable_in_unstable_core::new_unstable_module::*; diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.rs b/tests/ui/stability-attribute/suggest-vec-allocator-api.rs index fac52ab77c6..61a48c19e72 100644 --- a/tests/ui/stability-attribute/suggest-vec-allocator-api.rs +++ b/tests/ui/stability-attribute/suggest-vec-allocator-api.rs @@ -1,9 +1,9 @@ fn main() { - let _: Vec<u8, _> = vec![]; //~ ERROR use of unstable library feature 'allocator_api' + let _: Vec<u8, _> = vec![]; //~ ERROR use of unstable library feature `allocator_api` #[rustfmt::skip] let _: Vec< String, - _> = vec![]; //~ ERROR use of unstable library feature 'allocator_api' - let _ = Vec::<u16, _>::new(); //~ ERROR use of unstable library feature 'allocator_api' - let _boxed: Box<u32, _> = Box::new(10); //~ ERROR use of unstable library feature 'allocator_api' + _> = vec![]; //~ ERROR use of unstable library feature `allocator_api` + let _ = Vec::<u16, _>::new(); //~ ERROR use of unstable library feature `allocator_api` + let _boxed: Box<u32, _> = Box::new(10); //~ ERROR use of unstable library feature `allocator_api` } diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr index d7fcba4ced5..6662ceda90b 100644 --- a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr +++ b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'allocator_api' +error[E0658]: use of unstable library feature `allocator_api` --> $DIR/suggest-vec-allocator-api.rs:2:20 | LL | let _: Vec<u8, _> = vec![]; @@ -10,7 +10,7 @@ LL | let _: Vec<u8, _> = vec![]; = help: add `#![feature(allocator_api)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'allocator_api' +error[E0658]: use of unstable library feature `allocator_api` --> $DIR/suggest-vec-allocator-api.rs:6:9 | LL | _> = vec![]; @@ -26,7 +26,7 @@ LL + String, LL ~ _)> = vec![]; | -error[E0658]: use of unstable library feature 'allocator_api' +error[E0658]: use of unstable library feature `allocator_api` --> $DIR/suggest-vec-allocator-api.rs:8:26 | LL | let _boxed: Box<u32, _> = Box::new(10); @@ -36,7 +36,7 @@ LL | let _boxed: Box<u32, _> = Box::new(10); = help: add `#![feature(allocator_api)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'allocator_api' +error[E0658]: use of unstable library feature `allocator_api` --> $DIR/suggest-vec-allocator-api.rs:7:24 | LL | let _ = Vec::<u16, _>::new(); diff --git a/tests/ui/stable-mir-print/operands.rs b/tests/ui/stable-mir-print/operands.rs new file mode 100644 index 00000000000..34a74e2287e --- /dev/null +++ b/tests/ui/stable-mir-print/operands.rs @@ -0,0 +1,48 @@ +//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort +//@ check-pass +//@ only-x86_64 +//@ needs-unwind unwind edges are different with panic=abort +//! Check how stable mir pretty printer prints different operands and abort strategy. + +pub fn operands(val: u8) { + let array = [val; 10]; + let first = array[0]; + let last = array[10 - 1]; + assert_eq!(first, last); + + let reference = &first; + let dereferenced = *reference; + assert_eq!(dereferenced, first); + + let tuple = (first, last); + let (first_again, _) = tuple; + let first_again_again = tuple.0; + assert_eq!(first_again, first_again_again); + + let length = array.len(); + let size_of = std::mem::size_of_val(&length); + assert_eq!(length, size_of); +} + +pub struct Dummy { + c: char, + i: i32, +} + +pub enum Ctors { + Unit, + StructLike { d: Dummy }, + TupLike(bool), +} + +pub fn more_operands() -> [Ctors; 3] { + let dummy = Dummy { c: 'a', i: i32::MIN }; + let unit = Ctors::Unit; + let struct_like = Ctors::StructLike { d: dummy }; + let tup_like = Ctors::TupLike(false); + [unit, struct_like, tup_like] +} + +pub fn closures(x: bool, z: bool) -> impl FnOnce(bool) -> bool { + move |y: bool| (x ^ y) || z +} diff --git a/tests/ui/stable-mir-print/operands.stdout b/tests/ui/stable-mir-print/operands.stdout new file mode 100644 index 00000000000..3c27878b3cf --- /dev/null +++ b/tests/ui/stable-mir-print/operands.stdout @@ -0,0 +1,263 @@ +// WARNING: This is highly experimental output it's intended for stable-mir developers only. +// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir. +fn operands(_1: u8) -> () { + let mut _0: (); + let _2: [u8; 10]; + let _3: u8; + let _4: usize; + let mut _5: usize; + let mut _6: bool; + let _7: u8; + let _8: usize; + let mut _9: (usize, bool); + let mut _10: usize; + let mut _11: bool; + let mut _12: (&u8, &u8); + let mut _13: &u8; + let mut _14: &u8; + let _15: &u8; + let _16: &u8; + let mut _17: bool; + let mut _18: u8; + let mut _19: u8; + let _20: core::panicking::AssertKind; + let _21: !; + let mut _22: Option<Arguments<'_>>; + let _23: &u8; + let _24: u8; + let mut _25: (&u8, &u8); + let mut _26: &u8; + let mut _27: &u8; + let _28: &u8; + let _29: &u8; + let mut _30: bool; + let mut _31: u8; + let mut _32: u8; + let _33: core::panicking::AssertKind; + let _34: !; + let mut _35: Option<Arguments<'_>>; + let _36: (u8, u8); + let _37: u8; + let _38: u8; + let mut _39: (&u8, &u8); + let mut _40: &u8; + let mut _41: &u8; + let _42: &u8; + let _43: &u8; + let mut _44: bool; + let mut _45: u8; + let mut _46: u8; + let _47: core::panicking::AssertKind; + let _48: !; + let mut _49: Option<Arguments<'_>>; + let _50: usize; + let mut _51: &[u8]; + let mut _52: &[u8; 10]; + let _53: usize; + let _54: &usize; + let mut _55: (&usize, &usize); + let mut _56: &usize; + let mut _57: &usize; + let _58: &usize; + let _59: &usize; + let mut _60: bool; + let mut _61: usize; + let mut _62: usize; + let _63: core::panicking::AssertKind; + let _64: !; + let mut _65: Option<Arguments<'_>>; + debug val => _1; + debug array => _2; + debug first => _3; + debug last => _7; + debug left_val => _15; + debug right_val => _16; + debug kind => _20; + debug reference => _23; + debug dereferenced => _24; + debug left_val => _28; + debug right_val => _29; + debug kind => _33; + debug tuple => _36; + debug first_again => _37; + debug first_again_again => _38; + debug left_val => _42; + debug right_val => _43; + debug kind => _47; + debug length => _50; + debug size_of => _53; + debug left_val => _58; + debug right_val => _59; + debug kind => _63; + bb0: { + _2 = [_1; 10]; + _4 = 0_usize; + _5 = 10_usize; + _6 = Lt(_4, _5); + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; + } + bb1: { + _3 = _2[_4]; + _9 = CheckedSub(10_usize, 1_usize); + assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable]; + } + bb2: { + _8 = move (_9.0: usize); + _10 = 10_usize; + _11 = Lt(_8, _10); + assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _8) -> [success: bb3, unwind unreachable]; + } + bb3: { + _7 = _2[_8]; + _13 = &_3; + _14 = &_7; + _12 = (move _13, move _14); + _15 = (_12.0: &u8); + _16 = (_12.1: &u8); + _18 = (*_15); + _19 = (*_16); + _17 = Eq(move _18, move _19); + switchInt(move _17) -> [0: bb5, otherwise: bb4]; + } + bb4: { + _23 = &_3; + _24 = (*_23); + _26 = &_24; + _27 = &_3; + _25 = (move _26, move _27); + _28 = (_25.0: &u8); + _29 = (_25.1: &u8); + _31 = (*_28); + _32 = (*_29); + _30 = Eq(move _31, move _32); + switchInt(move _30) -> [0: bb7, otherwise: bb6]; + } + bb5: { + _20 = core::panicking::AssertKind::Eq; + _22 = std::option::Option::None; + _21 = core::panicking::assert_failed::<u8, u8>(move _20, _15, _16, move _22) -> unwind unreachable; + } + bb6: { + _36 = (_3, _7); + _37 = (_36.0: u8); + _38 = (_36.0: u8); + _40 = &_37; + _41 = &_38; + _39 = (move _40, move _41); + _42 = (_39.0: &u8); + _43 = (_39.1: &u8); + _45 = (*_42); + _46 = (*_43); + _44 = Eq(move _45, move _46); + switchInt(move _44) -> [0: bb9, otherwise: bb8]; + } + bb7: { + _33 = core::panicking::AssertKind::Eq; + _35 = std::option::Option::None; + _34 = core::panicking::assert_failed::<u8, u8>(move _33, _28, _29, move _35) -> unwind unreachable; + } + bb8: { + _52 = &_2; + _51 = move _52 as &[u8]; + _50 = PtrMetadata(move _51); + _54 = &_50; + _53 = std::mem::size_of_val::<usize>(_54) -> [return: bb10, unwind unreachable]; + } + bb9: { + _47 = core::panicking::AssertKind::Eq; + _49 = std::option::Option::None; + _48 = core::panicking::assert_failed::<u8, u8>(move _47, _42, _43, move _49) -> unwind unreachable; + } + bb10: { + _56 = &_50; + _57 = &_53; + _55 = (move _56, move _57); + _58 = (_55.0: &usize); + _59 = (_55.1: &usize); + _61 = (*_58); + _62 = (*_59); + _60 = Eq(move _61, move _62); + switchInt(move _60) -> [0: bb12, otherwise: bb11]; + } + bb11: { + return; + } + bb12: { + _63 = core::panicking::AssertKind::Eq; + _65 = std::option::Option::None; + _64 = core::panicking::assert_failed::<usize, usize>(move _63, _58, _59, move _65) -> unwind unreachable; + } +} +fn operands::{constant#0}() -> usize { + let mut _0: usize; + bb0: { + _0 = 10_usize; + return; + } +} +fn more_operands() -> [Ctors; 3] { + let mut _0: [Ctors; 3]; + let _1: Dummy; + let _2: Ctors; + let _3: Ctors; + let _4: Ctors; + debug dummy => _1; + debug unit => _2; + debug struct_like => _3; + debug tup_like => _4; + bb0: { + _1 = Dummy('a', core::num::<impl i32>::MIN); + _2 = Ctors::Unit; + _3 = Ctors::StructLike(move _1); + _4 = Ctors::TupLike(false); + _0 = [move _2, move _3, move _4]; + return; + } +} +fn more_operands::{constant#0}() -> usize { + let mut _0: usize; + bb0: { + _0 = 3_usize; + return; + } +} +fn closures(_1: bool, _2: bool) -> {closure@$DIR/operands.rs:47:5: 47:19} { + let mut _0: {closure@$DIR/operands.rs:47:5: 47:19}; + debug x => _1; + debug z => _2; + bb0: { + _0 = {closure@$DIR/operands.rs:47:5: 47:19}(_1, _2); + return; + } +} +fn closures::{closure#0}(_1: {closure@$DIR/operands.rs:47:5: 47:19}, _2: bool) -> bool { + let mut _0: bool; + let mut _3: bool; + let mut _4: bool; + debug y => _2; + debug x => (_1.0: bool); + debug z => (_1.1: bool); + bb0: { + _4 = (_1.0: bool); + _3 = BitXor(move _4, _2); + switchInt(move _3) -> [0: bb2, otherwise: bb1]; + } + bb1: { + _0 = true; + goto -> bb3; + } + bb2: { + _0 = (_1.1: bool); + goto -> bb3; + } + bb3: { + return; + } +} +fn Ctors::TupLike(_1: bool) -> Ctors { + let mut _0: Ctors; + bb0: { + _0 = Ctors::TupLike(move _1); + return; + } +} diff --git a/tests/ui/statics/static-mut-shared-parens.rs b/tests/ui/statics/static-mut-shared-parens.rs new file mode 100644 index 00000000000..8e58152e27a --- /dev/null +++ b/tests/ui/statics/static-mut-shared-parens.rs @@ -0,0 +1,13 @@ +//Missing paren in diagnostic msg: https://github.com/rust-lang/rust/issues/131977 +//@check-pass + + +static mut TEST: usize = 0; + +fn main() { + let _ = unsafe { (&TEST) as *const usize }; + //~^WARN creating a shared reference to mutable static is discouraged + + let _ = unsafe { ((&mut TEST)) as *const usize }; + //~^WARN creating a mutable reference to mutable static is discouraged +} diff --git a/tests/ui/statics/static-mut-shared-parens.stderr b/tests/ui/statics/static-mut-shared-parens.stderr new file mode 100644 index 00000000000..aa7a760ded8 --- /dev/null +++ b/tests/ui/statics/static-mut-shared-parens.stderr @@ -0,0 +1,29 @@ +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-shared-parens.rs:8:22 + | +LL | let _ = unsafe { (&TEST) as *const usize }; + | ^^^^^^^ shared reference to mutable static + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html> + = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: `#[warn(static_mut_refs)]` on by default +help: use `&raw const` instead to create a raw pointer + | +LL | let _ = unsafe { (&raw const TEST) as *const usize }; + | ~~~~~~~~~~ + +warning: creating a mutable reference to mutable static is discouraged + --> $DIR/static-mut-shared-parens.rs:11:22 + | +LL | let _ = unsafe { ((&mut TEST)) as *const usize }; + | ^^^^^^^^^^^^^ mutable reference to mutable static + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html> + = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives +help: use `&raw mut` instead to create a raw pointer + | +LL | let _ = unsafe { ((&raw mut TEST)) as *const usize }; + | ~~~~~~~~ + +warning: 2 warnings emitted + diff --git a/tests/ui/std/channel-stack-overflow-issue-102246.rs b/tests/ui/std/channel-stack-overflow-issue-102246.rs new file mode 100644 index 00000000000..984ebdd553f --- /dev/null +++ b/tests/ui/std/channel-stack-overflow-issue-102246.rs @@ -0,0 +1,29 @@ +//@ run-pass +//@ needs-threads +//@ compile-flags: -Copt-level=0 + +// The channel's `Block::new` was causing a stack overflow because it held 32 item slots, which is +// 1MiB for this test's `BigStruct` -- instantiated on the stack before moving to `Box::new`. +// +// That block is now initialized directly on the heap. +// +// Ref: https://github.com/rust-lang/rust/issues/102246 + +use std::sync::mpsc::channel; +use std::thread; + +const N: usize = 32_768; +struct BigStruct { + _data: [u8; N], +} + +fn main() { + let (sender, receiver) = channel::<BigStruct>(); + + let thread1 = thread::spawn(move || { + sender.send(BigStruct { _data: [0u8; N] }).unwrap(); + }); + + thread1.join().unwrap(); + for _data in receiver.try_iter() {} +} diff --git a/tests/ui/structs-enums/rec-align-u32.rs b/tests/ui/structs-enums/rec-align-u32.rs index 9cd2a988871..44879189739 100644 --- a/tests/ui/structs-enums/rec-align-u32.rs +++ b/tests/ui/structs-enums/rec-align-u32.rs @@ -3,17 +3,10 @@ #![allow(unused_unsafe)] // Issue #2303 -#![feature(intrinsics, rustc_attrs)] +#![feature(core_intrinsics, rustc_attrs)] use std::mem; - -mod rusti { - extern "rust-intrinsic" { - pub fn pref_align_of<T>() -> usize; - #[rustc_safe_intrinsic] - pub fn min_align_of<T>() -> usize; - } -} +use std::intrinsics; // This is the type with the questionable alignment #[derive(Debug)] @@ -41,12 +34,12 @@ pub fn main() { // Send it through the shape code let y = format!("{:?}", x); - println!("align inner = {:?}", rusti::min_align_of::<Inner>()); + println!("align inner = {:?}", intrinsics::min_align_of::<Inner>()); println!("size outer = {:?}", mem::size_of::<Outer>()); println!("y = {:?}", y); // per clang/gcc the alignment of `inner` is 4 on x86. - assert_eq!(rusti::min_align_of::<Inner>(), m::align()); + assert_eq!(intrinsics::min_align_of::<Inner>(), m::align()); // per clang/gcc the size of `outer` should be 12 // because `inner`s alignment was 4. diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs index 313ce6d578d..8b501ea5509 100644 --- a/tests/ui/structs-enums/rec-align-u64.rs +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -4,17 +4,10 @@ // Issue #2303 -#![feature(intrinsics, rustc_attrs)] +#![feature(core_intrinsics, rustc_attrs)] use std::mem; - -mod rusti { - extern "rust-intrinsic" { - pub fn pref_align_of<T>() -> usize; - #[rustc_safe_intrinsic] - pub fn min_align_of<T>() -> usize; - } -} +use std::intrinsics; // This is the type with the questionable alignment #[derive(Debug)] @@ -90,12 +83,12 @@ pub fn main() { let y = format!("{:?}", x); - println!("align inner = {:?}", rusti::min_align_of::<Inner>()); + println!("align inner = {:?}", intrinsics::min_align_of::<Inner>()); println!("size outer = {:?}", mem::size_of::<Outer>()); println!("y = {:?}", y); // per clang/gcc the alignment of `Inner` is 4 on x86. - assert_eq!(rusti::min_align_of::<Inner>(), m::m::align()); + assert_eq!(intrinsics::min_align_of::<Inner>(), m::m::align()); // per clang/gcc the size of `Outer` should be 12 // because `Inner`s alignment was 4. diff --git a/tests/ui/structs/struct-field-cfg.stderr b/tests/ui/structs/struct-field-cfg.stderr index 2b9ba85ddcb..f30d343d582 100644 --- a/tests/ui/structs/struct-field-cfg.stderr +++ b/tests/ui/structs/struct-field-cfg.stderr @@ -24,6 +24,10 @@ LL | let Foo { present } = foo; | ~~~~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | let Foo { present: _ } = foo; + | ~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let Foo { .. } = foo; | ~~~~~~ diff --git a/tests/ui/structs/struct-pat-derived-error.stderr b/tests/ui/structs/struct-pat-derived-error.stderr index 78bb018cb4b..d1d68121cf1 100644 --- a/tests/ui/structs/struct-pat-derived-error.stderr +++ b/tests/ui/structs/struct-pat-derived-error.stderr @@ -27,6 +27,10 @@ LL | let A { x, y, b, c } = self.d; | ~~~~~~~~ help: if you don't care about these missing fields, you can explicitly ignore them | +LL | let A { x, y, b: _, c: _ } = self.d; + | ~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let A { x, y, .. } = self.d; | ~~~~~~ diff --git a/tests/ui/structs/struct-tuple-field-names.stderr b/tests/ui/structs/struct-tuple-field-names.stderr index 0b837a47a82..5f1ab2f9d68 100644 --- a/tests/ui/structs/struct-tuple-field-names.stderr +++ b/tests/ui/structs/struct-tuple-field-names.stderr @@ -32,6 +32,10 @@ LL | if let E::S { 0: a, 1: _ } = x { | ~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | if let E::S { 0: a, 1: _ } = x { + | ~~~~~~~~ +help: or always ignore missing fields here + | LL | if let E::S { 0: a, .. } = x { | ~~~~~~ diff --git a/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr index e8503f540c2..af530e2b759 100644 --- a/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr +++ b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr @@ -19,6 +19,10 @@ LL | Foo::Bar { a, aa: 1, c, b } => (), | ~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | Foo::Bar { a, aa: 1, c, b: _ } => (), + | ~~~~~~~~ +help: or always ignore missing fields here + | LL | Foo::Bar { a, aa: 1, c, .. } => (), | ~~~~~~ @@ -43,6 +47,10 @@ LL | Foo::Baz { bb: 1.0, a } => (), | ~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | Foo::Baz { bb: 1.0, a: _ } => (), + | ~~~~~~~~ +help: or always ignore missing fields here + | LL | Foo::Baz { bb: 1.0, .. } => (), | ~~~~~~ @@ -64,6 +72,10 @@ LL | Foo::Bar { a, aa: "", c, b } => (), | ~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | Foo::Bar { a, aa: "", c, b: _ } => (), + | ~~~~~~~~ +help: or always ignore missing fields here + | LL | Foo::Bar { a, aa: "", c, .. } => (), | ~~~~~~ @@ -85,6 +97,10 @@ LL | Foo::Baz { bb: "", a } => (), | ~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | Foo::Baz { bb: "", a: _ } => (), + | ~~~~~~~~ +help: or always ignore missing fields here + | LL | Foo::Baz { bb: "", .. } => (), | ~~~~~~ diff --git a/tests/ui/suggestions/partialeq_suggest_swap.rs b/tests/ui/suggestions/partialeq_suggest_swap.rs new file mode 100644 index 00000000000..ee5583a5488 --- /dev/null +++ b/tests/ui/suggestions/partialeq_suggest_swap.rs @@ -0,0 +1,11 @@ +struct T(i32); + +impl PartialEq<i32> for T { + fn eq(&self, other: &i32) -> bool { + &self.0 == other + } +} + +fn main() { + 4i32 == T(4); //~ mismatched types [E0308] +} diff --git a/tests/ui/suggestions/partialeq_suggest_swap.stderr b/tests/ui/suggestions/partialeq_suggest_swap.stderr new file mode 100644 index 00000000000..2cadc5a16d5 --- /dev/null +++ b/tests/ui/suggestions/partialeq_suggest_swap.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/partialeq_suggest_swap.rs:10:13 + | +LL | 4i32 == T(4); + | ---- ^^^^ expected `i32`, found `T` + | | + | expected because this is `i32` + | + = note: `T` implements `PartialEq<i32>` +help: consider swapping the equality + | +LL | T(4) == 4i32; + | ~~~~ ~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/suggest-let-and-typo-issue-132483.rs b/tests/ui/suggestions/suggest-let-and-typo-issue-132483.rs new file mode 100644 index 00000000000..d56a6b78d37 --- /dev/null +++ b/tests/ui/suggestions/suggest-let-and-typo-issue-132483.rs @@ -0,0 +1,7 @@ +fn main() { + let x1 = 0; + x2 = 1; + //~^ ERROR E0425 + other_val = 2; + //~^ ERROR E0425 +} diff --git a/tests/ui/suggestions/suggest-let-and-typo-issue-132483.stderr b/tests/ui/suggestions/suggest-let-and-typo-issue-132483.stderr new file mode 100644 index 00000000000..c84f9363f03 --- /dev/null +++ b/tests/ui/suggestions/suggest-let-and-typo-issue-132483.stderr @@ -0,0 +1,29 @@ +error[E0425]: cannot find value `x2` in this scope + --> $DIR/suggest-let-and-typo-issue-132483.rs:3:5 + | +LL | x2 = 1; + | ^^ + | +help: a local variable with a similar name exists + | +LL | x1 = 1; + | ~~ +help: you might have meant to introduce a new binding + | +LL | let x2 = 1; + | +++ + +error[E0425]: cannot find value `other_val` in this scope + --> $DIR/suggest-let-and-typo-issue-132483.rs:5:5 + | +LL | other_val = 2; + | ^^^^^^^^^ + | +help: you might have meant to introduce a new binding + | +LL | let other_val = 2; + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/auxiliary/using-target-feature-unstable.rs b/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs index 2682028936c..2682028936c 100644 --- a/tests/ui/auxiliary/using-target-feature-unstable.rs +++ b/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs diff --git a/tests/ui/target-feature/feature-hierarchy.rs b/tests/ui/target-feature/feature-hierarchy.rs index 7f14d700ecb..d62b86693c2 100644 --- a/tests/ui/target-feature/feature-hierarchy.rs +++ b/tests/ui/target-feature/feature-hierarchy.rs @@ -18,10 +18,12 @@ trait Sized {} trait Copy {} impl Copy for bool {} -extern "rust-intrinsic" { - #[stable(feature = "test", since = "1.0.0")] - #[rustc_const_stable(feature = "test", since = "1.0.0")] - fn unreachable() -> !; +#[stable(feature = "test", since = "1.0.0")] +#[rustc_const_stable(feature = "test", since = "1.0.0")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +const unsafe fn unreachable() -> ! { + loop {} } #[rustc_builtin_macro] diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.rs b/tests/ui/target-feature/forbidden-target-feature-attribute.rs new file mode 100644 index 00000000000..91c56b43689 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-attribute.rs @@ -0,0 +1,12 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +#[target_feature(enable = "soft-float")] +//~^ERROR: cannot be toggled with +pub unsafe fn my_fun() {} diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr new file mode 100644 index 00000000000..fb318531f7e --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr @@ -0,0 +1,8 @@ +error: target feature `soft-float` cannot be toggled with `#[target_feature]`: unsound because it changes float ABI + --> $DIR/forbidden-target-feature-attribute.rs:10:18 + | +LL | #[target_feature(enable = "soft-float")] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/forbidden-target-feature-cfg.rs b/tests/ui/target-feature/forbidden-target-feature-cfg.rs new file mode 100644 index 00000000000..5df26e26793 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-cfg.rs @@ -0,0 +1,15 @@ +//@ compile-flags: --target=x86_64-unknown-none --crate-type=lib +//@ needs-llvm-components: x86 +//@ check-pass +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![allow(unexpected_cfgs)] + +#[lang = "sized"] +pub trait Sized {} + +// The compile_error macro does not exist, so if the `cfg` evaluates to `true` this +// complains about the missing macro rather than showing the error... but that's good enough. +#[cfg(target_feature = "soft-float")] +compile_error!("the soft-float feature should not be exposed in `cfg`"); diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs new file mode 100644 index 00000000000..b27e8a10afe --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-soft-float +// For now this is just a warning. +//@ build-pass +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr b/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr new file mode 100644 index 00000000000..508e1fe0cf4 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr @@ -0,0 +1,7 @@ +warning: target feature `soft-float` cannot be toggled with `-Ctarget-feature`: unsound because it changes float ABI + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344> + +warning: 1 warning emitted + diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.rs b/tests/ui/target-feature/forbidden-target-feature-flag.rs new file mode 100644 index 00000000000..93cebc6b536 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-flag.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=+soft-float +// For now this is just a warning. +//@ build-pass +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.stderr b/tests/ui/target-feature/forbidden-target-feature-flag.stderr new file mode 100644 index 00000000000..508e1fe0cf4 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-flag.stderr @@ -0,0 +1,7 @@ +warning: target feature `soft-float` cannot be toggled with `-Ctarget-feature`: unsound because it changes float ABI + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344> + +warning: 1 warning emitted + diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs index f0c887bc1e0..10268686405 100644 --- a/tests/ui/target-feature/no-llvm-leaks.rs +++ b/tests/ui/target-feature/no-llvm-leaks.rs @@ -16,10 +16,12 @@ trait Sized {} trait Copy {} impl Copy for bool {} -extern "rust-intrinsic" { - #[stable(feature = "test", since = "1.0.0")] - #[rustc_const_stable(feature = "test", since = "1.0.0")] - fn unreachable() -> !; +#[stable(feature = "test", since = "1.0.0")] +#[rustc_const_stable(feature = "test", since = "1.0.0")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +const unsafe fn unreachable() -> ! { + loop {} } #[rustc_builtin_macro] diff --git a/tests/ui/using-target-feature-unstable.rs b/tests/ui/target-feature/using-target-feature-unstable.rs index 5ec0bda5eef..5ec0bda5eef 100644 --- a/tests/ui/using-target-feature-unstable.rs +++ b/tests/ui/target-feature/using-target-feature-unstable.rs diff --git a/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs b/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs new file mode 100644 index 00000000000..48a98efea5e --- /dev/null +++ b/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs @@ -0,0 +1,20 @@ +// issue#132534 + +trait X { + fn a<T>() -> T::unknown<{}> {} + //~^ ERROR: associated type `unknown` not found for `T` + //~| ERROR: associated type `unknown` not found for `T` +} + +trait Y { + fn a() -> NOT_EXIST::unknown<{}> {} + //~^ ERROR: failed to resolve: use of undeclared type `NOT_EXIST` +} + +trait Z<T> { + fn a() -> T::unknown<{}> {} + //~^ ERROR: associated type `unknown` not found for `T` + //~| ERROR: associated type `unknown` not found for `T` +} + +fn main() {} diff --git a/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr b/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr new file mode 100644 index 00000000000..9598c373e6e --- /dev/null +++ b/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr @@ -0,0 +1,38 @@ +error[E0220]: associated type `unknown` not found for `T` + --> $DIR/unknown-assoc-with-const-arg.rs:4:21 + | +LL | fn a<T>() -> T::unknown<{}> {} + | ^^^^^^^ associated type `unknown` not found + +error[E0220]: associated type `unknown` not found for `T` + --> $DIR/unknown-assoc-with-const-arg.rs:15:18 + | +LL | fn a() -> T::unknown<{}> {} + | ^^^^^^^ associated type `unknown` not found + +error[E0220]: associated type `unknown` not found for `T` + --> $DIR/unknown-assoc-with-const-arg.rs:4:21 + | +LL | fn a<T>() -> T::unknown<{}> {} + | ^^^^^^^ associated type `unknown` not found + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0220]: associated type `unknown` not found for `T` + --> $DIR/unknown-assoc-with-const-arg.rs:15:18 + | +LL | fn a() -> T::unknown<{}> {} + | ^^^^^^^ associated type `unknown` not found + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0433]: failed to resolve: use of undeclared type `NOT_EXIST` + --> $DIR/unknown-assoc-with-const-arg.rs:10:15 + | +LL | fn a() -> NOT_EXIST::unknown<{}> {} + | ^^^^^^^^^ use of undeclared type `NOT_EXIST` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0220, E0433. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs index bbf88917905..bac7ee023f4 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Trait { diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs index 04ad94556c3..a0375cda079 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Znext-solver //@ known-bug: unknown -#![feature(const_trait_impl, effects, generic_const_exprs)] +#![feature(const_trait_impl, generic_const_exprs)] #![allow(incomplete_features)] #[const_trait] diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr index b8768bd5541..8d1c85c0c8a 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr @@ -1,8 +1,8 @@ error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed - --> $DIR/assoc-type-const-bound-usage-1.rs:4:39 + --> $DIR/assoc-type-const-bound-usage-1.rs:4:30 | -LL | #![feature(const_trait_impl, effects, generic_const_exprs)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![feature(const_trait_impl, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ | = help: remove one of these features diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs index 5e873082781..b3a636b0f71 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs @@ -5,8 +5,7 @@ // i.e. check that we validate the const conditions for the associated type // when considering one of implied const bounds. -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Trait { diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr index 1f6532c7a57..86bd07a5f59 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:23:5 | LL | T::Assoc::<U>::func(); | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:25:5 | LL | <T as Trait>::Assoc::<U>::func(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs index 73b3d142f7c..ce01086f0dc 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs @@ -4,8 +4,7 @@ // i.e. check that we validate the const conditions for the associated type // when considering one of implied const bounds. -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Trait { diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr index fb08e74eb7f..145fe2c41dd 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: ~const Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:17:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5 | LL | T::Assoc::func(); | ^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: ~const Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:19:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5 | LL | <T as Trait>::Assoc::func(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type.rs b/tests/ui/traits/const-traits/assoc-type.rs index a9394d90ed8..32c91fa51f1 100644 --- a/tests/ui/traits/const-traits/assoc-type.rs +++ b/tests/ui/traits/const-traits/assoc-type.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Add<Rhs = Self> { diff --git a/tests/ui/traits/const-traits/assoc-type.stderr b/tests/ui/traits/const-traits/assoc-type.stderr index 672eaf26f72..b318675b612 100644 --- a/tests/ui/traits/const-traits/assoc-type.stderr +++ b/tests/ui/traits/const-traits/assoc-type.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/assoc-type.rs:3:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied --> $DIR/assoc-type.rs:36:16 | @@ -19,6 +10,6 @@ note: required by a bound in `Foo::Bar` LL | type Bar: ~const Add; | ^^^^^^ required by this bound in `Foo::Bar` -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/auxiliary/cross-crate.rs b/tests/ui/traits/const-traits/auxiliary/cross-crate.rs index 8f63cd1d521..01921c140cb 100644 --- a/tests/ui/traits/const-traits/auxiliary/cross-crate.rs +++ b/tests/ui/traits/const-traits/auxiliary/cross-crate.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] pub trait MyTrait { diff --git a/tests/ui/traits/const-traits/auxiliary/staged-api.rs b/tests/ui/traits/const-traits/auxiliary/staged-api.rs index bb591321b84..abe22db702c 100644 --- a/tests/ui/traits/const-traits/auxiliary/staged-api.rs +++ b/tests/ui/traits/const-traits/auxiliary/staged-api.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/traits/const-traits/call-const-closure.rs b/tests/ui/traits/const-traits/call-const-closure.rs index cbf3e6c3ac4..21f4374b8d5 100644 --- a/tests/ui/traits/const-traits/call-const-closure.rs +++ b/tests/ui/traits/const-traits/call-const-closure.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Znext-solver //@ edition:2021 -#![feature(const_trait_impl, effects, const_closures)] +#![feature(const_trait_impl, const_closures)] #![allow(incomplete_features)] #[const_trait] @@ -16,7 +16,7 @@ impl Bar for () { const FOO: () = { (const || ().foo())(); //~^ ERROR the trait bound `(): ~const Bar` is not satisfied - // FIXME(effects): The constness environment for const closures is wrong. + // FIXME(const_trait_impl): The constness environment for const closures is wrong. }; fn main() {} diff --git a/tests/ui/traits/const-traits/call-const-in-tilde-const.rs b/tests/ui/traits/const-traits/call-const-in-tilde-const.rs index 970ee93fd49..b6d1517499d 100644 --- a/tests/ui/traits/const-traits/call-const-in-tilde-const.rs +++ b/tests/ui/traits/const-traits/call-const-in-tilde-const.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Foo { fn foo(); diff --git a/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr b/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr index 49c310f1f75..e56968b9097 100644 --- a/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr +++ b/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr @@ -1,18 +1,9 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/call-const-in-tilde-const.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the trait bound `T: const Foo` is not satisfied - --> $DIR/call-const-in-tilde-const.rs:10:13 + --> $DIR/call-const-in-tilde-const.rs:9:13 | LL | const { T::foo() } | ^^^^^^^^ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.rs b/tests/ui/traits/const-traits/call-const-trait-method-fail.rs index 878f9a713a0..e06d04db804 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-fail.rs +++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] pub trait Plus { diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr index 40a06af85ed..b461fd9e39e 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied - --> $DIR/call-const-trait-method-fail.rs:27:5 + --> $DIR/call-const-trait-method-fail.rs:26:5 | LL | a.plus(b) | ^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr index 32f53137a00..9ae1ed18e35 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr @@ -24,18 +24,6 @@ LL | const ADD_INT: Int = Int(1i32) + Int(2i32); | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions - --> $DIR/call-const-trait-method-pass.rs:11:20 - | -LL | Int(self.0.plus(rhs.0)) - | ^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - error[E0015]: cannot call non-const fn `<Int as PartialEq>::eq` in constant functions --> $DIR/call-const-trait-method-pass.rs:20:15 | @@ -44,18 +32,6 @@ LL | !self.eq(other) | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions - --> $DIR/call-const-trait-method-pass.rs:36:7 - | -LL | a.plus(b) - | ^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.rs b/tests/ui/traits/const-traits/call-generic-in-impl.rs index 6b3a4ae1b95..6149dc3d126 100644 --- a/tests/ui/traits/const-traits/call-generic-in-impl.rs +++ b/tests/ui/traits/const-traits/call-generic-in-impl.rs @@ -1,5 +1,5 @@ //@ known-bug: #110395 -// FIXME(effects) check-pass +// FIXME(const_trait_impl) check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.rs b/tests/ui/traits/const-traits/call-generic-method-chain.rs index e5baedae818..74beab71208 100644 --- a/tests/ui/traits/const-traits/call-generic-method-chain.rs +++ b/tests/ui/traits/const-traits/call-generic-method-chain.rs @@ -2,9 +2,9 @@ //@ known-bug: #110395 //@ compile-flags: -Znext-solver -// FIXME(effects) check-pass +// FIXME(const_trait_impl) check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] struct S; diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr index 6dbf3ad2526..9a53c61d019 100644 --- a/tests/ui/traits/const-traits/call-generic-method-chain.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-chain.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/call-generic-method-chain.rs:7:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/call-generic-method-chain.rs:11:12 | @@ -64,6 +55,6 @@ LL | !self.eq(other) | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs index 83a4bb25436..ec615d8484c 100644 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs @@ -1,8 +1,8 @@ //@ compile-flags: -Znext-solver //@ known-bug: #110395 -// FIXME(effects) check-pass +// FIXME(const_trait_impl) check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] struct S; diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr index 08877daad79..a168171cfe8 100644 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/call-generic-method-dup-bound.rs:5:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/call-generic-method-dup-bound.rs:9:12 | @@ -76,6 +67,6 @@ help: consider further restricting this bound LL | const fn equals_self2<T: A + ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { | ++++++++++++++++++++++++++++ -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.rs b/tests/ui/traits/const-traits/call-generic-method-fail.rs index 6bfbbef6f76..66881334a29 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.rs +++ b/tests/ui/traits/const-traits/call-generic-method-fail.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] pub const fn equals_self<T: PartialEq>(t: &T) -> bool { *t == *t diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.stderr b/tests/ui/traits/const-traits/call-generic-method-fail.stderr index 5cd4216dce1..07e50a7f7da 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-fail.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-fail.rs:6:5 + --> $DIR/call-generic-method-fail.rs:5:5 | LL | *t == *t | ^^^^^^^^ diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.rs b/tests/ui/traits/const-traits/call-generic-method-nonconst.rs index f9e79d41752..446a74eb7b7 100644 --- a/tests/ui/traits/const-traits/call-generic-method-nonconst.rs +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] struct S; diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr index 06b99375cda..d881bd5f4de 100644 --- a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `S: const Foo` is not satisfied - --> $DIR/call-generic-method-nonconst.rs:25:22 + --> $DIR/call-generic-method-nonconst.rs:24:22 | LL | pub const EQ: bool = equals_self(&S); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.rs b/tests/ui/traits/const-traits/call-generic-method-pass.rs index cbeeb2567dd..af793b8da03 100644 --- a/tests/ui/traits/const-traits/call-generic-method-pass.rs +++ b/tests/ui/traits/const-traits/call-generic-method-pass.rs @@ -2,9 +2,9 @@ //@ compile-flags: -Znext-solver //@ known-bug: #110395 -// FIXME(effects) check-pass +// FIXME(const_trait_impl) check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] struct S; diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr index ac08c057435..af6e6d25dc9 100644 --- a/tests/ui/traits/const-traits/call-generic-method-pass.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-pass.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/call-generic-method-pass.rs:7:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/call-generic-method-pass.rs:11:12 | @@ -50,6 +41,6 @@ LL | !self.eq(other) | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call.rs b/tests/ui/traits/const-traits/call.rs index f96fb614ac2..b985e3da345 100644 --- a/tests/ui/traits/const-traits/call.rs +++ b/tests/ui/traits/const-traits/call.rs @@ -1,6 +1,6 @@ -// FIXME(effects) check-pass +// FIXME(const_trait_impl) check-pass //@ compile-flags: -Znext-solver -#![feature(const_closures, const_trait_impl, effects)] +#![feature(const_closures, const_trait_impl)] #![allow(incomplete_features)] pub const _: () = { diff --git a/tests/ui/traits/const-traits/const-bound-in-host.rs b/tests/ui/traits/const-traits/const-bound-in-host.rs index 6fbc21074b6..b4c4f5a6de1 100644 --- a/tests/ui/traits/const-traits/const-bound-in-host.rs +++ b/tests/ui/traits/const-traits/const-bound-in-host.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Foo { fn foo(); diff --git a/tests/ui/traits/const-traits/const-bound-in-host.stderr b/tests/ui/traits/const-traits/const-bound-in-host.stderr deleted file mode 100644 index b815f745ee8..00000000000 --- a/tests/ui/traits/const-traits/const-bound-in-host.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-bound-in-host.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs index 7c3e2af1797..c735f855bce 100644 --- a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs +++ b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs @@ -1,7 +1,6 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait MyTrait { diff --git a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr index ae1260ffab7..50ab52ade49 100644 --- a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr +++ b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr @@ -1,23 +1,23 @@ error: `~const` is not allowed here - --> $DIR/const-bound-on-not-const-associated-fn.rs:12:40 + --> $DIR/const-bound-on-not-const-associated-fn.rs:11:40 | LL | fn do_something_else() where Self: ~const MyTrait; | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/const-bound-on-not-const-associated-fn.rs:12:8 + --> $DIR/const-bound-on-not-const-associated-fn.rs:11:8 | LL | fn do_something_else() where Self: ~const MyTrait; | ^^^^^^^^^^^^^^^^^ error: `~const` is not allowed here - --> $DIR/const-bound-on-not-const-associated-fn.rs:23:32 + --> $DIR/const-bound-on-not-const-associated-fn.rs:22:32 | LL | pub fn foo(&self) where T: ~const MyTrait { | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/const-bound-on-not-const-associated-fn.rs:23:12 + --> $DIR/const-bound-on-not-const-associated-fn.rs:22:12 | LL | pub fn foo(&self) where T: ~const MyTrait { | ^^^ diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs b/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs index d51d231b8a9..e446eb15481 100644 --- a/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs +++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs @@ -1,5 +1,5 @@ // Regression test for issue #117244. -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] trait NonConst {} diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr index 8e836685eb0..2436c97ccf2 100644 --- a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr +++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-bounds-non-const-trait.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-bounds-non-const-trait.rs:6:21 | @@ -27,5 +18,5 @@ error: `const` can only be applied to `#[const_trait]` traits LL | fn operate<T: const NonConst>() {} | ^^^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs index 7f9b38b8207..0330ed5ca8b 100644 --- a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs +++ b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] struct S; #[const_trait] diff --git a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr index ba12854987e..d111a9d5639 100644 --- a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr +++ b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-check-fns-in-const-impl.rs:3:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0015]: cannot call non-const fn `non_const` in constant functions --> $DIR/const-check-fns-in-const-impl.rs:14:16 | @@ -15,6 +6,6 @@ LL | fn foo() { non_const() } | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.rs b/tests/ui/traits/const-traits/const-default-method-bodies.rs index a0333153f85..0ef11a7f0c9 100644 --- a/tests/ui/traits/const-traits/const-default-method-bodies.rs +++ b/tests/ui/traits/const-traits/const-default-method-bodies.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait ConstDefaultFn: Sized { diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.stderr b/tests/ui/traits/const-traits/const-default-method-bodies.stderr index 071eaf49541..5879330f158 100644 --- a/tests/ui/traits/const-traits/const-default-method-bodies.stderr +++ b/tests/ui/traits/const-traits/const-default-method-bodies.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied - --> $DIR/const-default-method-bodies.rs:26:5 + --> $DIR/const-default-method-bodies.rs:25:5 | LL | NonConstImpl.a(); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.rs b/tests/ui/traits/const-traits/const-drop-fail-2.rs index 7b57e0405af..5d7bafa3887 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.rs +++ b/tests/ui/traits/const-traits/const-drop-fail-2.rs @@ -20,7 +20,7 @@ impl A for NonTrivialDrop {} const fn check<T: ~const Destruct>(_: T) {} -/* FIXME(effects) +/* FIXME(const_trait_impl) struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stderr index 102dbb1a599..fde106599c2 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stderr @@ -21,33 +21,21 @@ LL | const fn check<T: ~const Destruct>(_: T) {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop-fail-2.rs:20:36 - | -LL | const fn check<T: ~const Destruct>(_: T) {} - | ^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions - error[E0277]: the trait bound `T: ~const A` is not satisfied --> $DIR/const-drop-fail-2.rs:41:9 | LL | T::a(); | ^^^^^^ -error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions - --> $DIR/const-drop-fail-2.rs:41:9 - | -LL | T::a(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/const-drop-fail-2.rs:20:36 | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0015, E0277, E0493. -For more information about an error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0277, E0493. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-drop.precise.stderr b/tests/ui/traits/const-traits/const-drop.precise.stderr index 7471b200c33..ed90b234761 100644 --- a/tests/ui/traits/const-traits/const-drop.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop.precise.stderr @@ -84,19 +84,7 @@ error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied LL | T::foo(); | ^^^^^^^^ -error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions - --> $DIR/const-drop.rs:69:13 - | -LL | T::foo(); - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0015, E0277, E0493. -For more information about an error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0277, E0493. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-drop.stock.stderr b/tests/ui/traits/const-traits/const-drop.stock.stderr index 71378349161..2b46b048e90 100644 --- a/tests/ui/traits/const-traits/const-drop.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop.stock.stderr @@ -86,19 +86,7 @@ error[E0277]: the trait bound `T: ~const SomeTrait` is not satisfied LL | T::foo(); | ^^^^^^^^ -error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions - --> $DIR/const-drop.rs:69:13 - | -LL | T::foo(); - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0015, E0277, E0493. -For more information about an error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0277, E0493. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-fns-are-early-bound.rs b/tests/ui/traits/const-traits/const-fns-are-early-bound.rs index 6d08d8bdd91..c26eaf67454 100644 --- a/tests/ui/traits/const-traits/const-fns-are-early-bound.rs +++ b/tests/ui/traits/const-traits/const-fns-are-early-bound.rs @@ -1,7 +1,7 @@ //@ known-bug: #110395 //@ failure-status: 101 //@ dont-check-compiler-stderr -// FIXME(effects) check-pass +// FIXME(const_trait_impl) check-pass //@ compile-flags: -Znext-solver #![crate_type = "lib"] diff --git a/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs b/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs index e49e9090eb4..6bea664b65f 100644 --- a/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs +++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(const_trait_impl)] pub trait A {} diff --git a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr index 828e2174f00..bcaae381949 100644 --- a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr +++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `A` which is not marked with `#[const_trait]` - --> $DIR/const-impl-requires-const-trait.rs:7:12 + --> $DIR/const-impl-requires-const-trait.rs:6:12 | LL | pub trait A {} | - help: mark `A` as const: `#[const_trait]` diff --git a/tests/ui/traits/const-traits/const-in-closure.rs b/tests/ui/traits/const-traits/const-in-closure.rs index 51b22c53036..ebc17a50c86 100644 --- a/tests/ui/traits/const-traits/const-in-closure.rs +++ b/tests/ui/traits/const-traits/const-in-closure.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Trait { fn method(); diff --git a/tests/ui/traits/const-traits/const-in-closure.stderr b/tests/ui/traits/const-traits/const-in-closure.stderr deleted file mode 100644 index f4b03b9ed20..00000000000 --- a/tests/ui/traits/const-traits/const-in-closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-in-closure.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs index 691bce19dc2..2dac1970835 100644 --- a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs +++ b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs @@ -1,5 +1,5 @@ #![feature(const_trait_impl)] -// FIXME(effects) add effects +// FIXME(const_trait_impl) add effects //@ edition: 2021 #[const_trait] diff --git a/tests/ui/traits/const-traits/const-trait-bounds.rs b/tests/ui/traits/const-traits/const-trait-bounds.rs index 3b4ba6a998f..8722d9909ed 100644 --- a/tests/ui/traits/const-traits/const-trait-bounds.rs +++ b/tests/ui/traits/const-traits/const-trait-bounds.rs @@ -1,7 +1,7 @@ //@ known-bug: #110395 //@ compile-flags: -Znext-solver -// FIXME(effects): check-pass -#![feature(const_trait_impl, effects, generic_const_exprs)] +// FIXME(const_trait_impl): check-pass +#![feature(const_trait_impl, generic_const_exprs)] #![allow(incomplete_features)] fn main() { diff --git a/tests/ui/traits/const-traits/const-trait-bounds.stderr b/tests/ui/traits/const-traits/const-trait-bounds.stderr index 698b1b5b578..29a01b9d7dc 100644 --- a/tests/ui/traits/const-traits/const-trait-bounds.stderr +++ b/tests/ui/traits/const-traits/const-trait-bounds.stderr @@ -1,8 +1,8 @@ error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed - --> $DIR/const-trait-bounds.rs:4:39 + --> $DIR/const-trait-bounds.rs:4:30 | -LL | #![feature(const_trait_impl, effects, generic_const_exprs)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![feature(const_trait_impl, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ | = help: remove one of these features diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr index 3ccae5a83e6..95f6f32f21d 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'derive_const' +error[E0658]: use of unstable library feature `derive_const` --> $DIR/derive-const-gate.rs:1:3 | LL | #[derive_const(Default)] diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs index 5896091f8c4..7bda7117a47 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs @@ -1,5 +1,5 @@ //@ known-bug: #110395 -#![feature(derive_const, effects)] +#![feature(derive_const)] pub struct A; diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr index 8f4235dabad..9492000a563 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/derive-const-non-const-type.rs:2:26 - | -LL | #![feature(derive_const, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `Default` which is not marked with `#[const_trait]` --> $DIR/derive-const-non-const-type.rs:10:16 | @@ -28,6 +19,6 @@ LL | pub struct S(A); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.rs b/tests/ui/traits/const-traits/const_derives/derive-const-use.rs index cb649b1ec79..1e447147213 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-use.rs +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.rs @@ -1,6 +1,6 @@ //@ known-bug: #110395 -#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] +#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] pub struct A; diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr index 7fc44229e2a..6f4fc90f636 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr @@ -1,22 +1,13 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/derive-const-use.rs:3:76 - | -LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0635]: unknown feature `const_cmp` --> $DIR/derive-const-use.rs:3:30 | -LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] +LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] | ^^^^^^^^^ error[E0635]: unknown feature `const_default_impls` --> $DIR/derive-const-use.rs:3:41 | -LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] +LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] | ^^^^^^^^^^^^^^^^^^^ error: const `impl` for trait `Default` which is not marked with `#[const_trait]` @@ -117,7 +108,7 @@ LL | pub struct S((), A); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 12 previous errors; 1 warning emitted +error: aborting due to 12 previous errors Some errors have detailed explanations: E0015, E0635. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs index c032c76d38f..18b224af278 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs +++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs @@ -1,8 +1,8 @@ //@ known-bug: #110395 -// FIXME(effects) check-pass +// FIXME(const_trait_impl) check-pass #![feature(derive_const)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[derive_const(PartialEq)] pub struct Reverse<T>(T); diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr index 1395947bb15..21cf64f89ea 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/derive-const-with-params.rs:5:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/derive-const-with-params.rs:7:16 | @@ -38,6 +29,6 @@ LL | a == b | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/cross-crate-default-method-body-is-const.rs b/tests/ui/traits/const-traits/cross-crate-default-method-body-is-const.rs index 9ee5254dbf8..80b4124a644 100644 --- a/tests/ui/traits/const-traits/cross-crate-default-method-body-is-const.rs +++ b/tests/ui/traits/const-traits/cross-crate-default-method-body-is-const.rs @@ -3,8 +3,7 @@ // //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] //@ aux-build: cross-crate.rs extern crate cross_crate; diff --git a/tests/ui/traits/const-traits/cross-crate.rs b/tests/ui/traits/const-traits/cross-crate.rs index 30d2260a744..9558ec6164e 100644 --- a/tests/ui/traits/const-traits/cross-crate.rs +++ b/tests/ui/traits/const-traits/cross-crate.rs @@ -1,7 +1,7 @@ //@ revisions: stock gated stocknc gatednc //@ [gated] check-pass //@ compile-flags: -Znext-solver -#![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))] +#![cfg_attr(any(gated, gatednc), feature(const_trait_impl))] #![allow(incomplete_features)] //@ aux-build: cross-crate.rs diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr index 308a60c08d3..0534f3eb8d2 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr @@ -3,12 +3,6 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied | LL | foo::<()>(); | ^^^^^^^^^^^ - | -note: required by a bound in `foo` - --> $DIR/default-method-body-is-const-body-checking.rs:7:28 - | -LL | const fn foo<T>() where T: ~const Tr {} - | ^^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs index 0c2d93775a4..b3beba08237 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs +++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] pub trait Tr { diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr index 7b4d512e391..d987cad6f14 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied - --> $DIR/default-method-body-is-const-same-trait-ck.rs:10:9 + --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:9 | LL | ().a() | ^^^^^^ diff --git a/tests/ui/traits/const-traits/do-not-const-check-override.rs b/tests/ui/traits/const-traits/do-not-const-check-override.rs index 71e6375283f..2b8e1d38ac9 100644 --- a/tests/ui/traits/const-traits/do-not-const-check-override.rs +++ b/tests/ui/traits/const-traits/do-not-const-check-override.rs @@ -1,7 +1,7 @@ //@ check-pass //@ compile-flags: -Znext-solver #![allow(incomplete_features)] -#![feature(const_trait_impl, rustc_attrs, effects)] +#![feature(const_trait_impl, rustc_attrs)] #[const_trait] trait Foo { diff --git a/tests/ui/traits/const-traits/do-not-const-check.rs b/tests/ui/traits/const-traits/do-not-const-check.rs index d227a9a9c09..443b6385735 100644 --- a/tests/ui/traits/const-traits/do-not-const-check.rs +++ b/tests/ui/traits/const-traits/do-not-const-check.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(const_trait_impl, rustc_attrs, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl, rustc_attrs)] #[const_trait] trait IntoIter { diff --git a/tests/ui/traits/const-traits/do-not-const-check.stderr b/tests/ui/traits/const-traits/do-not-const-check.stderr deleted file mode 100644 index 0d81ef74e8d..00000000000 --- a/tests/ui/traits/const-traits/do-not-const-check.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/do-not-const-check.rs:2:43 - | -LL | #![feature(const_trait_impl, rustc_attrs, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/dont-observe-host-opaque.rs b/tests/ui/traits/const-traits/dont-observe-host-opaque.rs index 4a5ae346e39..751ba1cb8c7 100644 --- a/tests/ui/traits/const-traits/dont-observe-host-opaque.rs +++ b/tests/ui/traits/const-traits/dont-observe-host-opaque.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] const fn opaque() -> impl Sized {} diff --git a/tests/ui/traits/const-traits/dont-observe-host-opaque.stderr b/tests/ui/traits/const-traits/dont-observe-host-opaque.stderr deleted file mode 100644 index 1b457ab7643..00000000000 --- a/tests/ui/traits/const-traits/dont-observe-host-opaque.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/dont-observe-host-opaque.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/dont-observe-host.rs b/tests/ui/traits/const-traits/dont-observe-host.rs index d027d578c42..06050385f91 100644 --- a/tests/ui/traits/const-traits/dont-observe-host.rs +++ b/tests/ui/traits/const-traits/dont-observe-host.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Trait { diff --git a/tests/ui/traits/const-traits/dont-observe-host.stderr b/tests/ui/traits/const-traits/dont-observe-host.stderr deleted file mode 100644 index 64ef611f011..00000000000 --- a/tests/ui/traits/const-traits/dont-observe-host.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/dont-observe-host.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/effects/auxiliary/cross-crate.rs b/tests/ui/traits/const-traits/effects/auxiliary/cross-crate.rs index 779527e22d4..e02bf6a4d2c 100644 --- a/tests/ui/traits/const-traits/effects/auxiliary/cross-crate.rs +++ b/tests/ui/traits/const-traits/effects/auxiliary/cross-crate.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] pub const fn foo() {} diff --git a/tests/ui/traits/const-traits/effects/minicore.rs b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs index 1f0d22eeb38..209a111c243 100644 --- a/tests/ui/traits/const-traits/effects/minicore.rs +++ b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs @@ -1,28 +1,34 @@ -//@ known-bug: #110395 -//@ failure-status: 101 -//@ normalize-stderr-test: ".*note: .*\n\n" -> "" -//@ normalize-stderr-test: "thread 'rustc' panicked.*:\n.*\n" -> "" -//@ rustc-env:RUST_BACKTRACE=0 -// FIXME(effects) check-pass -//@ compile-flags: -Znext-solver - -#![crate_type = "lib"] -#![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs, staged_api)] -#![feature(fundamental, marker_trait_attr)] -#![feature(const_trait_impl, effects)] +//@ compile-flags: -Znext-solver -Cpanic=abort +//@ no-prefer-dynamic + +#![crate_type = "rlib"] +#![feature( + no_core, + lang_items, + unboxed_closures, + auto_traits, + intrinsics, + rustc_attrs, + fundamental, + marker_trait_attr, + const_trait_impl +)] #![allow(internal_features, incomplete_features)] #![no_std] #![no_core] -#![stable(feature = "minicore", since = "1.0.0")] #[lang = "sized"] -trait Sized {} +pub trait Sized {} #[lang = "copy"] -trait Copy {} +pub trait Copy {} + +impl Copy for bool {} +impl Copy for u8 {} +impl<T: ?Sized> Copy for &T {} #[lang = "add"] #[const_trait] -trait Add<Rhs = Self> { +pub trait Add<Rhs = Self> { type Output; fn add(self, rhs: Rhs) -> Self::Output; @@ -43,10 +49,9 @@ const fn bar() { let x = 42_i32 + 43_i32; } - #[lang = "Try"] #[const_trait] -trait Try: FromResidual<Self::Residual> { +pub trait Try: FromResidual<Self::Residual> { type Output; type Residual; @@ -57,9 +62,8 @@ trait Try: FromResidual<Self::Residual> { fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; } -// FIXME -// #[const_trait] -trait FromResidual<R = <Self as /* FIXME: ~const */ Try>::Residual> { +#[const_trait] +pub trait FromResidual<R = <Self as Try>::Residual> { #[lang = "from_residual"] fn from_residual(residual: R) -> Self; } @@ -74,71 +78,32 @@ enum ControlFlow<B, C = ()> { #[const_trait] #[lang = "fn"] #[rustc_paren_sugar] -trait Fn<Args: Tuple>: ~const FnMut<Args> { +pub trait Fn<Args: Tuple>: ~const FnMut<Args> { extern "rust-call" fn call(&self, args: Args) -> Self::Output; } #[const_trait] #[lang = "fn_mut"] #[rustc_paren_sugar] -trait FnMut<Args: Tuple>: ~const FnOnce<Args> { +pub trait FnMut<Args: Tuple>: ~const FnOnce<Args> { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } #[const_trait] #[lang = "fn_once"] #[rustc_paren_sugar] -trait FnOnce<Args: Tuple> { +pub trait FnOnce<Args: Tuple> { #[lang = "fn_once_output"] type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } -struct ConstFnMutClosure<CapturedData, Function> { - data: CapturedData, - func: Function, -} - #[lang = "tuple_trait"] -trait Tuple {} - -macro_rules! impl_fn_mut_tuple { - ($($var:ident)*) => { - impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const - FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue, - Function: ~const Destruct, - { - type Output = ClosureReturnValue; - - extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { - self.call_mut(args) - } - } - impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const - FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, - Function: ~const Destruct, - { - extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { - #[allow(non_snake_case)] - let ($($var),*) = &mut self.data; - (self.func)(($($var),*), args) - } - } - }; -} -//impl_fn_mut_tuple!(A); -//impl_fn_mut_tuple!(A B); -//impl_fn_mut_tuple!(A B C); -//impl_fn_mut_tuple!(A B C D); -//impl_fn_mut_tuple!(A B C D E); +pub trait Tuple {} #[lang = "legacy_receiver"] -trait LegacyReceiver {} +pub trait LegacyReceiver {} impl<T: ?Sized> LegacyReceiver for &T {} @@ -146,30 +111,26 @@ impl<T: ?Sized> LegacyReceiver for &mut T {} #[lang = "destruct"] #[const_trait] -trait Destruct {} +pub trait Destruct {} #[lang = "freeze"] -unsafe auto trait Freeze {} +pub unsafe auto trait Freeze {} #[lang = "drop"] #[const_trait] -trait Drop { +pub trait Drop { fn drop(&mut self); } -/* #[const_trait] -trait Residual<O> { +pub trait Residual<O> { type TryType: ~const Try<Output = O, Residual = Self> + Try<Output = O, Residual = Self>; } -*/ const fn size_of<T>() -> usize { 42 } -impl Copy for u8 {} - impl usize { #[rustc_allow_incoherent_impl] const fn repeat_u8(x: u8) -> usize { @@ -190,15 +151,14 @@ fn panic_fmt() {} #[lang = "index"] #[const_trait] -trait Index<Idx: ?Sized> { +pub trait Index<Idx: ?Sized> { type Output: ?Sized; fn index(&self, index: Idx) -> &Self::Output; } - #[const_trait] -unsafe trait SliceIndex<T: ?Sized> { +pub unsafe trait SliceIndex<T: ?Sized> { type Output: ?Sized; fn index(self, slice: &T) -> &Self::Output; } @@ -214,7 +174,7 @@ where index.index(self) } } -/* FIXME + impl<T, I, const N: usize> const Index<I> for [T; N] where [T]: ~const Index<I>, @@ -222,35 +182,29 @@ where type Output = <[T] as Index<I>>::Output; #[inline] - // FIXME: make `Self::Output` act like `<Self as ~const Index<I>>::Output` fn index(&self, index: I) -> &<[T] as Index<I>>::Output { Index::index(self as &[T], index) } } -*/ #[lang = "unsize"] -trait Unsize<T: ?Sized> { -} +pub trait Unsize<T: ?Sized> {} #[lang = "coerce_unsized"] -trait CoerceUnsized<T: ?Sized> { -} +pub trait CoerceUnsized<T: ?Sized> {} impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} - #[lang = "deref"] -// #[const_trait] FIXME -trait Deref { +#[const_trait] +pub trait Deref { #[lang = "deref_target"] type Target: ?Sized; fn deref(&self) -> &Self::Target; } - -impl<T: ?Sized> /* const */ Deref for &T { +impl<T: ?Sized> const Deref for &T { type Target = T; fn deref(&self) -> &T { @@ -258,7 +212,7 @@ impl<T: ?Sized> /* const */ Deref for &T { } } -impl<T: ?Sized> /* const */ Deref for &mut T { +impl<T: ?Sized> const Deref for &mut T { type Target = T; fn deref(&self) -> &T { @@ -291,7 +245,6 @@ impl<T> Option<T> { use Option::*; -/* const fn as_deref<T>(opt: &Option<T>) -> Option<&T::Target> where T: ~const Deref, @@ -301,15 +254,14 @@ where Option::None => Option::None, } } -*/ #[const_trait] -trait Into<T>: Sized { +pub trait Into<T>: Sized { fn into(self) -> T; } #[const_trait] -trait From<T>: Sized { +pub trait From<T>: Sized { fn from(value: T) -> Self; } @@ -344,7 +296,7 @@ fn from_str(s: &str) -> Result<bool, ()> { #[lang = "eq"] #[const_trait] -trait PartialEq<Rhs: ?Sized = Self> { +pub trait PartialEq<Rhs: ?Sized = Self> { fn eq(&self, other: &Rhs) -> bool; fn ne(&self, other: &Rhs) -> bool { !self.eq(other) @@ -366,10 +318,9 @@ impl PartialEq for str { } } - #[lang = "not"] #[const_trait] -trait Not { +pub trait Not { type Output; fn not(self) -> Self::Output; } @@ -381,9 +332,6 @@ impl const Not for bool { } } -impl Copy for bool {} -impl<'a> Copy for &'a str {} - #[lang = "pin"] #[fundamental] #[repr(transparent)] @@ -404,23 +352,21 @@ impl<'a, T: ?Sized> Pin<&'a T> { } } - impl<P: Deref> Pin<P> { - /* const */ fn as_ref(&self) -> Pin<&P::Target> + const fn as_ref(&self) -> Pin<&P::Target> where - P: /* ~const */ Deref, + P: ~const Deref, { unsafe { Pin::new_unchecked(&*self.pointer) } } } - impl<'a, T: ?Sized> Pin<&'a mut T> { const unsafe fn get_unchecked_mut(self) -> &'a mut T { self.pointer } } -/* FIXME lol + impl<T> Option<T> { const fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> { match Pin::get_ref(self).as_ref() { @@ -438,16 +384,15 @@ impl<T> Option<T> { } } } -*/ -impl<P: /* ~const */ Deref> /* const */ Deref for Pin<P> { +impl<P: ~const Deref> const Deref for Pin<P> { type Target = P::Target; fn deref(&self) -> &P::Target { Pin::get_ref(Pin::as_ref(self)) } } -impl<T> /* const */ Deref for Option<T> { +impl<T> const Deref for Option<T> { type Target = T; fn deref(&self) -> &T { loop {} @@ -499,23 +444,22 @@ impl<T: ?Sized> Deref for Ref<'_, T> { #[lang = "clone"] #[rustc_trivial_field_reads] -#[const_trait] -trait Clone: Sized { +// FIXME: #[const_trait] +pub trait Clone: Sized { fn clone(&self) -> Self; fn clone_from(&mut self, source: &Self) where - Self: ~const Destruct, + // FIXME: Self: ~const Destruct, { *self = source.clone() } } #[lang = "structural_peq"] -trait StructuralPartialEq {} +pub trait StructuralPartialEq {} -const fn drop<T: ~const Destruct>(_: T) {} +// FIXME: const fn drop<T: ~const Destruct>(_: T) {} -#[rustc_const_stable_indirect] #[rustc_intrinsic_must_be_overridden] #[rustc_intrinsic] const fn const_eval_select<ARG: Tuple, F, G, RET>( @@ -529,10 +473,3 @@ where { loop {} } - -fn test_const_eval_select() { - const fn const_fn() {} - fn rt_fn() {} - - const_eval_select((), const_fn, rt_fn); -} diff --git a/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs index 8f8e9f06584..877249135cd 100644 --- a/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs +++ b/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(const_closures, const_trait_impl, effects)] +#![feature(const_closures, const_trait_impl)] #![allow(incomplete_features)] trait Foo { @@ -13,5 +13,5 @@ impl Foo for () { fn main() { (const || { (()).foo() })(); //~^ ERROR: cannot call non-const fn `<() as Foo>::foo` in constant functions - // FIXME(effects) this should probably say constant closures + // FIXME(const_trait_impl) this should probably say constant closures } diff --git a/tests/ui/traits/const-traits/effects/effect-param-infer.rs b/tests/ui/traits/const-traits/effects/effect-param-infer.rs index 958b9ac6d57..fcacf458a9f 100644 --- a/tests/ui/traits/const-traits/effects/effect-param-infer.rs +++ b/tests/ui/traits/const-traits/effects/effect-param-infer.rs @@ -3,8 +3,7 @@ // //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] pub trait Foo<Rhs: ?Sized = Self> { diff --git a/tests/ui/traits/const-traits/effects/fallback.rs b/tests/ui/traits/const-traits/effects/fallback.rs index 4cfba00526b..253d16f3251 100644 --- a/tests/ui/traits/const-traits/effects/fallback.rs +++ b/tests/ui/traits/const-traits/effects/fallback.rs @@ -1,7 +1,5 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(effects)] pub const fn owo() {} diff --git a/tests/ui/traits/const-traits/effects/helloworld.rs b/tests/ui/traits/const-traits/effects/helloworld.rs deleted file mode 100644 index 54f362b4413..00000000000 --- a/tests/ui/traits/const-traits/effects/helloworld.rs +++ /dev/null @@ -1,33 +0,0 @@ -//@ check-pass -//@ compile-flags: -Znext-solver -// gate-test-effects -// ^ effects doesn't have a gate so we will trick tidy into thinking this is a gate test -#![allow(incomplete_features)] -#![feature( - const_trait_impl, - effects, - core_intrinsics, - const_eval_select -)] - -// ensure we are passing in the correct host effect in always const contexts. - -pub const fn hmm<T>() -> usize { - // FIXME(const_trait_impl): maybe we should have a way to refer to the (hidden) effect param - fn one() -> usize { 1 } - const fn zero() -> usize { 0 } - unsafe { - std::intrinsics::const_eval_select((), zero, one) - } -} - -const _: () = { - let x = hmm::<()>(); - assert!(0 == x); -}; - -pub const fn uwu(x: [u8; hmm::<()>()]) { - let [] = x; -} - -fn main() {} diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs index ab530b109e1..c467088ab3d 100644 --- a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs +++ b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] const fn test() -> impl ~const Fn() { //~^ ERROR `~const` can only be applied to `#[const_trait]` traits diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr index 36184856035..6d7edaf19f2 100644 --- a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr +++ b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr @@ -8,15 +8,6 @@ LL | const move || { = help: add `#![feature(const_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/ice-112822-expected-type-for-param.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/ice-112822-expected-type-for-param.rs:3:25 | @@ -49,7 +40,7 @@ LL | assert_eq!(first, &b'f'); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/effects/ice-113375-index-out-of-bounds-generics.rs b/tests/ui/traits/const-traits/effects/ice-113375-index-out-of-bounds-generics.rs index 06e3377c5ee..f3cbaf847a9 100644 --- a/tests/ui/traits/const-traits/effects/ice-113375-index-out-of-bounds-generics.rs +++ b/tests/ui/traits/const-traits/effects/ice-113375-index-out-of-bounds-generics.rs @@ -3,7 +3,7 @@ // effects ice https://github.com/rust-lang/rust/issues/113375 index out of bounds #![allow(incomplete_features, unused)] -#![feature(effects, adt_const_params)] +#![feature(adt_const_params)] struct Bar<T>(T); diff --git a/tests/ui/traits/const-traits/effects/infer-fallback.rs b/tests/ui/traits/const-traits/effects/infer-fallback.rs index 581c3949d38..a7342d72a9c 100644 --- a/tests/ui/traits/const-traits/effects/infer-fallback.rs +++ b/tests/ui/traits/const-traits/effects/infer-fallback.rs @@ -1,7 +1,6 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] const fn a() {} diff --git a/tests/ui/traits/const-traits/effects/minicore-deref-fail.rs b/tests/ui/traits/const-traits/effects/minicore-deref-fail.rs new file mode 100644 index 00000000000..f4a7678a009 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore-deref-fail.rs @@ -0,0 +1,20 @@ +//@ aux-build:minicore.rs +//@ compile-flags: --crate-type=lib -Znext-solver -Cpanic=abort + +#![feature(no_core, const_trait_impl)] +#![no_std] +#![no_core] + +extern crate minicore; +use minicore::*; + +struct Ty; +impl Deref for Ty { + type Target = (); + fn deref(&self) -> &Self::Target { &() } +} + +const fn foo() { + *Ty; + //~^ ERROR the trait bound `Ty: ~const minicore::Deref` is not satisfied +} diff --git a/tests/ui/traits/const-traits/effects/minicore-deref-fail.stderr b/tests/ui/traits/const-traits/effects/minicore-deref-fail.stderr new file mode 100644 index 00000000000..a1f840114fc --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore-deref-fail.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `Ty: ~const minicore::Deref` is not satisfied + --> $DIR/minicore-deref-fail.rs:18:5 + | +LL | *Ty; + | ^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/effects/minicore-works.rs b/tests/ui/traits/const-traits/effects/minicore-works.rs new file mode 100644 index 00000000000..bfbfa8b2d05 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore-works.rs @@ -0,0 +1,22 @@ +//@ aux-build:minicore.rs +//@ compile-flags: --crate-type=lib -Znext-solver -Cpanic=abort +//@ check-pass + +#![feature(no_core)] +#![no_std] +#![no_core] +#![feature(const_trait_impl)] + +extern crate minicore; +use minicore::*; + +struct Custom; +impl const Add for Custom { + type Output = (); + fn add(self, _other: Self) {} +} + +const fn test_op() { + let _x = Add::add(1, 2); + let _y = Custom + Custom; +} diff --git a/tests/ui/traits/const-traits/effects/minicore.stderr b/tests/ui/traits/const-traits/effects/minicore.stderr deleted file mode 100644 index 568d98cfe87..00000000000 --- a/tests/ui/traits/const-traits/effects/minicore.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [typeck] type-checking `Clone::clone_from` -#1 [analysis] running analysis passes on this crate -end of query stack - -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [typeck] type-checking `test_const_eval_select` -#1 [analysis] running analysis passes on this crate -end of query stack diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr index eea6a06c1c8..d1180dbd80e 100644 --- a/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr @@ -7,7 +7,7 @@ LL | foo::<false>(); | expected 0 generic arguments | note: function defined here, with 0 generic parameters - --> $DIR/auxiliary/cross-crate.rs:5:14 + --> $DIR/auxiliary/cross-crate.rs:4:14 | LL | pub const fn foo() {} | ^^^ @@ -21,7 +21,7 @@ LL | <() as Bar<false>>::bar(); | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/auxiliary/cross-crate.rs:8:11 + --> $DIR/auxiliary/cross-crate.rs:7:11 | LL | pub trait Bar { | ^^^ @@ -35,7 +35,7 @@ LL | foo::<true>(); | expected 0 generic arguments | note: function defined here, with 0 generic parameters - --> $DIR/auxiliary/cross-crate.rs:5:14 + --> $DIR/auxiliary/cross-crate.rs:4:14 | LL | pub const fn foo() {} | ^^^ @@ -49,7 +49,7 @@ LL | <() as Bar<true>>::bar(); | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/auxiliary/cross-crate.rs:8:11 + --> $DIR/auxiliary/cross-crate.rs:7:11 | LL | pub trait Bar { | ^^^ diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs b/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs index c6b94fa2230..76663292223 100644 --- a/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] const fn foo() {} diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr index bd9acc7a6d2..0b8e4696c46 100644 --- a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/no-explicit-const-params.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/no-explicit-const-params.rs:22:5 | @@ -69,7 +60,7 @@ note: trait defined here, with 0 generic parameters LL | trait Bar { | ^^^ -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors Some errors have detailed explanations: E0107, E0277. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/const-traits/effects/project.rs b/tests/ui/traits/const-traits/effects/project.rs index 9f6ca1f294f..139299753e5 100644 --- a/tests/ui/traits/const-traits/effects/project.rs +++ b/tests/ui/traits/const-traits/effects/project.rs @@ -1,7 +1,6 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(const_trait_impl)] #[const_trait] pub trait Owo<X = <Self as Uwu>::T> {} diff --git a/tests/ui/traits/const-traits/effects/span-bug-issue-121418.rs b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.rs index e6e41c472bd..50a7e12f2a7 100644 --- a/tests/ui/traits/const-traits/effects/span-bug-issue-121418.rs +++ b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.rs @@ -1,5 +1,4 @@ #![feature(const_trait_impl)] -#![feature(effects)] //~ WARN the feature `effects` is incomplete struct S; trait T {} diff --git a/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr index 97663232fcf..fe1e5e558b2 100644 --- a/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr +++ b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr @@ -1,5 +1,5 @@ error: inherent impls cannot be `const` - --> $DIR/span-bug-issue-121418.rs:7:12 + --> $DIR/span-bug-issue-121418.rs:6:12 | LL | impl const dyn T { | ----- ^^^^^ inherent impl for this type @@ -8,17 +8,8 @@ LL | impl const dyn T { | = note: only trait implementations may be annotated with `const` -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/span-bug-issue-121418.rs:2:12 - | -LL | #![feature(effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0308]: mismatched types - --> $DIR/span-bug-issue-121418.rs:9:27 + --> $DIR/span-bug-issue-121418.rs:8:27 | LL | pub const fn new() -> std::sync::Mutex<dyn T> {} | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `Mutex<dyn T>`, found `()` @@ -29,7 +20,7 @@ LL | pub const fn new() -> std::sync::Mutex<dyn T> {} found unit type `()` error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at compilation time - --> $DIR/span-bug-issue-121418.rs:9:27 + --> $DIR/span-bug-issue-121418.rs:8:27 | LL | pub const fn new() -> std::sync::Mutex<dyn T> {} | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -39,7 +30,7 @@ note: required because it appears within the type `Mutex<(dyn T + 'static)>` --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL = note: the return type of a function must have a statically known size -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs index d29cd93d3fb..c85b1746967 100644 --- a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs +++ b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs @@ -1,6 +1,5 @@ // Fixes #119830 -#![feature(effects)] //~ WARN the feature `effects` is incomplete #![feature(min_specialization)] #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr index 273f9943212..5659102c5e5 100644 --- a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr +++ b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/spec-effectvar-ice.rs:3:12 - | -LL | #![feature(effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` - --> $DIR/spec-effectvar-ice.rs:11:15 + --> $DIR/spec-effectvar-ice.rs:10:15 | LL | trait Foo {} | - help: mark `Foo` as const: `#[const_trait]` @@ -20,7 +11,7 @@ LL | impl<T> const Foo for T {} = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` - --> $DIR/spec-effectvar-ice.rs:14:15 + --> $DIR/spec-effectvar-ice.rs:13:15 | LL | trait Foo {} | - help: mark `Foo` as const: `#[const_trait]` @@ -32,28 +23,28 @@ LL | impl<T> const Foo for T where T: const Specialize {} = note: adding a non-const method body in the future would be a breaking change error: `const` can only be applied to `#[const_trait]` traits - --> $DIR/spec-effectvar-ice.rs:14:34 + --> $DIR/spec-effectvar-ice.rs:13:34 | LL | impl<T> const Foo for T where T: const Specialize {} | ^^^^^ error: specialization impl does not specialize any associated items - --> $DIR/spec-effectvar-ice.rs:14:1 + --> $DIR/spec-effectvar-ice.rs:13:1 | LL | impl<T> const Foo for T where T: const Specialize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: impl is a specialization of this impl - --> $DIR/spec-effectvar-ice.rs:11:1 + --> $DIR/spec-effectvar-ice.rs:10:1 | LL | impl<T> const Foo for T {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: cannot specialize on trait `Specialize` - --> $DIR/spec-effectvar-ice.rs:14:34 + --> $DIR/spec-effectvar-ice.rs:13:34 | LL | impl<T> const Foo for T where T: const Specialize {} | ^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors diff --git a/tests/ui/traits/const-traits/effects/trait-fn-const.rs b/tests/ui/traits/const-traits/effects/trait-fn-const.rs index d63dbfbf57d..07eac032a82 100644 --- a/tests/ui/traits/const-traits/effects/trait-fn-const.rs +++ b/tests/ui/traits/const-traits/effects/trait-fn-const.rs @@ -1,5 +1,5 @@ // Regression test for issue #113378. -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Trait { diff --git a/tests/ui/traits/const-traits/effects/trait-fn-const.stderr b/tests/ui/traits/const-traits/effects/trait-fn-const.stderr index 33914cb306d..4d0b03046d2 100644 --- a/tests/ui/traits/const-traits/effects/trait-fn-const.stderr +++ b/tests/ui/traits/const-traits/effects/trait-fn-const.stderr @@ -54,15 +54,6 @@ LL + #[const_trait] LL | trait NonConst { | -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-fn-const.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/traits/const-traits/fn-ptr-lub.rs b/tests/ui/traits/const-traits/fn-ptr-lub.rs index 0fc32678827..8f1a29e612c 100644 --- a/tests/ui/traits/const-traits/fn-ptr-lub.rs +++ b/tests/ui/traits/const-traits/fn-ptr-lub.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] const fn foo() {} const fn bar() {} diff --git a/tests/ui/traits/const-traits/fn-ptr-lub.stderr b/tests/ui/traits/const-traits/fn-ptr-lub.stderr deleted file mode 100644 index b333311b660..00000000000 --- a/tests/ui/traits/const-traits/fn-ptr-lub.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/fn-ptr-lub.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/hir-const-check.rs b/tests/ui/traits/const-traits/hir-const-check.rs index 0ffd60682b0..ea1783b7c2c 100644 --- a/tests/ui/traits/const-traits/hir-const-check.rs +++ b/tests/ui/traits/const-traits/hir-const-check.rs @@ -2,7 +2,7 @@ // Regression test for #69615. -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] pub trait MyTrait { diff --git a/tests/ui/traits/const-traits/hir-const-check.stderr b/tests/ui/traits/const-traits/hir-const-check.stderr index a22ac2c9739..ef5dba0dc0e 100644 --- a/tests/ui/traits/const-traits/hir-const-check.stderr +++ b/tests/ui/traits/const-traits/hir-const-check.stderr @@ -1,12 +1,3 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/hir-const-check.rs:5:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0658]: `?` is not allowed in a `const fn` --> $DIR/hir-const-check.rs:14:9 | @@ -37,7 +28,7 @@ note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs index c2f452a9925..dc1e719bded 100644 --- a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs +++ b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs @@ -1,5 +1,5 @@ #![allow(incomplete_features)] -#![feature(const_trait_impl, effects, try_trait_v2)] +#![feature(const_trait_impl, try_trait_v2)] use std::ops::FromResidual; diff --git a/tests/ui/traits/const-traits/ice-120503-async-const-method.rs b/tests/ui/traits/const-traits/ice-120503-async-const-method.rs index 9cd18d4566d..4c337a42a68 100644 --- a/tests/ui/traits/const-traits/ice-120503-async-const-method.rs +++ b/tests/ui/traits/const-traits/ice-120503-async-const-method.rs @@ -1,5 +1,4 @@ //@ edition: 2021 -#![feature(effects)] //~ WARN the feature `effects` is incomplete trait MyTrait {} diff --git a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr index 1a11aec4b26..66862d97bf9 100644 --- a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr +++ b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr @@ -1,5 +1,5 @@ error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const` - --> $DIR/ice-120503-async-const-method.rs:7:11 + --> $DIR/ice-120503-async-const-method.rs:6:11 | LL | async const fn bar(&self) { | ------^^^^^ @@ -10,7 +10,7 @@ LL | async const fn bar(&self) { = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` error[E0379]: functions in trait impls cannot be declared const - --> $DIR/ice-120503-async-const-method.rs:7:11 + --> $DIR/ice-120503-async-const-method.rs:6:11 | LL | async const fn bar(&self) { | ^^^^^- @@ -19,7 +19,7 @@ LL | async const fn bar(&self) { | help: remove the `const` error: functions cannot be both `const` and `async` - --> $DIR/ice-120503-async-const-method.rs:7:5 + --> $DIR/ice-120503-async-const-method.rs:6:5 | LL | async const fn bar(&self) { | -^^^^ ^^^^^ `const` because of this @@ -35,7 +35,7 @@ LL | | } | |_____- error[E0407]: method `bar` is not a member of trait `MyTrait` - --> $DIR/ice-120503-async-const-method.rs:7:5 + --> $DIR/ice-120503-async-const-method.rs:6:5 | LL | / async const fn bar(&self) { LL | | @@ -46,17 +46,8 @@ LL | | LL | | } | |_____^ not a member of trait `MyTrait` -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/ice-120503-async-const-method.rs:2:12 - | -LL | #![feature(effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0425]: cannot find function `main8` in this scope - --> $DIR/ice-120503-async-const-method.rs:12:9 + --> $DIR/ice-120503-async-const-method.rs:11:9 | LL | main8().await; | ^^^^^ help: a function with a similar name exists: `main` @@ -64,7 +55,7 @@ LL | main8().await; LL | fn main() {} | --------- similarly named function `main` defined here -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors Some errors have detailed explanations: E0379, E0407, E0425. For more information about an error, try `rustc --explain E0379`. diff --git a/tests/ui/traits/const-traits/ice-121536-const-method.rs b/tests/ui/traits/const-traits/ice-121536-const-method.rs index a01329278d7..b89786bfd93 100644 --- a/tests/ui/traits/const-traits/ice-121536-const-method.rs +++ b/tests/ui/traits/const-traits/ice-121536-const-method.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] pub struct Vec3; diff --git a/tests/ui/traits/const-traits/ice-121536-const-method.stderr b/tests/ui/traits/const-traits/ice-121536-const-method.stderr index 4fe88f263c8..408958abf63 100644 --- a/tests/ui/traits/const-traits/ice-121536-const-method.stderr +++ b/tests/ui/traits/const-traits/ice-121536-const-method.stderr @@ -14,15 +14,6 @@ help: ... and declare the impl to be const instead LL | impl const Add for Vec3 { | +++++ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/ice-121536-const-method.rs:1:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs index 29f40604747..fadcaa39816 100644 --- a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs +++ b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs @@ -1,5 +1,5 @@ #![allow(incomplete_features)] -#![feature(generic_const_exprs, const_trait_impl, effects)] +#![feature(generic_const_exprs, const_trait_impl)] const fn with_positive<F: ~const Fn()>() {} //~^ ERROR `~const` can only be applied to `#[const_trait]` traits diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs index d4fcbfb1b83..d6df1714314 100644 --- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs @@ -1,7 +1,6 @@ //@ compile-flags: -Znext-solver=coherence -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Foo {} diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr index 0b1f8b40898..183c2c2cdf4 100644 --- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Foo` for type `i32` - --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:11:1 + --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:10:1 | LL | impl const Foo for i32 {} | ---------------------- first implementation here diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs index da97a0e70ed..9ce81031b27 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs @@ -1,5 +1,5 @@ #![allow(incomplete_features)] -#![feature(const_trait_impl, effects, try_trait_v2, const_try)] +#![feature(const_trait_impl, try_trait_v2, const_try)] use std::ops::{FromResidual, Try}; struct TryMe; diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs b/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs index 49741ca24c7..6df9696f2cb 100644 --- a/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs +++ b/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs @@ -1,5 +1,4 @@ -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Tr { diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr b/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr index 0135296526f..36c8163f1c5 100644 --- a/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr +++ b/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `req` - --> $DIR/impl-with-default-fn-fail.rs:13:1 + --> $DIR/impl-with-default-fn-fail.rs:12:1 | LL | fn req(&self); | -------------- `req` from trait diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs b/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs index 2c375036941..c776a29716f 100644 --- a/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs +++ b/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs @@ -1,7 +1,6 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Tr { diff --git a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs index 8638c4bbd7f..86cb38e0bcf 100644 --- a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs +++ b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs @@ -8,8 +8,7 @@ //@ compile-flags: -Znext-solver -Zinline-mir=yes -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] trait Trait { fn foo(self); diff --git a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr index 096b00dd302..c4547f4c43d 100644 --- a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr +++ b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:11:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters - --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:20:12 + --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:19:12 | LL | fn foo(self); | - expected 0 type parameters @@ -17,14 +8,14 @@ LL | fn foo<T>(self) { | ^ found 1 type parameter error[E0015]: cannot call non-const fn `<() as Trait>::foo` in constant functions - --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:27:8 + --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:26:8 | LL | ().foo(); | ^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors Some errors have detailed explanations: E0015, E0049. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/issue-100222.rs b/tests/ui/traits/const-traits/issue-100222.rs index 13c469d656c..55722d35075 100644 --- a/tests/ui/traits/const-traits/issue-100222.rs +++ b/tests/ui/traits/const-traits/issue-100222.rs @@ -3,7 +3,7 @@ //@ check-pass #![allow(incomplete_features)] -#![feature(const_trait_impl, effects, associated_type_defaults)] +#![feature(const_trait_impl, associated_type_defaults)] #[cfg_attr(any(yn, yy), const_trait)] pub trait Index { diff --git a/tests/ui/traits/const-traits/issue-79450.rs b/tests/ui/traits/const-traits/issue-79450.rs index cdefebc87d6..521576d27ef 100644 --- a/tests/ui/traits/const-traits/issue-79450.rs +++ b/tests/ui/traits/const-traits/issue-79450.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Tr { diff --git a/tests/ui/traits/const-traits/issue-79450.stderr b/tests/ui/traits/const-traits/issue-79450.stderr index 49f380c1a2b..85996c21211 100644 --- a/tests/ui/traits/const-traits/issue-79450.stderr +++ b/tests/ui/traits/const-traits/issue-79450.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `_print` in constant functions - --> $DIR/issue-79450.rs:10:9 + --> $DIR/issue-79450.rs:9:9 | LL | println!("lul"); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs b/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs index e666355db6f..a3edc5ff8b1 100644 --- a/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs +++ b/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs @@ -3,8 +3,7 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(const_trait_impl)] #[const_trait] pub trait Super {} diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.rs b/tests/ui/traits/const-traits/item-bound-entailment-fails.rs index 42799e3700c..f4bfcbda0ac 100644 --- a/tests/ui/traits/const-traits/item-bound-entailment-fails.rs +++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Foo { type Assoc<T>: ~const Bar diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr index 054a8ac7577..3fc6f584709 100644 --- a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr +++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr @@ -1,36 +1,27 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/item-bound-entailment-fails.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the trait bound `N<T>: ~const Bar` is not satisfied - --> $DIR/item-bound-entailment-fails.rs:18:21 + --> $DIR/item-bound-entailment-fails.rs:17:21 | LL | type Assoc<T> = N<T> | ^^^^ | note: required by a bound in `Foo::Assoc` - --> $DIR/item-bound-entailment-fails.rs:6:20 + --> $DIR/item-bound-entailment-fails.rs:5:20 | LL | type Assoc<T>: ~const Bar | ^^^^^^ required by this bound in `Foo::Assoc` error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/item-bound-entailment-fails.rs:25:21 + --> $DIR/item-bound-entailment-fails.rs:24:21 | LL | type Assoc<T> = C<T> | ^^^^ | note: required by a bound in `Foo::Assoc` - --> $DIR/item-bound-entailment-fails.rs:6:20 + --> $DIR/item-bound-entailment-fails.rs:5:20 | LL | type Assoc<T>: ~const Bar | ^^^^^^ required by this bound in `Foo::Assoc` -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/item-bound-entailment.rs b/tests/ui/traits/const-traits/item-bound-entailment.rs index 3670eabd66c..11db57be815 100644 --- a/tests/ui/traits/const-traits/item-bound-entailment.rs +++ b/tests/ui/traits/const-traits/item-bound-entailment.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Foo { type Assoc<T>: ~const Bar diff --git a/tests/ui/traits/const-traits/item-bound-entailment.stderr b/tests/ui/traits/const-traits/item-bound-entailment.stderr deleted file mode 100644 index b4a4ebdbee2..00000000000 --- a/tests/ui/traits/const-traits/item-bound-entailment.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/item-bound-entailment.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/predicate-entailment-fails.rs b/tests/ui/traits/const-traits/predicate-entailment-fails.rs index 5d6109bfad3..266a49f9e38 100644 --- a/tests/ui/traits/const-traits/predicate-entailment-fails.rs +++ b/tests/ui/traits/const-traits/predicate-entailment-fails.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Bar {} impl const Bar for () {} diff --git a/tests/ui/traits/const-traits/predicate-entailment-fails.stderr b/tests/ui/traits/const-traits/predicate-entailment-fails.stderr index c50009e9b8c..369e95688a9 100644 --- a/tests/ui/traits/const-traits/predicate-entailment-fails.stderr +++ b/tests/ui/traits/const-traits/predicate-entailment-fails.stderr @@ -1,14 +1,5 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/predicate-entailment-fails.rs:2:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0276]: impl has stricter requirements than trait - --> $DIR/predicate-entailment-fails.rs:15:31 + --> $DIR/predicate-entailment-fails.rs:14:31 | LL | type Bar<T> where T: ~const Bar; | ----------- definition of `Bar` from trait @@ -17,7 +8,7 @@ LL | type Bar<T> = () where T: const Bar; | ^^^^^ impl has extra requirement `T: const Bar` error[E0276]: impl has stricter requirements than trait - --> $DIR/predicate-entailment-fails.rs:18:26 + --> $DIR/predicate-entailment-fails.rs:17:26 | LL | fn foo<T>() where T: ~const Bar; | -------------------------------- definition of `foo` from trait @@ -26,7 +17,7 @@ LL | fn foo<T>() where T: const Bar {} | ^^^^^ impl has extra requirement `T: const Bar` error[E0276]: impl has stricter requirements than trait - --> $DIR/predicate-entailment-fails.rs:29:31 + --> $DIR/predicate-entailment-fails.rs:28:31 | LL | type Bar<T> where T: Bar; | ----------- definition of `Bar` from trait @@ -35,7 +26,7 @@ LL | type Bar<T> = () where T: const Bar; | ^^^^^ impl has extra requirement `T: const Bar` error[E0276]: impl has stricter requirements than trait - --> $DIR/predicate-entailment-fails.rs:32:26 + --> $DIR/predicate-entailment-fails.rs:31:26 | LL | fn foo<T>() where T: Bar; | ------------------------- definition of `foo` from trait @@ -44,7 +35,7 @@ LL | fn foo<T>() where T: const Bar {} | ^^^^^ impl has extra requirement `T: const Bar` error[E0276]: impl has stricter requirements than trait - --> $DIR/predicate-entailment-fails.rs:36:31 + --> $DIR/predicate-entailment-fails.rs:35:31 | LL | type Bar<T> where T: Bar; | ----------- definition of `Bar` from trait @@ -53,7 +44,7 @@ LL | type Bar<T> = () where T: ~const Bar; | ^^^^^^ impl has extra requirement `T: ~const Bar` error[E0276]: impl has stricter requirements than trait - --> $DIR/predicate-entailment-fails.rs:39:26 + --> $DIR/predicate-entailment-fails.rs:38:26 | LL | fn foo<T>() where T: Bar; | ------------------------- definition of `foo` from trait @@ -61,6 +52,6 @@ LL | fn foo<T>() where T: Bar; LL | fn foo<T>() where T: ~const Bar {} | ^^^^^^ impl has extra requirement `T: ~const Bar` -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/traits/const-traits/predicate-entailment-passes.rs b/tests/ui/traits/const-traits/predicate-entailment-passes.rs index b660329151b..9c8d5a5e3f6 100644 --- a/tests/ui/traits/const-traits/predicate-entailment-passes.rs +++ b/tests/ui/traits/const-traits/predicate-entailment-passes.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(const_trait_impl, effects)] -//~^ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #[const_trait] trait Bar {} impl const Bar for () {} diff --git a/tests/ui/traits/const-traits/predicate-entailment-passes.stderr b/tests/ui/traits/const-traits/predicate-entailment-passes.stderr deleted file mode 100644 index dcaeea73b58..00000000000 --- a/tests/ui/traits/const-traits/predicate-entailment-passes.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/predicate-entailment-passes.rs:4:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs index 69dcb403aa9..5af9ee8614f 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs +++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs @@ -1,7 +1,7 @@ // Tests that trait bounds on specializing trait impls must be `~const` if the // same bound is present on the default impl and is `~const` there. //@ known-bug: #110395 -// FIXME(effects) ^ should error +// FIXME(const_trait_impl) ^ should error #![feature(const_trait_impl)] #![feature(rustc_attrs)] diff --git a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs index a48a50b9e5c..89ad61c3c31 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs +++ b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs @@ -1,8 +1,7 @@ // Tests that a const default trait impl can be specialized by another const // trait impl and that the specializing impl will be used during const-eval. -//@ known-bug: #110395 -// FIXME(effects) run-pass +//@ run-pass #![feature(const_trait_impl)] #![feature(min_specialization)] diff --git a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr deleted file mode 100644 index f127268d2a1..00000000000 --- a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions - --> $DIR/const-default-const-specialized.rs:16:5 - | -LL | T::value() - | ^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs index 40fc3b17ae4..a3bb9b3f93e 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs @@ -1,6 +1,6 @@ // Tests that specializing trait impls must be at least as const as the default impl. -#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl)] #![feature(min_specialization)] #[const_trait] diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr index 363fbee1f8b..e356621ba47 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr @@ -1,17 +1,8 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-default-impl-non-const-specialized-impl.rs:3:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: cannot specialize on const impl with non-const impl --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1 | LL | impl Value for FortyTwo { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs index 912b35095f9..e9b494bc2c0 100644 --- a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs +++ b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs @@ -1,7 +1,7 @@ // Tests that a non-const default impl can be specialized by a const trait impl, // but that the default impl cannot be used in a const context. -//@ known-bug: #110395 -// FIXME(effects) run-pass + +//@ run-pass #![feature(const_trait_impl)] #![feature(min_specialization)] diff --git a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr deleted file mode 100644 index a4095d7e8ce..00000000000 --- a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions - --> $DIR/non-const-default-const-specialized.rs:15:5 - | -LL | T::value() - | ^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/specializing-constness-2.stderr b/tests/ui/traits/const-traits/specializing-constness-2.stderr index 98a9de2324a..4ad5e3157d4 100644 --- a/tests/ui/traits/const-traits/specializing-constness-2.stderr +++ b/tests/ui/traits/const-traits/specializing-constness-2.stderr @@ -4,19 +4,6 @@ error[E0277]: the trait bound `T: ~const A` is not satisfied LL | <T as A>::a(); | ^^^^^^^^^^^^^ -error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions - --> $DIR/specializing-constness-2.rs:27:5 - | -LL | <T as A>::a(); - | ^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0015, E0277. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/specializing-constness.rs b/tests/ui/traits/const-traits/specializing-constness.rs index 3aabaf137d5..632121924a6 100644 --- a/tests/ui/traits/const-traits/specializing-constness.rs +++ b/tests/ui/traits/const-traits/specializing-constness.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] //~ WARN the feature `effects` is incomplete +#![feature(const_trait_impl, min_specialization, rustc_attrs)] #[rustc_specialization_trait] #[const_trait] @@ -22,7 +22,7 @@ impl<T: ~const Spec> const A for T { impl<T: Spec + Sup> A for T { //~^ ERROR: cannot specialize -//FIXME(effects) ~| ERROR: missing `~const` qualifier +//FIXME(const_trait_impl) ~| ERROR: missing `~const` qualifier fn a() -> u32 { 3 } diff --git a/tests/ui/traits/const-traits/specializing-constness.stderr b/tests/ui/traits/const-traits/specializing-constness.stderr index 226295bf949..21e21c2cb71 100644 --- a/tests/ui/traits/const-traits/specializing-constness.stderr +++ b/tests/ui/traits/const-traits/specializing-constness.stderr @@ -1,17 +1,8 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specializing-constness.rs:1:30 - | -LL | #![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - error: cannot specialize on const impl with non-const impl --> $DIR/specializing-constness.rs:23:1 | LL | impl<T: Spec + Sup> A for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/staged-api.rs b/tests/ui/traits/const-traits/staged-api.rs index 59fe6d52d5d..401a81d8142 100644 --- a/tests/ui/traits/const-traits/staged-api.rs +++ b/tests/ui/traits/const-traits/staged-api.rs @@ -3,8 +3,7 @@ #![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. #![cfg_attr(unstable, feature(local_feature))] -#![feature(const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(const_trait_impl)] #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/tests/ui/traits/const-traits/staged-api.stable.stderr b/tests/ui/traits/const-traits/staged-api.stable.stderr index 40045081f93..8f491b2f182 100644 --- a/tests/ui/traits/const-traits/staged-api.stable.stderr +++ b/tests/ui/traits/const-traits/staged-api.stable.stderr @@ -1,5 +1,5 @@ error: trait implementations cannot be const stable yet - --> $DIR/staged-api.rs:22:1 + --> $DIR/staged-api.rs:21:1 | LL | / impl const MyTrait for Foo { LL | | @@ -10,7 +10,7 @@ LL | | } = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information error: function has missing const stability attribute - --> $DIR/staged-api.rs:49:1 + --> $DIR/staged-api.rs:48:1 | LL | / pub const fn const_context_not_const_stable() { LL | | @@ -22,7 +22,7 @@ LL | | } | |_^ error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:35:5 + --> $DIR/staged-api.rs:34:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | Unstable::func(); = help: add `#![feature(unstable)]` to the crate attributes to enable error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable - --> $DIR/staged-api.rs:38:5 + --> $DIR/staged-api.rs:37:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | Foo::func(); = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:42:5 + --> $DIR/staged-api.rs:41:5 | LL | Unstable2::func(); | ^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL | Unstable2::func(); = help: add `#![feature(unstable2)]` to the crate attributes to enable error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:51:5 + --> $DIR/staged-api.rs:50:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | Unstable::func(); = help: add `#![feature(unstable)]` to the crate attributes to enable error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable - --> $DIR/staged-api.rs:53:5 + --> $DIR/staged-api.rs:52:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | Foo::func(); = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:56:5 + --> $DIR/staged-api.rs:55:5 | LL | Unstable2::func(); | ^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | Unstable2::func(); = help: add `#![feature(unstable2)]` to the crate attributes to enable error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:64:5 + --> $DIR/staged-api.rs:63:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | Unstable::func(); = help: add `#![feature(unstable)]` to the crate attributes to enable error: `<Foo as staged_api::MyTrait>::func` cannot be (indirectly) exposed to stable - --> $DIR/staged-api.rs:67:5 + --> $DIR/staged-api.rs:66:5 | LL | Foo::func(); | ^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/staged-api.unstable.stderr b/tests/ui/traits/const-traits/staged-api.unstable.stderr index 64b3a8ab19f..76275452e90 100644 --- a/tests/ui/traits/const-traits/staged-api.unstable.stderr +++ b/tests/ui/traits/const-traits/staged-api.unstable.stderr @@ -1,5 +1,5 @@ error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]` - --> $DIR/staged-api.rs:35:5 + --> $DIR/staged-api.rs:34:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | const fn const_context() { | error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]` - --> $DIR/staged-api.rs:38:5 + --> $DIR/staged-api.rs:37:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | const fn const_context() { | error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:42:5 + --> $DIR/staged-api.rs:41:5 | LL | Unstable2::func(); | ^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | Unstable2::func(); = help: add `#![feature(unstable2)]` to the crate attributes to enable error: `<staged_api::Unstable2 as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:56:5 + --> $DIR/staged-api.rs:55:5 | LL | Unstable2::func(); | ^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | Unstable2::func(); = help: add `#![feature(unstable2)]` to the crate attributes to enable error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]` - --> $DIR/staged-api.rs:64:5 + --> $DIR/staged-api.rs:63:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | const fn stable_const_context() { | error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]` - --> $DIR/staged-api.rs:67:5 + --> $DIR/staged-api.rs:66:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | const fn stable_const_context() { | error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]` - --> $DIR/staged-api.rs:71:5 + --> $DIR/staged-api.rs:70:5 | LL | const_context_not_const_stable() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr index 8de1bb07e90..e7f54b4c5bd 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr @@ -1,23 +1,23 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-2.rs:12:1 + --> $DIR/super-traits-fail-2.rs:11:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -25,7 +25,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -33,7 +33,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/super-traits-fail-2.rs:21:7 + --> $DIR/super-traits-fail-2.rs:20:7 | LL | x.a(); | ^^^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr index 82b306aeff6..a09fe81f716 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr @@ -1,11 +1,11 @@ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -13,7 +13,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -21,7 +21,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -29,7 +29,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -37,7 +37,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/super-traits-fail-2.rs:21:7 + --> $DIR/super-traits-fail-2.rs:20:7 | LL | x.a(); | ^^^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.rs b/tests/ui/traits/const-traits/super-traits-fail-2.rs index 1e41d709d6b..53a84bcdd1b 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-2.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] //@ revisions: yy yn ny nn #[cfg_attr(any(yy, yn), const_trait)] diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr index ec6ca107289..01ae209016a 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr @@ -1,17 +1,17 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-2.rs:12:12 + --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-2.rs:12:1 + --> $DIR/super-traits-fail-2.rs:11:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:21:5 + --> $DIR/super-traits-fail-2.rs:20:5 | LL | x.a(); | ^^^^^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr index 3fa6256abc3..ae4c65e4aee 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:21:5 + --> $DIR/super-traits-fail-2.rs:20:5 | LL | x.a(); | ^^^^^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr index 1dd4a2ed5a5..599b8c826f7 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr @@ -1,23 +1,23 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-3.rs:14:1 + --> $DIR/super-traits-fail-3.rs:13:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -25,7 +25,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -33,13 +33,13 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:22:17 + --> $DIR/super-traits-fail-3.rs:21:17 | LL | const fn foo<T: ~const Bar>(x: &T) { | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:22:17 + --> $DIR/super-traits-fail-3.rs:21:17 | LL | const fn foo<T: ~const Bar>(x: &T) { | ^^^^^^ @@ -47,7 +47,7 @@ LL | const fn foo<T: ~const Bar>(x: &T) { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/super-traits-fail-3.rs:25:7 + --> $DIR/super-traits-fail-3.rs:24:7 | LL | x.a(); | ^^^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr index e619b8bd6ba..a880c2a2206 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr @@ -1,11 +1,11 @@ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -13,7 +13,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -21,7 +21,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -29,7 +29,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ @@ -37,7 +37,7 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/super-traits-fail-3.rs:25:7 + --> $DIR/super-traits-fail-3.rs:24:7 | LL | x.a(); | ^^^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.rs b/tests/ui/traits/const-traits/super-traits-fail-3.rs index 414337956e2..bd95ae8d96a 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-3.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] //@ revisions: yy yn ny nn //@[yy] check-pass diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr index 0a36d40d931..8fcada1bfd1 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr @@ -1,23 +1,23 @@ error: `~const` is not allowed here - --> $DIR/super-traits-fail-3.rs:14:12 + --> $DIR/super-traits-fail-3.rs:13:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ | note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds - --> $DIR/super-traits-fail-3.rs:14:1 + --> $DIR/super-traits-fail-3.rs:13:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:22:17 + --> $DIR/super-traits-fail-3.rs:21:17 | LL | const fn foo<T: ~const Bar>(x: &T) { | ^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:22:17 + --> $DIR/super-traits-fail-3.rs:21:17 | LL | const fn foo<T: ~const Bar>(x: &T) { | ^^^^^^ @@ -25,7 +25,7 @@ LL | const fn foo<T: ~const Bar>(x: &T) { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-3.rs:25:5 + --> $DIR/super-traits-fail-3.rs:24:5 | LL | x.a(); | ^^^^^ diff --git a/tests/ui/traits/const-traits/super-traits-fail.rs b/tests/ui/traits/const-traits/super-traits-fail.rs index c07619fbf62..9fd6263118b 100644 --- a/tests/ui/traits/const-traits/super-traits-fail.rs +++ b/tests/ui/traits/const-traits/super-traits-fail.rs @@ -1,7 +1,6 @@ //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Foo { diff --git a/tests/ui/traits/const-traits/super-traits-fail.stderr b/tests/ui/traits/const-traits/super-traits-fail.stderr index 7a734a6c9f1..1f453edf035 100644 --- a/tests/ui/traits/const-traits/super-traits-fail.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `S: ~const Foo` is not satisfied - --> $DIR/super-traits-fail.rs:18:20 + --> $DIR/super-traits-fail.rs:17:20 | LL | impl const Bar for S {} | ^ diff --git a/tests/ui/traits/const-traits/super-traits.rs b/tests/ui/traits/const-traits/super-traits.rs index ff7349bba3c..73ddc037cd7 100644 --- a/tests/ui/traits/const-traits/super-traits.rs +++ b/tests/ui/traits/const-traits/super-traits.rs @@ -1,7 +1,6 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Foo { diff --git a/tests/ui/traits/const-traits/tilde-const-and-const-params.rs b/tests/ui/traits/const-traits/tilde-const-and-const-params.rs index b316ac75a8a..706c77b6200 100644 --- a/tests/ui/traits/const-traits/tilde-const-and-const-params.rs +++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #![feature(generic_arg_infer)] #![feature(generic_const_exprs)] #![allow(incomplete_features)] diff --git a/tests/ui/traits/const-traits/tilde-const-assoc-fn-in-trait-impl.rs b/tests/ui/traits/const-traits/tilde-const-assoc-fn-in-trait-impl.rs index 8e7202ecaa1..73b2bdc4e3f 100644 --- a/tests/ui/traits/const-traits/tilde-const-assoc-fn-in-trait-impl.rs +++ b/tests/ui/traits/const-traits/tilde-const-assoc-fn-in-trait-impl.rs @@ -1,8 +1,7 @@ // Regression test for issue #119700. //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Main { diff --git a/tests/ui/traits/const-traits/tilde-const-in-struct-args.rs b/tests/ui/traits/const-traits/tilde-const-in-struct-args.rs index 4722be955e9..e7ec3d31eb9 100644 --- a/tests/ui/traits/const-traits/tilde-const-in-struct-args.rs +++ b/tests/ui/traits/const-traits/tilde-const-in-struct-args.rs @@ -2,7 +2,7 @@ //@ known-bug: #132067 //@ check-pass -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] struct S; #[const_trait] diff --git a/tests/ui/traits/const-traits/tilde-const-in-struct-args.stderr b/tests/ui/traits/const-traits/tilde-const-in-struct-args.stderr deleted file mode 100644 index a9759f10d06..00000000000 --- a/tests/ui/traits/const-traits/tilde-const-in-struct-args.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/tilde-const-in-struct-args.rs:5:30 - | -LL | #![feature(const_trait_impl, effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/traits/const-traits/tilde-const-inherent-assoc-const-fn.rs b/tests/ui/traits/const-traits/tilde-const-inherent-assoc-const-fn.rs index 71c5d8366b2..0e010695587 100644 --- a/tests/ui/traits/const-traits/tilde-const-inherent-assoc-const-fn.rs +++ b/tests/ui/traits/const-traits/tilde-const-inherent-assoc-const-fn.rs @@ -1,7 +1,6 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Foo { diff --git a/tests/ui/traits/const-traits/tilde-const-trait-assoc-tys.rs b/tests/ui/traits/const-traits/tilde-const-trait-assoc-tys.rs index 254cf2200d8..53ddb5c0cdf 100644 --- a/tests/ui/traits/const-traits/tilde-const-trait-assoc-tys.rs +++ b/tests/ui/traits/const-traits/tilde-const-trait-assoc-tys.rs @@ -1,12 +1,9 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Trait { - // FIXME(effects): `~const` bounds in trait associated types (excluding associated type bounds) - // don't look super useful. Should we forbid them again? type Assoc<T: ~const Bound>; } diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.rs b/tests/ui/traits/const-traits/trait-default-body-stability.rs index b36e9535ca1..5f7486eb176 100644 --- a/tests/ui/traits/const-traits/trait-default-body-stability.rs +++ b/tests/ui/traits/const-traits/trait-default-body-stability.rs @@ -2,7 +2,7 @@ //@ compile-flags: -Znext-solver #![allow(incomplete_features)] #![feature(staged_api)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #![feature(const_t_try)] #![feature(const_try)] #![feature(try_trait_v2)] diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.rs b/tests/ui/traits/const-traits/trait-where-clause-const.rs index 61e2bc38426..6f281ca5718 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.rs +++ b/tests/ui/traits/const-traits/trait-where-clause-const.rs @@ -4,8 +4,7 @@ // (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a // test is not enough. -#![feature(const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(const_trait_impl)] #[const_trait] trait Bar {} diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr index 30a7ef1fd0d..d7735ef282f 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:22:5 + --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); | ^^^^^^ error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:24:5 + --> $DIR/trait-where-clause-const.rs:23:5 | LL | T::c::<T>(); | ^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/trait-where-clause-run.rs b/tests/ui/traits/const-traits/trait-where-clause-run.rs index 2837c835429..2582a69acab 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-run.rs +++ b/tests/ui/traits/const-traits/trait-where-clause-run.rs @@ -1,8 +1,7 @@ //@ run-pass //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects)] -#![allow(incomplete_features)] +#![feature(const_trait_impl)] #[const_trait] trait Bar { diff --git a/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs b/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs index cb5cc924bfd..b6ac574a4fc 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs +++ b/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs @@ -1,7 +1,6 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![allow(incomplete_features)] -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait Foo { diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs index d336719f52e..6d19ef771af 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs @@ -2,7 +2,7 @@ // Ensure that we print unsatisfied always-const trait bounds as `const Trait` in diagnostics. //@ compile-flags: -Znext-solver -#![feature(const_trait_impl, effects, generic_const_exprs)] +#![feature(const_trait_impl, generic_const_exprs)] #![allow(incomplete_features)] fn require<T: const Trait>() {} @@ -24,10 +24,10 @@ fn main() { struct Container<const N: u32>; -// FIXME(effects): Somehow emit `the trait bound `T: const Trait` is not satisfied` here instead -// and suggest changing `Trait` to `const Trait`. +// FIXME(const_trait_impl): Somehow emit `the trait bound `T: const Trait` +// is not satisfied` here instead and suggest changing `Trait` to `const Trait`. fn accept0<T: Trait>(_: Container<{ T::make() }>) {} -// FIXME(effects): Instead of suggesting `+ const Trait`, suggest +// FIXME(const_trait_impl): Instead of suggesting `+ const Trait`, suggest // changing `~const Trait` to `const Trait`. const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index 35f3019b6ee..d04143fc464 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -1,8 +1,8 @@ error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed - --> $DIR/unsatisfied-const-trait-bound.rs:5:39 + --> $DIR/unsatisfied-const-trait-bound.rs:5:30 | -LL | #![feature(const_trait_impl, effects, generic_const_exprs)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![feature(const_trait_impl, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ | = help: remove one of these features diff --git a/tests/ui/traits/ice-index-out-of-bounds-issue-117446.rs b/tests/ui/traits/ice-index-out-of-bounds-issue-117446.rs new file mode 100644 index 00000000000..fa31d8b820c --- /dev/null +++ b/tests/ui/traits/ice-index-out-of-bounds-issue-117446.rs @@ -0,0 +1,24 @@ +//@ check-fail +// +// Regression for https://github.com/rust-lang/rust/issues/117446 + +pub struct Repeated<T>(Vec<T>); + +trait Foo<'a> { + fn outer<D>() -> Option<()>; +} + +impl<'a, T> Foo<'a> for Repeated<T> { + fn outer() -> Option<()> { + //~^ ERROR associated function `outer` has 0 type parameters but its trait declaration has 1 type parameter [E0049] + //~^^ ERROR mismatched types [E0308] + fn inner<Q>(value: Option<()>) -> Repeated<Q> { + match value { + _ => Self(unimplemented!()), + //~^ ERROR can't reference `Self` constructor from outer item [E0401] + } + } + } +} + +fn main() {} diff --git a/tests/ui/traits/ice-index-out-of-bounds-issue-117446.stderr b/tests/ui/traits/ice-index-out-of-bounds-issue-117446.stderr new file mode 100644 index 00000000000..ad33a70ed3b --- /dev/null +++ b/tests/ui/traits/ice-index-out-of-bounds-issue-117446.stderr @@ -0,0 +1,33 @@ +error[E0049]: associated function `outer` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/ice-index-out-of-bounds-issue-117446.rs:12:13 + | +LL | fn outer<D>() -> Option<()>; + | - expected 1 type parameter +... +LL | fn outer() -> Option<()> { + | ^ found 0 type parameters + +error[E0308]: mismatched types + --> $DIR/ice-index-out-of-bounds-issue-117446.rs:12:19 + | +LL | fn outer() -> Option<()> { + | ----- ^^^^^^^^^^ expected `Option<()>`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected enum `Option<()>` + found unit type `()` + +error[E0401]: can't reference `Self` constructor from outer item + --> $DIR/ice-index-out-of-bounds-issue-117446.rs:17:22 + | +LL | impl<'a, T> Foo<'a> for Repeated<T> { + | ----------------------------------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference +... +LL | _ => Self(unimplemented!()), + | ^^^^ help: replace `Self` with the actual type: `Repeated` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0049, E0308, E0401. +For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs index b97835bbc57..82b13cc0b62 100644 --- a/tests/ui/traits/issue-78372.rs +++ b/tests/ui/traits/issue-78372.rs @@ -1,8 +1,8 @@ -use std::ops::DispatchFromDyn; //~ ERROR use of unstable library feature 'dispatch_from_dyn' +use std::ops::DispatchFromDyn; //~ ERROR use of unstable library feature `dispatch_from_dyn` struct Smaht<T, MISC>(PhantomData); //~ ERROR cannot find type `PhantomData` in this scope impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U` in this scope //~^ ERROR cannot find type `MISC` in this scope -//~| ERROR use of unstable library feature 'dispatch_from_dyn' +//~| ERROR use of unstable library feature `dispatch_from_dyn` //~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures trait Foo: X<u32> {} trait X<T> { diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 9b93ffe8efb..4cc2c59fd8d 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -37,7 +37,7 @@ help: you might be missing a type parameter LL | impl<T, MISC> DispatchFromDyn<Smaht<U, MISC>> for T {} | ++++++ -error[E0658]: use of unstable library feature 'dispatch_from_dyn' +error[E0658]: use of unstable library feature `dispatch_from_dyn` --> $DIR/issue-78372.rs:1:5 | LL | use std::ops::DispatchFromDyn; @@ -46,7 +46,7 @@ LL | use std::ops::DispatchFromDyn; = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'dispatch_from_dyn' +error[E0658]: use of unstable library feature `dispatch_from_dyn` --> $DIR/issue-78372.rs:3:9 | LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} diff --git a/tests/ui/traits/next-solver/canonical/effect-var.rs b/tests/ui/traits/next-solver/canonical/effect-var.rs index d1e3e18cdc8..82dbde0413c 100644 --- a/tests/ui/traits/next-solver/canonical/effect-var.rs +++ b/tests/ui/traits/next-solver/canonical/effect-var.rs @@ -1,7 +1,6 @@ //@ compile-flags: -Znext-solver //@ check-pass -#![feature(effects)] //~ WARN the feature `effects` is incomplete #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/traits/next-solver/canonical/effect-var.stderr b/tests/ui/traits/next-solver/canonical/effect-var.stderr deleted file mode 100644 index 994228c51e5..00000000000 --- a/tests/ui/traits/next-solver/canonical/effect-var.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/effect-var.rs:4:12 - | -LL | #![feature(effects)] - | ^^^^^^^ - | - = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs index 07133aa5614..7fe2324698e 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs @@ -3,7 +3,7 @@ #![crate_type = "lib"] use std::mem::TransmuteFrom; -//~^ ERROR use of unstable library feature 'transmutability' [E0658] +//~^ ERROR use of unstable library feature `transmutability` [E0658] use std::mem::Assume; -//~^ ERROR use of unstable library feature 'transmutability' [E0658] +//~^ ERROR use of unstable library feature `transmutability` [E0658] diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr index a2096cd53e5..e4ad720ff69 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'transmutability' +error[E0658]: use of unstable library feature `transmutability` --> $DIR/feature-missing.rs:5:5 | LL | use std::mem::TransmuteFrom; @@ -8,7 +8,7 @@ LL | use std::mem::TransmuteFrom; = help: add `#![feature(transmutability)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'transmutability' +error[E0658]: use of unstable library feature `transmutability` --> $DIR/feature-missing.rs:8:5 | LL | use std::mem::Assume; diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs index 3c507a9669d..e638f3c6c40 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs @@ -3,12 +3,12 @@ use std::pat::pattern_type; type NonNullU32 = pattern_type!(u32 is 1..); -//~^ use of unstable library feature 'core_pattern_type' +//~^ use of unstable library feature `core_pattern_type` type Percent = pattern_type!(u32 is 0..=100); -//~^ use of unstable library feature 'core_pattern_type' +//~^ use of unstable library feature `core_pattern_type` type Negative = pattern_type!(i32 is ..=0); -//~^ use of unstable library feature 'core_pattern_type' +//~^ use of unstable library feature `core_pattern_type` type Positive = pattern_type!(i32 is 0..); -//~^ use of unstable library feature 'core_pattern_type' +//~^ use of unstable library feature `core_pattern_type` type Always = pattern_type!(Option<u32> is Some(_)); -//~^ use of unstable library feature 'core_pattern_type' +//~^ use of unstable library feature `core_pattern_type` diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr index 03e91b52a2a..6cbadf370a7 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature 'core_pattern_type' +error[E0658]: use of unstable library feature `core_pattern_type` --> $DIR/feature-gate-pattern_types.rs:5:19 | LL | type NonNullU32 = pattern_type!(u32 is 1..); @@ -8,7 +8,7 @@ LL | type NonNullU32 = pattern_type!(u32 is 1..); = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'core_pattern_type' +error[E0658]: use of unstable library feature `core_pattern_type` --> $DIR/feature-gate-pattern_types.rs:7:16 | LL | type Percent = pattern_type!(u32 is 0..=100); @@ -18,7 +18,7 @@ LL | type Percent = pattern_type!(u32 is 0..=100); = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'core_pattern_type' +error[E0658]: use of unstable library feature `core_pattern_type` --> $DIR/feature-gate-pattern_types.rs:9:17 | LL | type Negative = pattern_type!(i32 is ..=0); @@ -28,7 +28,7 @@ LL | type Negative = pattern_type!(i32 is ..=0); = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'core_pattern_type' +error[E0658]: use of unstable library feature `core_pattern_type` --> $DIR/feature-gate-pattern_types.rs:11:17 | LL | type Positive = pattern_type!(i32 is 0..); @@ -38,7 +38,7 @@ LL | type Positive = pattern_type!(i32 is 0..); = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature 'core_pattern_type' +error[E0658]: use of unstable library feature `core_pattern_type` --> $DIR/feature-gate-pattern_types.rs:13:15 | LL | type Always = pattern_type!(Option<u32> is Some(_)); diff --git a/tests/ui/typeck/foreign_struct_trait_unimplemented.stderr b/tests/ui/typeck/foreign_struct_trait_unimplemented.stderr index b9bb97548f6..70de107b1ae 100644 --- a/tests/ui/typeck/foreign_struct_trait_unimplemented.stderr +++ b/tests/ui/typeck/foreign_struct_trait_unimplemented.stderr @@ -6,12 +6,7 @@ LL | needs_test(foreign_struct_trait_unimplemented::B); | | | required by a bound introduced by this call | -help: there are multiple different versions of crate `foreign_struct_trait_unimplemented` in the dependency graph - --> $DIR/foreign_struct_trait_unimplemented.rs:3:1 - | -LL | extern crate foreign_struct_trait_unimplemented; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `foreign_struct_trait_unimplemented` is used here, as a direct dependency of the current crate - = help: you can use `cargo tree` to explore your dependency tree + = help: the trait `Test` is implemented for `A` note: required by a bound in `needs_test` --> $DIR/foreign_struct_trait_unimplemented.rs:10:23 | diff --git a/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr index 96ac481438f..b9bdf6f9a39 100644 --- a/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr +++ b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr @@ -10,6 +10,10 @@ LL | let foo::Foo { visible, .. } = foo::Foo::default(); | ~~~~~~~~~~~~~~~ help: if you don't care about this missing field, you can explicitly ignore it | +LL | let foo::Foo { visible: _, .. } = foo::Foo::default(); + | ~~~~~~~~~~~~~~~~~~ +help: or always ignore missing fields here + | LL | let foo::Foo { .. } = foo::Foo::default(); | ~~~~~~ diff --git a/triagebot.toml b/triagebot.toml index 7f4def6a11b..45b580787d1 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -611,6 +611,10 @@ cc = ["@bjorn3"] [mentions."compiler/rustc_codegen_gcc"] cc = ["@antoyo", "@GuillaumeGomez"] +[mentions."compiler/rustc_const_eval/src/"] +message = "Some changes occurred to the CTFE machinery" +cc = ["@rust-lang/wg-const-eval"] + [mentions."compiler/rustc_const_eval/src/interpret"] message = "Some changes occurred to the CTFE / Miri interpreter" cc = ["@rust-lang/miri"] @@ -633,7 +637,7 @@ cc = ["@compiler-errors", "@lcnr"] [mentions."compiler/rustc_middle/src/mir/interpret"] message = "Some changes occurred to the CTFE / Miri interpreter" -cc = ["@rust-lang/miri"] +cc = ["@rust-lang/miri", "@rust-lang/wg-const-eval"] [mentions."compiler/rustc_mir_transform/src/"] message = "Some changes occurred to MIR optimizations" @@ -706,7 +710,7 @@ message = """ Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter gets adapted for the changes, if necessary. """ -cc = ["@rust-lang/miri"] +cc = ["@rust-lang/miri", "@rust-lang/wg-const-eval"] [mentions."library/portable-simd"] message = """ diff --git a/x b/x index 426b58d0d4e..e656d37c1e4 100755 --- a/x +++ b/x @@ -36,7 +36,7 @@ for SEARCH_PYTHON in py python3 python python2; do fi done -python=$(bash -c "compgen -c python" | grep '^python[2-3]\.[0-9]\+$' | head -n1) +python=$(bash -c "compgen -c python" | grep '^python[2-3]\.[0-9]+$' | head -n1) if ! [ "$python" = "" ]; then exec "$python" "$xpy" "$@" fi |
