Skip to content

Commit d568423

Browse files
committed
Auto merge of rust-lang#124716 - matthiaskrgr:rollup-ni58ie1, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - rust-lang#122441 (Improve several `Read` implementations) - rust-lang#124584 (Various improvements to entrypoint code) - rust-lang#124699 (Use `unchecked_sub` in `split_at`) - rust-lang#124715 (interpret, miri: uniform treatments of intrinsics/functions with and without return block) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1a851da + 743be1e commit d568423

File tree

34 files changed

+279
-293
lines changed

34 files changed

+279
-293
lines changed

compiler/rustc_ast/src/entry.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,35 @@ use rustc_span::Symbol;
44

55
#[derive(Debug)]
66
pub enum EntryPointType {
7+
/// This function is not an entrypoint.
78
None,
9+
/// This is a function called `main` at the root level.
10+
/// ```
11+
/// fn main() {}
12+
/// ```
813
MainNamed,
14+
/// This is a function with the `#[rustc_main]` attribute.
15+
/// Used by the testing harness to create the test entrypoint.
16+
/// ```ignore (clashes with test entrypoint)
17+
/// #[rustc_main]
18+
/// fn main() {}
19+
/// ```
920
RustcMainAttr,
21+
/// This is a function with the `#[start]` attribute.
22+
/// ```ignore (clashes with test entrypoint)
23+
/// #[start]
24+
/// fn main() {}
25+
/// ```
1026
Start,
11-
OtherMain, // Not an entry point, but some other function named main
27+
/// This function is **not** an entrypoint but simply named `main` (not at the root).
28+
/// This is only used for diagnostics.
29+
/// ```
30+
/// #[allow(dead_code)]
31+
/// mod meow {
32+
/// fn main() {}
33+
/// }
34+
/// ```
35+
OtherMain,
1236
}
1337

1438
pub fn entry_point_type(

compiler/rustc_builtin_macros/src/test_harness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ fn generate_test_harness(
266266
///
267267
/// By default this expands to
268268
///
269-
/// ```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?)
269+
/// ```ignore (messes with test internals)
270270
/// #[rustc_main]
271271
/// pub fn main() {
272272
/// extern crate test;

compiler/rustc_const_eval/src/const_eval/machine.rs

+2-14
Original file line numberDiff line numberDiff line change
@@ -467,19 +467,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
467467
let intrinsic_name = ecx.tcx.item_name(instance.def_id());
468468

469469
// CTFE-specific intrinsics.
470-
let Some(ret) = target else {
471-
// Handle diverging intrinsics. We can't handle any of them (that are not already
472-
// handled above), but check if there is a fallback body.
473-
if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
474-
throw_unsup_format!(
475-
"intrinsic `{intrinsic_name}` is not supported at compile-time"
476-
);
477-
}
478-
return Ok(Some(ty::Instance {
479-
def: ty::InstanceDef::Item(instance.def_id()),
480-
args: instance.args,
481-
}));
482-
};
483470
match intrinsic_name {
484471
sym::ptr_guaranteed_cmp => {
485472
let a = ecx.read_scalar(&args[0])?;
@@ -559,7 +546,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
559546
}
560547
}
561548

562-
ecx.go_to_block(ret);
549+
// Intrinsic is done, jump to next block.
550+
ecx.return_to_block(target)?;
563551
Ok(None)
564552
}
565553

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
113113
) -> InterpResult<'tcx, bool> {
114114
let instance_args = instance.args;
115115
let intrinsic_name = self.tcx.item_name(instance.def_id());
116-
let Some(ret) = ret else {
117-
// We don't support any intrinsic without return place.
118-
return Ok(false);
119-
};
120116

121117
match intrinsic_name {
122118
sym::caller_location => {
@@ -376,7 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
376372
};
377373

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

436+
// Unsupported intrinsic: skip the return_to_block below.
440437
_ => return Ok(false),
441438
}
442439

443440
trace!("{:?}", self.dump_place(&dest.clone().into()));
444-
self.go_to_block(ret);
441+
self.return_to_block(ret)?;
445442
Ok(true)
446443
}
447444

compiler/rustc_passes/messages.ftl

