Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1848,7 +1848,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {

assert_eq!(tcx.trait_impl_of_assoc(def_id), None);
self.prove_clauses(
args.terms().map(|t| ty::ClauseKind::WellFormed(t.into())),
args.terms().map(|t| ty::ClauseKind::WellFormed(t)),
locations,
ConstraintCategory::Boring,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
_ => return interp_ok(false),
}

trace!("{:?}", self.dump_place(&dest.clone().into()));
trace!("{:?}", self.dump_place(&dest));
self.return_to_block(ret)?;
interp_ok(true)
}
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_hir_typeck/src/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ use rustc_hir::def::DefKind;
use rustc_hir_analysis::check::check_function_signature;
use rustc_infer::infer::RegionVariableOrigin;
use rustc_infer::traits::WellFormedLoc;
use rustc_lint_defs::builtin::UNSAFE_PANIC_HANDLERS;
use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
use rustc_span::def_id::LocalDefId;
use rustc_span::sym;
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
use tracing::{debug, instrument};

use crate::coercion::CoerceMany;
use crate::diagnostics::UnsafePanicHandlers;
use crate::gather_locals::GatherLocalsVisitor;
use crate::{CoroutineTypes, Diverges, FnCtxt};

Expand Down Expand Up @@ -177,6 +179,21 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>
tcx.dcx().span_err(span, "should have no const parameters");
}

if fn_sig.safety().is_unsafe() {
let hir_id = tcx.local_def_id_to_hir_id(fn_id);
let span = tcx.def_span(fn_id);
// If the function is implicitly "unsafe" because it has a `#[target_feature]` attribute,
// then we should already have emitted an error. Don't also emit a warning.
// See `tests/ui/panic-handler/panic-handler-with-target-feature.rs`
if let Some(hir_fn_sig) = tcx.hir_fn_sig_by_hir_id(hir_id)
&& hir_fn_sig.header.safety == hir::HeaderSafety::SafeTargetFeatures
{
tcx.dcx().span_delayed_bug(span, "`unsafe_panic_handlers` lint suppressed because there should already be an error for `#[target_feature]`");
} else {
tcx.emit_node_span_lint(UNSAFE_PANIC_HANDLERS, hir_id, span, UnsafePanicHandlers);
}
}

let panic_info_did = tcx.require_lang_item(LangItem::PanicInfo, span);

// build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !`
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_typeck/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1345,3 +1345,7 @@ impl ExprParenthesesNeeded {
ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
}
}

#[derive(Diagnostic)]
#[diag("`#[panic_handler]` functions can't be `unsafe`")]
pub(crate) struct UnsafePanicHandlers;
39 changes: 39 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5883,3 +5883,42 @@ declare_lint! {
report_in_deps: true,
};
}

declare_lint! {
/// The `unsafe_panic_handlers` lint detects unsafe functions with
/// the `#[panic_handler]` attribute.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![no_std]
///
/// use core::panic::PanicInfo;
///
/// #[panic_handler]
/// unsafe fn handle(_: &PanicInfo<'_>) -> ! {
/// loop {}
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Unsafe functions (declared as `unsafe fn`) are functions that can only be called
/// when the caller ensures that their safety requirements are met. On the other hand,
/// `#[panic_handler]` functions get called automatically by the compiler without
/// checking for any preconditions. Therefore, using the `#[panic_handler]` attribute
/// on unsafe functions is either incorrect or a misuse of `unsafe fn`.
///
/// This is a [future-incompatible] lint to transition this to a hard
/// error in the future. See [issue #163263] for more details.
///
/// [issue #163263]: https://github.com/rust-lang/rust/issues/163263
pub UNSAFE_PANIC_HANDLERS,
Warn,
"detects unsafe functions with the `#[panic_handler]` attribute",
@future_incompatible = FutureIncompatibleInfo {
reason: fcw!(FutureReleaseError #163263),
};
}
4 changes: 1 addition & 3 deletions compiler/rustc_middle/src/ptrauth/discriminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,7 @@ fn compute_fn_ptr_type_discriminator<'tcx>(

enc.push(b'E');

let hash = enc.finish();

hash.into()
enc.finish()
}

// Clang disc type.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2322,7 +2322,7 @@ impl<'a> Parser<'a> {
Applicability::MaybeIncorrect,
);
}
Err(err.into())
Err(err)
}

