Skip to content

Rollup of 4 pull requests #124716

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 4, 2024
26 changes: 25 additions & 1 deletion compiler/rustc_ast/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,35 @@ use rustc_span::Symbol;

#[derive(Debug)]
pub enum EntryPointType {
/// This function is not an entrypoint.
None,
/// This is a function called `main` at the root level.
/// ```
/// fn main() {}
/// ```
MainNamed,
/// This is a function with the `#[rustc_main]` attribute.
/// Used by the testing harness to create the test entrypoint.
/// ```ignore (clashes with test entrypoint)
/// #[rustc_main]
/// fn main() {}
/// ```
RustcMainAttr,
/// This is a function with the `#[start]` attribute.
/// ```ignore (clashes with test entrypoint)
/// #[start]
/// fn main() {}
/// ```
Start,
OtherMain, // Not an entry point, but some other function named main
/// This function is **not** an entrypoint but simply named `main` (not at the root).
/// This is only used for diagnostics.
/// ```
/// #[allow(dead_code)]
/// mod meow {
/// fn main() {}
/// }
/// ```
OtherMain,
}

pub fn entry_point_type(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/test_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ fn generate_test_harness(
///
/// By default this expands to
///
/// ```ignore UNSOLVED (I think I still need guidance for this one. Is it correct? Do we try to make it run? How do we nicely fill it out?)
/// ```ignore (messes with test internals)
/// #[rustc_main]
/// pub fn main() {
/// extern crate test;
Expand Down
16 changes: 2 additions & 14 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,19 +467,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
let intrinsic_name = ecx.tcx.item_name(instance.def_id());

// CTFE-specific intrinsics.
let Some(ret) = target else {
// Handle diverging intrinsics. We can't handle any of them (that are not already
// handled above), but check if there is a fallback body.
if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
throw_unsup_format!(
"intrinsic `{intrinsic_name}` is not supported at compile-time"
);
}
return Ok(Some(ty::Instance {
def: ty::InstanceDef::Item(instance.def_id()),
args: instance.args,
}));
};
match intrinsic_name {
sym::ptr_guaranteed_cmp => {
let a = ecx.read_scalar(&args[0])?;
Expand Down Expand Up @@ -559,7 +546,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
}

ecx.go_to_block(ret);
// Intrinsic is done, jump to next block.
ecx.return_to_block(target)?;
Ok(None)
}

Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
) -> InterpResult<'tcx, bool> {
let instance_args = instance.args;
let intrinsic_name = self.tcx.item_name(instance.def_id());
let Some(ret) = ret else {
// We don't support any intrinsic without return place.
return Ok(false);
};

match intrinsic_name {
sym::caller_location => {
Expand Down Expand Up @@ -376,7 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
};

M::panic_nounwind(self, &msg)?;
// Skip the `go_to_block` at the end.
// Skip the `return_to_block` at the end (we panicked, we do not return).
return Ok(true);
}
}
Expand Down Expand Up @@ -437,11 +433,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
}

// Unsupported intrinsic: skip the return_to_block below.
_ => return Ok(false),
}

trace!("{:?}", self.dump_place(&dest.clone().into()));
self.go_to_block(ret);
self.return_to_block(ret)?;
Ok(true)
}

Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ passes_attr_crate_level =
passes_attr_only_in_functions =
`{$attr}` attribute can only be used on functions

passes_attr_only_on_main =
`{$attr}` attribute can only be used on `fn main()`

passes_attr_only_on_root_main =
`{$attr}` attribute can only be used on root `fn main()`

passes_both_ffi_const_and_pure =
`#[ffi_const]` function cannot be `#[ffi_pure]`

