diff --git a/bootstrap.example.toml b/bootstrap.example.toml index e0cbb0c0e747c..662bcc5d61e75 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -302,6 +302,11 @@ # If you set this, you likely want to set `cargo` as well. #build.rustc = "/path/to/rustc" +# Use this rustdoc binary as the stage0 snapshot rustdoc. +# If unspecified, then the binary "rustdoc" (with platform-specific extension, e.g. ".exe") +# in the same directory as "rustc" will be used. +#build.rustdoc = "/path/to/rustdoc" + # Instead of downloading the src/stage0 version of rustfmt specified, # use this rustfmt binary instead as the stage0 snapshot rustfmt. #build.rustfmt = "/path/to/rustfmt" diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 738435891f16f..026758958f04f 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -4211,9 +4211,7 @@ impl ForeignItemKind { impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { - ForeignItemKind::Static(box static_foreign_item) => { - ItemKind::Static(Box::new(static_foreign_item)) - } + ForeignItemKind::Static(static_foreign_item) => ItemKind::Static(static_foreign_item), ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), ForeignItemKind::MacCall(a) => ItemKind::MacCall(a), @@ -4226,7 +4224,7 @@ impl TryFrom for ForeignItemKind { fn try_from(item_kind: ItemKind) -> Result { Ok(match item_kind { - ItemKind::Static(box static_item) => ForeignItemKind::Static(Box::new(static_item)), + ItemKind::Static(static_item) => ForeignItemKind::Static(static_item), ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind), ItemKind::MacCall(a) => ForeignItemKind::MacCall(a), diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index acc1c0b9f0de8..388503c720532 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -18,18 +18,18 @@ use rustc_attr_parsing::eval_config_entry; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; +use rustc_errors::DiagCtxtHandle; use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::attrs::NativeLibKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; -use rustc_macros::LintDiagnostic; +use rustc_macros::Diagnostic; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; use rustc_metadata::{ EncodedMetadata, NativeLibSearchFallback, find_native_static_library, walk_native_lib_search_dirs, }; use rustc_middle::bug; -use rustc_middle::lint::lint_level; +use rustc_middle::lint::diag_lint_level; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -662,7 +662,7 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("{$inner}")] /// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just /// end up with inconsistent languages within the same diagnostic. @@ -938,9 +938,7 @@ fn link_natively( let level = codegen_results.crate_info.lint_levels.linker_messages; let lint = |msg| { - lint_level(sess, LINKER_MESSAGES, level, None, |diag| { - LinkerOutput { inner: msg }.decorate_lint(diag) - }) + diag_lint_level(sess, LINKER_MESSAGES, level, None, LinkerOutput { inner: msg }); }; if !prog.stderr.is_empty() { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs index 303183fd924da..dc6841bb89dda 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs @@ -2,7 +2,6 @@ use either::Either; use rustc_abi::{BackendRepr, Endian}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_apfloat::{Float, Round}; -use rustc_data_structures::assert_matches; use rustc_middle::mir::interpret::{InterpErrorKind, Pointer, UndefinedBehaviorInfo}; use rustc_middle::ty::{FloatTy, ScalarInt, SimdAlign}; use rustc_middle::{bug, err_ub_format, mir, span_bug, throw_unsup_format, ty}; @@ -838,7 +837,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { vector_layout: TyAndLayout<'tcx>, alignment: SimdAlign, ) -> InterpResult<'tcx> { - assert_matches!(vector_layout.backend_repr, BackendRepr::SimdVector { .. }); + // Packed SIMD types with non-power-of-two element counts use BackendRepr::Memory + // instead of BackendRepr::SimdVector. We need to handle both cases. + // FIXME: remove the BackendRepr::Memory case when SIMD vectors are always passed as BackendRepr::SimdVector. + assert!(vector_layout.ty.is_simd(), "check_simd_ptr_alignment called on non-SIMD type"); + match vector_layout.backend_repr { + BackendRepr::SimdVector { .. } | BackendRepr::Memory { .. } => {} + _ => { + span_bug!( + self.cur_span(), + "SIMD type has unexpected backend_repr: {:?}", + vector_layout.backend_repr + ); + } + } let align = match alignment { ty::SimdAlign::Unaligned => { diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 583ca36f07130..a2807c852632e 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -109,10 +109,18 @@ impl MultiSpan { MultiSpan { primary_spans: vec, span_labels: vec![] } } + pub fn push_primary_span(&mut self, primary_span: Span) { + self.primary_spans.push(primary_span); + } + pub fn push_span_label(&mut self, span: Span, label: impl Into) { self.span_labels.push((span, label.into())); } + pub fn push_span_diag(&mut self, span: Span, diag: DiagMessage) { + self.span_labels.push((span, diag)); + } + /// Selects the first primary span (if any). pub fn primary_span(&self) -> Option { self.primary_spans.first().cloned() @@ -179,6 +187,11 @@ impl MultiSpan { span_labels } + /// Returns the span labels as contained by `MultiSpan`. + pub fn span_labels_raw(&self) -> &[(Span, DiagMessage)] { + &self.span_labels + } + /// Returns `true` if any of the span labels is displayable. pub fn has_span_labels(&self) -> bool { self.span_labels.iter().any(|(sp, _)| !sp.is_dummy()) diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index f039799c3b7b6..4204855f199d4 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,7 +2,7 @@ use std::cmp; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::{Diag, MultiSpan}; +use rustc_errors::{Diag, Diagnostic, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_lint_defs::EditionFcw; use rustc_macros::{Decodable, Encodable, HashStable}; @@ -482,3 +482,205 @@ pub fn lint_level( } lint_level_impl(sess, lint, level, span, Box::new(decorate)) } + +/// The innermost function for emitting lints implementing the [`trait@Diagnostic`] trait. +/// +/// If you are looking to implement a lint, look for higher level functions, +/// for example: +/// +/// - [`TyCtxt::emit_node_span_lint`] +/// - [`TyCtxt::node_span_lint`] +/// - [`TyCtxt::emit_node_lint`] +/// - [`TyCtxt::node_lint`] +/// - `LintContext::opt_span_lint` +/// +/// This function will replace `lint_level` once all `LintDiagnostic` items have been migrated to +/// `Diagnostic`. +#[track_caller] +pub fn diag_lint_level<'a, D: Diagnostic<'a, ()> + 'a>( + sess: &'a Session, + lint: &'static Lint, + level: LevelAndSource, + span: Option, + decorate: D, +) { + // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to + // the "real" work. + #[track_caller] + fn diag_lint_level_impl<'a>( + sess: &'a Session, + lint: &'static Lint, + level: LevelAndSource, + span: Option, + decorate: Box< + dyn FnOnce(rustc_errors::DiagCtxtHandle<'a>, rustc_errors::Level) -> Diag<'a, ()> + 'a, + >, + ) { + let LevelAndSource { level, lint_id, src } = level; + + // Check for future incompatibility lints and issue a stronger warning. + let future_incompatible = lint.future_incompatible; + + let has_future_breakage = future_incompatible.map_or( + // Default allow lints trigger too often for testing. + sess.opts.unstable_opts.future_incompat_test && lint.default_level != Level::Allow, + |incompat| incompat.report_in_deps, + ); + + // Convert lint level to error level. + let err_level = match level { + Level::Allow => { + if has_future_breakage { + rustc_errors::Level::Allow + } else { + return; + } + } + Level::Expect => { + // This case is special as we actually allow the lint itself in this context, but + // we can't return early like in the case for `Level::Allow` because we still + // need the lint diagnostic to be emitted to `rustc_error::DiagCtxtInner`. + // + // We can also not mark the lint expectation as fulfilled here right away, as it + // can still be cancelled in the decorate function. All of this means that we simply + // create a `Diag` and continue as we would for warnings. + rustc_errors::Level::Expect + } + Level::ForceWarn => rustc_errors::Level::ForceWarning, + Level::Warn => rustc_errors::Level::Warning, + Level::Deny | Level::Forbid => rustc_errors::Level::Error, + }; + // Finally, run `decorate`. `decorate` can call `trimmed_path_str` (directly or indirectly), + // so we need to make sure when we do call `decorate` that the diagnostic is eventually + // emitted or we'll get a `must_produce_diag` ICE. + // + // When is a diagnostic *eventually* emitted? Well, that is determined by 2 factors: + // 1. If the corresponding `rustc_errors::Level` is beyond warning, i.e. `ForceWarning(_)` + // or `Error`, then the diagnostic will be emitted regardless of CLI options. + // 2. If the corresponding `rustc_errors::Level` is warning, then that can be affected by + // `-A warnings` or `--cap-lints=xxx` on the command line. In which case, the diagnostic + // will be emitted if `can_emit_warnings` is true. + let skip = err_level == rustc_errors::Level::Warning && !sess.dcx().can_emit_warnings(); + + let disable_suggestions = if let Some(ref span) = span + // If this code originates in a foreign macro, aka something that this crate + // did not itself author, then it's likely that there's nothing this crate + // can do about it. We probably want to skip the lint entirely. + && span.primary_spans().iter().any(|s| s.in_external_macro(sess.source_map())) + { + true + } else { + false + }; + + let mut err: Diag<'_, ()> = if !skip { + decorate(sess.dcx(), err_level) + } else { + Diag::new(sess.dcx(), err_level, "") + }; + if let Some(span) = span + && err.span.primary_span().is_none() + { + // We can't use `err.span()` because it overwrites the labels, so we need to do it manually. + for primary in span.primary_spans() { + err.span.push_primary_span(*primary); + } + for (label_span, label) in span.span_labels_raw() { + err.span.push_span_diag(*label_span, label.clone()); + } + } + if let Some(lint_id) = lint_id { + err.lint_id(lint_id); + } + + if disable_suggestions { + // Any suggestions made here are likely to be incorrect, so anything we + // emit shouldn't be automatically fixed by rustfix. + err.disable_suggestions(); + + // If this is a future incompatible that is not an edition fixing lint + // it'll become a hard error, so we have to emit *something*. Also, + // if this lint occurs in the expansion of a macro from an external crate, + // allow individual lints to opt-out from being reported. + let incompatible = future_incompatible.is_some_and(|f| f.reason.edition().is_none()); + + if !incompatible && !lint.report_in_external_macro { + err.cancel(); + + // Don't continue further, since we don't want to have + // `diag_span_note_once` called for a diagnostic that isn't emitted. + return; + } + } + + err.is_lint(lint.name_lower(), has_future_breakage); + // Lint diagnostics that are covered by the expect level will not be emitted outside + // the compiler. It is therefore not necessary to add any information for the user. + // This will therefore directly call the decorate function which will in turn emit + // the diagnostic. + if let Level::Expect = level { + err.emit(); + return; + } + + if let Some(future_incompatible) = future_incompatible { + let explanation = match future_incompatible.reason { + FutureIncompatibilityReason::FutureReleaseError(_) => { + "this was previously accepted by the compiler but is being phased out; \ + it will become a hard error in a future release!" + .to_owned() + } + FutureIncompatibilityReason::FutureReleaseSemanticsChange(_) => { + "this will change its meaning in a future release!".to_owned() + } + FutureIncompatibilityReason::EditionError(EditionFcw { edition, .. }) => { + let current_edition = sess.edition(); + format!( + "this is accepted in the current edition (Rust {current_edition}) but is a hard error in Rust {edition}!" + ) + } + FutureIncompatibilityReason::EditionSemanticsChange(EditionFcw { + edition, .. + }) => { + format!("this changes meaning in Rust {edition}") + } + FutureIncompatibilityReason::EditionAndFutureReleaseError(EditionFcw { + edition, + .. + }) => { + format!( + "this was previously accepted by the compiler but is being phased out; \ + it will become a hard error in Rust {edition} and in a future release in all editions!" + ) + } + FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange( + EditionFcw { edition, .. }, + ) => { + format!( + "this changes meaning in Rust {edition} and in a future release in all editions!" + ) + } + FutureIncompatibilityReason::Custom(reason, _) => reason.to_owned(), + FutureIncompatibilityReason::Unreachable => unreachable!(), + }; + + if future_incompatible.explain_reason { + err.warn(explanation); + } + + let citation = + format!("for more information, see {}", future_incompatible.reason.reference()); + err.note(citation); + } + + explain_lint_level_source(sess, lint, level, src, &mut err); + err.emit(); + } + diag_lint_level_impl( + sess, + lint, + level, + span, + Box::new(move |dcx, level| decorate.into_diag(dcx, level)), + ); +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 47843a260440e..39d0f0756cd67 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1331,8 +1331,8 @@ impl<'tcx> TyCtxt<'tcx> { caller: DefId, ) -> Option>> { let fun_features = &self.codegen_fn_attrs(fun_def).target_features; - let callee_features = &self.codegen_fn_attrs(caller).target_features; - if self.is_target_feature_call_safe(&fun_features, &callee_features) { + let caller_features = &self.body_codegen_attrs(caller).target_features; + if self.is_target_feature_call_safe(&fun_features, &caller_features) { return Some(fun_sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Safe, ..sig })); } None diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs index a77724a572dca..1d83799d7dab1 100644 --- a/compiler/rustc_target/src/callconv/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs @@ -5,7 +5,7 @@ use rustc_abi::{Endian, HasDataLayout, TyAbiInterface}; use crate::callconv::{Align, ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::spec::{Env, HasTargetSpec, Os}; +use crate::spec::{Abi, HasTargetSpec, Os}; #[derive(Debug, Clone, Copy, PartialEq)] enum ABI { @@ -106,8 +106,10 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - let abi = if cx.target_spec().env == Env::Musl || cx.target_spec().os == Os::FreeBsd { + let abi = if cx.target_spec().options.abi == Abi::ElfV2 { ELFv2 + } else if cx.target_spec().options.abi == Abi::ElfV1 { + ELFv1 } else if cx.target_spec().os == Os::Aix { AIX } else { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 2d2f15651c431..d9c872c9b4352 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3194,6 +3194,27 @@ impl Target { "ARM targets must set `llvm-floatabi` to `hard` or `soft`", ) } + // PowerPC64 targets that are not AIX must set their ABI to either ELFv1 or ELFv2 + Arch::PowerPC64 => { + if self.os == Os::Aix { + check!( + self.llvm_abiname.is_empty(), + "AIX targets always use the AIX ABI and `llvm_abiname` should be left empty", + ); + } else if self.endian == Endian::Big { + check_matches!( + &*self.llvm_abiname, + "elfv1" | "elfv2", + "invalid PowerPC64 ABI name: {}", + self.llvm_abiname, + ); + } else { + check!( + self.llvm_abiname == "elfv2", + "little-endian PowerPC64 targets only support the `elfv2` ABI", + ); + } + } _ => {} } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 4e37871d28a25..077b8a6cd7f26 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -497,22 +497,19 @@ fn impl_intersection_has_negative_obligation( ) -> bool { debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id); - // N.B. We need to unify impl headers *with* intercrate mode, even if proving negative predicates - // do not need intercrate mode enabled. + // N.B. We need to unify impl headers *with* `TypingMode::Coherence`, + // even if proving negative predicates doesn't need `TypingMode::Coherence`. let ref infcx = tcx.infer_ctxt().with_next_trait_solver(true).build(TypingMode::Coherence); let root_universe = infcx.universe(); assert_eq!(root_universe, ty::UniverseIndex::ROOT); let impl1_header = fresh_impl_header(infcx, impl1_def_id, is_of_trait); - let param_env = - ty::EarlyBinder::bind(tcx.param_env(impl1_def_id)).instantiate(tcx, impl1_header.impl_args); - let impl2_header = fresh_impl_header(infcx, impl2_def_id, is_of_trait); // Equate the headers to find their intersection (the general type, with infer vars, // that may apply both impls). let Some(equate_obligations) = - equate_impl_headers(infcx, param_env, &impl1_header, &impl2_header) + equate_impl_headers(infcx, ty::ParamEnv::empty(), &impl1_header, &impl2_header) else { return false; }; @@ -530,7 +527,16 @@ fn impl_intersection_has_negative_obligation( root_universe, (impl1_header.impl_args, impl2_header.impl_args), ); - let param_env = infcx.resolve_vars_if_possible(param_env); + + // Right above we plug inference variables with placeholders, + // this gets us new impl1_header_args with the inference variables actually resolved + // to those placeholders. + let impl1_header_args = infcx.resolve_vars_if_possible(impl1_header.impl_args); + // So there are no infer variables left now, except regions which aren't resolved by `resolve_vars_if_possible`. + assert!(!impl1_header_args.has_non_region_infer()); + + let param_env = + ty::EarlyBinder::bind(tcx.param_env(impl1_def_id)).instantiate(tcx, impl1_header_args); util::elaborate(tcx, tcx.predicates_of(impl2_def_id).instantiate(tcx, impl2_header.impl_args)) .elaborate_sized() diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index cec41524325e0..f63351ebfd809 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -289,6 +289,7 @@ struct RcInner { } /// Calculate layout for `RcInner` using the inner value's layout +#[inline] fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { // Calculate layout using the given value layout. // Previously, layout was calculated on the expression @@ -2518,15 +2519,25 @@ impl Default for Rc { /// ``` #[inline] fn default() -> Self { + // First create an uninitialized allocation before creating an instance + // of `T`. This avoids having `T` on the stack and avoids the need to + // codegen a call to the destructor for `T` leading to generally better + // codegen. See #131460 for some more details. + let mut rc = Rc::new_uninit(); + + // SAFETY: this is a freshly allocated `Rc` so it's guaranteed there are + // no other strong or weak pointers other than `rc` itself. unsafe { - Self::from_inner( - Box::leak(Box::write( - Box::new_uninit(), - RcInner { strong: Cell::new(1), weak: Cell::new(1), value: T::default() }, - )) - .into(), - ) + let raw = Rc::get_mut_unchecked(&mut rc); + + // Note that `ptr::write` here is used specifically instead of + // `MaybeUninit::write` to avoid creating an extra stack copy of `T` + // in debug mode. See #136043 for more context. + ptr::write(raw.as_mut_ptr(), T::default()); } + + // SAFETY: this allocation was just initialized above. + unsafe { rc.assume_init() } } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index dc82357dd146b..d097588f8e633 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -392,6 +392,7 @@ struct ArcInner { } /// Calculate layout for `ArcInner` using the inner value's layout +#[inline] fn arcinner_layout_for_value_layout(layout: Layout) -> Layout { // Calculate layout using the given value layout. // Previously, layout was calculated on the expression @@ -3724,19 +3725,25 @@ impl Default for Arc { /// assert_eq!(*x, 0); /// ``` fn default() -> Arc { + // First create an uninitialized allocation before creating an instance + // of `T`. This avoids having `T` on the stack and avoids the need to + // codegen a call to the destructor for `T` leading to generally better + // codegen. See #131460 for some more details. + let mut arc = Arc::new_uninit(); + + // SAFETY: this is a freshly allocated `Arc` so it's guaranteed there + // are no other strong or weak pointers other than `arc` itself. unsafe { - Self::from_inner( - Box::leak(Box::write( - Box::new_uninit(), - ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), - data: T::default(), - }, - )) - .into(), - ) + let raw = Arc::get_mut_unchecked(&mut arc); + + // Note that `ptr::write` here is used specifically instead of + // `MaybeUninit::write` to avoid creating an extra stack copy of `T` + // in debug mode. See #136043 for more context. + ptr::write(raw.as_mut_ptr(), T::default()); } + + // SAFETY: this allocation was just initialized above. + unsafe { arc.assume_init() } } } diff --git a/library/core/src/bstr/mod.rs b/library/core/src/bstr/mod.rs index 3e3b78b452e01..4a99e0bdcc037 100644 --- a/library/core/src/bstr/mod.rs +++ b/library/core/src/bstr/mod.rs @@ -172,39 +172,38 @@ impl fmt::Debug for ByteStr { #[unstable(feature = "bstr", issue = "134915")] impl fmt::Display for ByteStr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for chunk in this.utf8_chunks() { - f.write_str(chunk.valid())?; - if !chunk.invalid().is_empty() { - f.write_str("\u{FFFD}")?; - } - } - Ok(()) - } - - let Some(align) = f.align() else { - return fmt_nopad(self, f); - }; let nchars: usize = self .utf8_chunks() .map(|chunk| { chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 } }) .sum(); + let padding = f.width().unwrap_or(0).saturating_sub(nchars); let fill = f.fill(); - let (lpad, rpad) = match align { - fmt::Alignment::Left => (0, padding), - fmt::Alignment::Right => (padding, 0), - fmt::Alignment::Center => { + + let (lpad, rpad) = match f.align() { + Some(fmt::Alignment::Right) => (padding, 0), + Some(fmt::Alignment::Center) => { let half = padding / 2; (half, half + padding % 2) } + // Either alignment is not specified or it's left aligned + // which behaves the same with padding + _ => (0, padding), }; + for _ in 0..lpad { write!(f, "{fill}")?; } - fmt_nopad(self, f)?; + + for chunk in self.utf8_chunks() { + f.write_str(chunk.valid())?; + if !chunk.invalid().is_empty() { + f.write_str("\u{FFFD}")?; + } + } + for _ in 0..rpad { write!(f, "{fill}")?; } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 94396752ac6da..33cf7af28df57 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -17,8 +17,8 @@ macro_rules! uint_impl { fsh_op = $fsh_op:literal, fshl_result = $fshl_result:literal, fshr_result = $fshr_result:literal, - clmul_lhs = $clmul_rhs:literal, - clmul_rhs = $clmul_lhs:literal, + clmul_lhs = $clmul_lhs:literal, + clmul_rhs = $clmul_rhs:literal, clmul_result = $clmul_result:literal, swap_op = $swap_op:literal, swapped = $swapped:literal, diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs index 62d247fafb7ad..6ee06cce5c630 100644 --- a/library/rtstartup/rsbegin.rs +++ b/library/rtstartup/rsbegin.rs @@ -90,12 +90,12 @@ pub mod eh_frames { unsafe extern "C" fn init() { // register unwind info on module startup - __register_frame_info(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8); + __register_frame_info(&__EH_FRAME_BEGIN__ as *const u8, &raw mut OBJ as *mut u8); } unsafe extern "C" fn uninit() { // unregister on shutdown - __deregister_frame_info(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8); + __deregister_frame_info(&__EH_FRAME_BEGIN__ as *const u8, &raw mut OBJ as *mut u8); } // MinGW-specific init/uninit routine registration diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index b32c6cd442ffa..ff3ae8145e0f6 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -573,7 +573,8 @@ impl<'a> ProcThreadAttributeListBuilder<'a> { /// /// # Example /// - /// ``` + #[cfg_attr(target_vendor = "win7", doc = "```no_run")] + #[cfg_attr(not(target_vendor = "win7"), doc = "```")] /// #![feature(windows_process_extensions_raw_attribute)] /// use std::ffi::c_void; /// use std::os::windows::process::{CommandExt, ProcThreadAttributeList}; diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs index 4094b7acd8749..8997b8ad192dc 100644 --- a/library/std/tests/path.rs +++ b/library/std/tests/path.rs @@ -2291,6 +2291,26 @@ fn display_format_flags() { assert_eq!(format!("a{:#<5}b", Path::new("a").display()), "aa####b"); } +#[test] +fn display_path_with_padding_no_align() { + assert_eq!(format!("{:10}", Path::new("/foo/bar").display()), "/foo/bar "); +} + +#[test] +fn display_path_with_padding_align_left() { + assert_eq!(format!("{:<10}", Path::new("/foo/bar").display()), "/foo/bar "); +} + +#[test] +fn display_path_with_padding_align_right() { + assert_eq!(format!("{:>10}", Path::new("/foo/bar").display()), " /foo/bar"); +} + +#[test] +fn display_path_with_padding_align_center() { + assert_eq!(format!("{:^10}", Path::new("/foo/bar").display()), " /foo/bar "); +} + #[test] fn into_rc() { let orig = "hello/world"; diff --git a/src/bootstrap/defaults/bootstrap.dist.toml b/src/bootstrap/defaults/bootstrap.dist.toml index bb0592ce947ab..cce3f068aabcd 100644 --- a/src/bootstrap/defaults/bootstrap.dist.toml +++ b/src/bootstrap/defaults/bootstrap.dist.toml @@ -24,6 +24,8 @@ channel = "auto-detect" download-rustc = false # Build the llvm-bitcode-linker llvm-bitcode-linker = true +# Required to make builds reproducible. +remap-debuginfo = true [dist] # Use better compression when preparing tarballs. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index bc68bfe396425..e975d71c8c70b 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -298,6 +298,7 @@ pub struct Config { // These are either the stage0 downloaded binaries or the locally installed ones. pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, + pub initial_rustdoc: PathBuf, pub initial_cargo_clippy: Option, pub initial_sysroot: PathBuf, pub initial_rustfmt: Option, @@ -456,6 +457,7 @@ impl Config { build_dir: build_build_dir, cargo: mut build_cargo, rustc: mut build_rustc, + rustdoc: build_rustdoc, rustfmt: build_rustfmt, cargo_clippy: build_cargo_clippy, docs: build_docs, @@ -751,6 +753,9 @@ impl Config { default_stage0_rustc_path(&out) }); + let initial_rustdoc = build_rustdoc + .unwrap_or_else(|| initial_rustc.with_file_name(exe("rustdoc", host_target))); + let initial_sysroot = t!(PathBuf::from_str( command(&initial_rustc) .args(["--print", "sysroot"]) @@ -1348,6 +1353,7 @@ impl Config { initial_cargo, initial_cargo_clippy: build_cargo_clippy, initial_rustc, + initial_rustdoc, initial_rustfmt, initial_sysroot, jemalloc: rust_jemalloc.unwrap_or(false), diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs index 192f875587209..27bf753f6914d 100644 --- a/src/bootstrap/src/core/config/toml/build.rs +++ b/src/bootstrap/src/core/config/toml/build.rs @@ -25,6 +25,7 @@ define_config! { build_dir: Option = "build-dir", cargo: Option = "cargo", rustc: Option = "rustc", + rustdoc: Option = "rustdoc", rustfmt: Option = "rustfmt", cargo_clippy: Option = "cargo-clippy", docs: Option = "docs", diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index ec5c6fbe1d01d..b9a914f53cec1 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -535,9 +535,7 @@ impl Build { initial_lld, initial_relative_libdir, initial_rustc: config.initial_rustc.clone(), - initial_rustdoc: config - .initial_rustc - .with_file_name(exe("rustdoc", config.host_target)), + initial_rustdoc: config.initial_rustdoc.clone(), initial_cargo: config.initial_cargo.clone(), initial_sysroot: config.initial_sysroot.clone(), local_rebuild: config.local_rebuild, diff --git a/src/ci/run.sh b/src/ci/run.sh index b486f0525f40d..215292965e65d 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -116,7 +116,6 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then else RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" fi - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo" if [ "$DEPLOY_ALT" != "" ] && isLinux; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level=2" @@ -139,6 +138,8 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-debug-assertions" fi else + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo=false" + # We almost always want debug assertions enabled, but sometimes this takes too # long for too little benefit, so we just turn them off. if [ "$NO_DEBUG_ASSERTIONS" = "" ]; then diff --git a/tests/codegen-llvm/issues/issue-111603.rs b/tests/codegen-llvm/issues/issue-111603.rs index 2ba5a3f876aed..91eb836478eb1 100644 --- a/tests/codegen-llvm/issues/issue-111603.rs +++ b/tests/codegen-llvm/issues/issue-111603.rs @@ -10,9 +10,9 @@ use std::sync::Arc; pub fn new_from_array(x: u64) -> Arc<[u64]> { // Ensure that we only generate one alloca for the array. - // CHECK: alloca + // CHECK: %[[A:.+]] = alloca // CHECK-SAME: [8000 x i8] - // CHECK-NOT: alloca + // CHECK-NOT: %[[B:.+]] = alloca let array = [x; 1000]; Arc::new(array) } @@ -20,8 +20,9 @@ pub fn new_from_array(x: u64) -> Arc<[u64]> { // CHECK-LABEL: @new_uninit #[no_mangle] pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { - // CHECK: call alloc::sync::arcinner_layout_for_value_layout - // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout + // CHECK: %[[A:.+]] = alloca + // CHECK-SAME: [8000 x i8] + // CHECK-NOT: %[[B:.+]] = alloca let mut arc = Arc::new_uninit(); unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]); unsafe { arc.assume_init() } @@ -30,8 +31,7 @@ pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { // CHECK-LABEL: @new_uninit_slice #[no_mangle] pub fn new_uninit_slice(x: u64) -> Arc<[u64]> { - // CHECK: call alloc::sync::arcinner_layout_for_value_layout - // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout + // CHECK-NOT: %[[B:.+]] = alloca let mut arc = Arc::new_uninit_slice(1000); for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } { elem.write(x); diff --git a/tests/ui/consts/const-eval/simd/simd-packed-non-pow2.rs b/tests/ui/consts/const-eval/simd/simd-packed-non-pow2.rs new file mode 100644 index 0000000000000..f09e52e9298bb --- /dev/null +++ b/tests/ui/consts/const-eval/simd/simd-packed-non-pow2.rs @@ -0,0 +1,18 @@ +//@ check-pass +// Fixes #151537 +#![feature(portable_simd, core_intrinsics)] +use std::intrinsics::simd::SimdAlign; +use std::{ptr::null, simd::prelude::*}; + +const _: () = { + let c = Simd::from_array([0; 3]); + unsafe { + core::intrinsics::simd::simd_masked_store::<_, _, _, { SimdAlign::Element }>( + c, + null::(), + c, + ) + }; +}; + +fn main() {} diff --git a/tests/ui/target-feature/const-target-feature-fn-ptr-coercion.rs b/tests/ui/target-feature/const-target-feature-fn-ptr-coercion.rs new file mode 100644 index 0000000000000..380de2412b728 --- /dev/null +++ b/tests/ui/target-feature/const-target-feature-fn-ptr-coercion.rs @@ -0,0 +1,33 @@ +//@ only-x86_64 +//@ check-pass +// +// Regression test for . + +#![allow(dead_code)] + +#[target_feature(enable = "sse2")] +const fn foo() {} + +// DefKind::Const +const _: () = unsafe { + let _: unsafe fn() = foo; +}; + +// DefKind::AssocConst +struct S; +impl S { + const C: () = unsafe { + let _: unsafe fn() = foo; + }; +} + +// DefKind::InlineConst +fn bar() { + let _ = const { + unsafe { + let _: unsafe fn() = foo; + } + }; +} + +fn main() {}