/// Handle encountering a symbol in a generic argument list that is not a `,` or `>`. In this
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
max_vis: Option<ty::Visibility>,
level: Level,
) -> bool {
let private_vis =
ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into());
let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
if max_vis != Some(private_vis) {
return self.effective_visibilities.update(
def_id,
Expand Down
18 changes: 9 additions & 9 deletions compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1608,15 +1608,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")),
ValuePairs::Aliases(ExpectedFound { expected, .. }) => {
let def_id = match expected.kind {
ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(),
ty::AliasTermKind::InherentTy { def_id } => def_id.into(),
ty::AliasTermKind::OpaqueTy { def_id } => def_id.into(),
ty::AliasTermKind::FreeTy { def_id } => def_id.into(),
ty::AliasTermKind::AnonConst { def_id } => def_id.into(),
ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(),
ty::AliasTermKind::FreeConst { def_id } => def_id.into(),
ty::AliasTermKind::InherentConstSelf { def_id } => def_id.into(),
ty::AliasTermKind::InherentConstImpl { def_id } => def_id.into(),
ty::AliasTermKind::ProjectionTy { def_id }
| ty::AliasTermKind::InherentTy { def_id }
| ty::AliasTermKind::OpaqueTy { def_id }
| ty::AliasTermKind::FreeTy { def_id }
| ty::AliasTermKind::AnonConst { def_id }
| ty::AliasTermKind::ProjectionConst { def_id }
| ty::AliasTermKind::FreeConst { def_id }
| ty::AliasTermKind::InherentConstSelf { def_id }
| ty::AliasTermKind::InherentConstImpl { def_id } => def_id,
};
(false, Mismatch::Fixed(self.tcx.def_descr(def_id)))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_traits/src/normalize_projection_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ fn normalize_canonicalized_inherent_projection<'tcx>(
let normalized_term = traits::normalize_inherent_projection(
selcx,
param_env,
goal.into(),
goal,
cause,
0,
&mut obligations,
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/raw_vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ impl<A: Allocator> RawVecInner<A> {
unsafe {
let alloc_size = elem_layout.size().unchecked_mul(self.cap.as_inner());
let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align());
Some((self.ptr.into(), layout))
Some((self.ptr, layout))
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion library/alloctests/tests/c_str_alloc_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! rust-lang/rust#70201 gave `<CStr as ToOwned>::clone_into` a path that moved the
//! target `CString`'s buffer out before growing a `Vec`; if that growth's allocation
//! failed and unwound, the target was left without its nul terminator. This only
//! reproduces under Miri: in a normal build the `#[global_allocator]` below can't
//! reproduces under Miri: in a normal build, the `#[global_allocator]` below can't
//! intercept the reallocation inside `CString::clone_into` (it lives in libstd, which
//! library tests link with `-C prefer-dynamic`), so as a regular test it just checks
//! the happy path.
Expand Down Expand Up @@ -46,6 +46,8 @@ unsafe impl GlobalAlloc for OneShotFailingAlloc {
}
}

// This doesn't actually do anything outside Miri because of `-C prefer-dynamic` which effectively
// hard-codes the default allocator.
#[global_allocator]
static ALLOC: OneShotFailingAlloc = OneShotFailingAlloc;

Expand Down
98 changes: 98 additions & 0 deletions library/core/src/attribute_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,104 @@ const _: () = ();
/// [the `no_std` attribute]: ../reference/names/preludes.html#the-no_std-attribute
const _: () = ();

#[doc(attribute = "no_main")]
/// Prevents emitting the `main` entrypoint symbol.
///
/// Written as an inner attribute at the top of the crate root, the `no_main` attribute prevents
/// the compiler from generating the program's standard Rust entrypoint, leaving that up to you.
/// This is useful when some other object being linked into the program defines the entrypoint,
/// or when you want to define the platform's `main` symbol yourself.
///
/// If you define an entry point symbol that is suitable for your target, it must also be exported
/// under an unmangled name using the [`no_mangle` attribute]:
///
/// ```no_run
/// #![no_main]
///
/// use std::ffi::{c_char, c_int};
///
/// #[unsafe(no_mangle)]
/// pub extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int {
/// println!("Hello world!");
/// 0
/// }
/// ```
///
/// Unlike `no_std`, the `no_main` attribute does not prevent the compiler from generating
/// the startup routine or linking the standard library provided by the operating system's executable [ABI].
///
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
/// [`no_mangle` attribute]: ../reference/abi.html#the-no_mangle-attribute
const _: () = ();

#[doc(attribute = "repr")]
/// Specifies the [representation] of a type.
///
/// Written as an outer attribute on a `struct`, `enum` or `union`, `repr` controls how the
/// type is laid out in memory. This is needed when passing types across an [FFI] boundary
/// or whenever you rely on a specific layout.
///
/// The available representations are:
///
/// * [`Rust`] (the default): the layout is unspecified and may change between compilations.
/// * [`C`]: the layout follows the rules of the C language for the target platform.
/// * The [primitive representations] (`u8`, `i32`, `usize`, ...): set the discriminant
/// type of an enum.
/// * [`transparent`]: the type has the same layout and ABI as its only non-zero-sized field.
///
/// The `align(N)` and `packed(N)` modifiers raise or lower the alignment of a type, respectively.
/// `N` must be a power of two no greater than 2<sup>29</sup>. The two modifiers cannot be
/// applied to the same type, and references to fields of a `packed` type cannot be created,
/// since they may be unaligned.
///
/// # Examples
///
/// ```
/// #[repr(C, align(16))]
/// struct Foo {
/// first: u32,
/// second: u32,
/// third: u32,
/// }
///
/// assert_eq!(align_of::<Foo>(), 16);
/// // 12 bytes of fields, rounded up to a multiple of the alignment.
/// assert_eq!(size_of::<Foo>(), 16);
/// ```
///
/// ```
/// #[repr(C, packed(2))]
/// struct Foo {
/// first: u32,
/// second: u32,
/// third: u32,
/// }
///
/// assert_eq!(align_of::<Foo>(), 2);
/// assert_eq!(size_of::<Foo>(), 12);
/// ```
///
/// ```
/// #[repr(C)]
/// struct Foo<T> {
/// item: T,
/// }
/// ```
///
/// `Foo` is laid out according to the C rules and is guaranteed to be 16-byte aligned.
///
/// The representation is a property of the type definition, so it does
/// parameters: below, `Foo<u8>` and `Foo<u64>` both use the `C` representation. Their actual
/// layouts still differ, because they depend on `T`.
///
/// [representation]: ../reference/type-layout.html#representations
/// [`Rust`]: ../reference/type-layout.html#the-rust-representation
/// [`C`]: ../reference/type-layout.html#the-c-representation
/// [primitive representations]: ../reference/type-layout.html#primitive-representations
/// [`transparent`]: ../reference/type-layout.html#the-transparent-representation
/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface
const _: () = ();

#[doc(attribute = "inline")]
//
/// Suggest that the compiler inline a function at its call sites.
Expand Down
12 changes: 4 additions & 8 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,12 +650,10 @@ impl CStr {
/// # Examples
///
/// ```
/// #![feature(cstr_display)]
///
/// let cstr = c"Hello, world!";
/// println!("{}", cstr.display());
/// ```
#[unstable(feature = "cstr_display", issue = "139984")]
#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this does not display the `CStr`; \
it returns an object that can be displayed"]
#[inline]
Expand Down Expand Up @@ -870,27 +868,25 @@ impl FusedIterator for Bytes<'_> {}
/// # Examples
///
/// ```
/// #![feature(cstr_display)]
///
/// let s = c"Hello, world!";
/// println!("{}", s.display());
/// ```
///
/// [`Display`]: fmt::Display
/// [`format!`]: ../../../std/macro.format.html
#[unstable(feature = "cstr_display", issue = "139984")]
#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")]
pub struct Display<'a> {
c_str: &'a CStr,
}

#[unstable(feature = "cstr_display", issue = "139984")]
#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")]
impl fmt::Debug for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.c_str, f)
}
}

#[unstable(feature = "cstr_display", issue = "139984")]
#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")]
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(crate::bstr::ByteStr::from_bytes(self.c_str.to_bytes()), f)
Expand Down
1 change: 0 additions & 1 deletion library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
#![feature(core_io_borrowed_buf)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
#![feature(cstr_display)]
#![feature(debug_closure_helpers)]
#![feature(dec2flt)]
#![feature(duration_constants)]
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub use alloc::ffi::c_str::IntoStringError;
pub use alloc::ffi::c_str::{CString, NulError};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::ffi::c_str::CStr;
#[unstable(feature = "cstr_display", issue = "139984")]
#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")]
pub use core::ffi::c_str::Display;
#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
pub use core::ffi::c_str::FromBytesUntilNulError;
Expand Down
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@
#![feature(core_io)]
#![feature(core_io_borrowed_buf)]
#![feature(core_io_internals)]
#![feature(cstr_display)]
#![feature(cursor_split)]
#![feature(derive_const)]
#![feature(duration_constants)]
Expand Down
9 changes: 9 additions & 0 deletions src/bootstrap/src/core/build_steps/perf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ struct SharedOpts {

#[clap(long, global = true)]
database_path: Option<String>,

/// Comma-separated list of thread counts for the parallel frontend. Maps directly to the
/// `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1.
#[clap(long, global = true, value_delimiter = ',')]
frontend_threads: Vec<usize>,
}

#[derive(Clone, Copy, Debug, PartialEq, clap::ValueEnum)]
Expand Down Expand Up @@ -257,4 +262,8 @@ fn apply_shared_opts(cmd: &mut BootstrapCommand, opts: &SharedOpts) {
cmd.arg("--scenarios")
.arg(opts.scenarios.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
}
if !opts.frontend_threads.is_empty() {
cmd.arg("--frontend-threads")
.arg(opts.frontend_threads.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
}
}
Loading
Loading