-6
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,6 @@ passes_attr_crate_level =
4949
passes_attr_only_in_functions =
5050
`{$attr}` attribute can only be used on functions
5151
52-
passes_attr_only_on_main =
53-
`{$attr}` attribute can only be used on `fn main()`
54-
55-
passes_attr_only_on_root_main =
56-
`{$attr}` attribute can only be used on root `fn main()`
57-
5852
passes_both_ffi_const_and_pure =
5953
`#[ffi_const]` function cannot be `#[ffi_pure]`
6054

compiler/rustc_passes/src/entry.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use crate::errors::{
1818
struct EntryContext<'tcx> {
1919
tcx: TyCtxt<'tcx>,
2020

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

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

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

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

4747
for id in tcx.hir().items() {
48-
find_item(id, &mut ctxt);
48+
check_and_search_item(id, &mut ctxt);
4949
}
5050

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

59-
fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
59+
fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
60+
if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) {
61+
for attr in [sym::start, sym::rustc_main] {
62+
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
63+
ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
64+
}
65+
}
66+
return;
67+
}
68+
6069
let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
6170

6271
let attrs = ctxt.tcx.hir().attrs(id.hir_id());
@@ -65,26 +74,20 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
6574
at_root,
6675
ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
6776
);
77+
6878
match entry_point_type {
69-
EntryPointType::None => (),
70-
_ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
71-
for attr in [sym::start, sym::rustc_main] {
72-
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
73-
ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
74-
}
75-
}
76-
}
77-
EntryPointType::MainNamed => (),
79+
EntryPointType::None => {}
80+
EntryPointType::MainNamed => {}
7881
EntryPointType::OtherMain => {
7982
ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
8083
}
8184
EntryPointType::RustcMainAttr => {
82-
if ctxt.attr_main_fn.is_none() {
83-
ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
85+
if ctxt.rustc_main_fn.is_none() {
86+
ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
8487
} else {
8588
ctxt.tcx.dcx().emit_err(MultipleRustcMain {
8689
span: ctxt.tcx.def_span(id.owner_id.to_def_id()),
87-
first: ctxt.attr_main_fn.unwrap().1,
90+
first: ctxt.rustc_main_fn.unwrap().1,
8891
additional: ctxt.tcx.def_span(id.owner_id.to_def_id()),
8992
});
9093
}
@@ -107,10 +110,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
107110
fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
108111
if let Some((def_id, _)) = visitor.start_fn {
109112
Some((def_id.to_def_id(), EntryFnType::Start))
110-
} else if let Some((local_def_id, _)) = visitor.attr_main_fn {
113+
} else if let Some((local_def_id, _)) = visitor.rustc_main_fn {
111114
let def_id = local_def_id.to_def_id();
112115
Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }))
113116
} else {
117+
// The actual resolution of main happens in the resolver, this here
114118
if let Some(main_def) = tcx.resolutions(()).main_def
115119
&& let Some(def_id) = main_def.opt_fn_def_id()
116120
{

compiler/rustc_passes/src/errors.rs

-16
Original file line numberDiff line numberDiff line change
@@ -1206,22 +1206,6 @@ pub struct NakedFunctionsMustUseNoreturn {
12061206
pub last_span: Span,
12071207
}
12081208

1209-
#[derive(Diagnostic)]
1210-
#[diag(passes_attr_only_on_main)]
1211-
pub struct AttrOnlyOnMain {
1212-
#[primary_span]
1213-
pub span: Span,
1214-
pub attr: Symbol,
1215-
}
1216-
1217-
#[derive(Diagnostic)]
1218-
#[diag(passes_attr_only_on_root_main)]
1219-
pub struct AttrOnlyOnRootMain {
1220-
#[primary_span]
1221-
pub span: Span,
1222-
pub attr: Symbol,
1223-
}
1224-
12251209
#[derive(Diagnostic)]
12261210
#[diag(passes_attr_only_in_functions)]
12271211
pub struct AttrOnlyInFunctions {

library/core/src/slice/mod.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use crate::cmp::Ordering::{self, Equal, Greater, Less};
1010
use crate::fmt;
1111
use crate::hint;
12-
use crate::intrinsics::exact_div;
12+
use crate::intrinsics::{exact_div, unchecked_sub};
1313
use crate::mem::{self, SizedTypeProperties};
1414
use crate::num::NonZero;
1515
use crate::ops::{Bound, OneSidedRange, Range, RangeBounds};
@@ -1983,7 +1983,7 @@ impl<T> [T] {
19831983
);
19841984

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

19891989
/// Divides one mutable slice into two at an index, without doing bounds checking.
@@ -2035,7 +2035,12 @@ impl<T> [T] {
20352035
//
20362036
// `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference
20372037
// is fine.
2038-
unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) }
2038+
unsafe {
2039+
(
2040+
from_raw_parts_mut(ptr, mid),
2041+
from_raw_parts_mut(ptr.add(mid), unchecked_sub(len, mid)),
2042+
)
2043+
}
20392044
}
20402045

20412046
/// Divides one slice into two at an index, returning `None` if the slice is

library/std/src/io/cursor.rs

+21
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,27 @@ where
364364
self.pos += n as u64;
365365
Ok(())
366366
}
367+
368+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
369+
let content = self.remaining_slice();
370+
let len = content.len();
371+
buf.try_reserve(len)?;
372+
buf.extend_from_slice(content);
373+
self.pos += len as u64;
374+
375+
Ok(len)
376+
}
377+
378+
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
379+
let content =
380+
crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?;
381+
let len = content.len();
382+
buf.try_reserve(len)?;
383+
buf.push_str(content);
384+
self.pos += len as u64;
385+
386+
Ok(len)
387+
}
367388
}
368389