Expand Down
42 changes: 23 additions & 19 deletions compiler/rustc_passes/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use crate::errors::{
struct EntryContext<'tcx> {
tcx: TyCtxt<'tcx>,

/// The function that has attribute named `main`.
attr_main_fn: Option<(LocalDefId, Span)>,
/// The function has the `#[rustc_main]` attribute.
rustc_main_fn: Option<(LocalDefId, Span)>,

/// The function that has the attribute 'start' on it.
/// The function that has the attribute `#[start]` on it.
start_fn: Option<(LocalDefId, Span)>,

/// The functions that one might think are `main` but aren't, e.g.
Expand All @@ -42,10 +42,10 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
}

let mut ctxt =
EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() };

for id in tcx.hir().items() {
find_item(id, &mut ctxt);
check_and_search_item(id, &mut ctxt);
}

configure_main(tcx, &ctxt)
Expand All @@ -56,7 +56,16 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti
attr::find_by_name(attrs, sym).map(|attr| attr.span)
}

fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) {
for attr in [sym::start, sym::rustc_main] {
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
}
}
return;
}

let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);

let attrs = ctxt.tcx.hir().attrs(id.hir_id());
Expand All @@ -65,26 +74,20 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
at_root,
ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
);

match entry_point_type {
EntryPointType::None => (),
_ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
for attr in [sym::start, sym::rustc_main] {
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
}
}
}
EntryPointType::MainNamed => (),
EntryPointType::None => {}
EntryPointType::MainNamed => {}
EntryPointType::OtherMain => {
ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
}
EntryPointType::RustcMainAttr => {
if ctxt.attr_main_fn.is_none() {
ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
if ctxt.rustc_main_fn.is_none() {
ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
} else {
ctxt.tcx.dcx().emit_err(MultipleRustcMain {
span: ctxt.tcx.def_span(id.owner_id.to_def_id()),
first: ctxt.attr_main_fn.unwrap().1,
first: ctxt.rustc_main_fn.unwrap().1,
additional: ctxt.tcx.def_span(id.owner_id.to_def_id()),
});
}
Expand All @@ -107,10 +110,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
if let Some((def_id, _)) = visitor.start_fn {
Some((def_id.to_def_id(), EntryFnType::Start))
} else if let Some((local_def_id, _)) = visitor.attr_main_fn {
} else if let Some((local_def_id, _)) = visitor.rustc_main_fn {
let def_id = local_def_id.to_def_id();
Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }))
} else {
// The actual resolution of main happens in the resolver, this here
if let Some(main_def) = tcx.resolutions(()).main_def
&& let Some(def_id) = main_def.opt_fn_def_id()
{
Expand Down
16 changes: 0 additions & 16 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1206,22 +1206,6 @@ pub struct NakedFunctionsMustUseNoreturn {
pub last_span: Span,
}

#[derive(Diagnostic)]
#[diag(passes_attr_only_on_main)]
pub struct AttrOnlyOnMain {
#[primary_span]
pub span: Span,
pub attr: Symbol,
}

#[derive(Diagnostic)]
#[diag(passes_attr_only_on_root_main)]
pub struct AttrOnlyOnRootMain {
#[primary_span]
pub span: Span,
pub attr: Symbol,
}

#[derive(Diagnostic)]
#[diag(passes_attr_only_in_functions)]
pub struct AttrOnlyInFunctions {
Expand Down
11 changes: 8 additions & 3 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::fmt;
use crate::hint;
use crate::intrinsics::exact_div;
use crate::intrinsics::{exact_div, unchecked_sub};
use crate::mem::{self, SizedTypeProperties};
use crate::num::NonZero;
use crate::ops::{Bound, OneSidedRange, Range, RangeBounds};
Expand Down Expand Up @@ -1983,7 +1983,7 @@ impl<T> [T] {
);

// SAFETY: Caller has to check that `0 <= mid <= self.len()`
unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) }
unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), unchecked_sub(len, mid))) }
}

/// Divides one mutable slice into two at an index, without doing bounds checking.
Expand Down Expand Up @@ -2035,7 +2035,12 @@ impl<T> [T] {
//
// `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference
// is fine.
unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) }
unsafe {
(
from_raw_parts_mut(ptr, mid),
from_raw_parts_mut(ptr.add(mid), unchecked_sub(len, mid)),
)
}
}

