Skip to content

Rollup of 5 pull requests #110818

New issue

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

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

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 48 additions & 40 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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 <foo> Warn about <foo>
@@ -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<LintId>)>, 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::<Vec<String>>()
.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<T>(
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('_', "-"),
20 changes: 20 additions & 0 deletions compiler/rustc_driver_impl/src/print.rs
Original file line number Diff line number Diff line change
@@ -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();
}
}
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -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`
72 changes: 69 additions & 3 deletions compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
@@ -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,15 +302,23 @@ 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)
}

fn consider_builtin_future_candidate(
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<CanonicalResponse<'tcx>> {
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);
3 changes: 2 additions & 1 deletion library/alloc/src/task.rs
Original file line number Diff line number Diff line change
@@ -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<T>(fut: impl Future<Output = T>) -> 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();
1 change: 0 additions & 1 deletion library/core/src/slice/sort.rs
Original file line number Diff line number Diff line change
@@ -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<T, F>(v: &mut [T], start: usize, mut end: usize, is_less: &mut F) -> usize
where
F: FnMut(&T, &T) -> bool,
31 changes: 31 additions & 0 deletions tests/run-make/inaccessbile-temp-dir/Makefile
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions tests/run-make/inaccessbile-temp-dir/program.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}
39 changes: 0 additions & 39 deletions tests/ui/io-checks/inaccessbile-temp-dir.rs

This file was deleted.

4 changes: 0 additions & 4 deletions tests/ui/io-checks/inaccessbile-temp-dir.stderr

This file was deleted.

16 changes: 4 additions & 12 deletions tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs
Original file line number Diff line number Diff line change
@@ -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"]
2 changes: 1 addition & 1 deletion tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr
Original file line number Diff line number Diff line change
@@ -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

40 changes: 40 additions & 0 deletions tests/ui/traits/new-solver/negative-coherence-bounds.rs
Original file line number Diff line number Diff line change
@@ -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<Self::Item>;
}

impl<I: Iterator + ?Sized> BoxIter for Box<I> {
type Item = I::Item;

default fn last(self) -> Option<I::Item> {
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<I: Iterator> BoxIter for Box<I> {
fn last(self) -> Option<I::Item> {
(*self).last()
}
}

fn main() {}
12 changes: 12 additions & 0 deletions tests/ui/traits/new-solver/negative-coherence-bounds.stderr
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/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