369390
#[stable(feature = "rust1", since = "1.0.0")]

library/std/src/io/impls.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,9 @@ impl Read for &[u8] {
329329
#[inline]
330330
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
331331
let content = str::from_utf8(self).map_err(|_| io::Error::INVALID_UTF8)?;
332-
buf.push_str(content);
333332
let len = self.len();
333+
buf.try_reserve(len)?;
334+
buf.push_str(content);
334335
*self = &self[len..];
335336
Ok(len)
336337
}
@@ -473,14 +474,8 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
473474

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

library/std/src/io/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,10 @@ where
384384
{
385385
let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
386386
let ret = f(g.buf);
387-
if str::from_utf8(&g.buf[g.len..]).is_err() {
387+
388+
// SAFETY: the caller promises to only append data to `buf`
389+
let appended = g.buf.get_unchecked(g.len..);
390+
if str::from_utf8(appended).is_err() {
388391
ret.and_then(|_| Err(Error::INVALID_UTF8))
389392
} else {
390393
g.len = g.buf.len();

library/std/src/process.rs

+4
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ impl Read for ChildStderr {
486486
fn is_read_vectored(&self) -> bool {
487487
self.inner.is_read_vectored()
488488
}
489+
490+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
491+
self.inner.read_to_end(buf)
492+
}
489493
}
490494

491495
impl AsInner<AnonPipe> for ChildStderr {

src/tools/miri/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub use rustc_const_eval::interpret::*;
9595
#[doc(no_inline)]
9696
pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};
9797

98+
pub use crate::shims::EmulateItemResult;
9899
pub use crate::shims::env::{EnvVars, EvalContextExt as _};
99100
pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _};
100101
pub use crate::shims::intrinsics::EvalContextExt as _;

src/tools/miri/src/shims/alloc.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use rustc_ast::expand::allocator::AllocatorKind;
44
use rustc_target::abi::{Align, Size};
55

66
use crate::*;
7-
use shims::foreign_items::EmulateForeignItemResult;
87

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

6160
let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
6261
// in real code, this symbol does not exist without an allocator
63-
return Ok(EmulateForeignItemResult::NotSupported);
62+
return Ok(EmulateItemResult::NotSupported);
6463
};
6564

6665
match allocator_kind {
@@ -70,11 +69,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
7069
// and not execute any Miri shim. Somewhat unintuitively doing so is done
7170
// by returning `NotSupported`, which triggers the `lookup_exported_symbol`
7271
// fallback case in `emulate_foreign_item`.
73-
return Ok(EmulateForeignItemResult::NotSupported);
72+
return Ok(EmulateItemResult::NotSupported);
7473
}
7574
AllocatorKind::Default => {
7675
default(this)?;
77-
Ok(EmulateForeignItemResult::NeedsJumping)
76+
Ok(EmulateItemResult::NeedsJumping)
7877
}
7978
}
8079
}

0 commit comments

Comments
 (0)