Auto merge of #124694 - compiler-errors:rollup-pfou5uu, r=compiler-errors

Rollup of 8 pull requests

Successful merges:

 - #124418 (Use a proof tree visitor to refine the `Obligation` for error reporting in new solver)
 - #124480 (Change `SIGPIPE` ui from `#[unix_sigpipe = "..."]` to `-Zon-broken-pipe=...`)
 - #124648 (Trim crate graph)
 - #124656 (release notes 1.78: add link to interior-mut breaking change)
 - #124658 (Migrate `run-make/doctests-keep-binaries` to new rmake.rs format)
 - #124678 (Stabilize `split_at_checked`)
 - #124681 (zkvm: fix run_tests)
 - #124687 (Make `Bounds.clauses` private)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-05-04 05:41:56 +00:00
commit 9fa862ff29
123 changed files with 778 additions and 551 deletions

View File

@ -3824,7 +3824,6 @@ dependencies = [
"rustc_session",
"rustc_smir",
"rustc_span",
"rustc_symbol_mangling",
"rustc_target",
"rustc_trait_selection",
"rustc_ty_utils",
@ -4008,7 +4007,6 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_fluent_macro",
"rustc_graphviz",
"rustc_hir",
"rustc_hir_analysis",
"rustc_hir_pretty",
@ -4468,7 +4466,6 @@ dependencies = [
"rustc_errors",
"rustc_fluent_macro",
"rustc_hir",
"rustc_hir_analysis",
"rustc_macros",
"rustc_middle",
"rustc_session",
@ -4515,7 +4512,6 @@ dependencies = [
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_type_ir",
"smallvec",
"thin-vec",
"tracing",

View File

@ -102,6 +102,10 @@ Compatibility Notes
- [Change equality of higher ranked types to not rely on subtyping](https://github.com/rust-lang/rust/pull/118247)
- [When called, additionally check bounds on normalized function return type](https://github.com/rust-lang/rust/pull/118882)
- [Expand coverage for `arithmetic_overflow` lint](https://github.com/rust-lang/rust/pull/119432/)
- [Fix detection of potential interior mutability in `const` initializers](https://github.com/rust-lang/rust/issues/121250)
This code was accidentally accepted. The fix can break generic code that borrows a value of unknown type,
as there is currently no way to declare "this type has no interior mutability". In the future, stabilizing
the [`Freeze` trait](https://github.com/rust-lang/rust/issues/121675) will allow proper support for such code.
<a id="1.78.0-Internal-Changes"></a>

View File

@ -1,5 +1,3 @@
#![feature(unix_sigpipe)]
// A note about jemalloc: rustc uses jemalloc when built for CI and
// distribution. The obvious way to do this is with the `#[global_allocator]`
// mechanism. However, for complicated reasons (see
@ -34,7 +32,6 @@
// https://github.com/rust-lang/rust/commit/b90cfc887c31c3e7a9e6d462e2464db1fe506175#diff-43914724af6e464c1da2171e4a9b6c7e607d5bc1203fa95c0ab85be4122605ef
// for an example of how to do so.
#[unix_sigpipe = "sig_dfl"]
fn main() {
// See the comment at the top of this file for an explanation of this.
#[cfg(feature = "jemalloc-sys")]

View File

@ -307,7 +307,7 @@ fn make_format_args(
return ExpandResult::Ready(Err(guar));
}
let to_span = |inner_span: rustc_parse_format::InnerSpan| {
let to_span = |inner_span: parse::InnerSpan| {
is_source_literal.then(|| {
fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end })
})
@ -577,7 +577,7 @@ enum ArgRef<'a> {
fn invalid_placeholder_type_error(
ecx: &ExtCtxt<'_>,
ty: &str,
ty_span: Option<rustc_parse_format::InnerSpan>,
ty_span: Option<parse::InnerSpan>,
fmt_span: Span,
) {
let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end)));

View File

@ -42,9 +42,8 @@ rustc_privacy = { path = "../rustc_privacy" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_resolve = { path = "../rustc_resolve" }
rustc_session = { path = "../rustc_session" }
rustc_smir ={ path = "../rustc_smir" }
rustc_smir = { path = "../rustc_smir" }
rustc_span = { path = "../rustc_span" }
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_ty_utils = { path = "../rustc_ty_utils" }

View File

@ -13,7 +13,7 @@
use rustc_span::Span;
use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
use rustc_type_ir as type_ir;
use rustc_type_ir::{ClosureKind, FloatTy};
use std::backtrace::Backtrace;
use std::borrow::Cow;
use std::fmt;
@ -196,7 +196,7 @@ fn into_diag_arg(self) -> DiagArgValue {
}
}
impl IntoDiagArg for type_ir::FloatTy {
impl IntoDiagArg for FloatTy {
fn into_diag_arg(self) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(self.name_str()))
}
@ -252,7 +252,7 @@ fn into_diag_arg(self) -> DiagArgValue {
}
}
impl IntoDiagArg for type_ir::ClosureKind {
impl IntoDiagArg for ClosureKind {
fn into_diag_arg(self) -> DiagArgValue {
DiagArgValue::Str(self.as_str().into())
}

View File

@ -396,10 +396,6 @@ pub struct BuiltinAttribute {
),
// Entry point:
gated!(
unix_sigpipe, Normal, template!(NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing,
EncodeCrossCrate::Yes, experimental!(unix_sigpipe)
),
ungated!(start, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),

View File

@ -619,8 +619,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows creation of instances of a struct by moving fields that have
/// not changed from prior instances of the same struct (RFC #2528)
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
/// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
(unstable, unix_sigpipe, "1.65.0", Some(97889)),
/// Allows unnamed fields of struct and union type
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
/// Allows unsized fn parameters.

View File

@ -23,7 +23,7 @@
/// include the self type (e.g., `trait_bounds`) but in others we do not
#[derive(Default, PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> {
pub clauses: Vec<(ty::Clause<'tcx>, Span)>,
clauses: Vec<(ty::Clause<'tcx>, Span)>,
}
impl<'tcx> Bounds<'tcx> {

View File

@ -12,7 +12,6 @@ rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_analysis = { path = "../rustc_hir_analysis" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }

View File

@ -10,7 +10,6 @@
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind};
use rustc_infer::infer;
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_lint as lint;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
@ -684,7 +683,7 @@ fn check_pat_ident(
{
// `mut x` resets the binding mode in edition <= 2021.
self.tcx.emit_node_span_lint(
lint::builtin::DEREFERENCING_MUT_BINDING,
rustc_lint::builtin::DEREFERENCING_MUT_BINDING,
pat.hir_id,
pat.span,
errors::DereferencingMutBinding { span: pat.span },

View File

@ -4,7 +4,6 @@
use crate::util;
use rustc_ast::{self as ast, visit};
use rustc_borrowck as mir_borrowck;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
use rustc_data_structures::steal::Steal;
@ -20,7 +19,6 @@
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
use rustc_middle::util::Providers;
use rustc_mir_build as mir_build;
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
use rustc_passes::{abi_test, hir_stats, layout_test};
use rustc_resolve::Resolver;
@ -616,8 +614,8 @@ pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) {
proc_macro_decls::provide(providers);
rustc_const_eval::provide(providers);
rustc_middle::hir::provide(providers);
mir_borrowck::provide(providers);
mir_build::provide(providers);
rustc_borrowck::provide(providers);
rustc_mir_build::provide(providers);
rustc_mir_transform::provide(providers);
rustc_monomorphize::provide(providers);
rustc_privacy::provide(providers);

View File

@ -20,7 +20,7 @@
use rustc_span::symbol::sym;
use rustc_span::{FileName, SourceFileHashAlgorithm};
use rustc_target::spec::{
CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi,
CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi,
};
use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
use std::collections::{BTreeMap, BTreeSet};
@ -809,6 +809,7 @@ macro_rules! tracked {
tracked!(no_profiler_runtime, true);
tracked!(no_trait_vptr, true);
tracked!(no_unique_section_names, true);
tracked!(on_broken_pipe, OnBrokenPipe::Kill);
tracked!(oom, OomStrategy::Panic);
tracked!(osx_rpath_install_name, true);
tracked!(packed_bundled_libs, true);

View File

@ -7,18 +7,16 @@
use rustc_metadata::{load_symbol_from_dylib, DylibError};
use rustc_middle::ty::CurrentGcx;
use rustc_parse::validate_attr;
use rustc_session as session;
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes};
use rustc_session::config::{host_triple, Cfg, OutFileName, OutputFilenames, OutputTypes};
use rustc_session::filesearch::sysroot_candidates;
use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
use rustc_session::{filesearch, Session};
use rustc_session::output::{categorize_crate_type, CRATE_TYPES};
use rustc_session::{filesearch, EarlyDiagCtxt, Session};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMapInputs;
use rustc_span::symbol::sym;
use rustc_target::spec::Target;
use session::output::{categorize_crate_type, CRATE_TYPES};
use session::EarlyDiagCtxt;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
@ -286,7 +284,7 @@ fn get_codegen_sysroot(
"cannot load the default codegen backend twice"
);
let target = session::config::host_triple();
let target = host_triple();
let sysroot_candidates = sysroot_candidates();
let sysroot = iter::once(sysroot)

View File

@ -273,6 +273,8 @@ pub enum GoalSource {
/// they are from an impl where-clause. This is necessary due to
/// backwards compatability, cc trait-system-refactor-initiatitive#70.
ImplWhereBound,
/// Instantiating a higher-ranked goal and re-proving it.
InstantiateHigherRanked,
}
/// Possible ways the given goal can be proven.

View File

@ -127,6 +127,7 @@ pub(super) fn format_probe(&mut self, probe: &Probe<'_>) -> std::fmt::Result {
let source = match source {
GoalSource::Misc => "misc",
GoalSource::ImplWhereBound => "impl where-bound",
GoalSource::InstantiateHigherRanked => "higher-ranked goal",
};
writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")?
}

View File

@ -695,9 +695,6 @@ passes_transparent_incompatible =
passes_undefined_naked_function_abi =
Rust ABI is unsupported in naked functions
passes_unix_sigpipe_values =
valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
passes_unknown_external_lang_item =
unknown external lang item: `{$lang_item}`

View File

@ -2523,7 +2523,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
sym::automatically_derived,
sym::start,
sym::rustc_main,
sym::unix_sigpipe,
sym::derive,
sym::test,
sym::test_case,

View File

@ -12,8 +12,7 @@
use rustc_span::{Span, Symbol};
use crate::errors::{
AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain,
MultipleStartFunctions, NoMainErr, UnixSigpipeValues,
AttrOnlyInFunctions, ExternMain, MultipleRustcMain, MultipleStartFunctions, NoMainErr,
};
struct EntryContext<'tcx> {
@ -67,11 +66,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
);
match entry_point_type {
EntryPointType::None => {
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
}
}
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) {
@ -81,9 +76,6 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
}
EntryPointType::MainNamed => (),
EntryPointType::OtherMain => {
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
ctxt.tcx.dcx().emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe });
}
ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
}
EntryPointType::RustcMainAttr => {
@ -98,9 +90,6 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
}
}
EntryPointType::Start => {
if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
}
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
} else {
@ -120,7 +109,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
Some((def_id.to_def_id(), EntryFnType::Start))
} else if let Some((local_def_id, _)) = visitor.attr_main_fn {
let def_id = local_def_id.to_def_id();
Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }))
Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }))
} else {
if let Some(main_def) = tcx.resolutions(()).main_def
&& let Some(def_id) = main_def.opt_fn_def_id()
@ -133,31 +122,19 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
return None;
}
return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }));
return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }));
}
no_main_err(tcx, visitor);
None
}
}
fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
if let Some(attr) = tcx.get_attr(def_id, sym::unix_sigpipe) {
match (attr.value_str(), attr.meta_item_list()) {
(Some(sym::inherit), None) => sigpipe::INHERIT,
(Some(sym::sig_ign), None) => sigpipe::SIG_IGN,
(Some(sym::sig_dfl), None) => sigpipe::SIG_DFL,
(Some(_), None) => {
tcx.dcx().emit_err(UnixSigpipeValues { span: attr.span });
sigpipe::DEFAULT
}
_ => {
// Keep going so that `fn emit_malformed_attribute()` can print
// an excellent error message
sigpipe::DEFAULT
}
}
} else {
sigpipe::DEFAULT
fn sigpipe(tcx: TyCtxt<'_>) -> u8 {
match tcx.sess.opts.unstable_opts.on_broken_pipe {
rustc_target::spec::OnBrokenPipe::Default => sigpipe::DEFAULT,
rustc_target::spec::OnBrokenPipe::Kill => sigpipe::SIG_DFL,
rustc_target::spec::OnBrokenPipe::Error => sigpipe::SIG_IGN,
rustc_target::spec::OnBrokenPipe::Inherit => sigpipe::INHERIT,
}
}

View File

@ -1259,13 +1259,6 @@ pub struct ExternMain {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_unix_sigpipe_values)]
pub struct UnixSigpipeValues {
#[primary_span]
pub span: Span,
}
pub struct NoMainErr {
pub sp: Span,
pub crate_name: Symbol,

View File

@ -11,7 +11,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_analysis = { path = "../rustc_hir_analysis" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }

View File

@ -19,7 +19,6 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
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"
tracing = "0.1"

View File

@ -2909,7 +2909,9 @@ pub(crate) mod dep_tracking {
use rustc_feature::UnstableFeatures;
use rustc_span::edition::Edition;
use rustc_span::RealFileName;
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi};
use rustc_target::spec::{
CodeModel, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi,
};
use rustc_target::spec::{
RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
};
@ -2973,6 +2975,7 @@ fn hash(
InstrumentXRay,
CrateType,
MergeFunctions,
OnBrokenPipe,
PanicStrategy,
RelroLevel,
OptLevel,

View File

@ -1,6 +1,6 @@
//! NOTE: Keep these constants in sync with `library/std/src/sys/pal/unix/mod.rs`!
/// The default value if `#[unix_sigpipe]` is not specified. This resolves
/// The default value if `-Zon-broken-pipe=...` is not specified. This resolves
/// to `SIG_IGN` in `library/std/src/sys/pal/unix/mod.rs`.
///
/// Note that `SIG_IGN` has been the Rust default since 2014. See

View File

@ -12,7 +12,7 @@
use rustc_span::RealFileName;
use rustc_span::SourceFileHashAlgorithm;
use rustc_target::spec::{
CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet, WasmCAbi,
CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, SanitizerSet, WasmCAbi,
};
use rustc_target::spec::{
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
@ -378,6 +378,7 @@ mod desc {
pub const parse_time_passes_format: &str = "`text` (default) or `json`";
pub const parse_passes: &str = "a space-separated list of passes, or `all`";
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
@ -708,6 +709,17 @@ pub(crate) fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) ->
true
}
pub(crate) fn parse_on_broken_pipe(slot: &mut OnBrokenPipe, v: Option<&str>) -> bool {
match v {
// OnBrokenPipe::Default can't be explicitly specified
Some("kill") => *slot = OnBrokenPipe::Kill,
Some("error") => *slot = OnBrokenPipe::Error,
Some("inherit") => *slot = OnBrokenPipe::Inherit,
_ => return false,
}
true
}
pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
match v {
Some("panic") => *slot = OomStrategy::Panic,
@ -1833,6 +1845,8 @@ pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool {
"do not use unique names for text and data sections when -Z function-sections is used"),
normalize_docs: bool = (false, parse_bool, [TRACKED],
"normalize associated items in rustdoc when generating documentation"),
on_broken_pipe: OnBrokenPipe = (OnBrokenPipe::Default, parse_on_broken_pipe, [TRACKED],
"behavior of std::io::ErrorKind::BrokenPipe (SIGPIPE)"),
oom: OomStrategy = (OomStrategy::Abort, parse_oom_strategy, [TRACKED],
"panic strategy for out-of-memory handling"),
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],

View File

@ -1936,7 +1936,6 @@
unit,
universal_impl_trait,
unix,
unix_sigpipe,
unlikely,
unmarked_api,
unnamed_fields,

View File

@ -778,6 +778,14 @@ pub enum PanicStrategy {
Abort,
}
#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
pub enum OnBrokenPipe {
Default,
Kill,
Error,
Inherit,
}
impl PanicStrategy {
pub fn desc(&self) -> &str {
match *self {

View File

@ -58,15 +58,15 @@ fn probe_and_match_goal_against_assumption(
/// goal by equating it with the assumption.
fn probe_and_consider_implied_clause(
ecx: &mut EvalCtxt<'_, 'tcx>,
source: CandidateSource,
parent_source: CandidateSource,
goal: Goal<'tcx, Self>,
assumption: ty::Clause<'tcx>,
requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
requirements: impl IntoIterator<Item = (GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>,
) -> Result<Candidate<'tcx>, NoSolution> {
Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
// FIXME(-Znext-solver=coinductive): check whether this should be
// `GoalSource::ImplWhereBound` for any caller.
ecx.add_goals(GoalSource::Misc, requirements);
Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| {
for (nested_source, goal) in requirements {
ecx.add_goal(nested_source, goal);
}
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
@ -85,9 +85,8 @@ fn probe_and_consider_object_bound_candidate(
let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
bug!("expected object type in `probe_and_consider_object_bound_candidate`");
};
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
ecx.add_goals(
GoalSource::Misc,
GoalSource::ImplWhereBound,
structural_traits::predicates_for_object_candidate(
ecx,
goal.param_env,

View File

@ -90,6 +90,8 @@ pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
&mut self,
certainty: Certainty,
) -> QueryResult<'tcx> {
self.inspect.make_canonical_response(certainty);
let goals_certainty = self.try_evaluate_added_goals()?;
assert_eq!(
self.tainted,
@ -98,8 +100,6 @@ pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
previous call to `try_evaluate_added_goals!`"
);
self.inspect.make_canonical_response(certainty);
// When normalizing, we've replaced the expected term with an unconstrained
// inference variable. This means that we dropped information which could
// have been important. We handle this by instead returning the nested goals

View File

@ -454,7 +454,7 @@ fn compute_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) -> QueryResult
} else {
self.infcx.enter_forall(kind, |kind| {
let goal = goal.with(self.tcx(), ty::Binder::dummy(kind));
self.add_goal(GoalSource::Misc, goal);
self.add_goal(GoalSource::InstantiateHigherRanked, goal);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}

View File

@ -1,15 +1,19 @@
use std::mem;
use std::ops::ControlFlow;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::solve::MaybeCause;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::solve::inspect::ProbeKind;
use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
use rustc_infer::traits::{
query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
PredicateObligation, SelectionError, TraitEngine,
self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
ObligationCause, PredicateObligation, SelectionError, TraitEngine,
};
use rustc_middle::ty;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, TyCtxt};
use super::eval_ctxt::GenerateProofTree;
use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
use super::{Certainty, InferCtxtEvalExt};
/// A trait engine using the new trait solver.
@ -133,9 +137,9 @@ fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<Fulfillme
.collect();
errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
root_obligation: obligation.clone(),
obligation: find_best_leaf_obligation(infcx, &obligation),
code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
obligation,
root_obligation: obligation,
}));
errors
@ -192,8 +196,10 @@ fn drain_unstalled_obligations(
fn fulfillment_error_for_no_solution<'tcx>(
infcx: &InferCtxt<'tcx>,
obligation: PredicateObligation<'tcx>,
root_obligation: PredicateObligation<'tcx>,
) -> FulfillmentError<'tcx> {
let obligation = find_best_leaf_obligation(infcx, &root_obligation);
let code = match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
FulfillmentErrorCode::ProjectionError(
@ -234,7 +240,8 @@ fn fulfillment_error_for_no_solution<'tcx>(
bug!("unexpected goal: {obligation:?}")
}
};
FulfillmentError { root_obligation: obligation.clone(), code, obligation }
FulfillmentError { obligation, code, root_obligation }
}
fn fulfillment_error_for_stalled<'tcx>(
@ -258,5 +265,136 @@ fn fulfillment_error_for_stalled<'tcx>(
}
});
FulfillmentError { obligation: obligation.clone(), code, root_obligation: obligation }
FulfillmentError {
obligation: find_best_leaf_obligation(infcx, &obligation),
code,
root_obligation: obligation,
}
}
fn find_best_leaf_obligation<'tcx>(
infcx: &InferCtxt<'tcx>,
obligation: &PredicateObligation<'tcx>,
) -> PredicateObligation<'tcx> {
let obligation = infcx.resolve_vars_if_possible(obligation.clone());
infcx
.visit_proof_tree(
obligation.clone().into(),
&mut BestObligation { obligation: obligation.clone() },
)
.break_value()
.unwrap_or(obligation)
}
struct BestObligation<'tcx> {
obligation: PredicateObligation<'tcx>,
}
impl<'tcx> BestObligation<'tcx> {
fn with_derived_obligation(
&mut self,
derived_obligation: PredicateObligation<'tcx>,
and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result,
) -> <Self as ProofTreeVisitor<'tcx>>::Result {
let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
let res = and_then(self);
self.obligation = old_obligation;
res
}
}
impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
type Result = ControlFlow<PredicateObligation<'tcx>>;
fn span(&self) -> rustc_span::Span {
self.obligation.cause.span
}
fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
// FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
// This most likely means that the goal just didn't unify at all, e.g. a param
// candidate with an alias in it.
let candidates = goal.candidates();
let [candidate] = candidates.as_slice() else {
return ControlFlow::Break(self.obligation.clone());
};
// FIXME: Could we extract a trait ref from a projection here too?
// FIXME: Also, what about considering >1 layer up the stack? May be necessary
// for normalizes-to.
let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else {
return ControlFlow::Break(self.obligation.clone());
};
let tcx = goal.infcx().tcx;
let mut impl_where_bound_count = 0;
for nested_goal in candidate.instantiate_nested_goals(self.span()) {
let obligation;
match nested_goal.source() {
GoalSource::Misc => {
continue;
}
GoalSource::ImplWhereBound => {
obligation = Obligation {
cause: derive_cause(
tcx,
candidate.kind(),
self.obligation.cause.clone(),
impl_where_bound_count,
parent_trait_pred,
),
param_env: nested_goal.goal().param_env,
predicate: nested_goal.goal().predicate,
recursion_depth: self.obligation.recursion_depth + 1,
};
impl_where_bound_count += 1;
}
GoalSource::InstantiateHigherRanked => {
obligation = self.obligation.clone();
}
}
// Skip nested goals that hold.
//FIXME: We should change the max allowed certainty based on if we're
// visiting an ambiguity or error obligation.
if matches!(nested_goal.result(), Ok(Certainty::Yes)) {
continue;
}
self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
}
ControlFlow::Break(self.obligation.clone())
}
}
fn derive_cause<'tcx>(
tcx: TyCtxt<'tcx>,
candidate_kind: ProbeKind<'tcx>,
mut cause: ObligationCause<'tcx>,
idx: usize,
parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> ObligationCause<'tcx> {
match candidate_kind {
ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } => {
if let Some((_, span)) =
tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx)
{
cause = cause.derived_cause(parent_trait_pred, |derived| {
traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause {
derived,
impl_or_alias_def_id: impl_def_id,
impl_def_predicate_index: Some(idx),
span,
}))
})
}
}
ProbeKind::TraitCandidate { source: CandidateSource::BuiltinImpl(..), result: _ } => {
cause = cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation);
}
_ => {}
};
cause
}

View File

@ -41,6 +41,7 @@ pub struct InspectGoal<'a, 'tcx> {
result: Result<Certainty, NoSolution>,
evaluation_kind: inspect::CanonicalGoalEvaluationKind<'tcx>,
normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
source: GoalSource,
}
/// The expected term of a `NormalizesTo` goal gets replaced
@ -90,7 +91,7 @@ fn constrain(
pub struct InspectCandidate<'a, 'tcx> {
goal: &'a InspectGoal<'a, 'tcx>,
kind: inspect::ProbeKind<'tcx>,
nested_goals: Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>,
final_state: inspect::CanonicalState<'tcx, ()>,
result: QueryResult<'tcx>,
shallow_certainty: Certainty,
@ -125,10 +126,8 @@ pub fn shallow_certainty(&self) -> Certainty {
/// back their inference constraints. This function modifies
/// the state of the `infcx`.
pub fn visit_nested_no_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
if self.goal.depth < visitor.config().max_depth {
for goal in self.instantiate_nested_goals(visitor.span()) {
try_visit!(visitor.visit_goal(&goal));
}
try_visit!(goal.visit_with(visitor));
}
V::Result::output()
@ -143,13 +142,16 @@ pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>>
let instantiated_goals: Vec<_> = self
.nested_goals
.iter()
.map(|goal| {
.map(|(source, goal)| {
(
*source,
canonical::instantiate_canonical_state(
infcx,
span,
param_env,
&mut orig_values,
*goal,
),
)
})
.collect();
@ -171,7 +173,7 @@ pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>>
instantiated_goals
.into_iter()
.map(|goal| match goal.predicate.kind().no_bound_vars() {
.map(|(source, goal)| match goal.predicate.kind().no_bound_vars() {
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
let unconstrained_term = match term.unpack() {
ty::TermKind::Ty(_) => infcx
@ -195,6 +197,7 @@ pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>>
self.goal.depth + 1,
proof_tree.unwrap(),
Some(NormalizesToTermHack { term, unconstrained_term }),
source,
)
}
_ => InspectGoal::new(
@ -202,6 +205,7 @@ pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>>
self.goal.depth + 1,
infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(),
None,
source,
),
})
.collect()
@ -227,16 +231,23 @@ pub fn result(&self) -> Result<Certainty, NoSolution> {
self.result
}
pub fn source(&self) -> GoalSource {
self.source
}
fn candidates_recur(
&'a self,
candidates: &mut Vec<InspectCandidate<'a, 'tcx>>,
nested_goals: &mut Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
nested_goals: &mut Vec<(
GoalSource,
inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>,
)>,
probe: &inspect::Probe<'tcx>,
) {
let mut shallow_certainty = None;
for step in &probe.steps {
match step {
&inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal),
&inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
inspect::ProbeStep::NestedProbe(ref probe) => {
// Nested probes have to prove goals added in their parent
// but do not leak them, so we truncate the added goals
@ -319,6 +330,7 @@ fn new(
depth: usize,
root: inspect::GoalEvaluation<'tcx>,
normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
source: GoalSource,
) -> Self {
let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root;
let inspect::GoalEvaluationKind::Root { orig_values } = kind else { unreachable!() };
@ -341,8 +353,17 @@ fn new(
result,
evaluation_kind: evaluation.kind,
normalizes_to_term_hack,
source,
}
}
pub(crate) fn visit_with<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
if self.depth < visitor.config().max_depth {
try_visit!(visitor.visit_goal(self));
}
V::Result::output()
}
}
/// The public API to interact with proof trees.
@ -367,6 +388,6 @@ fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>(
) -> V::Result {
let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
let proof_tree = proof_tree.unwrap();
visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None))
visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None, GoalSource::Misc))
}
}

View File

@ -389,7 +389,7 @@ fn consider_builtin_fn_trait_candidates(
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
goal,
pred,
[goal.with(tcx, output_is_sized_pred)],
[(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))],
)
}
@ -473,7 +473,8 @@ fn consider_builtin_async_fn_trait_candidates(
pred,
[goal.with(tcx, output_is_sized_pred)]
.into_iter()
.chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))),
.chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred)))
.map(|goal| (GoalSource::ImplWhereBound, goal)),
)
}

