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:
commit
9fa862ff29
@ -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",
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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")]
|
||||
|
@ -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)));
|
||||
|
@ -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" }
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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.
|
||||
|
@ -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> {
|
||||
|
@ -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" }
|
||||
|
@ -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 },
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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:?}")?
|
||||
}
|
||||
|
@ -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}`
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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" }
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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],
|
||||
|
@ -1936,7 +1936,6 @@
|
||||
unit,
|
||||
universal_impl_trait,
|
||||
unix,
|
||||
unix_sigpipe,
|
||||
unlikely,
|
||||
unmarked_api,
|
||||
unnamed_fields,
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
for goal in self.instantiate_nested_goals(visitor.span()) {
|
||||
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| {
|
||||
canonical::instantiate_canonical_state(
|
||||
infcx,
|
||||
span,
|
||||
param_env,
|
||||
&mut orig_values,
|
||||
*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))
|
||||
}
|
||||
}
|
||||
|
@ -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)),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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)),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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])> {
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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))?;
|
||||
|
@ -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)));
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
84
src/doc/unstable-book/src/compiler-flags/on-broken-pipe.md
Normal file
84
src/doc/unstable-book/src/compiler-flags/on-broken-pipe.md
Normal 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`.
|
@ -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.
|
@ -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(
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -1,6 +1,3 @@
|
||||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe = "sig_dfl"]
|
||||
fn main() {
|
||||
rustdoc::main()
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
68
tests/run-make/doctests-keep-binaries/rmake.rs
Normal file
68
tests/run-make/doctests-keep-binaries/rmake.rs
Normal 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);
|
||||
});
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe] //~ error: malformed `unix_sigpipe` attribute input
|
||||
fn main() {}
|
@ -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
|
||||
|
@ -1,4 +0,0 @@
|
||||
#![feature(unix_sigpipe)]
|
||||
#![unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute cannot be used at crate level
|
||||
|
||||
fn main() {}
|
@ -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
|
||||
|
@ -1,5 +0,0 @@
|
||||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe = "sig_ign"]
|
||||
#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
|
||||
fn main() {}
|
@ -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
|
||||
|
@ -1,5 +0,0 @@
|
||||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe = "inherit"]
|
||||
#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
|
||||
fn main() {}
|
@ -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
|
||||
|
@ -1,4 +0,0 @@
|
||||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe(sig_dfl)] //~ error: malformed `unix_sigpipe` attribute input
|
||||
fn main() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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 }
|
@ -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
|
||||
|
@ -1,4 +0,0 @@
|
||||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe("sig_dfl")] //~ error: malformed `unix_sigpipe` attribute input
|
||||
fn main() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
#![crate_type = "bin"]
|
||||
|
||||
#[unix_sigpipe = "inherit"] //~ the `#[unix_sigpipe]` attribute is an experimental feature
|
||||
fn main () {}
|
@ -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`.
|
@ -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
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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");
|
||||
|
4
tests/ui/runtime/on-broken-pipe/default.rs
Normal file
4
tests/ui/runtime/on-broken-pipe/default.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//@ compile-flags: -Zon-broken-pipe=default
|
||||
//@ check-fail
|
||||
|
||||
fn main() {}
|
2
tests/ui/runtime/on-broken-pipe/default.stderr
Normal file
2
tests/ui/runtime/on-broken-pipe/default.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: incorrect value `default` for unstable option `on-broken-pipe` - either `kill`, `error`, or `inherit` was expected
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
4
tests/ui/runtime/on-broken-pipe/no-flag-arg.rs
Normal file
4
tests/ui/runtime/on-broken-pipe/no-flag-arg.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//@ compile-flags: -Zon-broken-pipe
|
||||
//@ check-fail
|
||||
|
||||
fn main() {}
|
2
tests/ui/runtime/on-broken-pipe/no-flag-arg.stderr
Normal file
2
tests/ui/runtime/on-broken-pipe/no-flag-arg.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: unstable option `on-broken-pipe` requires either `kill`, `error`, or `inherit` (Z on-broken-pipe=<value>)
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
4
tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs
Normal file
4
tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//@ compile-flags: -Zon-broken-pipe=wrong
|
||||
//@ check-fail
|
||||
|
||||
fn main() {}
|
2
tests/ui/runtime/on-broken-pipe/wrong-flag-arg.stderr
Normal file
2
tests/ui/runtime/on-broken-pipe/wrong-flag-arg.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: incorrect value `wrong` for unstable option `on-broken-pipe` - either `kill`, `error`, or `inherit` was expected
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user