/// Divides one slice into two at an index, returning `None` if the slice is
Expand Down
21 changes: 21 additions & 0 deletions library/std/src/io/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,27 @@ where
self.pos += n as u64;
Ok(())
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
let content = self.remaining_slice();
let len = content.len();
buf.try_reserve(len)?;
buf.extend_from_slice(content);
self.pos += len as u64;

Ok(len)
}

fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
let content =
crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?;
let len = content.len();
buf.try_reserve(len)?;
buf.push_str(content);
self.pos += len as u64;

Ok(len)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
13 changes: 4 additions & 9 deletions library/std/src/io/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,9 @@ impl Read for &[u8] {
#[inline]
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
let content = str::from_utf8(self).map_err(|_| io::Error::INVALID_UTF8)?;
buf.push_str(content);
let len = self.len();
buf.try_reserve(len)?;
buf.push_str(content);
*self = &self[len..];
Ok(len)
}
Expand Down Expand Up @@ -473,14 +474,8 @@ impl<A: Allocator> Read for VecDeque<u8, A> {

#[inline]
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
// We have to use a single contiguous slice because the `VecDequeue` might be split in the
// middle of an UTF-8 character.
let len = self.len();
let content = self.make_contiguous();
let string = str::from_utf8(content).map_err(|_| io::Error::INVALID_UTF8)?;
buf.push_str(string);
self.clear();
Ok(len)
// SAFETY: We only append to the buffer
unsafe { io::append_to_string(buf, |buf| self.read_to_end(buf)) }
}
}

Expand Down
5 changes: 4 additions & 1 deletion library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,10 @@ where
{
let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
let ret = f(g.buf);
if str::from_utf8(&g.buf[g.len..]).is_err() {

// SAFETY: the caller promises to only append data to `buf`
let appended = g.buf.get_unchecked(g.len..);
if str::from_utf8(appended).is_err() {
ret.and_then(|_| Err(Error::INVALID_UTF8))
} else {
g.len = g.buf.len();
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ impl Read for ChildStderr {
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
}

impl AsInner<AnonPipe> for ChildStderr {
Expand Down
1 change: 1 addition & 0 deletions src/tools/miri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub use rustc_const_eval::interpret::*;
#[doc(no_inline)]
pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};

pub use crate::shims::EmulateItemResult;
pub use crate::shims::env::{EnvVars, EvalContextExt as _};
pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _};
pub use crate::shims::intrinsics::EvalContextExt as _;
Expand Down
9 changes: 4 additions & 5 deletions src/tools/miri/src/shims/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use rustc_ast::expand::allocator::AllocatorKind;
use rustc_target::abi::{Align, Size};

use crate::*;
use shims::foreign_items::EmulateForeignItemResult;

/// Check some basic requirements for this allocation request:
/// non-zero size, power-of-two alignment.
Expand Down Expand Up @@ -55,12 +54,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn emulate_allocator(
&mut self,
default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>,
) -> InterpResult<'tcx, EmulateForeignItemResult> {
) -> InterpResult<'tcx, EmulateItemResult> {
let this = self.eval_context_mut();

let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
// in real code, this symbol does not exist without an allocator
return Ok(EmulateForeignItemResult::NotSupported);
return Ok(EmulateItemResult::NotSupported);
};

match allocator_kind {
Expand All @@ -70,11 +69,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// and not execute any Miri shim. Somewhat unintuitively doing so is done
// by returning `NotSupported`, which triggers the `lookup_exported_symbol`
// fallback case in `emulate_foreign_item`.
return Ok(EmulateForeignItemResult::NotSupported);
return Ok(EmulateItemResult::NotSupported);
}
AllocatorKind::Default => {
default(this)?;
Ok(EmulateForeignItemResult::NeedsJumping)
Ok(EmulateItemResult::NeedsJumping)
}
}
}
Expand Down
Loading
Loading