View File

@ -321,7 +321,7 @@ fn consider_builtin_fn_trait_candidates(
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
goal,
pred,
[goal.with(tcx, output_is_sized_pred)],
[(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))],
)
}
@ -367,7 +367,8 @@ fn consider_builtin_async_fn_trait_candidates(
pred,
[goal.with(tcx, output_is_sized_pred)]
.into_iter()
.chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))),
.chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred)))
.map(|goal| (GoalSource::ImplWhereBound, goal)),
)
}

View File

@ -186,7 +186,6 @@
#![feature(ptr_metadata)]
#![feature(set_ptr_value)]
#![feature(slice_ptr_get)]
#![feature(split_at_checked)]
#![feature(str_internals)]
#![feature(str_split_inclusive_remainder)]
#![feature(str_split_remainder)]

View File

@ -2051,8 +2051,6 @@ pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
/// # Examples
///
/// ```
/// #![feature(split_at_checked)]
///
/// let v = [1, -2, 3, -4, 5, -6];
///
/// {
@ -2075,8 +2073,8 @@ pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
///
/// assert_eq!(None, v.split_at_checked(7));
/// ```
#[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
#[rustc_const_unstable(feature = "split_at_checked", issue = "119128")]
#[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
#[inline]
#[must_use]
pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> {
@ -2102,8 +2100,6 @@ pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> {
/// # Examples
///
/// ```
/// #![feature(split_at_checked)]
///
/// let mut v = [1, 0, 3, 0, 5, 6];
///
/// if let Some((left, right)) = v.split_at_mut_checked(2) {
@ -2116,8 +2112,8 @@ pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> {
///
/// assert_eq!(None, v.split_at_mut_checked(7));
/// ```
#[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
#[rustc_const_unstable(feature = "split_at_checked", issue = "119128")]
#[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")]
#[inline]
#[must_use]
pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> {

View File

@ -721,8 +721,6 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
/// # Examples
///
/// ```
/// #![feature(split_at_checked)]
///
/// let s = "Per Martin-Löf";
///
/// let (first, last) = s.split_at_checked(3).unwrap();
@ -734,7 +732,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
/// ```
#[inline]
#[must_use]
#[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
#[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
// is_char_boundary checks that the index is in [0, .len()]
if self.is_char_boundary(mid) {
@ -761,8 +759,6 @@ pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
/// # Examples
///
/// ```
/// #![feature(split_at_checked)]
///
/// let mut s = "Per Martin-Löf".to_string();
/// if let Some((first, last)) = s.split_at_mut_checked(3) {
/// first.make_ascii_uppercase();
@ -776,7 +772,7 @@ pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
/// ```
#[inline]
#[must_use]
#[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
#[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> {
// is_char_boundary checks that the index is in [0, .len()]
if self.is_char_boundary(mid) {

View File

@ -74,7 +74,7 @@ macro_rules! rtunwrap {
//
// Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to
// `SIG_IGN`. Applications have good reasons to want a different behavior
// though, so there is a `#[unix_sigpipe = "..."]` attribute on `fn main()` that
// though, so there is a `-Zon-broken-pipe` compiler flag that
// can be used to select how `SIGPIPE` shall be setup (if changed at all) before
// `fn main()` is called. See <https://github.com/rust-lang/rust/issues/97889>
// for more info.

View File

@ -55,8 +55,8 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// want!
//
// Hence, we set SIGPIPE to ignore when the program starts up in order
// to prevent this problem. Add `#[unix_sigpipe = "..."]` above `fn main()` to
// alter this behavior.
// to prevent this problem. Use `-Zon-broken-pipe=...` to alter this
// behavior.
reset_sigpipe(sigpipe);
stack_overflow::init();
@ -190,7 +190,7 @@ mod sigpipe {
_ => unreachable!(),
};
if sigpipe_attr_specified {
UNIX_SIGPIPE_ATTR_SPECIFIED.store(true, crate::sync::atomic::Ordering::Relaxed);
ON_BROKEN_PIPE_FLAG_USED.store(true, crate::sync::atomic::Ordering::Relaxed);
}
if let Some(handler) = handler {
rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR);
@ -210,7 +210,7 @@ mod sigpipe {
target_os = "fuchsia",
target_os = "horizon",
)))]
static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool =
static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool =
crate::sync::atomic::AtomicBool::new(false);
#[cfg(not(any(
@ -219,8 +219,8 @@ mod sigpipe {
target_os = "fuchsia",
target_os = "horizon",
)))]
pub(crate) fn unix_sigpipe_attr_specified() -> bool {
UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed)
pub(crate) fn on_broken_pipe_flag_used() -> bool {
ON_BROKEN_PIPE_FLAG_USED.load(crate::sync::atomic::Ordering::Relaxed)
}
// SAFETY: must be called only once during runtime cleanup.

View File

@ -353,11 +353,11 @@ unsafe fn do_exec(
// Inherit the signal mask from the parent rather than resetting it (i.e. do not call
// pthread_sigmask).
// If #[unix_sigpipe] is specified, don't reset SIGPIPE to SIG_DFL.
// If #[unix_sigpipe] is not specified, reset SIGPIPE to SIG_DFL for backward compatibility.
// If -Zon-broken-pipe is used, don't reset SIGPIPE to SIG_DFL.
// If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility.
//
// #[unix_sigpipe] is an opportunity to change the default here.
if !crate::sys::pal::unix_sigpipe_attr_specified() {
// -Zon-broken-pipe is an opportunity to change the default here.
if !crate::sys::pal::on_broken_pipe_flag_used() {
#[cfg(target_os = "android")] // see issue #88585
{
let mut action: libc::sigaction = mem::zeroed();
@ -450,7 +450,7 @@ fn posix_spawn(
) -> io::Result<Option<Process>> {
use crate::mem::MaybeUninit;
use crate::sys::weak::weak;
use crate::sys::{self, cvt_nz, unix_sigpipe_attr_specified};
use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used};
if self.get_gid().is_some()
|| self.get_uid().is_some()
@ -612,11 +612,11 @@ fn drop(&mut self) {
// Inherit the signal mask from this process rather than resetting it (i.e. do not call
// posix_spawnattr_setsigmask).
// If #[unix_sigpipe] is specified, don't reset SIGPIPE to SIG_DFL.
// If #[unix_sigpipe] is not specified, reset SIGPIPE to SIG_DFL for backward compatibility.
// If -Zon-broken-pipe is used, don't reset SIGPIPE to SIG_DFL.
// If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility.
//
// #[unix_sigpipe] is an opportunity to change the default here.
if !unix_sigpipe_attr_specified() {
// -Zon-broken-pipe is an opportunity to change the default here.
if !on_broken_pipe_flag_used() {
let mut default_set = MaybeUninit::<libc::sigset_t>::uninit();
cvt(sigemptyset(default_set.as_mut_ptr()))?;
cvt(sigaddset(default_set.as_mut_ptr(), libc::SIGPIPE))?;

View File

@ -589,7 +589,9 @@ pub fn run_test(
// If the platform is single-threaded we're just going to run
// the test synchronously, regardless of the concurrency
// level.
let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm");
let supports_threads = !cfg!(target_os = "emscripten")
&& !cfg!(target_family = "wasm")
&& !cfg!(target_os = "zkvm");
if supports_threads {
let cfg = thread::Builder::new().name(name.as_slice().to_owned());
let mut runtest = Arc::new(Mutex::new(Some(runtest)));

View File

@ -1006,6 +1006,13 @@ pub fn rustc_cargo(
cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
// If the rustc output is piped to e.g. `head -n1` we want the process to be
// killed, rather than having an error bubble up and cause a panic.
// FIXME: Synthetic #[cfg(bootstrap)]. Remove when the bootstrap compiler supports it.
if compiler.stage != 0 {
cargo.rustflag("-Zon-broken-pipe=kill");
}
// We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary
// and may just be a time sink.
if compiler.stage != 0 {

View File

@ -471,7 +471,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
features.push("jemalloc".to_string());
}
let cargo = prepare_tool_cargo(
let mut cargo = prepare_tool_cargo(
builder,
build_compiler,
Mode::ToolRustc,
@ -482,6 +482,14 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
features.as_slice(),
);
// If the rustdoc output is piped to e.g. `head -n1` we want the process
// to be killed, rather than having an error bubble up and cause a
// panic.
// FIXME: Synthetic #[cfg(bootstrap)]. Remove when the bootstrap compiler supports it.
if build_compiler.stage > 0 {
cargo.rustflag("-Zon-broken-pipe=kill");
}
let _guard = builder.msg_tool(
Kind::Build,
Mode::ToolRustc,

View File

@ -0,0 +1,84 @@
# `on-broken-pipe`
--------------------
The tracking issue for this feature is: [#97889]
Note: The ui for this feature was previously an attribute named `#[unix_sigpipe = "..."]`.
[#97889]: https://github.com/rust-lang/rust/issues/97889
---
## Overview
The `-Zon-broken-pipe=...` compiler flag can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This flag is ignored on non-Unix targets. The flag can be used with three different values or be omitted entirely. It affects `SIGPIPE` before `fn main()` and before children get `exec()`'ed:
| Compiler flag | `SIGPIPE` before `fn main()` | `SIGPIPE` before child `exec()` |
|----------------------------|------------------------------|---------------------------------|
| not used | `SIG_IGN` | `SIG_DFL` |
| `-Zon-broken-pipe=kill` | `SIG_DFL` | not touched |
| `-Zon-broken-pipe=error` | `SIG_IGN` | not touched |
| `-Zon-broken-pipe=inherit` | not touched | not touched |
## `-Zon-broken-pipe` not used
If `-Zon-broken-pipe` is not used, libstd will behave in the manner it has since 2014, before Rust 1.0. `SIGPIPE` will be set to `SIG_IGN` before `fn main()` and result in `EPIPE` errors which are converted to `std::io::ErrorKind::BrokenPipe`.
When spawning child processes, `SIGPIPE` will be set to `SIG_DFL` before doing the underlying `exec()` syscall.
## `-Zon-broken-pipe=kill`
Set the `SIGPIPE` handler to `SIG_DFL` before invoking `fn main()`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output.
When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_DFL` for `SIGPIPE`.
### Example
```rust,no_run
fn main() {
loop {
println!("hello world");
}
}
```
```console
$ rustc -Zon-broken-pipe=kill main.rs
$ ./main | head -n1
hello world
```
## `-Zon-broken-pipe=error`
Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers.
When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_IGN` for `SIGPIPE`.
### Example
```rust,no_run
fn main() {
loop {
println!("hello world");
}
}
```
```console
$ rustc -Zon-broken-pipe=error main.rs
$ ./main | head -n1
hello world
thread 'main' panicked at library/std/src/io/stdio.rs:1118:9:
failed printing to stdout: Broken pipe (os error 32)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
## `-Zon-broken-pipe=inherit`
Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `-Zon-broken-pipe=kill`.
When spawning child processes, `SIGPIPE` will not be touched. This normally means child processes inherit `SIG_DFL` for `SIGPIPE`.

View File

@ -1,62 +0,0 @@
# `unix_sigpipe`
The tracking issue for this feature is: [#97889]
[#97889]: https://github.com/rust-lang/rust/issues/97889
---
The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants:
* `#[unix_sigpipe = "inherit"]`
* `#[unix_sigpipe = "sig_dfl"]`
* `#[unix_sigpipe = "sig_ign"]`
## `#[unix_sigpipe = "inherit"]`
Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`.
## `#[unix_sigpipe = "sig_dfl"]`
Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output.
### Example
```rust,no_run
#![feature(unix_sigpipe)]
#[unix_sigpipe = "sig_dfl"]
fn main() { loop { println!("hello world"); } }
```
```bash
% ./main | head -n 1
hello world
```
## `#[unix_sigpipe = "sig_ign"]`
Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers.
This is what libstd has done by default since 2014. (However, see the note on child processes below.)
### Example
```rust,no_run
#![feature(unix_sigpipe)]
#[unix_sigpipe = "sig_ign"]
fn main() { loop { println!("hello world"); } }
```
```bash
% ./main | head -n 1
hello world
thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
### Note on child processes
When spawning child processes, the legacy Rust behavior if `#[unix_sigpipe]` is not specified is to
reset `SIGPIPE` to `SIG_DFL`.
If `#[unix_sigpipe = "..."]` is specified, no matter what its value is, the signal disposition of
`SIGPIPE` is no longer reset. This means that the child inherits the parent's `SIGPIPE` behavior.

View File

@ -387,7 +387,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
let main_ptr = ecx.fn_ptr(FnVal::Instance(entry_instance));
// Always using DEFAULT is okay since we don't support signals in Miri anyway.
// (This means we are effectively ignoring `#[unix_sigpipe]`.)
// (This means we are effectively ignoring `-Zon-broken-pipe`.)
let sigpipe = rustc_session::config::sigpipe::DEFAULT;
ecx.call_function(

View File

@ -261,6 +261,12 @@ pub fn run_fail(&mut self) -> ::std::process::Output {
}
output
}
/// Set the path where the command will be run.
pub fn current_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.current_dir(path);
self
}
}
};
}

View File

@ -207,7 +207,6 @@ macro_rules! experimental {
),
// Entry point:
gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)),
ungated!(start, Normal, template!(Word), WarnFollowing),
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),

View File

@ -1,6 +1,3 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe = "sig_dfl"]
fn main() {
rustdoc::main()
}

View File

@ -44,7 +44,6 @@ run-make/dep-graph/Makefile
run-make/dep-info-doesnt-run-much/Makefile
run-make/dep-info-spaces/Makefile
run-make/dep-info/Makefile
run-make/doctests-keep-binaries/Makefile
run-make/doctests-runtool/Makefile
run-make/dump-ice-to-disk/Makefile
run-make/dump-mono-stats/Makefile

View File

@ -1,33 +0,0 @@
# ignore-cross-compile
include ../tools.mk
# Check that valid binaries are persisted by running them, regardless of whether the --run or --no-run option is used.
MY_SRC_DIR := ${CURDIR}
all: run no_run test_run_directory
run:
mkdir -p $(TMPDIR)/doctests
$(RUSTC) --crate-type rlib t.rs
$(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs
$(TMPDIR)/doctests/t_rs_2_0/rust_out
$(TMPDIR)/doctests/t_rs_8_0/rust_out
rm -rf $(TMPDIR)/doctests
no_run:
mkdir -p $(TMPDIR)/doctests
$(RUSTC) --crate-type rlib t.rs
$(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs --no-run
$(TMPDIR)/doctests/t_rs_2_0/rust_out
$(TMPDIR)/doctests/t_rs_8_0/rust_out
rm -rf $(TMPDIR)/doctests
# Behavior with --test-run-directory with relative paths.
test_run_directory:
mkdir -p $(TMPDIR)/doctests
mkdir -p $(TMPDIR)/rundir
$(RUSTC) --crate-type rlib t.rs
( cd $(TMPDIR); \
$(RUSTDOC) -Zunstable-options --test --persist-doctests doctests --test-run-directory rundir --extern t=libt.rlib $(MY_SRC_DIR)/t.rs )
rm -rf $(TMPDIR)/doctests $(TMPDIR)/rundir

View File

@ -0,0 +1,68 @@
// Check that valid binaries are persisted by running them, regardless of whether the
// --run or --no-run option is used.
use run_make_support::{run, rustc, rustdoc, tmp_dir};
use std::fs::{create_dir, remove_dir_all};
use std::path::Path;
fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) {
let out_dir = tmp_dir().join("doctests");
create_dir(&out_dir).expect("failed to create doctests folder");
rustc().input("t.rs").crate_type("rlib").run();
callback(&out_dir, &tmp_dir().join("libt.rlib"));
remove_dir_all(out_dir);
}
fn check_generated_binaries() {
run("doctests/t_rs_2_0/rust_out");
run("doctests/t_rs_8_0/rust_out");
}
fn main() {
setup_test_env(|out_dir, extern_path| {
rustdoc()
.input("t.rs")
.arg("-Zunstable-options")
.arg("--test")
.arg("--persist-doctests")
.arg(out_dir)
.arg("--extern")
.arg(format!("t={}", extern_path.display()))
.run();
check_generated_binaries();
});
setup_test_env(|out_dir, extern_path| {
rustdoc()
.input("t.rs")
.arg("-Zunstable-options")
.arg("--test")
.arg("--persist-doctests")
.arg(out_dir)
.arg("--extern")
.arg(format!("t={}", extern_path.display()))
.arg("--no-run")
.run();
check_generated_binaries();
});
// Behavior with --test-run-directory with relative paths.
setup_test_env(|_out_dir, extern_path| {
let run_dir = "rundir";
let run_dir_path = tmp_dir().join("rundir");
create_dir(&run_dir_path).expect("failed to create rundir folder");
rustdoc()
.current_dir(tmp_dir())
.input(std::env::current_dir().unwrap().join("t.rs"))
.arg("-Zunstable-options")
.arg("--test")
.arg("--persist-doctests")
.arg("doctests")
.arg("--test-run-directory")
.arg(run_dir)
.arg("--extern")
.arg("t=libt.rlib")
.run();
remove_dir_all(run_dir_path);
});
}

View File

@ -1,4 +0,0 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe] //~ error: malformed `unix_sigpipe` attribute input
fn main() {}

View File

@ -1,8 +0,0 @@
error: malformed `unix_sigpipe` attribute input
--> $DIR/unix_sigpipe-bare.rs:3:1
|
LL | #[unix_sigpipe]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`
error: aborting due to 1 previous error

View File

@ -1,4 +0,0 @@
#![feature(unix_sigpipe)]
#![unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute cannot be used at crate level
fn main() {}

View File

@ -1,17 +0,0 @@
error: `unix_sigpipe` attribute cannot be used at crate level
--> $DIR/unix_sigpipe-crate.rs:2:1
|
LL | #![unix_sigpipe = "sig_dfl"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | fn main() {}
| ---- the inner attribute doesn't annotate this function
|
help: perhaps you meant to use an outer attribute
|
LL - #![unix_sigpipe = "sig_dfl"]
LL + #[unix_sigpipe = "sig_dfl"]
|
error: aborting due to 1 previous error

View File

@ -1,5 +0,0 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe = "sig_ign"]
#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
fn main() {}

View File

@ -1,14 +0,0 @@
error: multiple `unix_sigpipe` attributes
--> $DIR/unix_sigpipe-different-duplicates.rs:4:1
|
LL | #[unix_sigpipe = "inherit"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unix_sigpipe-different-duplicates.rs:3:1
|
LL | #[unix_sigpipe = "sig_ign"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -1,5 +0,0 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe = "inherit"]
#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
fn main() {}

View File

@ -1,14 +0,0 @@
error: multiple `unix_sigpipe` attributes
--> $DIR/unix_sigpipe-duplicates.rs:4:1
|
LL | #[unix_sigpipe = "inherit"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unix_sigpipe-duplicates.rs:3:1
|
LL | #[unix_sigpipe = "inherit"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -1,4 +0,0 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe(sig_dfl)] //~ error: malformed `unix_sigpipe` attribute input
fn main() {}

View File

@ -1,8 +0,0 @@
error: malformed `unix_sigpipe` attribute input
--> $DIR/unix_sigpipe-ident-list.rs:3:1
|
LL | #[unix_sigpipe(sig_dfl)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`
error: aborting due to 1 previous error

View File

@ -1,6 +0,0 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
fn f() {}
fn main() {}

View File

@ -1,8 +0,0 @@
error: `unix_sigpipe` attribute can only be used on `fn main()`
--> $DIR/unix_sigpipe-non-main-fn.rs:3:1
|
LL | #[unix_sigpipe = "sig_dfl"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -1,8 +0,0 @@
#![feature(unix_sigpipe)]
mod m {
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()`
fn main() {}
}
fn main() {}

View File

@ -1,8 +0,0 @@
error: `unix_sigpipe` attribute can only be used on root `fn main()`
--> $DIR/unix_sigpipe-non-root-main.rs:4:5
|
LL | #[unix_sigpipe = "sig_dfl"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -1,6 +0,0 @@
#![feature(start)]
#![feature(unix_sigpipe)]
#[start]
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 }

View File

@ -1,8 +0,0 @@
error: `unix_sigpipe` attribute can only be used on `fn main()`
--> $DIR/unix_sigpipe-start.rs:5:1
|
LL | #[unix_sigpipe = "sig_dfl"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -1,4 +0,0 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe("sig_dfl")] //~ error: malformed `unix_sigpipe` attribute input
fn main() {}

View File

@ -1,8 +0,0 @@
error: malformed `unix_sigpipe` attribute input
--> $DIR/unix_sigpipe-str-list.rs:3:1
|
LL | #[unix_sigpipe("sig_dfl")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`
error: aborting due to 1 previous error

View File

@ -1,6 +0,0 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
struct S;
fn main() {}

View File

@ -1,8 +0,0 @@
error: `unix_sigpipe` attribute can only be used on `fn main()`
--> $DIR/unix_sigpipe-struct.rs:3:1
|
LL | #[unix_sigpipe = "sig_dfl"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -1,4 +0,0 @@
#![feature(unix_sigpipe)]
#[unix_sigpipe = "wrong"] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
fn main() {}

View File

@ -1,8 +0,0 @@
error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
--> $DIR/unix_sigpipe-wrong.rs:3:1
|
LL | #[unix_sigpipe = "wrong"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -11,7 +11,7 @@ error[E0282]: type annotations needed
--> $DIR/opaques.rs:13:20
|
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
| ^ cannot infer type for struct `Container<T, T>`
| ^ cannot infer type for associated type `<T as Trait<T>>::Assoc`
error: aborting due to 2 previous errors

View File

@ -1,4 +0,0 @@
#![crate_type = "bin"]
#[unix_sigpipe = "inherit"] //~ the `#[unix_sigpipe]` attribute is an experimental feature
fn main () {}

View File

@ -1,13 +0,0 @@
error[E0658]: the `#[unix_sigpipe]` attribute is an experimental feature
--> $DIR/feature-gate-unix_sigpipe.rs:3:1
|
LL | #[unix_sigpipe = "inherit"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #97889 <https://github.com/rust-lang/rust/issues/97889> for more information
= help: add `#![feature(unix_sigpipe)]` 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: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -2,9 +2,14 @@ error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
--> $DIR/issue-20605.rs:6:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^ `dyn Iterator<Item = &'a mut u8>` is not an iterator
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
|
= help: the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
= note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
= note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
help: consider mutably borrowing here
|
LL | for item in &mut *things { *item = 0 }
| ++++
error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:6:17

View File

@ -23,7 +23,20 @@ error[E0283]: type annotations needed
LL | impls_indirect_leak::<Box<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak`
|
= note: cannot satisfy `for<'a> Box<_>: IndirectLeak<'a>`
note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found
--> $DIR/leak-check-in-selection-3.rs:9:1
|
LL | impl Leak<'_> for Box<u32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl Leak<'static> for Box<u16> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required for `Box<_>` to implement `for<'a> IndirectLeak<'a>`
--> $DIR/leak-check-in-selection-3.rs:23:23
|
LL | impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
| -------- ^^^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `impls_indirect_leak`
--> $DIR/leak-check-in-selection-3.rs:25:27
|

View File

@ -6,16 +6,14 @@
//@ ignore-horizon
//@ ignore-android
//@ normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
//@ compile-flags: -Zon-broken-pipe=error
// Test what the error message looks like when `println!()` panics because of
// `std::io::ErrorKind::BrokenPipe`
#![feature(unix_sigpipe)]
use std::env;
use std::process::{Command, Stdio};
#[unix_sigpipe = "sig_ign"]
fn main() {
let mut args = env::args();
let me = args.next().unwrap();

View File

@ -1,8 +1,6 @@
//@ aux-crate: sigpipe_utils=sigpipe-utils.rs
//@ compile-flags: -Zon-broken-pipe=inherit
#![feature(unix_sigpipe)]
#[unix_sigpipe = "inherit"]
fn main() {
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
}

View File

@ -1,8 +1,6 @@
//@ aux-crate: sigpipe_utils=sigpipe-utils.rs
//@ compile-flags: -Zon-broken-pipe=inherit
#![feature(unix_sigpipe)]
#[unix_sigpipe = "inherit"]
fn main() {
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
}

View File

@ -1,25 +1,20 @@
//@ revisions: default sig_dfl sig_ign inherit
//@ revisions: default error kill inherit
//@ ignore-cross-compile because aux-bin does not yet support it
//@ only-unix because SIGPIPE is a unix thing
//@ run-pass
//@ aux-bin:assert-sigpipe-disposition.rs
//@ aux-crate:sigpipe_utils=sigpipe-utils.rs
//@ [kill] compile-flags: -Zunstable-options -Zon-broken-pipe=kill
//@ [error] compile-flags: -Zunstable-options -Zon-broken-pipe=error
//@ [inherit] compile-flags: -Zunstable-options -Zon-broken-pipe=inherit
// Checks the signal disposition of `SIGPIPE` in child processes, and in our own
// process for robustness. Without any `unix_sigpipe` attribute, `SIG_IGN` is
// the default. But there is a difference in how `SIGPIPE` is treated in child
// processes with and without the attribute. Search for
// `unix_sigpipe_attr_specified()` in the code base to learn more.
#![cfg_attr(any(sig_dfl, sig_ign, inherit), feature(unix_sigpipe))]
// process for robustness.
extern crate sigpipe_utils;
use sigpipe_utils::*;
#[cfg_attr(sig_dfl, unix_sigpipe = "sig_dfl")]
#[cfg_attr(sig_ign, unix_sigpipe = "sig_ign")]
#[cfg_attr(inherit, unix_sigpipe = "inherit")]
fn main() {
// By default we get SIG_IGN but the child gets SIG_DFL through an explicit
// reset before exec:
@ -27,18 +22,18 @@ fn main() {
#[cfg(default)]
let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_DFL");
// With #[unix_sigpipe = "sig_dfl"] we get SIG_DFL and the child does too
// without any special code running before exec.
#[cfg(sig_dfl)]
// We get SIG_DFL and the child does too without any special code running
// before exec.
#[cfg(kill)]
let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL");
// With #[unix_sigpipe = "sig_ign"] we get SIG_IGN and the child does too
// without any special code running before exec.
#[cfg(sig_ign)]
// We get SIG_IGN and the child does too without any special code running
// before exec.
#[cfg(error)]
let (we_expect, child_expects) = (SignalHandler::Ignore, "SIG_IGN");
// With #[unix_sigpipe = "inherit"] we get SIG_DFL and the child does too
// without any special code running before exec.
// We get SIG_DFL and the child does too without any special code running
// before exec.
#[cfg(inherit)]
let (we_expect, child_expects) = (SignalHandler::Default, "SIG_DFL");

View File

@ -0,0 +1,4 @@
//@ compile-flags: -Zon-broken-pipe=default
//@ check-fail
fn main() {}

View File

@ -0,0 +1,2 @@
error: incorrect value `default` for unstable option `on-broken-pipe` - either `kill`, `error`, or `inherit` was expected

View File

@ -1,12 +1,10 @@
//@ revisions: with_feature without_feature
//@ run-pass
//@ aux-build:sigpipe-utils.rs
#![cfg_attr(with_feature, feature(unix_sigpipe))]
//@ compile-flags: -Zon-broken-pipe=error
fn main() {
extern crate sigpipe_utils;
// SIGPIPE shall be ignored since #[unix_sigpipe = "..."] is not used
// `-Zon-broken-pipe=error` is active, so we expect SIGPIPE to be ignored.
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
}

View File

@ -3,20 +3,20 @@
//@ aux-bin: assert-inherit-sig_dfl.rs
//@ aux-bin: assert-inherit-sig_ign.rs
//@ run-pass
//@ compile-flags: -Zon-broken-pipe=kill
#![feature(rustc_private, unix_sigpipe)]
#![feature(rustc_private)]
extern crate libc;
// By default the Rust runtime resets SIGPIPE to SIG_DFL before exec'ing child
// processes so opt-out of that with `#[unix_sigpipe = "sig_dfl"]`. See
// processes so opt-out of that with `-Zon-broken-pipe=kill`. See
// https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L359-L384
#[unix_sigpipe = "sig_dfl"]
fn main() {
// First expect SIG_DFL in a child process with #[unix_sigpipe = "inherit"].
// First expect SIG_DFL in a child process with -`Zon-broken-pipe=inherit`.
assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_dfl");
// With SIG_IGN we expect #[unix_sigpipe = "inherit"] to also get SIG_IGN.
// With SIG_IGN we expect `-Zon-broken-pipe=inherit` to also get SIG_IGN.
unsafe {
libc::signal(libc::SIGPIPE, libc::SIG_IGN);
}

View File

@ -1,13 +1,11 @@
//@ run-pass
//@ aux-build:sigpipe-utils.rs
//@ compile-flags: -Zon-broken-pipe=kill
#![feature(unix_sigpipe)]
#[unix_sigpipe = "sig_dfl"]
fn main() {
extern crate sigpipe_utils;
// #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE shall NOT be ignored, instead
// `-Zon-broken-pipe=kill` is active, so SIGPIPE shall NOT be ignored, instead
// the default handler shall be installed
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
}

View File

@ -0,0 +1,4 @@
//@ compile-flags: -Zon-broken-pipe
//@ check-fail
fn main() {}

View File

@ -0,0 +1,2 @@
error: unstable option `on-broken-pipe` requires either `kill`, `error`, or `inherit` (Z on-broken-pipe=<value>)

View File

@ -1,13 +1,9 @@
//@ run-pass
//@ aux-build:sigpipe-utils.rs
#![feature(unix_sigpipe)]
#[unix_sigpipe = "sig_ign"]
fn main() {
extern crate sigpipe_utils;
// #[unix_sigpipe = "sig_ign"] is active, so the legacy behavior of ignoring
// SIGPIPE shall be in effect
// SIGPIPE shall be ignored since `-Zon-broken-pipe` is not used
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
}

View File

@ -1,15 +1,14 @@
//@ run-pass
//@ aux-build:sigpipe-utils.rs
//@ compile-flags: -Zon-broken-pipe=kill
#![feature(unix_sigpipe)]
#![feature(rustc_attrs)]
#[unix_sigpipe = "sig_dfl"]
#[rustc_main]
fn rustc_main() {
extern crate sigpipe_utils;
// #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE handler shall be
// `-Zon-broken-pipe=kill` is active, so SIGPIPE handler shall be
// SIG_DFL. Note that we have a #[rustc_main], but it should still work.
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
}

View File

@ -0,0 +1,4 @@
//@ compile-flags: -Zon-broken-pipe=wrong
//@ check-fail
fn main() {}

View File

@ -0,0 +1,2 @@
error: incorrect value `wrong` for unstable option `on-broken-pipe` - either `kill`, `error`, or `inherit` was expected

View File

@ -1,18 +1,26 @@
error[E0277]: `impl Future<Output = ()>` cannot be sent between threads safely
error: future cannot be sent between threads safely
--> $DIR/auto-with-drop_tracking_mir.rs:25:13
|
LL | is_send(foo());
| ------- ^^^^^ `impl Future<Output = ()>` cannot be sent between threads safely
| |
| required by a bound introduced by this call
| ^^^^^ future returned by `foo` is not `Send`
|
= help: the trait `Send` is not implemented for `impl Future<Output = ()>`
= help: the trait `Sync` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send`
note: future is not `Send` as this value is used across an await
--> $DIR/auto-with-drop_tracking_mir.rs:16:11
|
LL | let x = &NotSync;
| - has type `&NotSync` which is not `Send`
LL | bar().await;
| ^^^^^ await occurs here, with `x` maybe used later
note: required by a bound in `is_send`
--> $DIR/auto-with-drop_tracking_mir.rs:24:24
|
LL | fn is_send(_: impl Send) {}
| ^^^^ required by this bound in `is_send`
help: consider dereferencing here
|
LL | is_send(*foo());
| +
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -23,5 +23,5 @@ async fn bar() {}
fn main() {
fn is_send(_: impl Send) {}
is_send(foo());
//[fail]~^ ERROR `impl Future<Output = ()>` cannot be sent between threads safely
//[fail]~^ ERROR future cannot be sent between threads safely
}

View File

@ -13,5 +13,5 @@ fn foo<F: Fn<T>, T: Tuple>(f: Option<F>, t: T) {
fn main() {
foo::<fn() -> str, _>(None, ());
//~^ expected a `Fn<_>` closure, found `fn() -> str`
//~^ the size for values of type `str` cannot be known at compilation time
}

View File

@ -1,10 +1,11 @@
error[E0277]: expected a `Fn<_>` closure, found `fn() -> str`
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/builtin-fn-must-return-sized.rs:15:11
|
LL | foo::<fn() -> str, _>(None, ());
| ^^^^^^^^^^^ expected an `Fn<_>` closure, found `fn() -> str`
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Fn<_>` is not implemented for `fn() -> str`
= help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>`
= note: required because it appears within the type `fn() -> str`
note: required by a bound in `foo`
--> $DIR/builtin-fn-must-return-sized.rs:10:11
|

Some files were not shown because too many files have changed in this diff Show More