diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1a80b4fc3140d..5fac485de6417 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -58,8 +58,16 @@ use std::str; use std::sync::LazyLock; use std::time::Instant; +// This import blocks the use of panicking `print` and `println` in all the code +// below. Please use `safe_print` and `safe_println` to avoid ICE when +// encountering an I/O error during print. +#[allow(unused_imports)] +use std::{compile_error as print, compile_error as println}; + pub mod args; pub mod pretty; +#[macro_use] +mod print; mod session_diagnostics; use crate::session_diagnostics::{ @@ -511,7 +519,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { if io::stdout().is_terminal() { show_content_with_pager(&text); } else { - print!("{text}"); + safe_print!("{text}"); } } Err(InvalidErrorCode) => { @@ -547,7 +555,7 @@ fn show_content_with_pager(content: &str) { // If pager fails for whatever reason, we should still print the content // to standard output if fallback_to_println { - print!("{content}"); + safe_print!("{content}"); } } @@ -601,7 +609,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co let path = &(*ifile); let mut v = Vec::new(); locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap(); - println!("{}", String::from_utf8(v).unwrap()); + safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { early_error(ErrorOutputType::default(), "cannot list metadata for stdin"); @@ -642,12 +650,12 @@ fn print_crate_info( TargetList => { let mut targets = rustc_target::spec::TARGETS.to_vec(); targets.sort_unstable(); - println!("{}", targets.join("\n")); + safe_println!("{}", targets.join("\n")); } - Sysroot => println!("{}", sess.sysroot.display()), - TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()), + Sysroot => safe_println!("{}", sess.sysroot.display()), + TargetLibdir => safe_println!("{}", sess.target_tlib_path.dir.display()), TargetSpec => { - println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); + safe_println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); } AllTargetSpecs => { let mut targets = BTreeMap::new(); @@ -656,7 +664,7 @@ fn print_crate_info( let target = Target::expect_builtin(&triple); targets.insert(name, target.to_json()); } - println!("{}", serde_json::to_string_pretty(&targets).unwrap()); + safe_println!("{}", serde_json::to_string_pretty(&targets).unwrap()); } FileNames | CrateName => { let Some(attrs) = attrs.as_ref() else { @@ -666,14 +674,14 @@ fn print_crate_info( let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess); let id = rustc_session::output::find_crate_name(sess, attrs); if *req == PrintRequest::CrateName { - println!("{id}"); + safe_println!("{id}"); continue; } let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { let fname = rustc_session::output::filename_for_input(sess, style, id, &t_outputs); - println!("{}", fname.file_name().unwrap().to_string_lossy()); + safe_println!("{}", fname.file_name().unwrap().to_string_lossy()); } } Cfg => { @@ -707,13 +715,13 @@ fn print_crate_info( cfgs.sort(); for cfg in cfgs { - println!("{cfg}"); + safe_println!("{cfg}"); } } CallingConventions => { let mut calling_conventions = rustc_target::spec::abi::all_names(); calling_conventions.sort_unstable(); - println!("{}", calling_conventions.join("\n")); + safe_println!("{}", calling_conventions.join("\n")); } RelocationModels | CodeModels @@ -733,7 +741,7 @@ fn print_crate_info( let stable = sess.target.options.supported_split_debuginfo.contains(split); let unstable_ok = sess.unstable_options(); if stable || unstable_ok { - println!("{split}"); + safe_println!("{split}"); } } } @@ -770,14 +778,14 @@ pub fn version_at_macro_invocation( ) { let verbose = matches.opt_present("verbose"); - println!("{binary} {version}"); + safe_println!("{binary} {version}"); if verbose { - println!("binary: {binary}"); - println!("commit-hash: {commit_hash}"); - println!("commit-date: {commit_date}"); - println!("host: {}", config::host_triple()); - println!("release: {release}"); + safe_println!("binary: {binary}"); + safe_println!("commit-hash: {commit_hash}"); + safe_println!("commit-date: {commit_date}"); + safe_println!("host: {}", config::host_triple()); + safe_println!("release: {release}"); let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); @@ -807,7 +815,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { } else { "" }; - println!( + safe_println!( "{options}{at_path}\nAdditional help: -C help Print codegen options -W help \ @@ -820,7 +828,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { } fn print_wall_help() { - println!( + safe_println!( " The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by default. Use `rustc -W help` to see all available lints. It's more common to put @@ -832,7 +840,7 @@ the command line flag directly. /// Write to stdout lint command options, together with a list of all available lints pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) { - println!( + safe_println!( " Available lint options: -W Warn about @@ -877,21 +885,21 @@ Available lint options: s }; - println!("Lint checks provided by rustc:\n"); + safe_println!("Lint checks provided by rustc:\n"); let print_lints = |lints: Vec<&Lint>| { - println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); - println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); + safe_println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); + safe_println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); for lint in lints { let name = lint.name_lower().replace('_', "-"); - println!( + safe_println!( " {} {:7.7} {}", padded(&name), lint.default_level(sess.edition()).as_str(), lint.desc ); } - println!("\n"); + safe_println!("\n"); }; print_lints(builtin); @@ -912,14 +920,14 @@ Available lint options: s }; - println!("Lint groups provided by rustc:\n"); + safe_println!("Lint groups provided by rustc:\n"); let print_lint_groups = |lints: Vec<(&'static str, Vec)>, all_warnings| { - println!(" {} sub-lints", padded("name")); - println!(" {} ---------", padded("----")); + safe_println!(" {} sub-lints", padded("name")); + safe_println!(" {} ---------", padded("----")); if all_warnings { - println!(" {} all lints that are set to issue warnings", padded("warnings")); + safe_println!(" {} all lints that are set to issue warnings", padded("warnings")); } for (name, to) in lints { @@ -929,26 +937,26 @@ Available lint options: .map(|x| x.to_string().replace('_', "-")) .collect::>() .join(", "); - println!(" {} {}", padded(&name), desc); + safe_println!(" {} {}", padded(&name), desc); } - println!("\n"); + safe_println!("\n"); }; print_lint_groups(builtin_groups, true); match (loaded_plugins, plugin.len(), plugin_groups.len()) { (false, 0, _) | (false, _, 0) => { - println!("Lint tools like Clippy can provide additional lints and lint groups."); + safe_println!("Lint tools like Clippy can provide additional lints and lint groups."); } (false, ..) => panic!("didn't load lint plugins but got them anyway!"), - (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."), + (true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."), (true, l, g) => { if l > 0 { - println!("Lint checks provided by plugins loaded by this crate:\n"); + safe_println!("Lint checks provided by plugins loaded by this crate:\n"); print_lints(plugin); } if g > 0 { - println!("Lint groups provided by plugins loaded by this crate:\n"); + safe_println!("Lint groups provided by plugins loaded by this crate:\n"); print_lint_groups(plugin_groups, false); } } @@ -996,12 +1004,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool { } fn describe_debug_flags() { - println!("\nAvailable options:\n"); + safe_println!("\nAvailable options:\n"); print_flag_list("-Z", config::Z_OPTIONS); } fn describe_codegen_flags() { - println!("\nAvailable codegen options:\n"); + safe_println!("\nAvailable codegen options:\n"); print_flag_list("-C", config::CG_OPTIONS); } @@ -1012,7 +1020,7 @@ fn print_flag_list( let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0); for &(name, _, _, desc) in flag_list { - println!( + safe_println!( " {} {:>width$}=val -- {}", cmdline_opt, name.replace('_', "-"), diff --git a/compiler/rustc_driver_impl/src/print.rs b/compiler/rustc_driver_impl/src/print.rs new file mode 100644 index 0000000000000..70de55320f7ae --- /dev/null +++ b/compiler/rustc_driver_impl/src/print.rs @@ -0,0 +1,20 @@ +use std::fmt; +use std::io::{self, Write as _}; + +macro_rules! safe_print { + ($($arg:tt)*) => {{ + $crate::print::print(std::format_args!($($arg)*)); + }}; +} + +macro_rules! safe_println { + ($($arg:tt)*) => { + safe_print!("{}\n", std::format_args!($($arg)*)) + }; +} + +pub(crate) fn print(args: fmt::Arguments<'_>) { + if let Err(_) = io::stdout().write_fmt(args) { + rustc_errors::FatalError.raise(); + } +} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 17647d13f9979..5149eed2e1af6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -861,6 +861,11 @@ impl<'tcx> PolyTraitPredicate<'tcx> { pub fn is_const_if_const(self) -> bool { self.skip_binder().is_const_if_const() } + + #[inline] + pub fn polarity(self) -> ImplPolarity { + self.skip_binder().polarity + } } /// `A: B` diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 8e7097ce4a779..c97473e6241f2 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -86,8 +86,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) -> QueryResult<'tcx> { if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() && poly_trait_pred.def_id() == goal.predicate.def_id() + && poly_trait_pred.polarity() == goal.predicate.polarity { - // FIXME: Constness and polarity + // FIXME: Constness ecx.probe(|ecx| { let assumption_trait_pred = ecx.instantiate_binder_with_infer(poly_trait_pred); @@ -111,6 +112,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) -> QueryResult<'tcx> { if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() && poly_trait_pred.def_id() == goal.predicate.def_id() + && poly_trait_pred.polarity() == goal.predicate.polarity { // FIXME: Constness and polarity ecx.probe(|ecx| { @@ -147,6 +149,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) { return result; } @@ -161,6 +167,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let tcx = ecx.tcx(); ecx.probe(|ecx| { @@ -176,6 +186,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.probe_and_evaluate_goal_for_constituent_tys( goal, structural_traits::instantiate_constituent_tys_for_sized_trait, @@ -186,6 +200,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.probe_and_evaluate_goal_for_constituent_tys( goal, structural_traits::instantiate_constituent_tys_for_copy_clone_trait, @@ -196,6 +214,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if goal.predicate.self_ty().has_non_region_infer() { return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); } @@ -217,6 +239,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let ty::FnPtr(..) = goal.predicate.self_ty().kind() { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { @@ -229,6 +255,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let tcx = ecx.tcx(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( @@ -259,6 +289,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let ty::Tuple(..) = goal.predicate.self_ty().kind() { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { @@ -268,8 +302,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_pointee_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, - _goal: Goal<'tcx, Self>, + goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -277,6 +315,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -297,6 +339,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let self_ty = goal.predicate.self_ty(); let ty::Generator(def_id, substs, _) = *self_ty.kind() else { return Err(NoSolution); @@ -326,6 +372,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let tcx = ecx.tcx(); let a_ty = goal.predicate.self_ty(); let b_ty = goal.predicate.trait_ref.substs.type_at(1); @@ -447,6 +497,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> Vec> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return vec![]; + } + let tcx = ecx.tcx(); let a_ty = goal.predicate.self_ty(); @@ -521,8 +575,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_discriminant_kind_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, - _goal: Goal<'tcx, Self>, + goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + // `DiscriminantKind` is automatically implemented for every type. ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -531,6 +589,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if !goal.param_env.is_const() { // `Destruct` is automatically implemented for every type in // non-const environments. @@ -545,6 +607,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + // `rustc_transmute` does not have support for type or const params if goal.has_non_region_placeholders() { return Err(NoSolution); diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 9d8e309a978d9..5d9772b878b03 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -39,6 +39,7 @@ use crate::sync::Arc; /// use std::sync::Arc; /// use std::task::{Context, Poll, Wake}; /// use std::thread::{self, Thread}; +/// use core::pin::pin; /// /// /// A waker that wakes up the current thread when called. /// struct ThreadWaker(Thread); @@ -52,7 +53,7 @@ use crate::sync::Arc; /// /// Run a future to completion on the current thread. /// fn block_on(fut: impl Future) -> T { /// // Pin the future so it can be polled. -/// let mut fut = Box::pin(fut); +/// let mut fut = pin!(fut); /// /// // Create a new context to be passed to the future. /// let t = thread::current(); diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 07fd96f929586..e6e3b55efa9ae 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -1456,7 +1456,6 @@ pub struct TimSortRun { /// Takes a range as denoted by start and end, that is already sorted and extends it to the right if /// necessary with sorts optimized for smaller ranges such as insertion sort. -#[cfg(not(no_global_oom_handling))] fn provide_sorted_batch(v: &mut [T], start: usize, mut end: usize, is_less: &mut F) -> usize where F: FnMut(&T, &T) -> bool, diff --git a/tests/run-make/inaccessbile-temp-dir/Makefile b/tests/run-make/inaccessbile-temp-dir/Makefile new file mode 100644 index 0000000000000..f701dde829b30 --- /dev/null +++ b/tests/run-make/inaccessbile-temp-dir/Makefile @@ -0,0 +1,31 @@ +# only-linux + +include ../tools.mk + +# Issue #66530: We would ICE if someone compiled with `-o /dev/null`, +# because we would try to generate auxiliary files in `/dev/` (which +# at least the OS X file system rejects). +# +# An attempt to `-Ztemps-dir` into a directory we cannot write into should +# indeed be an error; but not an ICE. +# +# However, some folks run tests as root, which can write `/dev/` and end +# up clobbering `/dev/null`. Instead we'll use an inaccessible path, which +# also used to ICE, but even root can't magically write there. +# +# Note that `-Ztemps-dir` uses `create_dir_all` so it is not sufficient to +# use a directory with non-existing parent like `/does-not-exist/output`. + +all: + # Create an inaccessible directory + mkdir $(TMPDIR)/inaccessible + chmod 000 $(TMPDIR)/inaccessible + + # Run rustc with `-Ztemps-dir` set to a directory + # *inside* the inaccessible one, so that it can't create it + $(RUSTC) program.rs -Ztemps-dir=$(TMPDIR)/inaccessible/tmp 2>&1 \ + | $(CGREP) "failed to find or create the directory specified by `--temps-dir`" + + # Make the inaccessible directory accessible, + # so that compiletest can delete the temp dir + chmod +rw $(TMPDIR)/inaccessible diff --git a/tests/run-make/inaccessbile-temp-dir/program.rs b/tests/run-make/inaccessbile-temp-dir/program.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/inaccessbile-temp-dir/program.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/ui/io-checks/inaccessbile-temp-dir.rs b/tests/ui/io-checks/inaccessbile-temp-dir.rs deleted file mode 100644 index 9c0aa01357217..0000000000000 --- a/tests/ui/io-checks/inaccessbile-temp-dir.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Issue #66530: We would ICE if someone compiled with `-o /dev/null`, -// because we would try to generate auxiliary files in `/dev/` (which -// at least the OS X file system rejects). -// -// An attempt to `-o` into a directory we cannot write into should indeed -// be an error; but not an ICE. -// -// However, some folks run tests as root, which can write `/dev/` and end -// up clobbering `/dev/null`. Instead we'll use a non-existent path, which -// also used to ICE, but even root can't magically write there. - -// compile-flags: -Z temps-dir=/does-not-exist/output - -// The error-pattern check occurs *before* normalization, and the error patterns -// are wildly different between build environments. So this is a cop-out (and we -// rely on the checking of the normalized stderr output as our actual -// "verification" of the diagnostic). - -// error-pattern: error - -// On Mac OS X, we get an error like the below -// normalize-stderr-test "failed to write bytecode to /does-not-exist/output.non_ice_error_on_worker_io_fail.*" -> "io error modifying /does-not-exist/" - -// On Linux, we get an error like the below -// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /does-not-exist/" - -// ignore-windows - this is a unix-specific test -// ignore-emscripten - the file-system issues do not replicate here -// ignore-wasm - the file-system issues do not replicate here -// ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu - -#![crate_type = "lib"] -#![cfg_attr(not(feature = "std"), no_std)] -pub mod task { - pub mod __internal { - use crate::task::Waker; - } - pub use core::task::Waker; -} diff --git a/tests/ui/io-checks/inaccessbile-temp-dir.stderr b/tests/ui/io-checks/inaccessbile-temp-dir.stderr deleted file mode 100644 index 2fc5f93ef791a..0000000000000 --- a/tests/ui/io-checks/inaccessbile-temp-dir.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: failed to find or create the directory specified by `--temps-dir` - -error: aborting due to previous error - diff --git a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs index 134e7d420e3ea..6ec81a943067b 100644 --- a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs +++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs @@ -9,7 +9,7 @@ // up clobbering `/dev/null`. Instead we'll use a non-existent path, which // also used to ICE, but even root can't magically write there. -// compile-flags: -o /does-not-exist/output +// compile-flags: -o ./does-not-exist/output // The error-pattern check occurs *before* normalization, and the error patterns // are wildly different between build environments. So this is a cop-out (and we @@ -19,22 +19,14 @@ // error-pattern: error // On Mac OS X, we get an error like the below -// normalize-stderr-test "failed to write bytecode to /does-not-exist/output.non_ice_error_on_worker_io_fail.*" -> "io error modifying /does-not-exist/" +// normalize-stderr-test "failed to write bytecode to ./does-not-exist/output.non_ice_error_on_worker_io_fail.*" -> "io error modifying ./does-not-exist/" // On Linux, we get an error like the below -// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /does-not-exist/" +// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying ./does-not-exist/" // ignore-windows - this is a unix-specific test // ignore-emscripten - the file-system issues do not replicate here // ignore-wasm - the file-system issues do not replicate here // ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu -#![crate_type="lib"] - -#![cfg_attr(not(feature = "std"), no_std)] -pub mod task { - pub mod __internal { - use crate::task::Waker; - } - pub use core::task::Waker; -} +#![crate_type = "lib"] diff --git a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr index edadecf273a7b..f1d9ed8ac8b76 100644 --- a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr +++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr @@ -1,6 +1,6 @@ warning: ignoring --out-dir flag due to -o flag -error: io error modifying /does-not-exist/ +error: io error modifying ./does-not-exist/ error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/traits/new-solver/negative-coherence-bounds.rs b/tests/ui/traits/new-solver/negative-coherence-bounds.rs new file mode 100644 index 0000000000000..5436b02c3ded2 --- /dev/null +++ b/tests/ui/traits/new-solver/negative-coherence-bounds.rs @@ -0,0 +1,40 @@ +// check-pass + +// This test verifies that negative trait predicate cannot be satisfied from a +// positive param-env candidate. + +// Negative coherence is one of the only places where we actually construct and +// evaluate negative predicates. Specifically, when verifying whether the first +// and second impls below overlap, we do not want to consider them disjoint, +// otherwise the second impl would be missing an associated type `type Item` +// which is provided by the first impl that it is specializing. + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete +#![feature(with_negative_coherence)] + +trait BoxIter { + type Item; + + fn last(self) -> Option; +} + +impl BoxIter for Box { + type Item = I::Item; + + default fn last(self) -> Option { + todo!() + } +} + +// When checking that this impl does/doesn't overlap the one above, we evaluate +// a negative version of all of the where-clause predicates of the impl below. +// For `I: !Iterator`, we should make sure that the param-env clause `I: Iterator` +// from above doesn't satisfy this predicate. +impl BoxIter for Box { + fn last(self) -> Option { + (*self).last() + } +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/negative-coherence-bounds.stderr b/tests/ui/traits/new-solver/negative-coherence-bounds.stderr new file mode 100644 index 0000000000000..4127f51f56da2 --- /dev/null +++ b/tests/ui/traits/new-solver/negative-coherence-bounds.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-coherence-bounds.rs:12:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted +